Cesium 加载GEOJSON

本文探讨了在三维场景中叠加大量点位数据的需求,介绍了如何利用Cesium创建GEOJSON图层,并改造Cesium的PrimitiveCluster类以实现动态聚合效果,提升视图流畅性。尽管每个图层点位数量不超过10万,但未进行数据切割处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#原因
目前涉及在三维上叠加大量点位数据,考虑到使用场景不一样,同时结合以前Arcgis与Mapboxgl使用习惯顺便写了两个类
#思考
一个GEOJSON为一个图层(GrahicLayer),同时改造Cesium的聚合类(PrimitiveCluster,仅对点作了处理),实现放大小缩小时自动聚合显示提高流畅度,因为本人目前使用的每个图层点位不超过10万,因此没有对数据进行处理切割处理。

/**
 * Defines how screen space objects (billboards, points, labels) are clustered.
 *
 * @param {Object} [options] An object with the following properties:
 * @param {Boolean} [options.enabled=false] Whether or not to enable clustering.
 * @param {Number} [options.pixelRange=80] The pixel range to extend the screen space bounding box.
 * @param {Number} [options.minimumClusterSize=2] The minimum number of screen space objects that can be clustered.
 * @param {Boolean} [options.clusterBillboards=true] Whether or not to cluster the billboards of an entity.
 * @param {Boolean} [options.clusterLabels=true] Whether or not to cluster the labels of an entity.
 * @param {Boolean} [options.clusterPoints=true] Whether or not to cluster the points of an entity.
 * @param {Boolean} [options.show=true] Determines if the entities in the cluster will be shown.
 *
 * @alias PrimitiveCluster
 * @constructor
 *
 * @demo {@link https://sandcastle.cesium.com/index.html?src=Clustering.html|Cesium Sandcastle Clustering Demo}
 */
function PrimitiveCluster(options) {
    options = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT);

    this._enabled = Cesium.defaultValue(options.enabled, false);
    this._pixelRange = Cesium.defaultValue(options.pixelRange, 80);
    this._minimumClusterSize = Cesium.defaultValue(options.minimumClusterSize, 2);
    this._clusterBillboards = Cesium.defaultValue(options.clusterBillboards, true);
    this._clusterLabels = Cesium.defaultValue(options.clusterLabels, true);
    this._clusterPoints = Cesium.defaultValue(options.clusterPoints, true);

    this._labelCollection = undefined;
    this._billboardCollection = undefined;
    this._pointCollection = undefined;

    this._clusterBillboardCollection = undefined;
    this._clusterLabelCollection = undefined;
    this._clusterPointCollection = undefined;

    this._collectionIndicesByEntity = {};

    this._unusedLabelIndices = [];
    this._unusedBillboardIndices = [];
    this._unusedPointIndices = [];

    this._previousClusters = [];
    this._previousHeight = undefined;

    this._enabledDirty = false;
    this._clusterDirty = false;

    this._cluster = undefined;
    this._removeEventListener = undefined;

    this._clusterEvent = new Cesium.Event();

    /**
     * Determines if entities in this collection will be shown.
     *
     * @type {Boolean}
     * @default true
     */
    this.show = Cesium.defaultValue(options.show, true);
}

function getX(point) {
    return point.coord.x;
}

function getY(point) {
    return point.coord.y;
}

function expandBoundingBox(bbox, pixelRange) {
    bbox.x -= pixelRange;
    bbox.y -= pixelRange;
    bbox.width += pixelRange * 2.0;
    bbox.height += pixelRange * 2.0;
}

var labelBoundingBoxScratch = new Cesium.BoundingRectangle();

function getBoundingBox(item, coord, pixelRange, entityCluster, result) {
    if (item &&
        Cesium.defined(item._billboardCollection) &&
        entityCluster._clusterBillboards
    ) {
        result = Cesium.Billboard.getScreenSpaceBoundingBox(item, coord, result);
    }

    expandBoundingBox(result, pixelRange);
    return result;
}

function addNonClusteredItem(item, entityCluster) {
    item.clusterShow = true;

    if (!Cesium.defined(item._labelCollection) &&
        Cesium.defined(item.id) &&
        hasLabelIndex(entityCluster, item.id.id) &&
        Cesium.defined(item.id._label)
    ) {
        var labelIndex =
            entityCluster._collectionIndicesByEntity[item.id.id].labelIndex;
        var label = entityCluster._labelCollection.get(labelIndex);
        label.clusterShow = true;
    }
}

function addCluster(position, numPoints, ids, entityCluster) {
    var cluster = {
        billboard: entityCluster._clusterBillboardCollection.add(),
        label: entityCluster._clusterLabelCollection.add(),
        // point: entityCluster._clusterPointCollection.add(),
    };

    cluster.billboard.show = true;
    cluster.billboard.count = numPoints
        //cluster.billboard.position = position
    cluster.billboard.disableDepthTestDistance = Number.POSITIVE_INFINITY;
    cluster.billboard.pixelOffset = new Cesium.Cartesian2(0.0, -20.0)
    cluster.billboard.image = entityCluster.bpts.get(0).image
    cluster.billboard.height = entityCluster.bpts.get(0).height
    cluster.billboard.width = entityCluster.bpts.get(0).width
    ids[0].data.ids = ids;
    cluster.billboard.id = ids[0];
    // cluster.point.show = false;
    cluster.label.show = true;
    cluster.label.showBackground = true
    cluster.label.backgroundColor = new Cesium.Color(1, 1, 1, 0.8)
    cluster.label.fillColor = Cesium.Color.GREEN;
    cluster.label.font = "12px monospace"
    cluster.label.horizontalOrigin = Cesium.HorizontalOrigin.CENTER
    cluster.label.verticalOrigin = Cesium.VerticalOrigin.BOTTOM
    cluster.label.pixelOffset = new Cesium.Cartesian2(0.0, -40.0)
    cluster.label.text = ids[0].data.name;
    cluster.label.id = ids[0];
    cluster.billboard.position = cluster.label.position = position //= cluster.point.position = position;


}

function hasLabelIndex(entityCluster, entityId) {
    return (
        Cesium.defined(entityCluster) &&
        Cesium.defined(entityCluster._collectionIndicesByEntity[entityId]) &&
        Cesium.defined(entityCluster._collectionIndicesByEntity[entityId].labelIndex)
    );
}

function getScreenSpacePositions(
    collection,
    points,
    scene,
    occluder,
    entityCluster
) {
    if (!Cesium.defined(collection)) {
        return;
    }

    var length = collection.length;
    for (var i = 0; i < length; ++i) {
        var item = collection.get(i);
        item.clusterShow = false;

        if (!item.show ||
            (entityCluster._scene.mode === Cesium.SceneMode.SCENE3D &&
                !occluder.isPointVisible(item.position))
        ) {
            continue;
        }

        var canClusterLabels =
            entityCluster._clusterLabels && Cesium.defined(item._labelCollection);
        var canClusterBillboards =
            entityCluster._clusterBillboards && Cesium.defined(item);
        var canClusterPoints =
            entityCluster._clusterPoints && Cesium.defined(item._point);
        if (canClusterLabels && (canClusterPoints || canClusterBillboards)) {
            continue;
        }

        var coord = item.computeScreenSpacePosition(scene);
        if (!Cesium.defined(coord)) {
            continue;
        }

        points.push({
            index: i,
            collection: collection,
            clustered: false,
            coord: coord,
        });
    }
}

var pointBoundinRectangleScratch = new Cesium.BoundingRectangle();
var totalBoundingRectangleScratch = new Cesium.BoundingRectangle();
var neighborBoundingRectangleScratch = new Cesium.BoundingRectangle();

function createDeclutterCallback(entityCluster) {

    return async function(amount) {
        entityCluster._clusterEvent.raiseEvent({});
        if (!entityCluster.show) return;
        var scene = entityCluster._scene;

        var labelCollection = entityCluster._labelCollection;
        var billboardCollection = entityCluster._billboardCollection;
        var pointCollection = entityCluster._pointCollection;

        if (
            (!Cesium.defined(labelCollection) &&
                !Cesium.defined(billboardCollection) &&
                !Cesium.defined(pointCollection)) ||
            (!entityCluster._clusterBillboards &&
                !entityCluster._clusterLabels &&
                !entityCluster._clusterPoints)
        ) {
            return;
        }

        var clusteredLabelCollection = entityCluster._clusterLabelCollection;
        var clusteredBillboardCollection =
            entityCluster._clusterBillboardCollection;
        // var clusteredPointCollection = entityCluster._clusterPointCollection;

        if (Cesium.defined(clusteredLabelCollection)) {
            clusteredLabelCollection.removeAll();
        } else {
            clusteredLabelCollection = entityCluster._clusterLabelCollection = new Cesium.LabelCollection({
                scene: scene,
            });
        }

        if (Cesium.defined(clusteredBillboardCollection)) {
            clusteredBillboardCollection.removeAll();
        } else {
            clusteredBillboardCollection = entityCluster._clusterBillboardCollection = new Cesium.BillboardCollection({
                scene: scene,
            });
        }
        var pixelRange = entityCluster._pixelRange;
        var minimumClusterSize = entityCluster._minimumClusterSize;

        var clusters = entityCluster._previousClusters;
        var newClusters =
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

tufeibobo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值