cesium系列篇:Entity vs Primitive 源码解析(从Entity到Primitive)01

Entity 和 Primitive的关系

官方教材中提到,Primitive API主要适用于图形渲染开发者,Entity API则适用于数据驱动的可视化,而Entity API的底层则使用了Primitive API。下面我们将通过cesium的源码探究当添加entity对象时,是如何在底层调用对应的Primitive API,创建相应的primitive对象。

这篇文章中,我们将先从viewer初始化开始,探究各个对象之间的关系以及其相互之间的相应关系。

这是下文中涉及到的类的类图,从中可以清晰的了解各个对象之间的关系,接下来我们结合代码来仔细讲解。

cesium系列篇:Entity vs Primitive 源码解析(从Entity到Primitive)01_第1张图片

地球伊始

  1. 通过viewer.entities我们定位到下面三个目标_dataSourceDisplaydefaultDataSourceentities
  entities: {
    get: function () {
      return this._dataSourceDisplay.defaultDataSource.entities;
    },
  },
  1. 看一下他们分别是如何创建的
  • 在对象viewer中创建对象_dataSourceDisplay
 // 创建dataSourceDisplay对象
 const dataSourceDisplay = new DataSourceDisplay({
    scene: scene,
    dataSourceCollection: dataSourceCollection,
  });
  
  this._dataSourceDisplay = dataSourceDisplay;
  • 创建defaultDataSource
const defaultDataSource = new CustomDataSource();
  • 创建对象_entityCollection
    • 结合下面的代码我们知道entities其实对应的是属性_entityCollection
  /**
   * Gets the collection of {@link Entity} instances.
   * @memberof CustomDataSource.prototype
   * @type {EntityCollection}
   */
  entities: {
    get: function () {
      return this._entityCollection;
    },
  },
    • 创建_entityCollection
this._entityCollection = new EntityCollection(this);

事件发出

  1. 可以发现在调用_entityCollection对象的add函数时,其内部调用了fireChangedEvent函数
EntityCollection.prototype.add = function (entity) {
  // 创建entity对象
  if (!(entity instanceof Entity)) {
    entity = new Entity(entity);
  }
  
  // 发出信号
  fireChangedEvent(this);
  return entity;
};
  1. fireChangedEvent则对外发出了一个信号,其中包含了当前添加的对象、移除的对象以及发生变化的对象
function fireChangedEvent(collection) {
    // evnet 对象发出信号
    collection._collectionChanged.raiseEvent(
        collection,
        addedArray,
        removedArray,
        changedArray
    );
}
  • 其中_collectionChanged_entityCollection初始化时创建的一个Event对象
this._collectionChanged = new Event();

事件监听

既然有信号被发出,那就需要找到监听的一方,查看源码可以发现

  1. _dataSourceDisplay中创建defaultDataSource之后,调用了函数
this._onDataSourceAdded(undefined, defaultDataSource);
  1. 其中对defaultDataSource_visualizers进行赋值
DataSourceDisplay.prototype._onDataSourceAdded = function (
  dataSourceCollection,
  dataSource
) {
  dataSource._visualizers = this._visualizersCallback(
    scene,
    entityCluster,
    dataSource
  );
};
  1. 我们看下this._visualizersCallback都返回了什么
  this._visualizersCallback = defaultValue(
    options.visualizersCallback,
    DataSourceDisplay.defaultVisualizersCallback
  );
  
  DataSourceDisplay.defaultVisualizersCallback = function (
  scene,
  entityCluster,
  dataSource
) {
  const entities = dataSource.entities;
  return [
    new BillboardVisualizer(entityCluster, entities),
    new GeometryVisualizer(
      scene,
      entities,
      dataSource._primitives,
      dataSource._groundPrimitives
    ),
    new LabelVisualizer(entityCluster, entities),
    new ModelVisualizer(scene, entities),
    new Cesium3DTilesetVisualizer(scene, entities),
    new PointVisualizer(entityCluster, entities),
    new PathVisualizer(scene, entities),
    new PolylineVisualizer(
      scene,
      entities,
      dataSource._primitives,
      dataSource._groundPrimitives
    ),
  ];
};

这段代码比较长,但还是可以看出是返回了一个包含了各类Visualizer的列表,其中将entities也就是我们上面的_entityCollection作为参数传递进去。
4. 以GeometryVisualizer为例,看看在构造函数阶段都做了什么

function GeometryVisualizer(
  scene,
  entityCollection,
  primitives,
  groundPrimitives
) {
  this._entityCollection = entityCollection;
  entityCollection.collectionChanged.addEventListener(
    GeometryVisualizer.prototype._onCollectionChanged,
    this
  );
}
  1. 通过_onCollectionChanged函数,可以看见其将添加到entity添加到了this._addedObjects属性中
/**
 * @private
 */
GeometryVisualizer.prototype._onCollectionChanged = function (
  entityCollection,
  added,
  removed
) {
  const addedObjects = this._addedObjects;

  for (i = added.length - 1; i > -1; i--) {
    entity = added[i];
    id = entity.id;
    if (removedObjects.remove(id)) {
      changedObjects.set(id, entity);
    } else {
      addedObjects.set(id, entity);
    }
  }
};

于是我们找到了监听collectionChanged事件的对象,以及如何将被添加的entity传递到GeometryVisualizer,从而完成了事件发出到监听的闭环。

在这之后又是如何根据GeometryVisualizer中的_addedObjects创建primitive呢,这我们将在下一篇文章中进行详细的描述。

你可能感兴趣的:(Cesium,cesium,entity,primitive,源码解析)