How to get polylineGeometry to work with coordinates in X-Z plane

1. A concise explanation of the problem you're experiencing.

If I set vertices to (x, y, 0) so that the polyline is in the X-Y plane, the polyline renders fine. If I use (x, 0 , z) so the polyline is in the X-Z plane, it doesn't render the polylineGeometry correctly. The vertices are correct and can be plotted in another drawing program. I set VertexFormat positions to true for 3D.

2. A minimal code example. If you've found a bug, this helps us reproduce and repair it.

const template = new Cesium.PolylineGeometry({
      positions: vertices,
      width: 4,
      vertexFormat: new Cesium.VertexFormat({
  position : true,
    })
});

where vertices are an array of (x, 0, z) values like
0.08715574274765804, 0, 1.9961946980917455,
0.1736481776669302, 0, 1.9848077530122081,
0.25881904510252063, 0, 1.9659258262890684,
0.3420201433256686, 0, 1.9396926207859084,

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.

Trying to draw a polyline primitive geometry in the X-Z plane

4. The Cesium version you're using, your operating system and browser.
"cesium": "1.48.0"
chrome Version 73.0.3683.103 (Official Build) (64-bit)

Are you able to provide a Sandcastle example that I can run? And/or can you elaborate on what you mean by “doesn’t render correctly” ?

I tried with a few sample positions in this Sandcastle and I’m able to see the polyline as expected when swapping out the 3 position arrays.

Nice work Omar!

I’m going to try to build on your sandcastle till my code breaks it. Thank you for the push out of the gate!

Omar - if you’re still listening, I changed your sandcastle example below by making the coordinates for the X-Z plane create a square in the XZ plane. The ‘model’ vertices are:

var positionsXZ = [

new Cesium.Cartesian3(0, 0, 0),

new Cesium.Cartesian3(10, 0, 0),

new Cesium.Cartesian3(10, 0, 10),

new Cesium.Cartesian3(0, 0, 10)

];

Then I use the modelMatrix transform to transform the coordinates to the center in lat/lon space at

var center = Cesium.Cartesian3.fromDegrees(-72.029957, 42.458760,3000);

This is where the polylineGeometry is failing. With this square model, i’m getting a Cesium developer error.

Thanks for any further insights.

Here is the modified code from your sandcastle:

var viewer = new Cesium.Viewer(‘cesiumContainer’, {

globe: false

});

var scene = viewer.scene;

var positions = [

new Cesium.Cartesian3(1353734.0802592516, -5052204.367465052, 3637866.909378095),

new Cesium.Cartesian3(-3000049.5875969846, -4284514.838654135, 3637866.909378095)

];

var positionsXZ = [

new Cesium.Cartesian3(0, 0, 0),

new Cesium.Cartesian3(10, 0, 0),

new Cesium.Cartesian3(10, 0, 10),

new Cesium.Cartesian3(0, 0, 10)

];

var positionsXY = [

new Cesium.Cartesian3(1353734.0802592516, -5052204.367465052, 0),

new Cesium.Cartesian3(-3000049.5875969846, -4284514.838654135, 0)

];

var polyline = new Cesium.PolylineGeometry({

//positions : positions,

positions: positionsXZ,

//positions: positionsXY,

width : 2.0,

color : [Cesium.Color.RED],

});

var center = Cesium.Cartesian3.fromDegrees(-72.029957, 42.458760,3000);

var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center);

var instance = new Cesium.GeometryInstance(

{geometry : polyline,

modelMatrix: modelMatrix });

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

geometryInstances : [instance],

appearance : new Cesium.PolylineMaterialAppearance({

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

})

}));

viewer.camera.setView({

destination : Cesium.Cartesian3.fromDegrees(-72.029957, 42.458760,3100)

});

Hi Marianne,

The issue with your polyline is that one of the positions is defined at the origin (0,0,0). When Cesium tries to create a polyline it attempts to extract heights via a call to ellipsoid.cartesianToCartographic (PolylinePipeline.js ln:52). The docs state that passing the origin value to this method returns 'undefined' (https://cesiumjs.org/Cesium/Build/Documentation/Ellipsoid.html). This makes sense since there are an infinite number of cartographic points that map to this cartesian point. It might feel odd to you because you are defining a model matrix for your geometry instance which you anticipate (0,0,0) to be at the origin of that transform. Unfortunately the polyline must be instantiated before the geometry instance so it has no idea about the modelmatrix ahead of time. I would suggest shifting your initial frame of reference to get around this even though it is a bit of a pain and maybe not quite as intuitive as you like. Curious if Omar has any other ideas as well.

Thanks for the response Beckerr, but the coordinate at (0,0,0) may be a different problem. The problem I’m trying to solve is to draw a polyline in the XZ plane using coordinates like these::

var positionsXZ = [

new Cesium.Cartesian3(1, 0, 1),

new Cesium.Cartesian3(10, 0, 1),

new Cesium.Cartesian3(10, 0, 10),

new Cesium.Cartesian3(1, 0, 10)

];

The problem seems to be with transforming the polylineGeometry to ECEF coordinates. Do you think this should be possible?

Hey Marianne,

If I understand correctly, the goal is to draw a rectangle that is perpendicular (and does not curve with the earth surface) to a fixed location above or on the earth like this exaggerated image when viewed from the side.

I have created a sandcastle demo that shows the steps to do this below. The main idea is that we calculate the positions by transforming them by the eastNorthUp matrix ahead of time.

//CODE STARTS HERE

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

var scene = viewer.scene;

var center = Cesium.Cartesian3.fromDegrees(45, 45, 100);

var originTransform = Cesium.Transforms.eastNorthUpToFixedFrame(center);

var topLeft = new Cesium.Cartesian3(-100,0, 100);

var topRight = new Cesium.Cartesian3(100,0,100);

var btmRight = new Cesium.Cartesian3(100,0,-100);

var btmLeft = new Cesium.Cartesian3(-100,0,-100);

//calculate the positions for the square corners…

Cesium.Matrix4.multiplyByPoint(originTransform, topLeft, topLeft);

Cesium.Matrix4.multiplyByPoint(originTransform, topRight, topRight);

Cesium.Matrix4.multiplyByPoint(originTransform, btmRight, btmRight);

Cesium.Matrix4.multiplyByPoint(originTransform, btmLeft, btmLeft);

//draw the full square

var positionsXZ = [

topRight,

topLeft,

btmLeft,

btmRight,

topRight

];

var polyline = new Cesium.PolylineGeometry({

positions: positionsXZ,

width : 2.0,

color : [Cesium.Color.RED]

});

var instance = new Cesium.GeometryInstance(

{geometry : polyline});

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

geometryInstances : [instance],

appearance : new Cesium.PolylineMaterialAppearance({

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

})

}));

viewer.camera.setView({

destination : Cesium.Cartesian3.fromDegrees(45, 45, 100)

});