cesium loads entities on demand

**Two words: fast, steady!
Welcome to inquire and reply back to [business cooperation] to get contact information!
Welcome to WeChat official account [3D mesh 3D]. Get the latest article for the first time.

**
When we use cesium, we often need to load the names of various regions in China. However, there is an upper limit to the number of entities that can be added in cesium. When a certain number is loaded, there will be jams or even browser crashes. At this time, we need to load our entity classes on demand. Next, we will introduce a method of on-demand loading, After the mouse is moved, judge whether to display or delete entity entity according to the current map level

1. Create an earth

// Default to China
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(90,-20,110,90)


// Define scene, label position array and entity array
let viewer,labelArr = [],entities = []

// Create earth
viewer = new Cesium.Viewer('cesiumContainer')

// Default display earth texture
viewer.baseLayerPicker.viewModel.selectedImagery= viewer.baseLayerPicker.viewModel.imageryProviderViewModels[3];

// Add display level gridlines
viewer.imageryLayers.addImageryProvider(new Cesium.TileCoordinatesImageryProvider())

// Whether the ancestors of the rendered block should be preloaded. Set this to true to optimize the zoom out experience and the newly exposed area when panning. The disadvantage is that more tiles need to be loaded.
viewer.scene.globe.preloadAncestors = false

// Turn off mouse operation inertia
var CesiumViewerSceneController = viewer.scene.screenSpaceCameraController;
CesiumViewerSceneController.inertiaSpin = 0;
CesiumViewerSceneController.inertiaTranslate = 0;
CesiumViewerSceneController.inertiaZoom = 0;

After the formation of the earth, the yellow lines outside are hierarchical grid lines

2. Load data

Next, we load the area data to be used as an example. We print it. We can find that the current amount of data has reached 13w, far exceeding the number of entities that cesium can accommodate

// Load json file
fetch('./AANP Natural place names.geojson').then((res)=>{

    return res.json()

})
.then(json=>{
    for(const item of json.features){

        // Take out the position of each area in the data
        let obj = [item.geometry.coordinates[0],item.geometry.coordinates[1]]
        labelArr.push(obj)

        // Create entity
        let entity = new Cesium.Entity({

            position:new Cesium.Cartesian3.fromDegrees(item.geometry.coordinates[0],item.geometry.coordinates[1]),
            
            label:{

                text:item.properties.NAME,
                fillColor:Cesium.Color.fromCssColorString ('red'),
                font:'20pt monospace',
                heightReference:Cesium.CLAMP_TO_GROUND

            }

        })

        // Use an array to save entities for subsequent retrieval and deletion
        entities.push(entity)
        
    }

    console.log(entities.length)

json data format loaded this time

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [
          112.27967881000006,
          3.9707323300000894
        ]
      },
      "properties": {
        "CLASS": "JH",
        "NAME": "Zengmu dark sand",
        "PINYIN": "Zengmu Ansha"
      }
    },

3. Load on demand

// Gets the collection of tiles currently being rendered
    const tilesToRender =viewer.scene.globe._surface._tilesToRender

    /**
     * Add the camera movement end event, that is, the mouse movement end event
     * Due to the inertia of the camera itself, turning off the inertia in advance will have a better experience
     * However, this in itself does not affect the function
     * */
    viewer.camera.moveEnd.addEventListener(()=>{

        // The tiles currently being rendered are merged into a large rectangle
        let renderRectangle = new Cesium.Rectangle()
        
        if( tilesToRender.length > 0 ) {

            // Initializes the total rendered rectangular tile
            Cesium.Rectangle.clone(tilesToRender[0].rectangle,renderRectangle)

            let num = 0

            tilesToRender.forEach(item => {

                /**
                 * Obtain tiles with current level greater than or equal to level 12, which can be customized. The specific level can be determined according to the number of loaded entities
                 * Generally, the number of tiles we can see is different due to different camera angles, so try to consider the number of tiles
                 * Maximum number of displays per tile
                */
                if( item.level >= 12 ) {

                    // It is used to judge whether there are qualified tiles being rendered
                    num += 1

                    // Intersection of all tiles greater than level 12
                    Cesium.Rectangle.union(item.rectangle, renderRectangle, renderRectangle)

                }

            })

            if( num > 0 ){

                // Determine whether the point is in the tile to be rendered
                for( let i = 0; i < entities.length; i++ ) {

                    // Convert degrees to radians
                    let cartographic = Cesium.Cartographic.fromDegrees(labelArr[i][0], labelArr[i][1])

                    // Judge whether the point is within the rectangle
                    if(Cesium.Rectangle.contains(renderRectangle,cartographic)){

                        // Judge whether the current entity has been loaded, skip if any, and load if none
                        if(viewer.entities.contains(entities[i])) continue

                        viewer.entities.add(entities[i])

                    } else {

                        // If it is not within the point, judge whether it is loaded or deleted
                        if(viewer.entities.contains(entities[i])){

                            viewer.entities.remove(entities[i])

                        }

                    }

                }

            } else{

                for( let i = 0; i < entities.length; i++ ){

                    /**
                     *  There are no qualified tiles loaded in the current visual range. Delete the desired tiles
                     * We can't use removeAll. We just need to manage the parts we load ourselves
                    */
                    if(viewer.entities.contains(entities[i])){

                        viewer.entities.remove(entities[i])

                    }

                }

            }
        }
    })

4. Summary

The implementation methods and ideas are explained in detail in the notes. This is certainly not the only implementation method or the best implementation method, but I think this is the easiest way to understand and get started. It does not need to have a very high proficiency in cesium, but can understand and use it directly.

Key points

  • Load json data, create entities, and control the tile level of loaded entities
  • Get the collection of tiles currently being rendered, and combine them to form a large rectangle (it may be more appropriate to call it range, but after all, the rectangle method is used)
  • Judge whether the point is in the rectangle according to the rectangle method. If it is, load the current entity, otherwise delete the current entity

Two words: fast, steady!
Welcome to inquire and reply back to [business cooperation] to get contact information!
Welcome to WeChat official account [3D mesh 3D]. Get the latest article for the first time.

Keywords: gis

Added by successor on Mon, 17 Jan 2022 12:29:54 +0200