Cesium中Entity与Primitive结合

Cesium中Entity与Primitive结合使用指南

📊 Entity与Primitive关系流程图

Cesium渲染流程
实体层Entity
图元层Primitive
高级API, 易用
底层API, 高性能
EntityCollection
DataSource
Primitive
PrimitiveCollection
GroundPrimitive
自动转换

🔍 Entity与Primitive基础比较

Entity特点

// Entity示例 - 高级API,简单易用
const entity = viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(116.39, 39.9),
    point: {
        pixelSize: 10,
        color: Cesium.Color.RED
    },
    label: {
        text: '北京'
    }
});

Primitive特点

// Primitive示例 - 底层API,性能更好
const positions = Cesium.Cartesian3.fromDegreesArray([
    116.39, 39.9,
    116.40, 39.9,
    116.40, 39.91,
    116.39, 39.91
]);

const polygonInstance = new Cesium.GeometryInstance({
    geometry: new Cesium.PolygonGeometry({
        polygonHierarchy: new Cesium.PolygonHierarchy(positions),
        vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
    }),
    attributes: {
        color: Cesium.ColorGeometryInstanceAttribute.fromColor(
            Cesium.Color.RED.withAlpha(0.7)
        )
    }
});

const primitive = new Cesium.Primitive({
    geometryInstances: polygonInstance,
    appearance: new Cesium.PerInstanceColorAppearance({
        flat: true,
        translucent: true
    })
});

viewer.scene.primitives.add(primitive);

🧠 两者优缺点对比

特性EntityPrimitive
API级别⭐高级,简单易用⭐底层,复杂但更灵活
性能中等,转换为Primitive渲染⭐高,直接渲染
拾取⭐自带实体拾取,易于互动手动实现拾取逻辑
数据量适合小到中等数据量⭐适合大数据量(10000+)
动画⭐简单实现动态效果需手动更新几何体
内存占用较多⭐更高效
批处理逐个添加⭐支持几何实例合并

🔄 Entity转Primitive技术

1. 通过API直接转换

// ⭐使用Entity API创建,但转换为Primitive渲染
function createEntityAsPrimitive() {
    // 1. 创建一个不添加到viewer的Entity
    const entity = new Cesium.Entity({
        position: Cesium.Cartesian3.fromDegrees(116.39, 39.9),
        ellipse: {
            semiMajorAxis: 500,
            semiMinorAxis: 300,
            material: Cesium.Color.RED.withAlpha(0.5),
            outline: true,
            outlineColor: Cesium.Color.BLACK,
            outlineWidth: 2
        }
    });
    
    // 2. 创建visualizer来转换Entity
    const entityCluster = new Cesium.EntityCluster();
    entityCluster._scene = viewer.scene;
    
    const visualizerCollection = new Cesium.VisualizerCollection([
        new Cesium.GeometryVisualizer(new Cesium.GeometryInstance(), viewer.scene, entityCluster)
    ]);
    
    // 3. 处理Entity
    visualizerCollection.update(Cesium.JulianDate.now(), [entity]);
    
    // 现在Entity被转换成了Primitive并添加到场景中
}

2. 使用工具函数手动映射

// ⭐Entity到Primitive的映射转换
function createPolygonEntityAsPrimitive(positions, color) {
    // 使用Entity API创建Primitive - 手动映射方式
    
    // 1. 从Entity参数构建Primitive参数
    const polygonHierarchy = new Cesium.PolygonHierarchy(positions);
    
    // 2. 创建几何实例
    const instance = new Cesium.GeometryInstance({
        geometry: new Cesium.PolygonGeometry({
            polygonHierarchy: polygonHierarchy,
            vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
        }),
        attributes: {
            color: Cesium.ColorGeometryInstanceAttribute.fromColor(color)
        },
        id: 'polygon-' + Math.random().toString(36).substring(2, 9) // 生成随机ID
    });
    
    // 3. 创建Primitive
    const primitive = new Cesium.Primitive({
        geometryInstances: instance,
        appearance: new Cesium.PerInstanceColorAppearance({
            flat: true,
            translucent: true
        })
    });
    
    // 4. 添加到场景
    viewer.scene.primitives.add(primitive);
    
    return primitive;
}

// 使用示例
const positions = Cesium.Cartesian3.fromDegreesArray([
    116.39, 39.9,
    116.40, 39.9,
    116.40, 39.91,
    116.39, 39.91
]);

const polygonPrimitive = createPolygonEntityAsPrimitive(
    positions, 
    Cesium.Color.BLUE.withAlpha(0.5)
);

📦 创建批量Primitive高性能图形

// ⭐批量创建点Primitive
function createPointsPrimitive(positions, colors) {
    // GLSL着色器 - 点大小由属性控制
    const vs = `
        attribute vec3 position;
        attribute vec4 color;
        attribute float pointSize;
        
        varying vec4 v_color;
        
        void main() {
            gl_Position = czm_modelViewProjection * vec4(position, 1.0);
            gl_PointSize = pointSize;
            v_color = color;
        }
    `;
    
    const fs = `
        varying vec4 v_color;
        
        void main() {
            float dist = distance(gl_PointCoord, vec2(0.5));
            if (dist > 0.5) {
                discard;
            }
            gl_FragColor = v_color;
        }
    `;
    
    // 创建几何体
    const geometry = new Cesium.Geometry({
        attributes: {
            position: new Cesium.GeometryAttribute({
                componentDatatype: Cesium.ComponentDatatype.DOUBLE,
                componentsPerAttribute: 3,
                values: new Float64Array(positions)
            }),
            color: new Cesium.GeometryAttribute({
                componentDatatype: Cesium.ComponentDatatype.UNSIGNED_BYTE,
                componentsPerAttribute: 4,
                values: new Uint8Array(colors),
                normalize: true
            }),
            pointSize: new Cesium.GeometryAttribute({
                componentDatatype: Cesium.ComponentDatatype.FLOAT,
                componentsPerAttribute: 1,
                values: new Float32Array(positions.length / 3).fill(10.0) // 所有点大小为10
            })
        },
        primitiveType: Cesium.PrimitiveType.POINTS
    });
    
    // 创建自定义命令
    const drawCommand = new Cesium.DrawCommand({
        vertexArray: Cesium.VertexArray.fromGeometry({
            context: viewer.scene.context,
            geometry: geometry,
            attributeLocations: {
                position: 0,
                color: 1,
                pointSize: 2
            },
            bufferUsage: Cesium.BufferUsage.STATIC_DRAW
        }),
        primitiveType: Cesium.PrimitiveType.POINTS,
        shaderProgram: Cesium.ShaderProgram.fromCache({
            context: viewer.scene.context,
            vertexShaderSource: vs,
            fragmentShaderSource: fs,
            attributeLocations: {
                position: 0,
                color: 1,
                pointSize: 2
            }
        }),
        pass: Cesium.Pass.OPAQUE
    });
    
    // 创建自定义primitive
    const customPrimitive = new Cesium.Primitive({
        geometryInstances: [],
        releaseGeometryInstances: false,
        update: function(frameState) {
            frameState.commandList.push(drawCommand);
        }
    });
    
    viewer.scene.primitives.add(customPrimitive);
    return customPrimitive;
}

// 使用示例 - 创建10000个随机点
function createManyPoints(count) {
    const positions = [];
    const colors = [];
    
    for (let i = 0; i < count; i++) {
        // 生成随机位置
        const lon = 116.39 + (Math.random() - 0.5) * 0.5;
        const lat = 39.9 + (Math.random() - 0.5) * 0.5;
        const height = Math.random() * 1000;
        
        const cartesian = Cesium.Cartesian3.fromDegrees(lon, lat, height);
        positions.push(cartesian.x, cartesian.y, cartesian.z);
        
        // 生成随机颜色
        colors.push(
            Math.floor(Math.random() * 255),  // R
            Math.floor(Math.random() * 255),  // G
            Math.floor(Math.random() * 255),  // B
            255  // A
        );
    }
    
    return createPointsPrimitive(positions, colors);
}

// 创建10000个点
const pointsPrimitive = createManyPoints(10000);

🔄 混合使用策略

1. 场景中同时使用两者

// ⭐混合使用Entity和Primitive
function createMixedScene() {
    // 创建实体 - 用于交互元素
    const pointEntity = viewer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(116.39, 39.9),
        point: {
            pixelSize: 15,
            color: Cesium.Color.RED,
            outlineColor: Cesium.Color.WHITE,
            outlineWidth: 2
        },
        label: {
            text: '北京中心',
            font: '14px sans-serif',
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            outlineWidth: 2,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            pixelOffset: new Cesium.Cartesian2(0, -10)
        }
    });
    
    // 创建几何实例 - 用于静态高性能元素
    const instances = [];
    
    // 创建1000个随机颜色矩形
    for (let i = 0; i < 1000; i++) {
        const lon = 116.39 + (Math.random() - 0.5) * 0.5;
        const lat = 39.9 + (Math.random() - 0.5) * 0.5;
        const width = Math.random() * 500 + 100;
        const height = Math.random() * 500 + 100;
        
        instances.push(new Cesium.GeometryInstance({
            geometry: new Cesium.RectangleGeometry({
                rectangle: Cesium.Rectangle.fromDegrees(
                    lon - 0.005, lat - 0.005, 
                    lon + 0.005, lat + 0.005
                ),
                vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
            }),
            attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                    Cesium.Color.fromRandom({alpha: 0.5})
                )
            },
            id: 'rectangle-' + i
        }));
    }
    
    // 批量添加作为单个primitive
    const rectanglesPrimitive = new Cesium.Primitive({
        geometryInstances: instances,
        appearance: new Cesium.PerInstanceColorAppearance({
            flat: true,
            translucent: true
        })
    });
    
    viewer.scene.primitives.add(rectanglesPrimitive);
    
    // 添加拾取支持
    const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction(function(click) {
        const pickedObject = viewer.scene.pick(click.position);
        
        if (Cesium.defined(pickedObject)) {
            if (pickedObject.id === pointEntity) {
                console.log('点击了实体:北京中心');
                // 处理实体点击
                viewer.flyTo(pointEntity);
            } else if (typeof pickedObject.id === 'string' && pickedObject.id.startsWith('rectangle-')) {
                console.log('点击了矩形:', pickedObject.id);
                // 处理矩形点击
                const primitiveIndex = parseInt(pickedObject.id.split('-')[1]);
                // 可以在这里处理primitive
            }
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    
    return {
        entity: pointEntity,
        primitive: rectanglesPrimitive,
        handler: handler
    };
}

// 创建混合场景
const mixedScene = createMixedScene();

2. 优化策略 - 选择性使用

// ⭐根据数据量动态选择Entity或Primitive
function createOptimizedObjects(positions, options = {}) {
    const threshold = options.threshold || 1000; // 阈值,超过则使用Primitive
    
    if (positions.length <= threshold) {
        // 数据量小,使用Entity
        console.log(`使用Entity API创建${positions.length}个对象`);
        
        const entities = [];
        for (let i = 0; i < positions.length; i++) {
            const position = positions[i];
            
            const entity = viewer.entities.add({
                position: Cesium.Cartesian3.fromDegrees(
                    position[0], position[1], position[2] || 0
                ),
                point: {
                    pixelSize: options.pixelSize || 10,
                    color: Cesium.Color.BLUE,
                    outlineColor: Cesium.Color.WHITE,
                    outlineWidth: 2
                }
            });
            
            entities.push(entity);
        }
        
        return {
            type: 'entity',
            objects: entities
        };
    } else {
        // 数据量大,使用Primitive
        console.log(`使用Primitive API创建${positions.length}个对象`);
        
        const positionsArray = [];
        const colorBytes = [];
        
        // 准备几何数据
        for (let i = 0; i < positions.length; i++) {
            const cartesian = Cesium.Cartesian3.fromDegrees(
                positions[i][0], positions[i][1], positions[i][2] || 0
            );
            
            positionsArray.push(cartesian.x, cartesian.y, cartesian.z);
            
            // 使用蓝色
            colorBytes.push(0, 0, 255, 255);
        }
        
        // 创建点primitive
        const pointsPrimitive = createPointsPrimitive(positionsArray, colorBytes);
        
        return {
            type: 'primitive',
            objects: pointsPrimitive
        };
    }
}

// 测试不同数据量
const smallPositions = [];
const largePositions = [];

// 生成小数据集
for (let i = 0; i < 100; i++) {
    smallPositions.push([
        116.39 + (Math.random() - 0.5) * 0.1,
        39.9 + (Math.random() - 0.5) * 0.1
    ]);
}

// 生成大数据集
for (let i = 0; i < 10000; i++) {
    largePositions.push([
        116.39 + (Math.random() - 0.5) * 0.1,
        39.9 + (Math.random() - 0.5) * 0.1
    ]);
}

// 测试
const smallResult = createOptimizedObjects(smallPositions);
const largeResult = createOptimizedObjects(largePositions);

console.log('小数据集使用:', smallResult.type);
console.log('大数据集使用:', largeResult.type);

🔄 Primitive绘制管理器

// ⭐创建Primitive绘制管理器 - 结合Entity和Primitive优势
class PrimitiveDrawingManager {
    constructor(viewer) {
        this.viewer = viewer;
        this.scene = viewer.scene;
        this.primitives = this.scene.primitives;
        this.entities = viewer.entities;
        
        // 存储临时绘制实体
        this.activeEntity = null;
        
        // 存储已创建的primitives
        this.drawnPrimitives = [];
        
        // 临时点集合
        this.points = [];
        
        // 事件处理器
        this.handler = new Cesium.ScreenSpaceEventHandler(this.scene.canvas);
        
        // 绘制状态
        this.drawingMode = null;
        this.isDrawing = false;
    }
    
    // 开始绘制模式
    startDrawing(mode) {
        // 结束之前的绘制
        this.endDrawing();
        
        this.drawingMode = mode;
        this.isDrawing = true;
        this.points = [];
        
        // 设置鼠标样式
        this.viewer.canvas.style.cursor = 'crosshair';
        
        // 设置点击事件
        this.handler.setInputAction(this.handleClick.bind(this), Cesium.ScreenSpaceEventType.LEFT_CLICK);
        
        // 设置移动事件 - 实时预览
        this.handler.setInputAction(this.handleMouseMove.bind(this), Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        
        // 设置双击事件 - 完成绘制
        this.handler.setInputAction(this.handleDoubleClick.bind(this), Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
        
        console.log(`开始${mode}绘制模式`);
    }
    
    // 处理点击事件
    handleClick(click) {
        if (!this.isDrawing) return;
        
        // 拾取点位置
        const ray = this.viewer.camera.getPickRay(click.position);
        const cartesian = this.scene.globe.pick(ray, this.scene);
        
        if (!cartesian) return;
        
        // 添加点到集合
        this.points.push(cartesian);
        
        // 添加点标记 - 使用Entity
        this.entities.add({
            position: cartesian,
            point: {
                pixelSize: 8,
                color: Cesium.Color.YELLOW,
                outlineColor: Cesium.Color.BLACK,
                outlineWidth: 1
            }
        });
        
        // 更新临时实体
        this.updateActiveEntity();
    }
    
    // 处理鼠标移动
    handleMouseMove(movement) {
        if (!this.isDrawing || this.points.length === 0) return;
        
        // 获取鼠标位置
        const ray = this.viewer.camera.getPickRay(movement.endPosition);
        const cartesian = this.scene.globe.pick(ray, this.scene);
        
        if (!cartesian) return;
        
        // 更新临时实体
        this.updateActiveEntity(cartesian);
    }
    
    // 处理双击 - 完成绘制
    handleDoubleClick(click) {
        if (!this.isDrawing) return;
        
        // 转换为Primitive并清理临时实体
        this.finishDrawing();
    }
    
    // 更新临时绘制实体
    updateActiveEntity(currentPosition) {
        // 移除之前的临时实体
        if (this.activeEntity) {
            this.entities.remove(this.activeEntity);
        }
        
        if (this.points.length === 0) return;
        
        // 创建临时几何体
        const positions = [...this.points];
        if (currentPosition) {
            positions.push(currentPosition);
        }
        
        // 根据绘制模式创建不同实体
        switch (this.drawingMode) {
            case 'polyline':
                this.activeEntity = this.entities.add({
                    polyline: {
                        positions: positions,
                        width: 3,
                        material: Cesium.Color.YELLOW,
                        clampToGround: true
                    }
                });
                break;
                
            case 'polygon':
                if (positions.length >= 3) {
                    this.activeEntity = this.entities.add({
                        polygon: {
                            hierarchy: new Cesium.PolygonHierarchy(positions),
                            material: Cesium.Color.YELLOW.withAlpha(0.5),
                            outline: true,
                            outlineColor: Cesium.Color.BLACK
                        }
                    });
                } else {
                    this.activeEntity = this.entities.add({
                        polyline: {
                            positions: [...positions, positions[0]],
                            width: 3,
                            material: Cesium.Color.YELLOW,
                            clampToGround: true
                        }
                    });
                }
                break;
                
            case 'rectangle':
                if (positions.length >= 2) {
                    // 创建矩形
                    const rect = this.calculateRectangle(positions[0], positions[1]);
                    this.activeEntity = this.entities.add({
                        rectangle: {
                            coordinates: rect,
                            material: Cesium.Color.YELLOW.withAlpha(0.5),
                            outline: true,
                            outlineColor: Cesium.Color.BLACK
                        }
                    });
                }
                break;
        }
    }
    
    // 计算矩形坐标
    calculateRectangle(p1, p2) {
        const cart1 = Cesium.Cartographic.fromCartesian(p1);
        const cart2 = Cesium.Cartographic.fromCartesian(p2);
        
        const west = Math.min(cart1.longitude, cart2.longitude);
        const east = Math.max(cart1.longitude, cart2.longitude);
        const south = Math.min(cart1.latitude, cart2.latitude);
        const north = Math.max(cart1.latitude, cart2.latitude);
        
        return new Cesium.Rectangle(west, south, east, north);
    }
    
    // 完成绘制并转为Primitive
    finishDrawing() {
        if (this.points.length < 2) {
            this.endDrawing();
            return;
        }
        
        // 转换为Primitive
        let primitive;
        
        switch (this.drawingMode) {
            case 'polyline':
                primitive = this.createPolylinePrimitive(this.points);
                break;
                
            case 'polygon':
                primitive = this.createPolygonPrimitive(this.points);
                break;
                
            case 'rectangle':
                const rect = this.calculateRectangle(this.points[0], this.points[1]);
                primitive = this.createRectanglePrimitive(rect);
                break;
        }
        
        if (primitive) {
            this.drawnPrimitives.push(primitive);
            console.log(`创建${this.drawingMode} Primitive, 总数: ${this.drawnPrimitives.length}`);
        }
        
        // 清理临时实体
        this.endDrawing();
    }
    
    // 结束绘制并清理
    endDrawing() {
        // 移除临时实体
        if (this.activeEntity) {
            this.entities.remove(this.activeEntity);
            this.activeEntity = null;
        }
        
        // 移除临时点
        this.entities.removeAll();
        
        // 重置状态
        this.isDrawing = false;
        this.points = [];
        
        // 重置事件处理器
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
        
        // 重置鼠标样式
        this.viewer.canvas.style.cursor = 'default';
    }
    
    // 创建折线Primitive
    createPolylinePrimitive(positions) {
        const material = Cesium.Material.fromType('Color', {
            color: Cesium.Color.YELLOW
        });
        
        const polyline = new Cesium.PolylineGeometry({
            positions: positions,
            width: 3.0,
            vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT
        });
        
        const instance = new Cesium.GeometryInstance({
            geometry: polyline,
            id: 'polyline-' + Date.now()
        });
        
        const primitive = new Cesium.Primitive({
            geometryInstances: instance,
            appearance: new Cesium.PolylineMaterialAppearance({
                material: material
            })
        });
        
        this.scene.primitives.add(primitive);
        return primitive;
    }
    
    // 创建多边形Primitive
    createPolygonPrimitive(positions) {
        const polygonHierarchy = new Cesium.PolygonHierarchy(positions);
        
        const polygon = new Cesium.PolygonGeometry({
            polygonHierarchy: polygonHierarchy,
            vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
        });
        
        const instance = new Cesium.GeometryInstance({
            geometry: polygon,
            attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                    Cesium.Color.YELLOW.withAlpha(0.5)
                )
            },
            id: 'polygon-' + Date.now()
        });
        
        const primitive = new Cesium.Primitive({
            geometryInstances: instance,
            appearance: new Cesium.PerInstanceColorAppearance({
                flat: true,
                translucent: true
            })
        });
        
        this.scene.primitives.add(primitive);
        return primitive;
    }
    
    // 创建矩形Primitive
    createRectanglePrimitive(rectangle) {
        const rect = new Cesium.RectangleGeometry({
            rectangle: rectangle,
            vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
        });
        
        const instance = new Cesium.GeometryInstance({
            geometry: rect,
            attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                    Cesium.Color.YELLOW.withAlpha(0.5)
                )
            },
            id: 'rectangle-' + Date.now()
        });
        
        const primitive = new Cesium.Primitive({
            geometryInstances: instance,
            appearance: new Cesium.PerInstanceColorAppearance({
                flat: true,
                translucent: true
            })
        });
        
        this.scene.primitives.add(primitive);
        return primitive;
    }
    
    // 清除所有primitive
    clearAll() {
        this.endDrawing();
        
        for (const primitive of this.drawnPrimitives) {
            this.scene.primitives.remove(primitive);
        }
        
        this.drawnPrimitives = [];
        console.log('已清除所有图形');
    }
}

// 使用绘制管理器
const drawingManager = new PrimitiveDrawingManager(viewer);

// 创建绘制控制按钮
function createDrawingUI() {
    const container = document.createElement('div');
    container.className = 'drawing-controls';
    container.style.position = 'absolute';
    container.style.top = '10px';
    container.style.left = '10px';
    container.style.zIndex = '1000';
    container.style.backgroundColor = 'rgba(40, 40, 40, 0.8)';
    container.style.color = 'white';
    container.style.padding = '10px';
    container.style.borderRadius = '5px';
    
    const buttons = [
        { name: '画线', mode: 'polyline' },
        { name: '多边形', mode: 'polygon' },
        { name: '矩形', mode: 'rectangle' },
        { name: '清除', action: 'clear' }
    ];
    
    buttons.forEach(btn => {
        const button = document.createElement('button');
        button.textContent = btn.name;
        button.style.margin = '5px';
        button.style.padding = '5px 10px';
        
        button.addEventListener('click', () => {
            if (btn.action === 'clear') {
                drawingManager.clearAll();
            } else {
                drawingManager.startDrawing(btn.mode);
            }
        });
        
        container.appendChild(button);
    });
    
    document.body.appendChild(container);
}

// 添加UI
createDrawingUI();

🧩 Entity与Primitive协同使用最佳实践

  1. 选择策略:

    • Entity: 用于交互元素、动态变化的对象、小量数据
    • Primitive: 用于静态背景、大量数据、性能敏感场景
  2. 数据量阈值:

    • <500: 首选Entity - 开发便捷,后期便于交互
    • 500-5000: 根据交互需求选择
    • 5000: 首选Primitive - 性能更佳

  3. 混合使用推荐:

    • 静态背景层用Primitive
    • 交互前景层用Entity
    • 临时绘制对象用Entity
    • 持久化存储的形状用Primitive
  4. 性能优化:

    • 合并相似材质的Primitive
    • 使用批处理渲染(Batch)
    • 动态调整可见性而非创建/销毁
  5. 高级协同技术:

    • 使用Entity绘制,转换为Primitive存储
    • 大数据集自动降级到Primitive
    • 结合Entity拾取与Primitive渲染

🧩 记忆助手

选择指南: Entity适合交互与少量数据,Primitive适合性能与大量数据
协同技巧: 用Entity画草图,用Primitive做成品
性能黄金法则: 可见性控制 > 批量处理 > 延迟创建

Cesium 中,`Entity` `Primitive` 是两个核心概念,它们分别用于不同的场景目的。理解它们之间的区别对于高效使用 Cesium 构建三维地理空间可视化应用非常重要。 --- ## 一、`Entity` `Primitive` 的区别 ### 1. `Entity` - **定位**:`Entity` 是 Cesium 提供的高级 API,面向用户开发者,适合快速构建可视化场景。 - **特点**: - 更易于使用,封装了大量底层细节。 - 支持时间动态数据(如动画、轨迹)。 - 自动管理图形资源(如几何、材质、图形状态)。 - 支持多种图形类型(点、线、面、模型等)。 - 可以 `DataSource` 配合使用(如 GeoJsonDataSource、KmlDataSource 等),实现数据驱动的图形渲染。 - **适用场景**: - 快速开发。 - 动态数据展示(如飞行路径、时间序列数据)。 - 交互式应用(如点击实体显示信息)。 #### 示例代码:创建一个 Entity(点 + 标签) ```javascript const viewer = new Cesium.Viewer('cesiumContainer'); const entity = viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(-115.0, 37.0), point: { pixelSize: 10, color: Cesium.Color.RED }, label: { text: 'Hello Cesium', font: '14pt monospace', style: Cesium.LabelStyle.FILL_AND_OUTLINE } }); viewer.entities.add(entity); viewer.zoomTo(viewer.entities); ``` --- ### 2. `Primitive` - **定位**:`Primitive` 是 Cesium 的底层 API,面向图形开发者,适合需要精细控制图形渲染的场景。 - **特点**: - 更接近图形硬件,性能更高。 - 需要手动管理图形资源(如几何体、材质、着色器等)。 - 不支持时间动态数据自动更新。 - 更加灵活,但使用复杂。 - **适用场景**: - 对性能要求极高的场景。 - 自定义图形渲染(如自定义着色器)。 - 大规模数据渲染(如地形、图像、模型批处理)。 #### 示例代码:创建一个 Primitive(红色点) ```javascript const viewer = new Cesium.Viewer('cesiumContainer'); const pointPrimitive = new Cesium.PointPrimitive({ position: Cesium.Cartesian3.fromDegrees(-115.0, 32.0), pixelSize: 10, color: Cesium.Color.RED }); viewer.scene.primitives.add(pointPrimitive); ``` --- ## 二、总结对比表 | 特性 | Entity | Primitive | |------|--------|-----------| | 层级 | 高级 API | 底层 API | | 易用性 | 高(封装好) | 低(需手动管理) | | 动态数据支持 | ✅ 支持时间动态 | ❌ 不支持自动时间更新 | | 图形控制 | 自动管理 | 手动精细控制 | | 适用场景 | 快速开发、交互式应用 | 高性能、自定义渲染 | | 渲染效率 | 相对较低 | 更高 | --- ## 三、何时使用 Entity?何时使用 Primitive? - **使用 Entity**: - 开发周期短、功能多。 - 数据驱动、动态更新。 - 交互需求多(如点击、弹窗)。 - **使用 Primitive**: - 对性能要求极高。 - 需要自定义图形渲染。 - 处理大规模数据(如点云、图像图层)。 --- ## 四、相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端熊猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值