Polygon anchor point(center point)

1,872 views
Skip to first unread message

nilo...@gmail.com

unread,
Dec 14, 2014, 11:14:20 AM12/14/14
to cesiu...@googlegroups.com
Hello. I am working with geojson data and load data with using
Cesium.GeoJsonDataSource(). I access entities and they are Polygon.

I want to access lat lon point of Polyon Center(Anchor point). Because I want to put label to center of each polygon.How can I do this?

Zach Seaman

unread,
Dec 15, 2014, 12:27:29 PM12/15/14
to cesiu...@googlegroups.com, nilo...@gmail.com
If you have the lat, long stored in the GeoJSON properties, you could access them directly when you load the GeoJSON. Here's the code I use:

        var dataSource = new Cesium.GeoJsonDataSource();
        viewer.dataSources.add(dataSource);

        dataSource.loadUrl('../../SampleData/predios_FeatureCollection.geojson').then(function() {
        //Get the array of entities
        var entities = dataSource.entities.entities;

        var labels = scene.primitives.add(new Cesium.LabelCollection());
        for (var i = 0; i < entities.length; i++) {

            var entity = entities[i];
            var id = entity.id;
            var coordinadas = entity.properties.coordinates;
            var coordsArreglo = coordinadas.split(',');
            var lat = coordsArreglo[0];
            var lon = coordsArreglo[1];
            

            // Etiquetas para GeoJSON

            labels.add({
                position  : Cesium.Cartesian3.fromDegrees(lat, lon),
                text      : id,
                // CSS font-family
                font      : '8px SoberanaSans',
                fillColor : Cesium.Color.WHITE,
                outlineColor : Cesium.Color.BLACK,
                outlineWidth : 1,
                style : Cesium.LabelStyle.FILL_AND_OUTLINE
            });
            }
        }); 

Matthew Amato

unread,
Dec 15, 2014, 11:57:52 PM12/15/14
to cesiu...@googlegroups.com
While Zach's code will work, a cleaner solution is to use the existing Entity label capabilities rather than maintain your own LabelCollection primitive.  This allows someone to select/zoom to a feature when it's clicked on, for example.  It will also automatically get rid of the labels when the GeoJSON is unloaded.  Finally, I also added code to get the real surface center of the polygon, rather than just using the first point.  I'm also actively working on changes to make the below code easier to write/read; for example we'll be removing the requirement to explicitly have "new Cesium.ConstantProperty" everywhere if you are using static values and you'll be able to use a template object, as Zach does for the lower level Label primitive.  I've also floated around the idea of auto-computing centroid positions for all GeoJSON polygon/polylines, rather than having to explicitly set them like I do here.

//Get the array of entities
var entities = dataSource.entities.entities;
for (var i = 0; i < entities.length; i++) {
    var entity = entities[i];
    var name = entity.name;

    //Make sure it's a polygon and doesn't already have a position.
    if (!entity.position && entity.polygon) {
        var center = Cesium.BoundingSphere.fromPoints(entity.polygon.positions.getValue()).center;
        Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(center, center);
        entity.position = new Cesium.ConstantPositionProperty(center);
    }

    //Set up the label.
    var label = new Cesium.LabelGraphics();
    label.text = new Cesium.ConstantProperty(name);
    label.font = new Cesium.ConstantProperty('12pt SoberanaSans');
    label.fillColor = new Cesium.ConstantProperty(Cesium.Color.WHITE);
    label.outlineColor = new Cesium.ConstantProperty(Cesium.Color.BLACK);
    label.outlineWidth = new Cesium.ConstantProperty(1);
    label.style = new Cesium.ConstantProperty(Cesium.LabelStyle.FILL_AND_OUTLINE)
    entity.label = label;
}


--
You received this message because you are subscribed to the Google Groups "cesium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cesium-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

emree...@gmail.com

unread,
Dec 16, 2014, 8:33:46 AM12/16/14
to cesiu...@googlegroups.com
Thank you very much, I will try your solutions.

emree...@gmail.com

unread,
Dec 16, 2014, 5:14:03 PM12/16/14
to cesiu...@googlegroups.com, nilo...@gmail.com
I tried your solution. Label is rendering but label is rendering below globe. I want to render label on globe surface.

Screenshot>
http://tinypic.com/r/2cnhwk8/8

Zach Seaman

unread,
Dec 17, 2014, 1:29:47 PM12/17/14
to cesiu...@googlegroups.com, nilo...@gmail.com, emree...@gmail.com
Matthew's cleaner solution is way more sustainable. Here's my results:

It appears that the Label graphics are being rendered half inside the GeoJSON at times. Zooming in makes it better for some but not all. Not sure if it's a GeoJSON rendering problem or if there's a way to assign the z value higher than the GeoJSON polygons.


Trying

scene.globe.depthTestingAgainstTerrain = true;

(as per the post "label is rendering under ground"), I couldn't get any results.


If you need a temporary workaround, try my above code using LabelCollection. It looks like this:

Matthew Amato

unread,
Dec 17, 2014, 1:56:17 PM12/17/14
to cesiu...@googlegroups.com
Since labels are in 3D space, what you're seeing is the label going under polygon (and terrain if you are using it).  Ideally you want the label to be either completely visible or completely invisible depending on it's position, but this is actually a pretty hard problem to solve (not just in Cesium, but 3D globes in general).  The best workaround for this is to use the labels eyeOffset property with a negative Z value.  Eye offset allows you to move the rendering location of the label (or billboard) based on the viewers position.  Positive X moves to the viewer's right, Y moves up and Z moves into the screen.  By using a negative Z value only, you are saying "make this label appear closer to the user than it really is." The affect of this is that it gets rendered above the polygon.  Here's what I used for my ground based examples.

label.eyeOffset = new Cesium.ConstantProperty(new Cesium.Cartesian3(0, 0, -100000));

There are 2 drawbacks to this approach.  Neither of them are a deal breaker in many use cases; but you should be aware of them.

1. When the viewer gets within Z meters of the label, it will disappear (because it's now behind the viewer).

2. If you something in front of the label (like another shape or volume) by less than Z meters; the label will show up on top of that object (because we told it to be closer to us when looking at it).

Hope that helps,

Matt

--

emree...@gmail.com

unread,
Dec 17, 2014, 3:58:11 PM12/17/14
to cesiu...@googlegroups.com, nilo...@gmail.com
Thank you very much. it is worked. I can see all labels over globe.

On Sunday, December 14, 2014 6:14:20 PM UTC+2, nilo...@gmail.com wrote:

Ian Walberg

unread,
Dec 16, 2016, 11:06:21 AM12/16/16
to cesium-dev
I this still valid?  We are getting entity.polygon.positions as undefined.

Thanks, Ian

Hannah Pinkos

unread,
Dec 16, 2016, 1:53:49 PM12/16/16
to cesium-dev
Hi Ian,

Try entity.polygon.hierarchy

-Hannah

Ian Walberg

unread,
Dec 16, 2016, 2:08:30 PM12/16/16
to cesiu...@googlegroups.com

Hannah,

 

Thanks, this works.

 

var center = Cesium.BoundingSphere.fromPoints(entity.polygon.hierarchy.getValue().positions).center;

 

Regards

 

Ian

Ashley Mort

unread,
Jun 12, 2017, 2:32:31 PM6/12/17
to cesium-dev

One of our guys is trying to resolve this  'label under polygon' issue and we're on Cesium 1.28.  Any updated ways of dealing with this?


The problem Im running into is that labels at first appear on top of the polygon, but go behind it when the user zooms out.  I draw the label with z_value =  (shape_z_value) + constant, which should always be on top.

I
ve tried modifying the label.eyeOffset, but it isnt acceptable to my users for the label to go behind the camera (and thus off the screen) when they zoom in to a particular zoom level.

I should also mention that I
m using the Primitives API, not the Entity API, so Labels arent associated with a shape, necessarily.

Rachel Hwang

unread,
Jun 12, 2017, 3:05:54 PM6/12/17
to cesium-dev
Hi Ashley,

If you read Matt's explanation earlier in the thread, that suggestion of using eye offset is still probably our best workaround. Unfortunately, this label issue is a tricky one. 

If the offset solution doesn't work for you for some reason, here's another (warning, hacky for reasons described in that thread) solution:


Use the code example in the above thread to determine whether your label is visible from current vantage, then hide the label if it doesn't pass the visibility test.

If you just need the label to always be visible, then disable the depth test for that label as seen in this this billboard example ("disable depth test..."): http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Billboards.html&label=Showcases

Hope that helps,
- Rachel

burnin...@gmail.com

unread,
Jun 13, 2017, 12:17:37 PM6/13/17
to cesium-dev
I'm trying this answer with code updated to match the current version of Cesium, and it does not center the label, particularly on large polygons. I'm loading the data in from a KML file, then trying to center the label.

var kml_data = Cesium.KmlDataSource.load(url)
kml_data.then(function(data) {
viewer.dataSources.add(data);

// Iterate over all the KML entities
$.each(data.entities.values, function(i, entity) {
var poly_center = Cesium.BoundingSphere.fromPoints(entity.polygon.hierarchy.getValue().positions).center;
poly_center = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(poly_center);
entity.position = poly_center;
});
}

Rachel Hwang

unread,
Jun 13, 2017, 12:54:18 PM6/13/17
to cesium-dev, burnin...@gmail.com
Hi there,

I don't see anything immediately wrong with your logic, but if you post a gist with your code we may be able to help you debug.

Best,
- Rachel

burnin...@gmail.com

unread,
Jun 13, 2017, 1:05:45 PM6/13/17
to cesium-dev, burnin...@gmail.com
Unfortunately this is for a company project so I cannot post the code. Any ideas as to what might be wrong?

Rachel Hwang

unread,
Jun 14, 2017, 8:55:21 AM6/14/17
to cesium-dev, burnin...@gmail.com
Looks like your method works just fine. I created a code example here (look at the custom styling option): http://cesiumjs.org/Cesium/Apps/Sandcastle/?src=Hello%20World.html&label=Showcases&gist=834086ff0430ae5e813f36933a963acb

Note that for an irregular, non-convex shape like California, the labels will not truly be centered because the bounding sphere calculation doesn't take the concavity into account.

Hope that helps,
- Rachel

john...@gmail.com

unread,
Aug 4, 2017, 12:00:01 PM8/4/17
to cesium-dev, burnin...@gmail.com
Are there any workaround to account for the concavity of a large geometry shape?

Rachel Hwang

unread,
Aug 8, 2017, 10:34:55 AM8/8/17
to cesium-dev, burnin...@gmail.com, john...@gmail.com
Hi there,


Best,
- Rachel
Reply all
Reply to author
Forward
0 new messages