Search code examples
javascripthtmlangularjscesiumjs

CesiumJS Rectangle Entity Overlap and Size Issue


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:

Box Distortion

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:

Zoom

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.


Solution

  • 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>