Center of a line, if followSurface is activated

Is there a way to calculate center of a line, if followSurface is activated, so I can display a text near the line? My first idea was to take average value of both cartographic coordinates, but it seems I’m wrong :(.

My code:

var viewer = new Cesium.Viewer(‘cesiumContainer’);

viewer.scene.primitives.add(new Cesium.Primitive({

geometryInstances : new Cesium.GeometryInstance({

geometry : new Cesium.PolylineGeometry({

positions : Cesium.Cartesian3.fromDegreesArrayHeights([

0.0, 45.0, 0,

90.0, 45.0, 0

]),

followSurface: true,

width : 2.0,

vertexFormat : Cesium.PolylineMaterialAppearance.VERTEX_FORMAT

})

}),

appearance : new Cesium.PolylineMaterialAppearance({

material : Cesium.Material.fromType(‘Color’),

renderState : {

depthTest : {

enabled : false

},

cull : {

enabled : true,

face : Cesium.CullFace.BACK

}

}

})

}));

var labelCollection = new Cesium.LabelCollection();

labelCollection.add({

position: Cesium.Cartesian3.fromDegrees(45.0, 45.0, 0.0),

text: ‘Test’,

font: ‘20px sans-serif’,

style: Cesium.LabelStyle.FILL_AND_OUTLINE,

outlineWidth: 4.0,

horizontalOrigin: Cesium.HorizontalOrigin.CENTER,

verticalOrigin: Cesium.VerticalOrigin.CENTER,

disableDepthTestDistance: Number.POSITIVE_INFINITY

});

viewer.scene.primitives.add(labelCollection);

``

The shortest curve connecting two points on the ellipsoid surface is called a geodesic.

In Cesium, you can use the EllipsoidGeodesic class, specifically interpolateUsingFraction, to find the midpoint (fraction of 1/2)

https://cesiumjs.org/Cesium/Build/Documentation/EllipsoidGeodesic.html?

Hi,

I want to connect two nodes on the earth by a curve line (I do not care about the elevation height) instead of straight line. I understand that EllipsoidGeodesic can do that. I am just wondering to know if there is any sample in the sandcastle.

Thanks

There is. Just enter EllipsoidGeodesic in the search field of the Sandcastle toolbar. In case that isn’t sufficiently helpful, maybe the code below will be.

Scott

//******************************************************************************

// formatNumber

//******************************************************************************

function formatNumber(number, width, precision) {

var formattedValue;

var value = number.toFixed(precision);

var valueLength = value.length;

var wholePart = value.substring(0, value.indexOf('.'));

var decimalPart = value.substring(value.indexOf('.') + 1);

if (wholePart.length > width) {

    // Wrong length, but the value's all there.

    formattedValue = value;

} else {

    // Everything fits, need to pad left side

    formattedValue = value;

    var padLength = width - valueLength;

    for (var i = 0; i < padLength; i++) {

        formattedValue = ' ' + formattedValue;

    }

}

return formattedValue;

}

//******************************************************************************

// prettyCartographic

//******************************************************************************

function prettyCartographic(cartographic) {

var longitude = formatNumber(Cesium.Math.toDegrees(cartographic.longitude), 11, 6);

var latitude = formatNumber(Cesium.Math.toDegrees(cartographic.latitude), 10, 6);

return '(' + longitude + ', ' + latitude + ')';

}

//******************************************************************************

// Main

//******************************************************************************

var viewer = new Cesium.Viewer(‘cesiumContainer’);

// Create a geodesic from New York City to London, UK

var heightAboveSurface = 100000.0;

var nyc = Cesium.Cartographic.fromDegrees(-74.0060, 40.7128, heightAboveSurface);

var london = Cesium.Cartographic.fromDegrees(0.1278, 51.5074, heightAboveSurface);

var geodesic = new Cesium.EllipsoidGeodesic(nyc, london);

//------------------------------------------------------------------------------

// Compute evenly spaced points along the geodesic at 10 km intervals

// with even spacing at both ends.

//------------------------------------------------------------------------------

var unitFraction = 100.0 / (Math.ceil(geodesic.surfaceDistance / 10000.0) - 1);

var points = ;

var fractionalPoint;

fractionalPoint = geodesic.interpolateUsingFraction(0.0, new Cesium.Cartographic());

fractionalPoint.height = heightAboveSurface;

points.push(fractionalPoint);

for (var fraction = unitFraction * 0.25; fraction < 1.0; fraction += unitFraction) {

fractionalPoint = geodesic.interpolateUsingFraction(fraction, new Cesium.Cartographic());

fractionalPoint.height = heightAboveSurface;

points.push(fractionalPoint);

}

fractionalPoint = geodesic.interpolateUsingFraction(1.0, new Cesium.Cartographic());

fractionalPoint.height = heightAboveSurface;

points.push(fractionalPoint);

//------------------------------------------------------------------------------

// Dump the points to the console

//------------------------------------------------------------------------------

console.log(prettyCartographic(nyc) + ’ NYC’);

for (var point = 0; point < points.length; point++) {

console.log(prettyCartographic(points[point]));

}

console.log(prettyCartographic(london) + ’ London’);

//------------------------------------------------------------------------------

// Draw the points

//------------------------------------------------------------------------------

for (point = 0; point < points.length; point++) {

viewer.entities.add({

    position: Cesium.Cartographic.toCartesian(points[point]),

    point: {

        color: Cesium.Color.DODGERBLUE,

        pixelSize: 7,

        outlineColor: Cesium.Color.WHITE,

        outlineWidth: 2

    }

});

}

//------------------------------------------------------------------------------

// Draw the line

//------------------------------------------------------------------------------

var endPoints = [

Cesium.Cartographic.toCartesian(nyc),

Cesium.Cartographic.toCartesian(london)];

viewer.entities.add({

polyline: {

    positions: endPoints,

    followSurface: true,

    width: 3

}

});

viewer.zoomTo(viewer.entities);

``

Thank you so much Scott.

Hi every one,

I have a question about connecting two lines with a arc (as shown with orange curve in the figure).

Setting followSurface:true in PolylineGraphics cannot do that (still it gives me red line).

Also, I use EllipsoidGeodesic to get some points on my path but changing altitude, longitude and height a little bit to build a curve is not easy for different points.

I really appreciate if you can help me.

regards,

1.PNG

Hey Maryam,

I looked this up, and this seemed like the most relevant thread:

https://groups.google.com/d/msg/cesium-dev/-KY0xlBkem8/fLwp9qjzAgAJ

But it looks like CesiumJS does not have a built-in method of drawing an arbitrary arc off the surface like that. You might have to write a function to compute those points yourself to create that arc.

If you figure it out it’d be great to post your code back here, or better, contribute it back to CesiumJS so others can use it! You’ll probably find implementations for this on other graphics libraries since I think it’s a common enough thing.