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();
};
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?
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
entity.corridor
``
. Here’s an example: http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Corridor.html&label=Geometries
Hope that helps,
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
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);
});
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
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);
}).otherwise(function(error) {
//Display any errors encountered while loading.
window.alert(error);
});
This is how it looks when entity.polygon.perPositionHeight = false;
and entity.polygon.perPositionHeight = true;
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.
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.
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
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);
});
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!