Measuring Distance
Switch the mouse mode to distance measurement mode, then measure the distance between clicked points. The measurement results are returned as events and visualized using POI and Line.

Interface Functionality
When you click on the point you want to measure, the distance value between that point and the previous one is displayed. Double-clicking ends the distance measurement. Clicking on another point after ending a measurement will display a new set of measurement results.
The result values display both the intermediate distance values and the cumulative distance values.

Following are the detailed steps of the code.
Implementing the Functionality
Global Variables
Before implementing the functionality, declare variables that will be used globally.
var GLOBAL = {
m_objcount: 0, // Count of POI displaying measurement objects
m_mercount: 0, // Measurement object count
};
These variables help manage the count of POI objects and measurement objects after ending a measurement.
step 1. Creating a Layer
A layer is created to visualize the distance measurement icons and values. Since the distance values will be displayed as POI, the layer type is set to ELT_3DPOINT.
For more information on layer types, please refer here.
let layerList = new Module.JSLayerList(true);
let layer = layerList.createLayer("MEASURE_POI", Module.ELT_3DPOINT);
layer.setMaxDistance(20000.0);
layer.setSelectable(false);
step 2 - 1. Setting Callback Functions
Callback functions are registered to receive the calculated distance from the engine. Callback functions are registered through JSOption.
(For detailed API descriptions, see callBackAddPoint and callBackCompletePoint).
Two types of callback functions are registered:
A callback function called when a measurement point is selected (step 2-2. Distance Measurement Callback Function Creation).
A callback function called when double-clicking to end distance measurement (step 2-3. Distance Measurement End Callback Function Creation).
Module.getOption().callBackAddPoint(addPoint); // Callback on mouse input, returns success on success or failure error on failure
Module.getOption().callBackCompletePoint(endPoint); // Callback on measurement end (double-click), returns success on success or failure error on failure
When the mouse mode is set to MML_ANALYS
_DISTANCE_STRAIGHT, the specified callback function is called upon clicking the measurement points.
For setting the mouse mode, refer to step 3. Changing Mouse Mode.
step 2 - 2. Distance Measurement Callback Function Creation
This is the callback function executed on left mouse click. It visualizes the calculated distance.
function addPoint(e) {
// e components
// dMidLon, dMidLat, dMidAlt : Midpoint (longitude, latitude, altitude) between the previous and current points
// dLon, dLat, dAlt : Current point (longitude, latitude, altitude)
// dDistance : Length between the current and previous points
// dTotalDistance : Length between all points
let partDistance = e.dDistance,
totalDistance = e.dTotalDistance;
if (partDistance == 0 && totalDistance == 0) {
GLOBAL.m_objcount = 0; // Reset POI count
createPOI(new Module.JSVector3D(e.dLon, e.dLat, e.dAlt), "rgba(255, 204, 198, 0.8)", "Start", true);
} else {
if (e.dDistance > 0.01) {
createPOI(new Module.JSVector3D(e.dMidLon, e.dMidLat, e.dMidAlt), "rgba(255, 255, 0, 0.8)", e.dDistance, false);
}
createPOI(new Module.JSVector3D(e.dLon, e.dLat, e.dAlt), "rgba(255, 204, 198, 0.8)", e.dTotalDistance, true);
}
}
step 2 - 3. Distance Measurement End Callback Function Creation
This is the callback function executed on double-click. It ends the distance measurement.
function endPoint(e) {
viewListOBjKey(e);
GLOBAL.m_mercount++;
}
step 3. Changing Mouse Mode
The mouse mode is changed for distance measurement.
For more information on mouse modes, please refer here.
Module.XDSetMouseState(Module.MML_ANALYS_DISTANCE_STRAIGHT);
step 4 - 1. Creating Distance Icon
An icon is created to render the returned distance value. The icon image created in this step will be applied to the POI object that will display the measurement value.
The process of creating a POI object and applying the result image is described in step 5. Creating Distance Object.
function drawIcon(_canvas, _color, _value, _balloonType) {
// Return context and clear background
var ctx = _canvas.getContext("2d"),
width = _canvas.width,
height = _canvas.height;
ctx.clearRect(0, 0, width, height);
// Set Draw Path for background then draw text
if (_balloonType) {
drawBalloon(ctx, height * 0.5, width, height, 5, height * 0.25, _color);
setText(ctx, width * 0.5, height * 0.2, _value);
} else {
drawRoundRect(ctx, 0, height * 0.3, width, height * 0.25, 5, _color);
setText(ctx, width * 0.5, height * 0.5, _value);
}
return ctx.getImageData(0, 0, _canvas.width, _canvas.height).data;
}
There are two types of images created in this step:
Middle distance display icon image.

drawRoundRect function (step 4-3. Create distance rectangle icon) and setText([step 4-4. Create distance measurement result value icon](tutorial _distance.md#step-4-4.-icon)) Combine the functions to create a round text box image.
Cumulative distance display icon image

drawBalloon function (step 4-2. Create distance speech bubble icon) and setText([step 4-4. Create distance measurement result value icon](tutorial _distance.md#step-4-4.-icon)) Combine the functions to create a round text box image.
step 4 - 2. Creating Distance Balloon Icon
A balloon image is drawn to display the cumulative distance values.
function drawBalloon(ctx, marginBottom, width, height, barWidth, barHeight, color) {
var wCenter = width * 0.5,
hCenter = height * 0.5;
// Set Draw Path for balloon shape
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(0, height - barHeight - marginBottom);
ctx.lineTo(wCenter - barWidth, height - barHeight - marginBottom);
ctx.lineTo(wCenter, height - marginBottom);
ctx.lineTo(wCenter + barWidth, height - barHeight - marginBottom);
ctx.lineTo(width, height - barHeight - marginBottom);
ctx.lineTo(width, 0);
ctx.closePath();
// Draw balloon
ctx.fillStyle = color;
ctx.fill();
}
step 4 - 3. Creating Distance Rectangle Icon
A rounded rectangle balloon image is drawn to display the intermediate distance values.
function drawRoundRect(ctx, x, y, width, height, radius, color) {
if (width < 2 * radius) radius = width * 0.5;
if (height < 2 * radius) radius = height * 0.5;
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.arcTo(x + width, y, x + width, y + height, radius);
ctx.arcTo(x + width, y + height, x, y + height, radius);
ctx.arcTo(x, y + height, x, y, radius);
ctx.arcTo(x, y, x + width, y, radius);
ctx.closePath();
// Draw rectangle
ctx.fillStyle = color;
ctx.fill();
return ctx;
}
step 4 - 4. Creating Distance Measurement Result Value Icon
The calculated distance value is drawn as text on the drawn balloon.
function setText(_ctx, _posX, _posY, _value) {
var strText = "";
// Set text string
if (typeof _value == "number") {
strText = setKilloUnit(_value, 0.001, 0);
} else {
strText = _value;
}
// Set text style
_ctx.font = "bold 16px sans-serif";
_ctx.textAlign = "center";
_ctx.fillStyle = "rgb(0, 0, 0)";
// Draw text
_ctx.fillText(strText, _posX, _posY);
}
step 4 - 5. Converting Distance Measurement Units (m/km)
The returned distance value is optionally converted to m/km text.
function setKilloUnit(_text, _meterToKilloRate, _decimalSize) {
if (_decimalSize < 0) _decimalSize = 0;
if (typeof _text == "number") {
if (_text < 1.0 / (_meterToKilloRate * Math.pow(10, _decimalSize))) {
_text = _text.toFixed(1).toString() + "m";
} else {
_text = (_text * _meterToKilloRate).toFixed(2).toString() + "km";
}
}
return _text;
}
step 5. Creating Distance Object
A POI object is created using the icon and added to the layer.
The image is applied to the newly created POI object by storing the image drawn on the canvas in JSSymbol.
JSSymbol
XDWorld has a JSSymbol class for storing and managing textures.
The images created in step 4 are stored in JSSymbol and will be linked to the newly created POI object.

function createPOI(_position, _color, _value, _balloonType) {
// Parameters
// _position : POI creation location
// _color : Color configuration for drawIcon
// _value : Text displayed on drawIcon
// _balloonType : Corner option for drawIcon (true: sharp corners, false: rounded corners)
// Create a canvas to draw the POI icon image
var drawCanvas = document.createElement("canvas");
// Canvas size (image size)
drawCanvas.width = 100;
drawCanvas.height = 100;
// Return icon image data
let imageData = drawIcon(drawCanvas, _color, _value, _balloonType);
let Symbol = Module.getSymbol();
let layerList = new Module.JSLayerList(true);
let layer = layerList.nameAtLayer("MEASURE_POI");
poi = Module.createPoint(GLOBAL.m_mercount + "_POI_" + GLOBAL.m_objcount);
poi.setPosition(_position); // Set location
poi.setImage(imageData, drawCanvas.width, drawCanvas.height); // Set icon
layer.addObject(poi, 0); // Register POI in layer
GLOBAL.m_objcount++;
}
step 6. Resetting Distance Measurement
The distance measurement results and objects are reset.
function clearAnalysis() {
// Reset ongoing analysis content
Module.XDClearDistanceMeasurement();
GLOBAL.m_mercount = 0;
// Delete layer
let layerList = new Module.JSLayerList(true);
let layer = layerList.nameAtLayer("MEASURE_POI");
layer.removeAll();
}
Result Screen
After completing all the steps, the distance measurement functionality is completed, displaying distance information for clicked points.

If you want to see the live code for the distance measurement process, please click here.
Last updated