Skip to content
Cesium通过Primitive加载geojson

需求

需要保证加载效率,传geojson进去就能进行加载,然后能飞能定位,能贴地

Geojson数据处理代码

javascript
    _geojsonTransformation(featureCollection, targetType) {

        const features = [];

        if (targetType === 'point') {

            featureCollection.features.forEach(feature => {

                const points = turf.explode(feature).features;

                features.push(...points);

            });

        } else if (targetType === 'line') {

            // 遍历GeoJSON中的每个feature

            featureCollection.features.forEach(feature => {

                const geometry = feature.geometry;

                const coordinates = geometry.coordinates;

  

                // 初始化最小和最大经纬度

                let minLon = Number.POSITIVE_INFINITY,

                    maxLon = Number.NEGATIVE_INFINITY;

                let minLat = Number.POSITIVE_INFINITY,

                    maxLat = Number.NEGATIVE_INFINITY;

  

                // 计算边界范围的函数

                function updateBounds(lon, lat) {

                    minLon = Math.min(minLon, lon);

                    maxLon = Math.max(maxLon, lon);

                    minLat = Math.min(minLat, lat);

                    maxLat = Math.max(maxLat, lat);

                }

  

                // 处理LineString

                if (geometry.type === 'LineString') {

                    const positions = coordinates.flatMap(coord => {

                        updateBounds(coord[0], coord[1]); // 更新边界

                        return [coord[0], coord[1]];

                    });

  

                    features.push({

                        type: 'LineString',

                        positions: Cesium.Cartesian3.fromDegreesArray(positions),

                        bounds: { minLon, maxLon, minLat, maxLat },

                    });

                }

  

                // 处理MultiLineString

                else if (geometry.type === 'MultiLineString') {

                    coordinates.forEach(line => {

                        const positions = line.flatMap(coord => {

                            updateBounds(coord[0], coord[1]); // 更新边界

                            return [coord[0], coord[1]];

                        });

  

                        features.push({

                            type: 'MultiLineString',

                            positions: Cesium.Cartesian3.fromDegreesArray(positions),

                            bounds: { minLon, maxLon, minLat, maxLat },

                        });

                    });

                }

            });

        } else if (targetType === 'polygon') {

            // 遍历GeoJSON中的每个feature

            featureCollection.features.forEach(feature => {

                const geometry = feature.geometry;

                const coordinates = geometry.coordinates;

  

                // 初始化最小和最大经纬度

                let minLon = Number.POSITIVE_INFINITY,

                    maxLon = Number.NEGATIVE_INFINITY;

                let minLat = Number.POSITIVE_INFINITY,

                    maxLat = Number.NEGATIVE_INFINITY;

  

                // 计算边界范围的函数

                function updateBounds(lon, lat) {

                    minLon = Math.min(minLon, lon);

                    maxLon = Math.max(maxLon, lon);

                    minLat = Math.min(minLat, lat);

                    maxLat = Math.max(maxLat, lat);

                }

  

                // 处理Polygon

                if (geometry.type === 'Polygon') {

                    let positions = coordinates[0].flatMap(coord => {

                        updateBounds(coord[0], coord[1]); // 更新边界

                        return [coord[0], coord[1]];

                    });

  

                    // 判断头和尾的坐标是否一致

                    if (

                        positions[0] !== positions[positions.length - 2] ||

                        positions[1] !== positions[positions.length - 1]

                    ) {

                        positions.push(positions[0], positions[1]);

                    }

  

                    features.push({

                        type: 'Polygon',

                        positions: Cesium.Cartesian3.fromDegreesArray(positions),

                        bounds: { minLon, maxLon, minLat, maxLat },

                    });

                }

  

                // 处理MultiPolygon

                else if (geometry.type === 'MultiPolygon') {

                    coordinates.forEach(polygon => {

                        let positions = polygon[0].flatMap(coord => {

                            updateBounds(coord[0], coord[1]); // 更新边界

                            return [coord[0], coord[1]];

                        });

  

                        // 判断头和尾的坐标是否一致

                        if (

                            positions[0] !== positions[positions.length - 2] ||

                            positions[1] !== positions[positions.length - 1]

                        ) {

                            positions.push(positions[0], positions[1]);

                        }

  

                        features.push({

                            type: 'MultiPolygon',

                            positions: Cesium.Cartesian3.fromDegreesArray(positions),

                            bounds: { minLon, maxLon, minLat, maxLat },

                        });

                    });

                }

            });

        }

        return features;

    }

点primitive数据加载

测试示例

javascript
const testParams = { data: { type: "FeatureCollection", features: [ { type: "Feature", geometry: { type: "Point", coordinates: [120.0, 30.0, 100.0] }, properties: {} }, { type: "Feature", geometry: { type: "Point", coordinates: [121.0, 31.0, 200.0] }, properties: {} } ] }, loadOptions: { color: "#FF0000", // 红色 opacity: 1.0, // 透明度 radius: 20 // 半径 }, needFly: true, // 是否飞到点的位置 clampToGround: true // 是否贴地 }; addPointGeojsonEffect(testParams.data,testParams.loadOptions,testParams.needFly,testParams.clampToGround)

加载代码

javascript
    _addPointGeojsonEffect(data, loadOptions, needFly, clampToGround) {

        const { color, opacity, radius } = loadOptions;

        const viewer = window.viewer;

        // const pointCollection = viewer.scene.primitives.add(new Cesium.PrimitiveCollection());

        const pointCollection = viewer.scene.primitives.add(new Cesium.PointPrimitiveCollection());

        const features = this._geojsonTransformation(data, 'point');

        const pointArray = [];

        features.forEach(async feature => {

            const { geometry } = feature;

            const { coordinates } = geometry;

            const position = Cesium.Cartesian3.fromDegrees(

                coordinates[0],

                coordinates[1],

                coordinates[2] || 0

            );

            pointArray.push(position);

            if (clampToGround) {

                try {

                    const cartographicPosition = Cesium.Cartographic.fromCartesian(position);

                    const updatedPositions = await Cesium.sampleTerrainMostDetailed(

                        map3d_viewer.viewer.scene.terrainProvider,

                        [cartographicPosition],

                        true

                    );

                    pointCollection.add({

                        position: Cesium.Cartographic.toCartesian(updatedPositions[0]),

                        color: Cesium.Color.fromCssColorString(color).withAlpha(opacity),

                        pixelSize: radius,

                    });

                } catch (error) {

                    // A tile request error occurred.

                    console.error(error);

                    // 正常加载

                    pointCollection.add({

                        position: position,

                        color: Cesium.Color.fromCssColorString(color).withAlpha(opacity),

                        pixelSize: radius,

                    });

                }

            } else {

                pointCollection.add({

                    position: position,

                    color: Cesium.Color.fromCssColorString(color).withAlpha(opacity),

                    pixelSize: radius,

                });

            }

        });

        if (needFly) {

            const rectangle = Cesium.Rectangle.fromCartesianArray(pointArray);

            const expandedRectangle = Cesium.Rectangle.expand(rectangle, 0.1); // 增加矩形的高度

            // 飞到点的位置

            map3d_viewer.viewer.camera.flyTo({

                destination: expandedRectangle,

                duration: 2.0, // 设置飞行时间

            });

        }

        return [pointCollection];

    }

线primitive数据加载

测试示例

javascript
const testParams = { data: { "type": "FeatureCollection", "features": [ { "type": "Feature", "id": 8843, "properties": { "_draw_type": "line" }, "geometry": { "type": "LineString", "coordinates": [ [ 114.11329217, 22.57045667 ], [ 114.15516134, 22.59674445 ], [ 114.21545293, 22.59751754 ], [ 114.23471297, 22.62495966 ], [ 114.22717668, 22.64621393 ] ] }, "bbox": [ 114.11329217, 22.57045667, 114.23471297, 22.64621393 ] } ] }, loadOptions: { color: "#FF0000", // 红色 opacity: 1.0, // 透明度 width: 2 }, needFly: true, // 是否飞到点的位置 clampToGround: true// 是否贴地 }; addLineGeojsonEffect(testParams.data,testParams.loadOptions,testParams.needFly,testParams.clampToGround)

加载代码

javascript
    _addLineGeojsonEffect(data, loadOptions, needFly, clampToGround) {

        const { color, opacity, width } = loadOptions;

        const viewer = window.viewer;

        const polylineCollection = viewer.scene.primitives.add(new Cesium.PrimitiveCollection());

        const transformedFeatures = this._geojsonTransformation(data, 'line');

        transformedFeatures.forEach(feature => {

            let polyline;

  

            const polylineAppearance = new Cesium.PolylineMaterialAppearance({

                material: Cesium.Material.fromType('Color', {

                    color: Cesium.Color.fromCssColorString(color).withAlpha(opacity), // 点的颜色

                }),

            });

            if (clampToGround) {

                polyline = new Cesium.GeometryInstance({

                    geometry: new Cesium.GroundPolylineGeometry({

                        positions: feature.positions,

                        width: width,

                    }),

                });

                polylineCollection.add(

                    new Cesium.GroundPolylinePrimitive({

                        geometryInstances: polyline,

                        appearance: polylineAppearance,

                    })

                );

            } else {

                polyline = new Cesium.GeometryInstance({

                    geometry: new Cesium.PolylineGeometry({

                        positions: feature.positions,

                        width: width,

                    }),

                });

                polylineCollection.add(

                    new Cesium.Primitive({

                        geometryInstances: polyline,

                        appearance: polylineAppearance,

                        asynchronous: false, // 同步渲染

                    })

                );

            }

  

            const rectangle = Cesium.Rectangle.fromDegrees(

                feature.bounds.minLon,

                feature.bounds.minLat,

                feature.bounds.maxLon,

                feature.bounds.maxLat

            );

            if (needFly) {

                // 飞到线条位置

                viewer.camera.flyTo({

                    destination: rectangle,

                    duration: 2.0, // 设置飞行时间

                });

            }

        });

        return [polylineCollection];

    }

面数据加载

测试示例

javascript
const testParams = { data: { type: 'FeatureCollection', features: [ { type: 'Feature', id: 4385, properties: { _draw_type: 'fill' }, geometry: { type: 'Polygon', coordinates: [ [ [114.06953141, 22.60794206], [114.03559538, 22.56155188], [114.08407557, 22.54282868], [114.19425786, 22.58474811], [114.06953141, 22.60794206], ], ], }, bbox: [114.03559538, 22.54282868, 114.19425786, 22.60794206], }, ], }, loadOptions: { fillColor: '#FF0000', // 红色 lineColor: '#ff0000', opacity: 0.6, // 透明度 lineWidth: 2, }, needFly: true, // 是否飞到点的位置 clampToGround: true, // 是否贴地 }; addPolygonGeojsonEffect(testParams.data, testParams.loadOptions, testParams.needFly, testParams.clampToGround);

加载代码

javascript
addPolygonGeojsonEffect(data, loadOptions, needFly, clampToGround) {

        const { fillColor, opacity, lineColor, lineWidth } = loadOptions;

        const viewer = window.viewer;

        const polygonCollection = viewer.scene.primitives.add(new Cesium.PrimitiveCollection());

        const transformedFeatures = this._geojsonTransformation(data, 'polygon');

        transformedFeatures.forEach(feature => {

            let polygon;

            let polyline;

            const polygonAppearance = new Cesium.MaterialAppearance({

                material: Cesium.Material.fromType('Color', {

                    color: Cesium.Color.fromCssColorString(fillColor).withAlpha(opacity),

                }),

            });

            const polylineAppearance = new Cesium.PolylineMaterialAppearance({

                material: Cesium.Material.fromType('Color', {

                    color: Cesium.Color.fromCssColorString(lineColor).withAlpha(opacity), // 点的颜色

                }),

            });

            if (clampToGround) {

                polygon = new Cesium.GeometryInstance({

                    geometry: new Cesium.PolygonGeometry({

                        polygonHierarchy: new Cesium.PolygonHierarchy(feature.positions),

                    }),

                });

                polyline = new Cesium.GeometryInstance({

                    geometry: new Cesium.GroundPolylineGeometry({

                        positions: feature.positions,

                        width: lineWidth,

                    }),

                });

                polygonCollection.add(

                    new Cesium.GroundPrimitive({

                        geometryInstances: polygon,

                        appearance: polygonAppearance,

                    })

                );

                polygonCollection.add(

                    new Cesium.GroundPolylinePrimitive({

                        geometryInstances: polyline,

                        appearance: polylineAppearance,

                    })

                );

            } else {

                polygon = new Cesium.GeometryInstance({

                    geometry: new Cesium.PolygonGeometry({

                        polygonHierarchy: new Cesium.PolygonHierarchy(feature.positions),

                    }),

                });

                polyline = new Cesium.GeometryInstance({

                    geometry: new Cesium.PolylineGeometry({

                        positions: feature.positions,

                        width: lineWidth,

                    }),

                });

                polygonCollection.add(

                    new Cesium.Primitive({

                        geometryInstances: polygon,

                        appearance: polygonAppearance,

                        asynchronous: false, // 同步渲染

                    })

                );

                polygonCollection.add(

                    new Cesium.Primitive({

                        geometryInstances: polyline,

                        appearance: polylineAppearance,

                        asynchronous: false, // 同步渲染

                    })

                );

            }

  

            const rectangle = Cesium.Rectangle.fromDegrees(

                feature.bounds.minLon,

                feature.bounds.minLat,

                feature.bounds.maxLon,

                feature.bounds.maxLat

            );

            if (needFly) {

                // 飞到线条位置

                viewer.camera.flyTo({

                    destination: rectangle,

                    duration: 2.0, // 设置飞行时间

                });

            }

        });

        return [polygonCollection];

    }

Updated at: