Creating Entities (创建实体)

Creating Entities (创建实体)

了解如何使用CesiumJS中的Entity API绘制空间数据,例如点,标记,标签,线,模型,形状和体积。 如果您不熟悉CesiumJS,则可能要开始使用 Getting Started 教程。


What is the Entity API? (什么是 Entity API)

CesiumJS具有丰富的空间数据API,可以将其分为两类:面向图形开发人员的低级Primitive API和用于数据驱动的可视化的高级Entity API。

低级原始API暴露了执行手头任务所需的最少抽象量。 它的结构旨在为图形开发人员提供灵活的实现,而不是为了实现API一致性。 加载模型与创建广告牌不同,并且两者都与创建多边形完全不同。 每种可视化类型都有其自己独特的功能。 此外,每个都有不同的性能特征,并且需要不同的最佳实践。 尽管此方法功能强大且灵活,但可以为更高级别的抽象更好地服务于大多数应用程序。

Entity API公开了一组一致设计的高级对象,这些对象将相关的可视化和信息聚合到一个统一的数据结构中,我们称之为 Entity。它使我们能够专注于数据的表示,而不必担心可视化的潜在机制。 它还提供了一些结构,可轻松构建复杂的,时间动态的可视化文件,并使其自然地适合静态数据。 虽然Entity API实际上是在后台使用Primitive API,但这是我们几乎不必担心的实现细节。 通过将各种启发式方法应用于我们提供的数据,Entity API能够提供灵活,高性能的可视化效果,同时公开一致,易学且易于使用的界面。


Our first entity (我们的第一个entity)

首先,在Sandcastle中打开 Hello World 示例。

从经度和纬度列表中为美国怀俄明州添加一个多边形。

var viewer = new Cesium.Viewer('cesiumContainer');

var wyoming = viewer.entities.add({
  polygon : {
    hierarchy : Cesium.Cartesian3.fromDegreesArray([
                              -109.080842,45.002073,
                              -105.91517,45.002073,
                              -104.058488,44.996596,
                              -104.053011,43.002989,
                              -104.053011,41.003906,
                              -105.728954,40.998429,
                              -107.919731,41.003906,
                              -109.04798,40.998429,
                              -111.047063,40.998429,
                              -111.047063,42.000709,
                              -111.047063,44.476286,
                              -111.05254,45.002073]),
    height : 0,
    material : Cesium.Color.RED.withAlpha(0.5),
    outline : true,
    outlineColor : Cesium.Color.BLACK
  }
});

viewer.zoomTo(wyoming);

点击工具栏中的 Run 按钮(或键盘上的F8)将产生以下结果:

wyoming
上面的代码创建了 Viewer ,后者创建了Globe和其他小部件。 我们通过 viewer.entities.add 创建了一个新的实体。 我们传递来添加的对象为实体提供了初始值。 返回值是实际的Entity实例。 最后,viewer.zoomTo 缩放摄影机以查看实体。

有很多实体选项。 我们为 polygon (多边形) 填充了半透明的红色和指定了黑色的轮廓。


Shapes and volumes (形状和体积)

以下是我们可以使用Entity API创建的受支持的形状和体积的完整列表:

typeprammarexampledocumentation
Boxesentity.boxCode exampleReference documentation
Circles and ellipsesentity.ellipseCode exampleReference documentation
Corridorentity.corridorCode exampleReference documentation
Cylinder and conesentity.cylinderCode exampleReference documentation
Polygonsentity.polygonCode exampleReference documentation
Polylinesentity.polylineCode exampleReference documentation
Polyline volumesentity.polylineVolumeCode exampleReference documentation
Rectanglesentity.rectangleCode exampleReference documentation
Spheres and ellipsoidsentity.ellipsoidCode exampleReference documentation
Wallsentity.wallCode exampleReference documentation

Materials and outlines (材料和轮廓)
所有形状和体积都有一组共同的属性来控制其外观。 fill 属性指定是否填充几何图形,而 outline 属性指定是否绘制几何图形。

当fill为true时,material 属性确定该填充的外观。 下面将创建一个半透明的蓝色椭圆。

var entity = viewer.entities.add({
  position: Cesium.Cartesian3.fromDegrees(-103.0, 40.0),
  ellipse : {
    semiMinorAxis : 250000.0,
    semiMajorAxis : 400000.0,
    material : Cesium.Color.BLUE.withAlpha(0.5)
  }
});
viewer.zoomTo(viewer.entities);

var ellipse = entity.ellipse; // For upcoming examples

ellipse
Image
我们还可以指定图像的URL而不是颜色。

ellipse.material = '/docs/tutorials/creating-entities/images/cats.jpg';

image
在以上两种情况下,都会在分配时自动为我们创建 ColorMaterialPropertyImageMaterialProperty 。 对于更复杂的材料,我们需要自己创建一个 MaterialProperty 实例。 当前,实体形状和体积支持颜色,图像,棋盘格(Checkerboard),条纹(Stripe)和网格材料(Grid)。

Checkerboard

ellipse.material = new Cesium.CheckerboardMaterialProperty({
  evenColor : Cesium.Color.WHITE,
  oddColor : Cesium.Color.BLACK,
  repeat : new Cesium.Cartesian2(4, 4)
});

checkerBoard
Stripe

ellipse.material = new Cesium.StripeMaterialProperty({
  evenColor : Cesium.Color.WHITE,
  oddColor : Cesium.Color.BLACK,
  repeat : 32
});

stripe
Grid

ellipse.material = new Cesium.GridMaterialProperty({
  color : Cesium.Color.YELLOW,
  cellAlpha : 0.2,
  lineCount : new Cesium.Cartesian2(8, 8),
  lineThickness : new Cesium.Cartesian2(2.0, 2.0)
});

grid
Outlines
outline依赖于outlineColor和outlineWidth属性。 outlineWidth仅适用于非Windows系统,例如Android,iOS,Linux和OSX。在Windows系统上,轮廓的宽度始终为1。这是由于在Windows上实现WebGL的方式受到限制。

ellipse.fill = false;
ellipse.outline = true;
ellipse.outlineColor = Cesium.Color.YELLOW;
ellipse.outlineWidth = 2.0;

outline
Polylines
折线是一种特殊情况,因为它们没有填充或轮廓属性。 他们依靠专业材料来制作颜色以外的任何东西。 由于这些特殊的材料,宽度和轮廓宽度不同的折线将适用于所有系统。

var entity = viewer.entities.add({
    polyline : {
        positions : Cesium.Cartesian3.fromDegreesArray([-77, 35,
                                                        -77.1, 35]),
    width : 5,
    material : Cesium.Color.RED
}});
viewer.zoomTo(viewer.entities);

var polyline = entity.polyline // For upcoming examples

polyline
Polyline outline

polyline.material = new Cesium.PolylineOutlineMaterialProperty({
    color : Cesium.Color.ORANGE,
    outlineWidth : 3,
    outlineColor : Cesium.Color.BLACK
});

polyOutline
Heights and extrusions
可以将包括走廊,椭圆形,多边形和矩形在内的曲面形状放置在高空或挤压成一个体积。 在这两种情况下,形状或体积仍将符合WGS84椭球的曲率。

在相应的图形对象上设置height属性(以米为单位)。 下面的代码行将多边形升高到地球上方25万米。

wyoming.polygon.height = 250000;

polyHeight
要将形状挤出为体积,请设置 extrudedHeight 属性。 该体积将在 height 和 extrudedHeight 之间创建。 如果高度未定义,则体积从0开始。创建一个体积从200,000米开始并扩展到250,000米的体积。

wyoming.polygon.height = 200000;
wyoming.polygon.extrudedHeight = 250000;

polyExtrudeHeight


Entity features in the Viewer (查看器中的实体功能)

让我们看一下Viewer提供的与实体配合使用的即用型功能。

Selection and description (选择和描述)
在查看器中单击一个实体将在该实体的位置显示 SelectionIndicator 小部件,并调出 InfoBox 以提供更多信息。 我们可以设置一个 name,该名称确定InfoBox的标题。 我们还可以提供HTML作为Entity.description属性。

wyoming.name = 'wyoming';
wyoming.description = '\
<img\
  width="50%"\
  style="float:left; margin: 0 1em 1em 0;"\
  src="//cesium.com/docs/tutorials/creating-entities/Flag_of_Wyoming.svg"/>\
<p>\
  Wyoming is a state in the mountain region of the Western \
  United States.\
</p>\
<p>\
  Wyoming is the 10th most extensive, but the least populous \
  and the second least densely populated of the 50 United \
  States. The western two thirds of the state is covered mostly \
  with the mountain ranges and rangelands in the foothills of \
  the eastern Rocky Mountains, while the eastern third of the \
  state is high elevation prairie known as the High Plains. \
  Cheyenne is the capital and the most populous city in Wyoming, \
  with a population estimate of 63,624 in 2017.\
</p>\
<p>\
  Source: \
  <a style="color: WHITE"\
    target="_blank"\
    href="http://en.wikipedia.org/wiki/Wyoming">Wikpedia</a>\
</p>';

SelectionAndDescription
信息框中显示的所有HTML均已沙箱化。 这样可以防止外部数据源将恶意代码注入Cesium应用程序。 要在描述中运行JavaScript或浏览器插件,请通过viewer.infoBox.frame属性访问用于沙箱处理的iframe。 有关控制iframe沙箱的更多信息,请参见本文


Camera controls (相机控制)
使用viewer.zoomTo命令查看特定实体。 还有一个 viewer.flyTo 方法,该方法执行动画照相机飞行到实体。 这两种方法都可以传递给Entity,EntityCollection,DataSource 或实体数组。

两种方法都会计算所有提供的实体的视图。 默认情况下,相机朝北,并从45度角向下看。 通过传入HeadingPitchRange对其进行自定义。

var heading = Cesium.Math.toRadians(90);
var pitch = Cesium.Math.toRadians(-30);
viewer.zoomTo(wyoming, new Cesium.HeadingPitchRange(heading, pitch));

HeadingPitchRange
zoomTo和flyTo都是异步函数。 也就是说,不能保证他们在返回之前已经完成。 例如,飞越实体会发生在许多动画帧上。 这两个函数都返回 Promises,可用于计划在飞行或缩放完成后要执行的功能。 用下面的代码片段替换示例中的zoomTo。 这将飞往怀俄明州,并在飞行完成后将其选中。

viewer.flyTo(wyoming).then(function(result){
    if (result) {
        viewer.selectedEntity = wyoming;
    }
});

如果成功完成了飞行,则传递给我们的回调函数的结果参数将为true;如果取消飞行,即用户在此飞行完成之前发起了另一个飞行或缩放,或者因为目标没有相应的可视化效果,即存在 没有可缩放的内容。

有时,尤其是在使用时间动态数据时,我们希望相机保持在实体上而不是在地球上居中。 这是通过设置viewer.trackedEntity 来完成的。 跟踪实体需要设置 position。

wyoming.position = Cesium.Cartesian3.fromDegrees(-107.724, 42.68);
viewer.trackedEntity = wyoming;

通过将 viewer.trackedEntity 设置为undefined或通过双击实体来停止跟踪。 调用zoomTo或flyTo也将取消跟踪。


Managing entities (管理 entities)

EntityCollection 是用于管理和监视一组实体的关联数组。 viewer.entities是一个EntityCollection。 EntityCollection包括用于管理实体的方法,例如 addremoveremoveAll

有时我们需要更新先前创建的实体。 所有实体实例都有一个唯一的 ID,可用于从集合中检索实体。 我们可以指定一个ID,否则将自动生成一个。

viewer.entities.add({
    id : 'uniqueId'
}); 

使用 getById 检索实体。 如果不存在具有提供的ID的实体,则返回undefined。

var entity = viewer.entities.getById('uniqueId');

要获取实体或创建一个不存在的实体,请使用 getOrCreateEntity

var entity = viewer.entities.getOrCreateEntity('uniqueId');

手动创建一个新实体,然后使用 add 将其添加到集合中。 如果集合中已经存在具有相同ID的实体,则抛出此方法。

var entity = new Entity({
    id : 'uniqueId'
});
viewer.entities.add(entity);

EntityCollection的功能通过 collectionChanged 事件发挥作用。 当在集合中添加,删除或更新实体时,这会通知侦听器。

使用 Sandcastle 中的 Geometry Showcase 示例。 在创建查看器的行之后粘贴以下代码。

function onChanged(collection, added, removed, changed){
  var msg = 'Added ids';
  for(var i = 0; i < added.length; i++) {
    msg += '\n' + added[i].id;
  }
  console.log(msg);
}
viewer.entities.collectionChanged.addEventListener(onChanged);

运行该示例时,您应该在控制台中看到大约65条消息,每个对viewer.entities.add的调用都将显示一条消息。

一次更新大量实体时,将更改排队并在最后发送一个大事件的性能更高。 这样,Cesium 就可以一次处理所需的更改。 在 viewer.entities.add 之前调用 viewer.entities.suspendEvents ,并在示例末尾调用viewer.entities.resumeEvents。 当我们再次运行该演示时,我们现在得到一个包含所有65个实体的事件。 这些调用是引用计数,因此可以嵌套多个暂停和恢复调用。

Picking

拾取(单击以选择一个对象)是我们需要与Primitive API进行短暂交互的区域之一。 使用 scene.pickscene.drillPick 检索实体。

/**
 * Returns the top-most entity at the provided window coordinates
 * or undefined if no entity is at that location.
 *
 * @param {Cartesian2} windowPosition The window coordinates.
 * @returns {Entity} The picked entity or undefined.
 */
function pickEntity(viewer, windowPosition) {
  var picked = viewer.scene.pick(windowPosition);
  if (defined(picked)) {
    var id = Cesium.defaultValue(picked.id, picked.primitive.id);
    if (id instanceof Cesium.Entity) {
      return id;
    }
  }
  return undefined;
};

/**
 * Returns the list of entities at the provided window coordinates.
 * The entities are sorted front to back by their visual order.
 *
 * @param {Cartesian2} windowPosition The window coordinates.
 * @returns {Entity[]} The picked entities or undefined.
 */
function drillPickEntities(viewer, windowPosition) {
  var i;
  var entity;
  var picked;
  var pickedPrimitives = viewer.scene.drillPick(windowPosition);
  var length = pickedPrimitives.length;
  var result = [];
  var hash = {};

  for (i = 0; i < length; i++) {
    picked = pickedPrimitives[i];
    entity = Cesium.defaultValue(picked.id, picked.primitive.id);
    if (entity instanceof Cesium.Entity &&
        !Cesium.defined(hash[entity.id])) {
      result.push(entity);
      hash[entity.id] = true;
    }
  }
  return result;
};

Points, billboards, and labels

通过设置位置,pointlabel 来创建图形点或标签。 例如,在我们最喜欢的运动队的主场上放置一个点。

var viewer = new Cesium.Viewer('cesiumContainer');

var citizensBankPark = viewer.entities.add({
    name : 'Citizens Bank Park',
    position : Cesium.Cartesian3.fromDegrees(-75.166493, 39.9060534),
    point : {
        pixelSize : 5,
        color : Cesium.Color.RED,
        outlineColor : Cesium.Color.WHITE,
        outlineWidth : 2
    },
    label : {
        text : 'Citizens Bank Park',
        font : '14pt monospace',
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth : 2,
        verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
        pixelOffset : new Cesium.Cartesian2(0, -9)
    }
});

viewer.zoomTo(viewer.entities);

point
默认情况下,标签在水平和垂直方向上居中。 由于标签和点共享相同的位置,因此它们在屏幕上重叠。 为避免这种情况,请指定标签原点 VerticalOrigin.BOTTOM 并将像素偏移设置为(0,-9)。

billboard 代替该点,广告牌(billboard)是始终面向用户的标记。

var citizensBankPark = viewer.entities.add({
  position : Cesium.Cartesian3.fromDegrees(-75.166493, 39.9060534),
  billboard : {
    image : '//cesium.com/images/docs/tutorials/creating-entities/Philadelphia_Phillies.png',
    width : 64,
    height : 64
  },
  label : {
    text : 'Citizens Bank Park',
    font : '14pt monospace',
    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    outlineWidth : 2,
    verticalOrigin : Cesium.VerticalOrigin.TOP,
    pixelOffset : new Cesium.Cartesian2(0, 32)
  }
});

billboard
有关更多自定义选项,请参阅Sandcastle LabelsBillboards Sandcastle示例。

3D models

CesiumJS通过运行时资产格式 glTF 支持 3D models。 您可以在3D模型Sandcastle示例中找到示例模型。

为glTF模型设置位置和URI,以创建模型实体。

var viewer = new Cesium.Viewer('cesiumContainer');
var entity = viewer.entities.add({
    position : Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706),
    model : {
        uri : '../../../../Apps/SampleData/models/GroundVehicle/GroundVehicle.glb'
    }
});
viewer.trackedEntity = entity;

GroundVehicle
默认情况下,模型是直立的并面向东。 通过为 Entity.orientation属性指定一个 Quaternion 来控制模型的方向。 这将控制模型的航向,俯仰和横滚。

var viewer = new Cesium.Viewer('cesiumContainer');
var position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706);
var heading = Cesium.Math.toRadians(45.0);
var pitch = Cesium.Math.toRadians(15.0);
var roll = Cesium.Math.toRadians(0.0);
var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, new Cesium.HeadingPitchRoll(heading, pitch, roll));

var entity = viewer.entities.add({
    position : position,
    orientation : orientation,
    model : {
        uri : '../../../../Apps/SampleData/models/GroundVehicle/GroundVehicle.glb'
    }
});
viewer.trackedEntity = entity;

有关更多高级模型功能,请参见 3D Model 教程。 如果您创建自己的模型,请务必查看我们在 glTF Tips for Artists


The property system

我们为实体定义的所有值都存储为Property对象。 例如,请参见怀俄明州大纲的值:

console.log(typeof wyoming.polygon.outline);

outline是 ConstantProperty 的一个实例。 本教程使用一种称为“隐式属性转换”的简写形式,该形式会自动获取原始值并在后台创建相应的Property。 如果没有这个速记,我们将不得不编写一个更长的版本来显示初始示例:

var wyoming = new Cesium.Entity();
wyoming.name = 'Wyoming';

var polygon = new Cesium.PolygonGraphics();
polygon.material = new Cesium.ColorMaterialProperty(Cesium.Color.RED.withAlpha(0.5));
polygon.outline = new Cesium.ConstantProperty(true);
polygon.outlineColor = new Cesium.ConstantProperty(Cesium.Color.BLACK);
wyoming.polygon = polygon;

viewer.entities.add(wyoming);

使用属性是因为Entity API不仅可以表示常量值,还可以表示随时间变化的值。 请参阅 Callback PropertyInterpolation Sandcastle examples,以了解一些动态属性。


Resources

查看 Cesium Workshop 教程,以获取有关如何使用GeoJSON和CZML设置样式和创建实体的示例。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

高建伟-joe

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

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

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

打赏作者

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

抵扣说明:

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

余额充值