Polylines - drawing and measuring distance between two points

Hello,
I'm trying to create a polyline which will measure distance between two points.

I've used two examples I've seen:

1. drawing polylines on mouse click and movement:

the issue I'm having with the above is that the temp polylines are "blinking", this must be because of the line position callback property.

2.Adding a label to the polyline entity which will display the distance between two points.
for this I've used a part of the Callbackproperty sample in sandcastle:

2.a. Adding a label to the final polyline is fine but the position as I've explained above.
2.b. adding the label to the templine caused the templine to be recreated again and again.

I've taken the Midpoint function but it gives me the wrong position and therefore my label isn't displayed good.

Attached below my code:

    ruler()
    {
        let viewer = this.viewer;
        var screenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

        var startPoint = new Cesium.Cartographic();
        var endPoint = new Cesium.Cartographic();

// Event handler for left click
        screenSpaceEventHandler.setInputAction(function(click) {

            // get position of click
            var clickPosition = viewer.camera.pickEllipsoid(click.position);

            // Event handler for mouse movement
            screenSpaceEventHandler.setInputAction(function(movement) {

                // get position of mouse
                var mousePosition = viewer.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid, mousePosition);

                // create an empty array where the coordinates of the line will be stored
                var lineArray = ;

                // convert mouse and click position to lon/lat coordinates and add them to the array
                var cartographicMouse = Cesium.Ellipsoid.WGS84.cartesianToCartographic(mousePosition);
                var cartographicClick = Cesium.Ellipsoid.WGS84.cartesianToCartographic(clickPosition);

                startPoint.longitude = cartographicClick.longitude;
                startPoint.latitude = cartographicClick.latitude;
                endPoint.longitude = cartographicMouse.longitude;
                endPoint.latitude = cartographicMouse.latitude;

                var x = Cesium.Math.toDegrees(cartographicMouse.longitude);
                var y = Cesium.Math.toDegrees(cartographicMouse.latitude);
                lineArray.push(x);
                lineArray.push(y);

                x = Cesium.Math.toDegrees(cartographicClick.longitude);
                y = Cesium.Math.toDegrees(cartographicClick.latitude);
                lineArray.push(x);
                lineArray.push(y);

                // use callback property to get cartesian coordinates for the line; if there is an existing line remove it, store in varible
                var linePosition = new Cesium.CallbackProperty(function(time, result) {
                    if (typeof tempLine !== 'undefined') {
                        viewer.entities.remove(tempLine);
                    }
                    return new Cesium.Cartesian3.fromDegreesArray(lineArray);
                }, false);
                let surfacePositions = Cesium.PolylinePipeline.generateArc({
                    positions: linePosition.getValue(),
                });
                let scratchCartesian3 = new Cesium.Cartesian3();
                let surfacePositionsLength = surfacePositions.length;
                let totalDistanceInMeters = 0;
                for (let i = 3; i < surfacePositionsLength; i += 3) {
                    scratchCartesian3.x = surfacePositions[i] - surfacePositions[i - 3];
                    scratchCartesian3.y = surfacePositions[i + 1] - surfacePositions[i - 2];
                    scratchCartesian3.z = surfacePositions[i + 2] - surfacePositions[i - 1];
                    totalDistanceInMeters += Cesium.Cartesian3.magnitude(scratchCartesian3);
                }
                let totalDistanceInKm = totalDistanceInMeters * 0.001;
                // draw tempLine
                var startCartographic = Cesium.Cartographic.fromDegrees(startPoint.longitude, startPoint.latitude);
                var endCartographic = new Cesium.Cartographic();
                var geodesic = new Cesium.EllipsoidGeodesic();
                var scratch = new Cesium.Cartographic();
                function getMidpointT(time, result) {
                    // Get the end position from the polyLine's callback.
                    var endPoint = tempLine.polyline.positions.getValue(time, result)[1];
                    endCartographic = Cesium.Cartographic.fromCartesian(endPoint);
                    geodesic.setEndPoints(startCartographic, endCartographic);
                    var midpointCartographic = geodesic.interpolateUsingFraction(0.5, scratch);
                    return Cesium.Cartesian3.fromRadians(midpointCartographic.longitude, midpointCartographic.latitude);
                }

                var tempLine = viewer.entities.add({
                    position : new Cesium.CallbackProperty(getMidpointT, false),
                    polyline: {
                        positions: linePosition,
                        width: 5,
                        material: Cesium.Color.RED
                    },
                    label: {
                        text: totalDistanceInKm.toFixed(2)+' km',
                        show : true,
                        showBackground : false,
                        font : '14px monospace',
                    },

                });
                console.log(viewer.entities);
                // Event handler for second click; draw line with position from variable linePosition
                screenSpaceEventHandler.setInputAction(function(click) {

                    // get position of click
                    let clickPosition = viewer.camera.pickEllipsoid(click.position);
                    var startCartographic = Cesium.Cartographic.fromDegrees(startPoint.longitude, startPoint.latitude);
                    var endCartographic = new Cesium.Cartographic();
                    var geodesic = new Cesium.EllipsoidGeodesic();
                    var scratch = new Cesium.Cartographic();
                    function getMidpoint(time, result) {
                        // Get the end position from the polyLine's callback.
                        var endPoint = Line.polyline.positions.getValue(time, result)[1];
                        endCartographic = Cesium.Cartographic.fromCartesian(endPoint);
                        geodesic.setEndPoints(startCartographic, endCartographic);
                        var midpointCartographic = geodesic.interpolateUsingFraction(0.5, scratch);
                        return Cesium.Cartesian3.fromRadians(midpointCartographic.longitude, midpointCartographic.latitude);
                    }
                    var Line = viewer.entities.add({
                        position : new Cesium.CallbackProperty(getMidpoint, false),
                        polyline: {
                            positions: linePosition,
                            width: 5,
                            material: Cesium.Color.RED
                        },
                        label: {
                            text: totalDistanceInKm.toFixed(2)+' km',
                            show : true,
                            showBackground : false,
                            font : '14px monospace',
                        },
                    });
                    console.log(Line);
                    screenSpaceEventHandler = screenSpaceEventHandler && screenSpaceEventHandler.destroy();

                }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    }

I would very much like an assistant with the issues above.

thanks a lot,
Lior.

I thought about a solution for the label position problem but couldn't manage to find how to get that.

i've seen that if i'm not picking a position for the entity itself,only for the polyline,when clicking(selecting) the polyline I'm getting the midpoint of it.

is there a way to get that position without selection?

Hey Lior,

There seems to be a lot going on here. It would help if you could isolate your problem with maybe an example I can run on Sandcastle (https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/). Are you saying you’ve figured out a solution for the first issue?

Here’s the official Sandcastle example on drawing a polyline:

Let me know if that helps. Also, if you’re interested, the Cesium ion SDK does actually have a measuring tool like you’re describing. You can reach out to Tim (tim@cesium.com) if you’re interested in checking that out.

Hey Omar,

I've sent an email to Tim.

Thanks a lot!
Lior.

I am here