Airspaces, defining volumes and extruding polygons!

Hi Cesium Dev!

I’m new to all of this and I was trying (without any luck) to get something like the Worldwind Airspaces example at a very basic level working in Cesium.

After examining the examples, I’ve found nothing similar like defining upper and lower altitude boundaries to get a volume.

I’ve tried to create a polygon with each vertex at a different height with no good results, is that possible?

Is there a way to extrude a polygon, obtaining a resulting volume similar to the attached image?

Or is any way to create polygons (and of course volumes) with their height based not in FL but in AGL?

Sorry if I’ve gone too far!

Thank you for your time!

Martin.-

Hi Martin,

Currently, the best thing to do to create a volume is to create two polygons, one on the ground and one at altitude, for the bottom and top caps. Then create polylines vertically connecting the end points of each polygon. We also support ellipsoids, but I don’t think they will help you here. If you are up for writing some custom rendering code, you can build on the box example.

We have better volume support on the Roadmap. “draw more shapes - walls, cylinders, boxes, extruded volumes”, but hopefully these ideas will suffice until Cesium has more complete support.

Regards,

Patrick

Hi Patrick,

I'm also trying to extrude a polygon, in this case a circle, and to do that I started with CylinderGeometry.

My goal is to draw a cylinder with dynamic height through the on mouse movement.

I was able to achieve this but have two problems:
- I need to create GeometryInstance and CylinderGeometry on every frame because I could not set the geometry attributes on the fly. I believe that this causes the draw of the cylinder to be very slow;
- The cylinder grows for both sides instead of just towards the sky.

This is my code on my onMouseMove handler:

if (me.currentState === me.States.Extrude) {
                console.log('extrude');
                // distance: the mouse distance from the on click position
                var length = distance;
                var topRadius = me.radius;
                var bottomRadius = me.radius;
                var modelMatrix = Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(
//startPointCarte: the on click position
                       startPointCarte),
                        new Cesium.Cartesian3(0.0, 0.0, 1.0));

                var cylinderInstance = new Cesium.GeometryInstance({
                    geometry: new Cesium.CylinderGeometry({
                        length: length,
                        topRadius: topRadius,
                        bottomRadius: bottomRadius,
                        vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
                    }),
                    modelMatrix: modelMatrix,
                    attributes: {
                        color: Cesium.ColorGeometryInstanceAttribute.fromColor(me.color)
                    }
                });

                var xcylinder = new Cesium.Primitive({
                    geometryInstances: [cylinderInstance],
                    appearance: new Cesium.PerInstanceColorAppearance({
                        translucent: false,
                        closed: true
                    })
                });

                var oldpoly = me.cylinderPrimitive;

                xprimitives.add(xcylinder);
                
                me.cylinderPrimitive = xcylinder;
                
                xprimitives.remove(oldpoly);
            }

Is there a better way to achieve this? Or something that I'm missing in order to get the results?

Any help would be much appreciated,
Thank you,

Hello,

I believe that currently the only way to change the geometry is to create a new one each time, the way you are doing it in the above code snippet.

Your cylinder is growing from both sides because of the model matrix you’re using. The cylinder is initially created with the center at the origin, then re-positioned with the model matrix. The coordinate point argument for Cesium.Transforms.eastNorthUpToFixedFrame() should be the new center of the cylinder, which you’ll have to calculate. You may also have to change the Cartesian3 used for the translation in order to move the cylinder to the surface.

It may be easier to use the CircleGeometry instead because you wouldn’t need to deal with a model matrix. You can extrude it using the extrudedHeight option. This also will automatically curve the circle to match the curved surface of the earth, where the top and bottom of the cylinder lie in one plane. (If you don’t want it to curve, you can set the granularity option to a larger degree.)

Here’s a link to an example of in sandastle: http://cesium.agi.com/Cesium/Apps/Sandcastle/index.html?src=Circle.html&label=Geometries

Hope this helps!

-Hannah

Hello Hannah,

thank you for your reply,

I've changed to use a CircleGeometry and extrude it and the 'grow to both sides' is resolved.

On the dynamic height problem, the CircleGeometry also need a new instance instead of just re-assigning the extrudedHeight property, am I correct?

Anyway, the cylinder is drawn only when I stop to move the mouse instead of being drawn at each onMouseMove call. I'm not sure if this problem is due the CircleGeometry instantiation ate each frame.
Do you have any clue how can I solve this?

//in onMouseMove function
if (me.currentState === me.States.Extrude) {
                // cylinder
                var oldcylinder = me.cylinderPrimitive;
                xprimitives.remove(oldcylinder);

               // Create extruded ellipse
               //TODO: Change the EllipseGeometry to CircleGeometry
                var rotation = Cesium.Math.toRadians(0);
                var height = 0;
                var extrudedHeight = distance;
                var extrudedEllipse = new Cesium.GeometryInstance({
                    geometry : new Cesium.EllipseGeometry({
                        center : startPointCarte,
                        semiMinorAxis : me.radius,
                        semiMajorAxis : me.radius,
                        vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
                        height : 0,
                        rotation : rotation,
                        extrudedHeight : extrudedHeight
                    }),
                    attributes : {
                        color : Cesium.ColorGeometryInstanceAttribute.fromColor(me.color)
                    }
                });
                
                var xcylinder = new Cesium.Primitive({
                    geometryInstances : [extrudedEllipse],
                    appearance : new Cesium.PerInstanceColorAppearance({
                    translucent : false,
                    closed : true,
                    asynchronous: false
                })});
                
                xprimitives.add(xcylinder);
                
                me.cylinderPrimitive = xcylinder;
            }

Thank you!

> Hello,

>

>

> I believe that currently the only way to change the geometry is to create a new one each time, the way you are doing it in the above code snippet.

>

>

> Your cylinder is growing from both sides because of the model matrix you're using. The cylinder is initially created with the center at the origin, then re-positioned with the model matrix. The coordinate point argument for Cesium.Transforms.eastNorthUpToFixedFrame() should be the new center of the cylinder, which you'll have to calculate. You may also have to change the Cartesian3 used for the translation in order to move the cylinder to the surface.

>

>

> It may be easier to use the CircleGeometry instead because you wouldn't need to deal with a model matrix. You can extrude it using the extrudedHeight option. This also will automatically curve the circle to match the curved surface of the earth, where the top and bottom of the cylinder lie in one plane. (If you don't want it to curve, you can set the granularity option to a larger degree.)

>

>

> Here's a link to an example of in sandastle: http://cesium.agi.com/Cesium/Apps/Sandcastle/index.html?src=Circle.html&label=Geometries

>

>

> Hope this helps!

>

>

> -Hannah

>

>

> > Hi Martin,

>

> >

>

> >

>

> > Currently, the best thing to do to create a volume is to create two polygons, one on the ground and one at altitude, for the bottom and top caps. Then create polylines vertically connecting the end points of each polygon. We also support ellipsoids, but I don't think they will help you here. If you are up for writing some custom rendering code, you can build on the box example.

>

> >

>

> >

>

> >

>

> > We have better volume support on the Roadmap. "draw more shapes - walls, cylinders, boxes, extruded volumes", but hopefully these ideas will suffice until Cesium has more complete support.

>

> >

>

> >

>

> >

>

> > Regards,

>

> > Patrick

>

> >

>

> >

>

> >

>

>

> >

>

> > Hi Cesium Dev!

>

> >

>

> >

>

> >

>

> > I'm new to all of this and I was trying (without any luck) to get something like the Worldwind Airspaces example at a very basic level working in Cesium.

>

> >

>

> > After examining the examples, I've found nothing similar like defining upper and lower altitude boundaries to get a volume.

>

> >

>

> >

>

> >

>

> > I've tried to create a polygon with each vertex at a different height with no good results, is that possible?

>

> >

>

> >

>

> >

>

> >

>

> > Is there a way to extrude a polygon, obtaining a resulting volume similar to the attached image?

>

> >

>

> >

>

> > Or is any way to create polygons (and of course volumes) with their height based not in FL but in AGL?

>

> >

>

> >

>

> >

>

> > Sorry if I've gone too far!

>

> >

>

> >

>

> >

>

> > Thank you for your time!

>

> > Martin.-

>

> >

>

> >

>

> >

>

> >

>

> >

>

> >

>

> >

>

> >

>

> >

>

> >

>

> >

>

> >

>

> > --

>

> >

>

> >

>

> >

>

> >

>

> >

>

> >

>

> >

>

> >

>

> >

>

> > --

>

> > www.seas.upenn.edu/~pcozzi/

>

>

>

> Hi Patrick,

>

>

>

> I'm also trying to extrude a polygon, in this case a circle, and to do that I started with CylinderGeometry.

>

>

>

> My goal is to draw a cylinder with dynamic height through the on mouse movement.

>

>

>

> I was able to achieve this but have two problems:

>

> - I need to create GeometryInstance and CylinderGeometry on every frame because I could not set the geometry attributes on the fly. I believe that this causes the draw of the cylinder to be very slow;

>

> - The cylinder grows for both sides instead of just towards the sky.

>

>

>

>

>

> This is my code on my onMouseMove handler:

>

>

>

> if (me.currentState === me.States.Extrude) {

>

> console.log('extrude');

>

> // distance: the mouse distance from the on click position

>

> var length = distance;

>

> var topRadius = me.radius;

>

> var bottomRadius = me.radius;

>

> var modelMatrix = Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(

>

> //startPointCarte: the on click position

>

> startPointCarte),

>

> new Cesium.Cartesian3(0.0, 0.0, 1.0));

>

>

>

> var cylinderInstance = new Cesium.GeometryInstance({

>

> geometry: new Cesium.CylinderGeometry({

>

> length: length,

>

> topRadius: topRadius,

>

> bottomRadius: bottomRadius,

>

> vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT

>

> }),

>

> modelMatrix: modelMatrix,

>

> attributes: {

>

> color: Cesium.ColorGeometryInstanceAttribute.fromColor(me.color)

>

> }

>

> });

>

>

>

> var xcylinder = new Cesium.Primitive({

>

> geometryInstances: [cylinderInstance],

>

> appearance: new Cesium.PerInstanceColorAppearance({

>

> translucent: false,

>

> closed: true

>

> })

>

> });

>

>

>

> var oldpoly = me.cylinderPrimitive;

>

>

>

> xprimitives.add(xcylinder);

>

>

>

> me.cylinderPrimitive = xcylinder;

>

>

>

> xprimitives.remove(oldpoly);

>

> }

>

>

>

>

>

> Is there a better way to achieve this? Or something that I'm missing in order to get the results?

>

>

>

> Any help would be much appreciated,

>

> Thank you,

Hello Hannah,

thank you for your reply,

I've changed to use a CircleGeometry and extrude it and the 'grow to both sides' is resolved.

On the dynamic height problem, the CircleGeometry also need a new instance instead of just re-assigning the extrudedHeight property, am I correct?

Anyway, the cylinder is drawn only when I stop to move the mouse instead of being drawn at each onMouseMove call. I'm not sure if this problem is due the CircleGeometry instantiation ate each frame.

Do you have any clue how can I solve this?

//in onMouseMove function

if (me.currentState === me.States.Extrude) {

                // cylinder

                var oldcylinder = me.cylinderPrimitive;

                xprimitives.remove(oldcylinder);

               // Create extruded ellipse

               //TODO: Change the EllipseGeometry to CircleGeometry

                var rotation = Cesium.Math.toRadians(0);

                var height = 0;

                var extrudedHeight = distance;

                var extrudedEllipse = new Cesium.GeometryInstance({

                    geometry : new Cesium.EllipseGeometry({

                        center : startPointCarte,

                        semiMinorAxis : me.radius,

                        semiMajorAxis : me.radius,

                        vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,

                        height : 0,

                        rotation : rotation,

                        extrudedHeight : extrudedHeight

                    }),

                    attributes : {

                        color : Cesium.ColorGeometryInstanceAttribute.fromColor(me.color)

                    }

                });

                var xcylinder = new Cesium.Primitive({

                    geometryInstances : [extrudedEllipse],

                    appearance : new Cesium.PerInstanceColorAppearance({

                    translucent : false,

                    closed : true,

                    asynchronous: false

                })});

                xprimitives.add(xcylinder);

                me.cylinderPrimitive = xcylinder;

            }

Thank you!

Hello Hannah,

I've just figure it out:
the problem was on the asynchronous attribute which I put on the wrong place:

var xcylinder = new Cesium.Primitive({
                    geometryInstances : [extrudedEllipse],
                    appearance : new Cesium.PerInstanceColorAppearance({
                    translucent : false,
                    closed : true,
                    asynchronous: false
                })});

is now

var xcylinder = new Cesium.Primitive({
                    geometryInstances : [extrudedEllipse],
                    asynchronous: false,
                    appearance : new Cesium.PerInstanceColorAppearance({
                        translucent : false,
                        closed : true,
                     }
                   )});

Thank you!