I have developed an application, using the Cesium Earth library.
The problem is, the drawn line (entity path) has very low quality, it's not smooth. How to make it better?
viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider: false,
shadows:true,
skyAtmosphere: false,
geocoder: false,
shouldAnimate:true,
clockViewModel: new Cesium.ClockViewModel(clock),
imageryProviderViewModels: imageryViewModels,
requestRenderMode : true
});
entity[i] = viewer.entities.add({
path:{
leadTime:leadTime,
trailTime:trailTime,
width:1.5,
material: color,
resolution:10
}
});
satellite[id].position.setInterpolationOptions({
interpolationDegree : 10,
interpolationAlgorithm : Cesium.HermitePolynomialApproximation
});
Look into adding an anti-aliasing pass to your view, and possibly making the dimensions of your container div double what they actually are on the screen (scale it to half size with CSS). I have a similar scene, but it's in three.js, here: https://ccnmtl.github.io/astro-interactives/sun-motion-simulator/ source code is here: https://github.com/ccnmtl/astro-interactives/blob/master/sun-motion-simulator/src/HorizonView.jsx
Related
We have added vector tiles to the map drawn with Mapbox GL JS. We changed the tiles of addSource based on the sample below, and it shows what we expected.
https://docs.mapbox.com/mapbox-gl-js/example/third-party/
const source = "xxx"
map.addSource(source, {
type: "vector",
tiles: [`http://tiles.url/{z}/{x}/{y}.mvt`],
minzoom: 7,
maxzoom: 17,
});
const sourceLayer = "yyy";
const layerId = "zzz";
map.addLayer(
{
id: layerId,
type: "fill",
source,
"source-layer": sourceLayer,
paint: {
"fill-color": "#ff0000",
},
},
"road-label"
);
map.setPaintProperty(layerId, "fill-opacity", 0.6);
map.setPaintProperty(layerId, "fill-antialias", false);
We added a button there, and we made it so that when the button is pressed, it switches to another source and layer, which is also working as we expected.
const layerId = "zzz";
map.removeLayer(layerId);
const source = "xxx"
map.removeSource(source);
However, when we try the same thing after manipulating the zoom with NavigationControl, the tiles do not show up. How can we solve this trouble?
We have set the maxZoom and minZoom of our maps and sources appropriately. At this zoom the tiles should be visible.
After this problem is encountered, when we manipulate the zoom level, the tiles will reappear. However, if we just manipulate the zoom level from the program, the tiles will not appear.
We also tried adding all the sources and layers and changing the visibility to visible or none to switch, but the same problem occurs.
map.setLayoutProperty(
layerId,
'visibility',
isShow ? 'visible' : 'none'
)
Do you have any advice or tips for us?
I'm extending Leaflet's GridLayer to show canvas tiles on which I draw some data points - the problem is that after zooming in and out the other zoom layers are still visible, or are partially chopped off in random ways.
E.g. on the left is zoom level 13, on the right is after zooming out to 11 and back to 13 -
How can I show only the current zoom level, and prevent the canvas tiles from getting chopped off?
This is how I ended up fixing it, though there might be better ways...
Here's my GridCanvas class -
L.GridLayer.GridCanvas = L.GridLayer.extend({
onAdd: function (map) {
L.GridLayer.prototype.onAdd.call(this, map);
map.on('zoomend', e => this.onZoomEnd(e.target._zoom));
},
// on zoom end, want to hide all the tiles that are not on this zoom level,
// and show all the ones that are
onZoomEnd: function (zoom) {
Object.values(this._levels).forEach(level => {
level.el.style.display = (level.zoom === zoom) ? 'block' : 'none';
});
},
createTile,
});
The visibility of the tiles also gets set in seemingly random ways - this seemed to fix the problem - adding a class to the canvas elements and setting them to always be visible -
function createTile(coords, done) {
const canvas = L.DomUtil.create('canvas', 'grid-canvas-tile');
...
}
with styles.css:
.grid-canvas-tile {
visibility: visible !important;
}
I'm building a cesium app and I need my points to indicate a rotational heading. I'm using billboards to display an image I created to show this heading; however, when I rotate the globe, the points don't rotate with it, making the heading indicators incorrect.
In other words, the rotation of my billboards stay constant with the screen space, but not with the globe.
Here's an aerial view of New York. The points in question are in the lower left corner of the image. Note that the heading indicators are pointing northeast.
Here's the same view, but rotated 180° so that up is South. Now, the heading indicators are still pointing to the northwest of the screen, but I need it to be pointing to the globe's northeast, i.e. towards Manhattan.
Here's the code that displays a point:
var entity = {
id: data.cluster_number + '_' + point.id,
name: point.id,
position: Cesium.Cartesian3.fromDegrees(point.lon, point.lat),
billboard: {
image: 'assets/img/point.png',
color: color,
rotation: -1 * toRadians(point.heading),
scale: point.size * 0.07
}
};
if (!angular.isDefined(viewer.entities.getById(entity.id))) {
viewer.entities.add(entity);
}
What's the easiest/most effective way to get the points to rotate with the globe/map?
You need to do a few things.
1 - Update the rotation property of the billboard to be a CesiumCallbackProperty.
rotation: new Cesium.CallbackProperty(
function () {
return -1 * toRadians(point.heading);
}, false);
2 - You'll need to update the heading property of the point based on the camera's heading.
point.heading = viewer.camera.heading;
3 - You'll want to update that point on an interval, either using the cesium clock:
mapContext.clock.onTick.addEventListener(function() {...});
or using JavaScripts setInterval
Once all that is set up here is how it works.
The billboard on the map continuosly pulls the rotation from the point, and if it changes, it will update the billboard on the map. Each time the interval or clock ticks, the value being used changes, based on the heading of the camera.
NOTE: The heading property on the camera is in radians.
Set the billboard's alignedAxis to Cesium.Cartesian3.UNIT_Z instead of the default screen up vector. Run following sample in SandCastle to demonstrate that it works:
var viewer = new Cesium.Viewer('cesiumContainer');
var position = Cesium.Cartesian3.fromDegrees(-111.572177, 40.582083);
var cesiumTerrainProviderMeshes = new Cesium.CesiumTerrainProvider(
{ url : '//assets.agi.com/stk-terrain/world' }
);
//viewer.terrainProvider = cesiumTerrainProviderMeshes;
//viewer.scene.globe.depthTestAgainstTerrain = true;
var ellipsoid = viewer.scene.globe.ellipsoid;
var billboardCollection = viewer.scene.primitives.add(new Cesium.BillboardCollection(
{ scene : viewer.scene }
));
billboardCollection.add(
{ position : position, image : '../images/facility.gif', //heightReference : Cesium.HeightReference.CLAMP_TO_GROUND, rotation: Cesium.Math.PI/4, alignedAxis : Cesium.Cartesian3.UNIT_Z }
);
My team and I are attempting to develop an application on Cesium that requires circle and rectangle points. We are using the native PointGraphics to make the circles, but are creating entities for the rectangles. The code is shown below:
var entity = {
id: point.id,
box: {
dimensions: new Cesium.Cartesian3(20000,
20000,
0),
outline: true,
material: Cesium.Color.fromHsl(hue, 1, 0.5)
},
position: Cesium.Cartesian3.fromDegrees(point.lon, point.lat)
};
We are getting the boxes to draw but with some issues. First, when two boxes overlap, the graphic distorts as shown below:
I'm not sure if it's a code or browser issue. This screenshot is from Chrome, but we have tried it on Chrome and Firefox on two different machines.
Second, there is no automated zoom scaling. When we zoom out, the boxes stay the absolute size instead of relative to the zoom number like the PointGraphics. Compare the example below to the image above:
We may try multiplying the dimensions (not sure what unit they are in) by the zoom level as soon as we figure out how to get the zoom from Cesium, but I'm not sure if that will work since the entity creation may be static?
As a side note, we are using an angular version of Cesium, but I don't think that will prevent us from implementing a solution even if it's solved in regular JS.
The artifacts you're seeing are called "z-fighting", which is a common problem in 3D rendering when multiple polygons are rendered at the same depth and the depth buffer can't distinguish them.
But let's try a different approach: If you want these boxes to stay the same size regardless of zoom level, then you should probably switch to using Billboards to render the boxes. This will fix the z-fighting artifacts in the process. Run this code snippet and see if it's closer to your desired result.
var viewer = new Cesium.Viewer('cesiumContainer', {
navigationHelpButton: false, animation: false, timeline: false
});
var boxImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wwDFRU4/aN5pAAAACNJREFUKM9jYCARMDIwMPz//59Y1YyMTKTaMKphVAO1NJAMALu5AxxK3JB5AAAAAElFTkSuQmCC';
viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
billboard : {
image : boxImage,
color : Cesium.Color.LIME
}
});
viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-75.2, 39.8),
billboard : {
image : boxImage,
color : new Cesium.Color(0, 0.5, 1.0, 1.0)
}
});
viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-70.0, 41.0),
billboard : {
image : boxImage,
color : new Cesium.Color(0.5, 0.9, 1.0, 1.0)
}
});
viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-73.0, 37.0),
billboard : {
image : boxImage,
color : Cesium.Color.RED
}
});
viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-89.0, 35.0),
billboard : {
image : boxImage,
color : Cesium.Color.YELLOW,
scale : 2.0
}
});
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
font-family: sans-serif;
}
<link href="http://cesiumjs.org/releases/1.15/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"/>
<script src="http://cesiumjs.org/releases/1.15/Build/Cesium/Cesium.js">
</script>
<div id="cesiumContainer"></div>
I'm using a dat gui in three.js.
Unfortunately my gui is very very big, and I cant't resize it. I tried with autoplace=false.
How can I resolve this problem?
Try setting a width in the constructor parameters along with autoPlace: false
var gui = new dat.GUI( { autoPlace: false, width: 300 } );
I would use the following code to shrink your panel:
function datgui(){
let gui = new dat.GUI({
width : 300
});