Загрузка обновленных данных с помощью GeoJsonDataSource в Cesium.js

Я пытаюсь интегрировать Cesium 1.11 с существующим сервером, отправляющим GeoJSON. Я могу успешно загрузить данные в представление из первого сообщения, однако последующие вызовы load() не обновляют отображение.

Я упростил задачу до следующей, также доступной в виде скрипки.

  • Я ожидаю, что второй вызов загрузки обновит дисплей, чтобы переместить маркер в Нью-Йорк, однако он останется в Лондоне.
  • Окно функций по-прежнему показывает свойство «foo» как 123, я ожидаю, что 456.

Код

var viewer = new Cesium.Viewer('cesiumContainer');
var source = new Cesium.GeoJsonDataSource("name123");
viewer.dataSources.add(source);

source.load({
    type: "FeatureCollection",
    crs: {
        type: "name",
        properties: {
            name: "urn:ogc:def:crs:OGC:1.3:CRS84"
        }
    },
    features: [{
        type: "Feature",
        properties: {
            foo: 123,
        },
        geometry: {
            type: "Point",
            coordinates: [0.1275, 51.5072] // London
        },
        id: "123"
    }]
});

// workaround, but has side effect of destroying feature window
// source.entities.removeAll();

// sometime later...
source.load({
    type: "FeatureCollection",
    crs: {
        type: "name",
        properties: {
            name: "urn:ogc:def:crs:OGC:1.3:CRS84"
        }
    },
    features: [{
        type: "Feature",
        properties: {
            foo: 456,
        },
        geometry: {
            type: "Point",
            coordinates: [-75.1890, 42.3482] // New York
        },
        id: "123"
    }]
});

Что я пробовал

  • «принудительно» обновить, вызвав source.entities.removeAll(), однако это имеет побочный эффект закрытия окна функции, если оно открыто во время обновления. Я получаю сообщения каждую секунду, поэтому это нежелательно.

  • Да, я знаю о проприетарной системе CZML, однако я хотел бы придерживаться GeoJSON для этой относительно простой системы.

Обновление: дальнейшая отладка. Проблема видимо в конструктивной особенности...

  • Вспомогательный метод load() в GeoJsonDataSource вызывает that._entityCollection.removeAll(). Это находится между suspendEvents() и возобновитьEvents(), поэтому не приводит к закрытию окна функции.
  • После возобновления событий () события «изменения» запускаются, даже если сущности были фактически воссозданы
  • Существующий BillboardVisualizer, созданный Cesium.Viewer, хранит кэшированные экземпляры объектов, которые он использовал при первом рендеринге.
  • BillboardVisualizer.update() продолжает считывать первую позицию из «устаревших» экземпляров объекта, поэтому обновление не отображается.

person Adam    schedule 15.07.2015    source источник


Ответы (2)


Это похоже на ошибку в Cesium. Я только что отправил задачу #2891 и попытаюсь получить исправить в выпуске 1.12 от 3 августа. Тем временем вы должны быть в состоянии обойти проблему, используя стратегию removeAll в сочетании со сбросом выбранного объекта после загрузки (что должно сохранить InfoBox, что, как я полагаю, вы подразумеваете под окном функций). Вот полный пример того, что вы можете использовать Sandcastle, чтобы увидеть его в действии.

var viewer = new Cesium.Viewer('cesiumContainer');
var source = new Cesium.GeoJsonDataSource("name123");
viewer.dataSources.add(source);

Sandcastle.addToolbarButton('Load 1', function(){
    source.entities.removeAll();
    source.load({
        type: "FeatureCollection",
        crs: {
            type: "name",
            properties: {
                name: "urn:ogc:def:crs:OGC:1.3:CRS84"
            }
        },
        features: [{
            type: "Feature",
            properties: {
                foo: 123
            },
            geometry: {
                type: "Point",
                coordinates: [0.1275, 51.5072] // London
            },
            id: "123"
        }]
    }).then(function(){
        viewer.selectedEntity = source.entities.values[0];
    });
});

Sandcastle.addToolbarButton('Load 2', function() {
    source.entities.removeAll();
    source.load({
        type: "FeatureCollection",
        crs: {
            type: "name",
            properties: {
                name: "urn:ogc:def:crs:OGC:1.3:CRS84"
            }
        },
        features: [{
            type: "Feature",
            properties: {
                foo: 456
            },
            geometry: {
                type: "Point",
                coordinates: [-75.1890, 42.3482] // New York
            },
            id: "123"
        }]
    }).then(function(){
        viewer.selectedEntity = source.entities.values[0];
    });
});
person Matthew Amato    schedule 15.07.2015
comment
Спасибо, что посмотрели это, ваше решение действительно устраняет проблему с InfoBox, однако InfoBox по-прежнему всегда показывает «устаревшие» значения из первого обновления. - person Adam; 15.07.2015
comment
Попробуйте добавить viewer.selectedEntity = undefined; перед заданием. - person Matthew Amato; 15.07.2015

Альтернативное решение — просто использовать GeoJsonDataSource для создания сущностей из JSON и добавлять добавление/обновление вручную в глобальную коллекцию сущностей средства просмотра.

var viewer = new Cesium.Viewer('cesiumContainer');
var source = new Cesium.GeoJsonDataSource("name123");
// don't add source to viewer

source.load(...);

// sometime later...
source.load(...);

// manually update
viewer.entities.suspendEvents();
source.entities.values.forEach(function(entity) {
    var existing = viewer.entities.getById(entity.id);
    if (existing === undefined) {
        viewer.entities.add(entity);
    } else {
        entity.propertyNames.forEach(function(name) {
            existing[name] = entity[name];  
        });
    }
}, this);
viewer.entities.resumeEvents();
person Adam    schedule 15.07.2015