Transform GeoJson Linestring to Polyline?

1,825 views
Skip to first unread message

paula....@gmail.com

unread,
Jul 13, 2017, 7:38:25 AM7/13/17
to cesium-dev
I have GeoJson file with roads data as Linestrings. I want to load it in Cesium Sandcastle and make a custom line styles. In order to do so, line has to be Polyline, not Linestring (https://cesiumjs.org/Cesium/Build/Documentation/Entity.html?classFilter=enti ). Is there a way to transform Linestring to Polyline for GeoJson format? Otherwise, how can I style GeoJson data as Linestring?

Code:

//Add terrain
var viewer = new Cesium.Viewer('cesiumContainer');
var cesiumTerrainProviderMeshes = new Cesium.CesiumTerrainProvider({
url : 'https://assets.agi.com/stk-terrain/v1/tilesets/world/tiles',
requestWaterMask : true,
requestVertexNormals : true
});
viewer.terrainProvider = cesiumTerrainProviderMeshes;
viewer.scene.globe.depthTestAgainstTerrain = true;

//Load with default styling
Sandcastle.addToolbarButton('Default styling', function() {
Cesium.GeoJsonDataSource.clampToGround = true;
var dataRoads = Cesium.GeoJsonDataSource.load('../../SampleData/ceste_rab_okvir.geojson');
viewer.dataSources.add(dataRoads);
viewer.zoomTo(dataRoads);
});

//Apply custom graphics after load
Sandcastle.addToolbarButton('Custom styling', function() {
//Seed the random number generator for repeatable results
Cesium.Math.setRandomNumberSeed(0);

Cesium.GeoJsonDataSource.clampToGround = true;
var promise = Cesium.GeoJsonDataSource.load('../../SampleData/ceste_rab_okvir.geojson'); //data loaded from local folder
promise.then(function(dataSource) {
viewer.dataSources.add(dataSource);
viewer.zoomTo(promise);

//Get the array of entities
var entities = dataSource.entities.values;

var colorHash = {};
for (var i = 0; i < entities.length; i++) {
//For each entity, create a random color based on the road class
var entity = entities[i];
var roadClass = entity.fclass;
var color = colorHash[roadClass];
if (!color) {
color = Cesium.Color.fromRandom({
alpha : 1.0
});
colorHash[roadClass] = color;
}

//Set the polygon material to our random color.
//THIS IS THE PROBLEM
entity.polyline.material = color;
}
}).otherwise(function(error) {
//Display any errrors encountered while loading
window.alert(error);
});
});

//Reset the scene when switching demos.
Sandcastle.reset = function() {
viewer.dataSources.removeAll();
};

paula....@gmail.com

unread,
Jul 14, 2017, 8:59:43 AM7/14/17
to cesium-dev, paula....@gmail.com
I have seen examples of line styling (color, alpha etc.) and in examples, lines are hard-coded, but I have loaded data from local folder (which are Openstreetmap roads data in GeoJson format).

I loaded roads data:
Cesium.GeoJsonDataSource.load('../../SampleData/xxx');
clamped them to ground (stk terrain):
Cesium.GeoJsonDataSource.clampToGround = true;
and roads show nicely on terrain when in default style.

Then I tried changing linestyles according to attribute, but nothing shows on terrain and "entity.polyline.material = color;" throws error probably because GeoJson is linestring not polyline.

I want to color the roads differently according to road class (highway, residential, unclassified,...).
Is there a solution for this?

Rachel Hwang

unread,
Jul 17, 2017, 11:24:09 AM7/17/17
to cesium-dev, paula....@gmail.com
Hi there,

The issue is that we don't support polylines clamped to terrain. See this thread for more information: https://groups.google.com/d/msg/cesium-dev/JlR4KgkndlI/lPdzriSjxAEJ

As a workaround when you enable ground clamping with a linestring, we convert it to a corridor. Try applying your styling to

Hope that helps,
- Rachel 

paula....@gmail.com

unread,
Jul 18, 2017, 8:48:22 AM7/18/17
to cesium-dev, paula....@gmail.com
Hi Rachel,

thank you so much! It works with corridor.
But now, there's few other issue.
1) I don't see if there's something like corridorVolume? Like polylineVolume.
Corridor is fine for roads, but I will have to make pipeline cylinders with volume beneath the ground level (under terrain) from my local data. Is it possible?
2) Is it possible to read coordinates from loaded GeoJson file? I've seen an example with Cartesian3.fromDegreesArrayHeights but coordinates are hardcoded.

Thanks,
Paula

Rachel Hwang

unread,
Jul 21, 2017, 3:02:37 PM7/21/17
to cesium-dev, paula....@gmail.com
Hi Paula,

2. You can read from the corridor positions, and convert from cartesian3 to degrees using Cartographic.fromCartesian()

Hope that helps,
- Rachel

paula....@gmail.com

unread,
Aug 21, 2017, 8:16:33 AM8/21/17
to cesium-dev, paula....@gmail.com
Hi Rachel,

I don't see the way to make corridor to be round like cylinder. If I extrude it, it just extrudes top side and the edges are sharp not round. I need to make cylinder pipeline from lines I've loaded so that the lines are referent centerline from which I extrude cylinder with a certain radius. Do you have any idea how to do that?

Also, I tried doing it with this code, but every time it runs it shows error at this line -> shape: computeCircle(6),
the error says: "An error occurred while rendering. Rendering has stopped.
out of memory"

var viewer = new Cesium.Viewer('cesiumContainer');

function computeCircle(radius) {
var positions = [];
for (var i = 0; i < 360; i++) {
var radians = Cesium.Math.toRadians(i);
positions.push(new Cesium.Cartesian2(radius * Math.cos(radians), radius * Math.sin(radians)));
}
return positions;
}

viewer.zoomTo(viewer.entities);

var promise = Cesium.GeoJsonDataSource.load('../../SampleData/Ceste_izbrisano.geojson', {
clampToGround : false,
//extrudedHeight : 300.0,
width : 10.0,
cornerType: Cesium.CornerType.MITERED,
material : Cesium.Color.GREEN
});

console.log('adding data');
promise.then(function(dataSource) {
viewer.dataSources.add(dataSource);


//Get the array of entities
var entities = dataSource.entities.values;

for (var i = 0; i < entities.length; i++)
{
//Set the height and the material of each polyline


var entity = entities[i];

entity.polylineVolume = new Cesium.PolylineVolumeGraphics({
positions: entity.polyline.positions,
shape: computeCircle(6),
material: Cesium.Color.RED
});

if (entity.properties.Layer === 'CESTA') {
entity.polyline.material = Cesium.Color.YELLOW;
entity.polylineVolume.material = Cesium.Color.YELLOW;
}
if (entity.properties.Type === 'CESTA_KAO_GRANICA_POKROVA_ZEMLJISTA') {
entity.polyline.material = Cesium.Color.DEEPSKYBLUE;
entity.polylineVolume.material = Cesium.Color.DEEPSKYBLUE;
}

viewer.zoomTo(entities);
}

}).otherwise(function(error){
//Display any errors encountered while loading.
window.alert(error);
});

Gabby Getz

unread,
Aug 21, 2017, 4:54:37 PM8/21/17
to cesium-dev, paula....@gmail.com
Hi Paula,

In order to create a cylinder volume, use a PolylineVolumeGeometry (https://cesiumjs.org/Cesium/Build/Documentation/PolylineVolumeGeometry.html). However, we don't have support for under terrain/subsurface, but it has been often requested and is definitely on our radar. See this issue in the Cesium GitHub Repo: https://github.com/AnalyticalGraphicsInc/cesium/issues/5665

Here's a Sandcastle example showing off the options: https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Polyline%20Volume.html&label=Geometries

Thanks!
Gabby

paula....@gmail.com

unread,
Aug 23, 2017, 6:05:02 AM8/23/17
to cesium-dev, paula....@gmail.com
Hi Gabby,

thank you for help.

I have an alternative for subsurface visualization. I have made a geojson surface that represents terrain and it looks great and I have managed to create pipes with PolylineVolume that are under the surface.

Now, I have another issue which I don't know how to solve:
I want to show buildings on this surface. They are also geojson with defined 3D coordinates.
The problem is when I set perPositionHeight = false, bottom sides of buildings lower to the ellipsoid. But when I set perPositionHeight = true, bottom sides of buildings are okay on the surface but side "walls" of buildings dissapear.
Do you know what am I doing wrong and how can I fix this issue?

This is part of the code:

//TERRAIN SURFACE
var dataSourcePloha = Cesium.GeoJsonDataSource.load('../../SampleData/Ploha.geojson');
viewer.dataSources.add(dataSourcePloha);
viewer.zoomTo(dataSourcePloha);

//BUILDINGS
Cesium.Math.setRandomNumberSeed(1234);
var promiseBuildings = Cesium.GeoJsonDataSource.load('../../SampleData/Gradjevine_3d_wgs84_v2.json');
promiseBuildings.then(function(dataSourceBuildings) {
viewer.dataSources.add(dataSourceBuildings);
viewer.zoomTo(promiseBuildings);


//Get the array of entities

var entitiesBuildings = dataSourceBuildings.entities.values;

var colorHash = {};
for (var i = 0; i < entitiesBuildings.length; i++) {
var entity = entitiesBuildings[i];
var AttributeBuildings = entity.properties.Visina;
var color = colorHash[AttributeBuildings];


if (!color) {
color = Cesium.Color.fromRandom({
alpha: 1.0
});

colorHash[AttributeBuildings] = color;
}

entity.polygon.material = color;
entity.polygon.fill = true;
entity.polygon.outline = false;
entity.polygon.perPositionHeight = true;
//Extrude the polygon based on the height. Each entity stores the properties for the GeoJSON feature it was created from
entity.polygon.extrudedHeight = entity.properties.ukupna_visina;
}

viewer.zoomTo(entitiesBuildings);

paula....@gmail.com

unread,
Aug 23, 2017, 6:10:00 AM8/23/17
to cesium-dev, paula....@gmail.com
This is how it looks when entity.polygon.perPositionHeight = false;
https://ibb.co/nJB81k

and entity.polygon.perPositionHeight = true;
https://ibb.co/jXkU7Q

Gabby Getz

unread,
Aug 23, 2017, 4:54:05 PM8/23/17
to cesium-dev, paula....@gmail.com
This is explained in the PolygonGraphics.extrudedHeight docs:

If PolygonGraphics#perPositionHeight is false, the volume starts at PolygonGraphics#height and ends at this altitude. If PolygonGraphics#perPositionHeight is true, the volume starts at the height of each PolygonGraphics#hierarchy position and ends at this altitude.

So make sure you are specifying the height property for the base location of the building and use perPositionHeight accordingly.


--
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

paula....@gmail.com

unread,
Aug 24, 2017, 2:05:37 AM8/24/17
to cesium-dev, paula....@gmail.com
Hi Gabby,

I'm sorry I haven't explained the problem well, I think you didn't understand me.
I understand what exstrudedHeight means, I know it is an elevation above the elipsoid, that's why I had defined it as (height of terrain + height of building) as an attribute in my geojson file for each building.
In this two pictures https://ibb.co/nJB81k and https://ibb.co/jXkU7Q I just wanted to ask why are there missing/dissapearing walls on 2nd picture, but on 1st the walls are all there. I don't think it should be connected with height because the heights are just fine: they start at height which is defined in geojson and end at extruded height, and that's what I need. But walls are dissapearing as I rotate camera.
Do you know why is that so and can I fix it or is it some kind of a bug?

Thanks again for your help.

Gabby Getz

unread,
Aug 24, 2017, 3:43:25 PM8/24/17
to cesium-dev, Paula M
Hi Paula,

Sorry for the misunderstanding!

I think the culprit may be what Hannah explains here: https://github.com/AnalyticalGraphicsInc/cesium/issues/5203#issuecomment-293661265

I added the problem you are having to that issue so we can take a look at it. If you have anymore info that may help, please add it there. 

Thanks,
Gabby

paula....@gmail.com

unread,
Aug 24, 2017, 4:03:03 PM8/24/17
to cesium-dev, paula....@gmail.com
Hi Gabby,

I appreciate your help and effort!
I have managed to partially overcome this issue. I've noticed that when I set color transparency with alpha, the walls aren't dissapearing. Also, if outline = true it looks much better.

It looks like this: http://imgur.com/a/sxLNp

And this is the code if it may help:

//BUILDINGS
Cesium.Math.setRandomNumberSeed(0);


var promiseBuildings = Cesium.GeoJsonDataSource.load('../../SampleData/Gradjevine_3d_wgs84_v2.json');
promiseBuildings.then(function(dataSourceBuildings) {
viewer.dataSources.add(dataSourceBuildings);

//Get the array of entities
var entitiesBuildings = dataSourceBuildings.entities.values;

var colorHash = {};
for (var i = 0; i < entitiesBuildings.length; i++) {
var entity = entitiesBuildings[i];
var AttributeBuildings = entity.properties.Visina;
var color = colorHash[AttributeBuildings];
if (!color) {
color = Cesium.Color.fromRandom({

alpha: 0.9


});
colorHash[AttributeBuildings] = color;
}

entity.polygon.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(0, 2000);
entity.polygon.show = true;
entity.polygon.fill = true;
entity.polygon.material = color;
entity.polygon.outline = true;
entity.polygon.outlineColor = Cesium.Color.BLACK;
entity.polygon.closeTop = true;
entity.polygon.closeBottom = true;


entity.polygon.perPositionHeight = true;
//Extrude the polygon based on the height. Each entity stores the properties for the GeoJSON feature it was created from
entity.polygon.extrudedHeight = entity.properties.ukupna_visina;
}

}).otherwise(function(error) {
window.alert(error);
});

Gabby Getz

unread,
Aug 25, 2017, 2:44:45 PM8/25/17
to cesium-dev
I'm glad to hear you have a workaround for now! We'll keep this thread updated if there's a change to that issue.

Thanks!

Reply all
Reply to author
Forward
0 new messages