使用区域

区域是一个强大的 KML 地图项,可让您向 Google 地球添加大型数据集,而不会降低性能。只有当数据位于用户视图内且占用一定的屏幕部分时,系统才会加载并绘制该数据。使用区域,您可以为数据提供单独的细节级别,因此仅当数据占用了足够显示细节的屏幕部分时,系统才会加载微妙的细节。

重要概念

任何地图项都可以包含区域。区域会影响地标几何图形或叠加层图片的可见性。区域定义了受影响的几何图形或叠加层的剔除和细节级别行为。区域通过 KML 层次结构继承,并影响层次结构中定义较低的地图项的可见性。

本部分介绍了下面这些理解区域所必须掌握的重要概念:

继承

在 KML 中,某些类派生自“基”类。派生的类继承其基类的所有元素,并添加了某些自己的特有元素(这是面向对象的系统常用的技术)。为方便起见,本部分只介绍基类,没有列出所有的派生类。例如:

  • 术语 Feature 指派生自 Feaure 的任何 KML 元素:Document、Folder、GroundOverlay、NetworkLink、PhotoOverlay、Placemark 和 ScreenOverlay。
  • Geometry 指 KML 中的任何几何元素:Point、Polygon、LinearRing、LineString、Model 和 MultiGeometry。
  • Overlay 指派生自 Overlay 的元素:GroundOverlay、PhotoOverlay 和 Screen Overlay。

有关显示 KML 元素内继承的图表,请参见 KML 参考

边框

区域具有用于定义数据边框的 <LatLonAltBox>。边框是包括一组对象或数据点的范围。与 GroundOverlay 中的 <LatLonBox> 类似,区域中的 <LatLonAltBox> 具有北 (North)、南 (South)、东 (East) 和西 (West) 边界。如果区域包含的数据为3D或2D海拔,那么该区域的 <LatLonAltBox> 还需要包含最低海拔 <minAltitude> 和最高海拔 <maxAltitude>。

当 (1) 区域出现在视图中 (2) <LatLonAltBox> 的投影屏幕大小位于该区域指定的像素范围内(如细节级别 (LOD) 中所述)时,将绘制与此边框关联的对象。符合这两个条件时,区域即视为“活动的”。

细节级别 (LOD)

与区域关联的次要概念是细节级别,简称 LOD。由于计算机屏幕的空间有限,因此最有效的方法是激活区域,从而只在像素足以充分显示数据时才加载大量数据。当区域占用相当小的一部分屏幕(可能因为用户正在从远处查看,或从倾斜角度查看平面区域)时,LOD 机制可让您(KML 编写者)指定低分辨率的数据集来替代全分辨率数据。该低分辨率数据集的加载速度更快,但由于它还是占用了一小部分屏幕,因此用户可能无法辨别其差异。

在区域中,<minLodPixels> 和 <maxLodPixels> 元素可让您指定屏幕的区域(以方形像素为单位)。当数据投影到屏幕上时,所占用的屏幕区域必须大于 <minLodPixels> 且小于 <maxLodPixels>,投影才能显示。区域的投影大小超出这些限制后,投影将不再可见,区域会变为非激活状态。

在特殊情况下,当您希望数据激活到无限大时,可以为 <maxLodPixels> 指定−1(默认值)。

示例1:地面叠加层的区域

首先,让我们看看在地面为2D叠加层构建区域的简单示例。此示例使用包含历史数据的地面叠加层,显示1991年加利福尼亚州山景城的一部分。当用户放大该区域时,即会显示叠加层。下面是叠加层首次显示时的外观(示例文件还包含可让叠加层更加明显的白色 LineString):

在此示例中,<minLodPixels> 为128,表示当 GroundOverlay 占用屏幕上128个方形像素时开始显示(此示例对 <maxLodPixels> 使用默认值-1,这表示当用户在此角度放大时,GroundOverlay 仍然可见)。用于该叠加层的图片是256个方形像素的正方形。

下面是用户放大后显示的图片:

此处是因占用的屏幕空间小于 <minLodPixels> 值而变得不可见之前显示的倾斜图片:

此数据的 <LatLonAltBox> 不需要包含 <minAltitude> 和 <maxAltitude> 元素,因为该数据是地面的扁平数据。该区域的 <LatLonAltBox> 中的数据边框等同于地面叠加层的 <LatLonBox> 的边界,如以下 KML 文件所示:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>Flat Region</name>
<Region>
<LatLonAltBox>
<north>37.430419921875</north>
<south>37.41943359375</south>
<east>-122.080078125</east>
<west>-122.091064453125</west>
</LatLonAltBox>
<Lod>
<minLodPixels>128</minLodPixels>
</Lod>
</Region>
<GroundOverlay>
<name>Mountain View DOQQ</name>
<Icon>
<href>files/image.JPEG</href>
</Icon>
<LatLonBox>
<north>37.430419921875</north>
<south>37.41943359375</south>
<east>-122.080078125</east>
<west>-122.091064453125</west>
</LatLonBox>
</GroundOverlay> </Document> </kml>

另请注意,在 KML 文件中,该区域类似于可见性受其影响的图片(或几何图形)。

您有时间检查该 KML 文件的话,请点击以下链接将叠加层加载到 Google 地球。然后,根据区域要求的屏幕区域大小,尝试不同的视点,并查看该区域何时出现和消失。请注意,如果您将视图倾斜得足够远或者将视图缩小到非常小,该叠加层就会消失,因为它占用的屏幕空间太小而无法符合 <minLodPixels> 要求。

Google 地球中的视图示例 (historicOverlay.kmz)

海拔

示例2:3D模型的区域

以下示例显示如何在地面构建一个包含3D对象的区域。该区域的 <LatLonAltBox> 包含一个300米的 <maxAltitude>,该元素为建筑物的高度。您很可能会将这些建筑物视为纽约城里的联合国复合建筑。

请注意,该区域的 <LatLonAltBox> 的边界不必与模型的经纬度完全匹配,这点很重要。模型的坐标是相对于其本地原点而言的,可能与地球上模型的实际位置存在偏移。

<?xml version='1.0' encoding='UTF-8'?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>3D Region on ground</name>
<Placemark>
<name>United Nations Headquarters</name>
<visibility>0</visibility>
<Region>
<Lod>
<minLodPixels>128</minLodPixels>
</Lod>
<LatLonAltBox>
<north>40.750683130314</north>
<south>40.748162385230</south>
<east>-73.966608428427</east>
<west>-73.969476624071</west>
<minAltitude>0</minAltitude>
<maxAltitude>300</maxAltitude>
<altitudeMode>absolute</altitudeMode>
</LatLonAltBox>
</Region>
<Model>
<altitudeMode>absolute</altitudeMode>
<Location>
<longitude>-73.967763927199</longitude>
<latitude>40.749458312255</latitude>
<altitude>0.406173708576</altitude>
</Location>
<Link>
<href>models/un.dae</href>
</Link>
</Model>
</Placemark>
</Document>
</kml>

点击以下链接将文件加载到 Google 地球。再次尝试不同的视点,查看建筑何时变得可见,何时从视图中消失。

Google 地球中的视图示例 (unitedNations.kmz)

示例3:指定海拔的2D叠加层的区域

此示例显示如何添加要在地球表面上以指定海拔显示的2D叠加层。此技术对于显示锋面和空中交通方式的数据很有用。以下示例显示了海拔为100,000米(以海平面为基准)的一小片云层。

该区域的 <LatLonAltBox> 将 <minAltitude> 和 <maxAltitude> 元素的值均指定为100,000米(由于叠加层是没有厚度的2D图片,因此两个元素的值是相同的)。<altitudeMode> 为 absolute,表示该值是相对于海平面的。

请注意,GroundOverlay 的 <altitude> 值也是100,000(也就是说,它与该区域的边框的高度值匹配),GroundOverlay 的 <altitudeMode> 与该区域的 <altitudeMode> 的指定值匹配。

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>Flat Region at altitude</name>
<GroundOverlay>
<name>Cloud overlay</name>
<Region>
<LatLonAltBox>
<north>33.75</north>
<south>22.5</south>
<east>-45</east>
<west>-56.25</west>
<minAltitude>100000</minAltitude>
<maxAltitude>100000</maxAltitude>
<altitudeMode>absolute</altitudeMode>
</LatLonAltBox>
<Lod>
<minLodPixels>128</minLodPixels>
</Lod>
</Region>
<Icon>
<href>files/image.PNG</href>
</Icon>
<altitude>100000</altitude>
<altitudeMode>absolute</altitudeMode>
<LatLonBox>
<north>33.75</north>
<south>22.5</south>
<east>-45</east>
<west>-56.25</west>
</LatLonBox>
</GroundOverlay>
</Document>
</kml>

Google 地球中的视图示例 (cloudRegion.kmz)

淡变范围

您还可以为区域指定淡变范围,从而允许对象逐渐从透明过渡到不透明以及反向过渡。Google 地球使用“maxFadeExtent”来确定区域处于最大可见度时从完全透明到完全不透明的梯度,使用“minFadeExtent”来确定区域处于最小可见度时的淡出梯度。淡变范围是可选的,但它们可阻止不同分辨率的 LineString 或多边形之间的“弹出”效果。淡变效果对性能的影响较大,因此不应与图像一起使用。

请注意:淡变范围可用于除地标图标之外的所有对象。当淡变范围大于0.5时绘制这些图标。

以下示例说明淡变范围是如何影响 LineString 的。

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>Region in Placemark LineString</name>
<description>
The LineString corners mark the extent
of the Region LatLonAltBox.
The LineString minFadeExtent (at greatest range)
is 1/4 of the maxFadeExtent (at closest range)..
</description>
<Placemark>
<name>Region LineString</name>
<LineString>
<coordinates>
22,50,0
28,50,0
28,45,0
22,45,0
22,50,0
</coordinates>
</LineString>
<Region>
<LatLonAltBox>
<north>50</north>
<south>45</south>
<east>28</east>
<west>22</west>
</LatLonAltBox>
<Lod>
<minLodPixels>128</minLodPixels>
<maxLodPixels>1024</maxLodPixels>
<minFadeExtent>128</minFadeExtent>
<maxFadeExtent>512</maxFadeExtent>
</Lod>
</Region>
</Placemark>
</Document>
</kml>

Google 地球中的视图示例 (fadeLineString.kml)

嵌套区域

嵌套区域是区域功能的常用手法,较大的区域使用较粗略的分辨率关联,而较小的内部区域则使用精细度递增的细节级别关联。下图中,每个区域都有一组 LOD 限制,可指定激活关联区域所需的区域投影屏幕大小(以像素为单位)。随着用户视点的逐渐移近,精细度较高的细节级别 (LOD) 的区域会激活,因为此类区域占用的屏幕空间更多。精细度较高的 LOD 的区域会替换以前加载的精细度较低的 LOD 的区域。

随着嵌套区域不断激活,它们可以

  • 收集与每个区域(如以下超级叠加层示例所述)关联的数据
  • 用新数据替换以前加载的区域数据(如上图所示)

子区域中的 <LatLonAltBox> 应完全包含在其父区域的 <LatLonAltBox> 中。区域通过 Folder 和 NetworkLink 层次结构继承。本地定义的区域优先于 Folder 层次结构中定义更高的区域。以下示例说明本地区域范围如何覆盖层次结构中定义更高的区域。在此示例中,地标“ukraineRegion”继承其父文档的区域。文件夹“romaniaFolder”指定自己的区域,供地标“romaniaRegion”使用。有关如何在 NetworkLink 内最高效使用区域的更多示例,请参见下个部分“智能”加载基于区域的网络链接

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>Nested Regions</name> <Region> <LatLonAltBox> <north>56.25</north> <south>45</south> <east>33.75</east> <west>22.5</west> </LatLonAltBox> <Lod> <minLodPixels>128</minLodPixels> <maxLodPixels>1024</maxLodPixels> </Lod> </Region> <Placemark> <name>ukraineRegion</name> <LineString> <tessellate>1</tessellate> <coordinates> 22.5,45,0 33.75,45,0 33.75,56.25,0 22.5,56.25,0 22.5,45,0 </coordinates> </LineString> </Placemark> <Folder> <name>romaniaFolder</name> <Region> <LatLonAltBox> <north>50.625</north> <south>45</south> <east>28.125</east> <west>22.5</west> </LatLonAltBox> <Lod> <minLodPixels>128</minLodPixels> <maxLodPixels>1024</maxLodPixels> </Lod> </Region> <Placemark> <name>romaniaRegion</name> <LineString> <tessellate>1</tessellate> <coordinates> 22.5,45,0 28.125,45,0 28.125,50.625,0 22.5,50.625,0 22.5,45,0 </coordinates> </LineString> </Placemark> </Folder> </Document> </kml>

“智能”加载基于区域的网络链接

前面示例中显示的基于区域的 NetworkLink 是在 Google 地球中发布大型数据集的最有效方式。将区域与 NetworkLink 结合使用,您就可以创建指针层次结构,每个指针指向一个特定子区域。<viewRefreshMode> 有一个 onRegion 选项(如以下 KML 文件所示),用于指定只在区域激活时才加载区域数据。如果您提供了具有多个细节级别的嵌套区域,那么只有当用户视点触发下一次加载时,系统才会加载数量更大的数据。下面的超级叠加层部分提供了详细示例。

第1部分:父文件

要运行此示例,请和往常一样先保存第一部分。然后,将第二部分另存为“romaniaRegion.kml”,以便 NetworkLink 可以在区域激活时加载该区域。

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>Nested Regions</name> <Region> <LatLonAltBox> <north>56.25</north> <south>45</south> <east>33.75</east> <west>22.5</west> </LatLonAltBox> <Lod> <minLodPixels>128</minLodPixels> <maxLodPixels>1024</maxLodPixels> </Lod> </Region> <Placemark> <name>ukraineRegion</name> <LineString> <tessellate>1</tessellate> <coordinates> 22.5,45,0 33.75,45,0 33.75,56.25,0 22.5,56.25,0 22.5,45,0 </coordinates> </LineString> </Placemark> <NetworkLink> <name>romania NetworkLink</name> <Region> <LatLonAltBox> <north>50.625</north> <south>45</south> <east>28.125</east> <west>22.5</west> </LatLonAltBox> <Lod> <minLodPixels>128</minLodPixels> <maxLodPixels>1024</maxLodPixels> </Lod> </Region> <Link> <href>romaniaRegion.kml</href> <viewRefreshMode>onRegion</viewRefreshMode> </Link> </NetworkLink> </Document> </kml>

第2部分:基于区域的 NetworkLink 文件

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>romania Document</name>
<Region>
<LatLonAltBox> <north>50.625</north> <south>45</south> <east>28.125</east> <west>22.5</west> </LatLonAltBox>
<Lod> <minLodPixels>128</minLodPixels> <maxLodPixels>1024</maxLodPixels> </Lod>
</Region> <Placemark> <name>romaniaRegion</name> <LineString> <tessellate>1</tessellate> <coordinates> 22.5,45,0
28.125,45,0 28.125,50.625,0 22.5,50.625,0 22.5,45,0 </coordinates> </LineString> </Placemark>
</Document>
</kml>

超级叠加层

:我如何与全世界分享一张47MB的图片?
:一次分享一部分。

:如果每个人都试图这样做将会怎样?
:如果您使用的是基于区域的 NetworkLink,并像本教程中描述的那样为图像提供了多个细节级别,那么就没问题!

本部分介绍了如何创建“超级叠加层”- 可用来高效服务于大型图像集的区域和 NetworkLink 的层次结构。当图像区域的各部分逐渐可见时,加载分辨率适当的平铺图片;当视点移近时,加载分辨率较高的平铺图片。试图在1024 * 768的屏幕上显示7008 * 6720像素的图片几乎是白费力气。而且,如果用户位于离地球表面几英里的地方,那么所有数据可能都被挤压到少量像素中,这样效果极差。超级叠加层(例如显示加利福尼亚州山景城1991 DOQQ的示例)可让您利用 NetworkLink 及其功能来确定 (1) 给定区域是否在视图中 (2) 投影大小是否适合当前视点。如果区域为“活动的”(两个条件都符合),那么 NetworkLink 会加载该区域的相关数据。如果区域不是活动的,则不加载数据。如果将原始图片细分为细节级别递增的层次结构图片,Google 地球就可加载最适合当前视图的图像。

要查看如何使用该图片层次结构,请将此示例文件加载到 Google 地球中,并在相关区域上通过放大和缩小来进行尝试:山景城历史 DOQQ

使用基于区域的网络链接高效加载大型数据集的示例。原始图片为7008 * 6720像素。此处显示的斜视图只加载五个小的平铺图片来表示该图片(已添加白色 linestring 来突出平铺图片边界)。该应用显示代表山景城的历史图像 (1991 DOQQ)。

为超级叠加层准备数据

在该超级叠加层示例中,原始山景图片细分为上百个小的 GroundOverlay。这些叠加层或平铺图片分布在五层的层次结构中。出于示范目的,此处的讨论使用简单的三层层次结构和一组叠加层(共21个),但相关原则保持不变。请注意,这只是创建基于区域的网络链接层次结构的一种方法,还有其他方法可以实现此机制。

要创建超级叠加层,您需要执行以下操作:

  1. 准备图像,将其细分为可管理的块(推荐使用256 * 256像素的图像),
  2. 创建设置区域、链接、网络链接以及此示例中包含 GroundOverlay 的文件的 KML 文件。

准备图像

为平铺图片(具有不同分辨率的细分图片)选择一个标准大小,Google 地球将会在其相关区域激活时加载这些图片。出于示范目的,我们将对平铺图片使用256 * 256像素,这是可管理的最小像素。

  1. 从具有完整分辨率的原始图片开始。将该图片细分为n张平铺图片,然后将其中每张平铺图片再细分为n张平铺图片。
    继续细分直到获得给定大小(在我们的示例中,为256 * 256像素)的平铺图片。

    让我们假定原始图片为1024 * 1024像素。
    当我们细分图片时,将产生以下层次结构。

     

  2. 将该层次结构中的每张平铺图片重新采样为您选择的标准大小(例如256 * 256像素)。
    这些重新采样的平铺图片的细节级别更低,但与在更远处视点激活的区域相关联,
    因此用户感觉不到细节方面的损失。

下表显示了视点和嵌套区域的定义是如何确定实际加载哪些平铺图片的。同时,为此大型图像示例提供了三个细节级别。当用户从最远处观看该区域时,Google 地球会显示缩略图视图。此视图覆在整个 LatLonAltBox 上(但由于投影很小 - 256个方形像素,因此实际上视觉信息不会有所损失)。当用户放大该场景时,该区域被细分为四个区域。这四张“平铺图片”中,每张平铺图片的大小都与缩略图图片相同,但提供的图像更加详细。

如果用户继续放大该区域,那么是否会显示完整分辨率图像部分,取决于用户与图像的距离。远处的区域保持最初加载的不十分详细的图像。山景城 DOQQ 示例中,启用“框”并查看地标 AB,这些地标在区域周围使用 LineString 并一次显示层次结构的多个层。

请注意,该示例对所有区域的 minLodPixel 和 maxLodPixel 使用相同值(在层次结构的所有层)。LatLonAltBox 决定应该加载层次结构中的哪些层以及在区域中加载哪些平铺图片。

准备 KML 文件

为每张图片准备一个 KML 文件,将地面叠加层与区域和 NetworkLink 关联起来。此集合中的每个 KML 文件都具有以下元素:

  • 区域(包含 LatLonAltBox、minLodPixel 和 maxLodPixel,以便 Google 地球可以确定该区域是否在任何给定时间都是活动的)
  • 链接到子文件(层次结构的下一层中的平铺图片)的一组 NetworkLink
  • 该区域的地面叠加层

此示例显示山景城 DOQQ 示例的最高层 KML 文件。对于 maxLodPixel,它会指定-1,这具有“激活到无限大”的特殊含义。如果不指定此值,整个层次结构可能永远无法触发。

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<NetworkLink>
<name>SuperOverlay: MV DOQQ</name>
<Region>
<LatLonAltBox>
<north>37.44140625</north>
<south>37.265625</south>
<east>-121.9921875</east>
<west>-122.16796875</west>
</LatLonAltBox>
<Lod>
<minLodPixels>128</minLodPixels>
<maxLodPixels>-1</maxLodPixels>
</Lod>
</Region>
<Link>
<href>http://mw1.google.com/mw-earth-vectordb/kml-samples/mv-070501/1.kml</href>
<viewRefreshMode>onRegion</viewRefreshMode>
</Link>
</NetworkLink>
</kml>

以下文件显示山景城 DOQQ 示例中的区域 (179.kml)。此文件包含五个 href 标签:四个指向图片层次结构下一层中的四个 KML 文件,一个指向此平铺图片的 GroundOverlay 所用的图片文件。

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<Region>
<Lod>
<minLodPixels>128</minLodPixels><maxLodPixels>-1</maxLodPixels>
</Lod>
<LatLonAltBox>
<north>37.430419921875</north><south>37.41943359375</south>
<east>-122.091064453125</east><west>-122.10205078125</west>
</LatLonAltBox>
</Region>
<NetworkLink>
<name>001120</name>
<Region>
<Lod>
<minLodPixels>128</minLodPixels><maxLodPixels>-1</maxLodPixels>
</Lod>
<LatLonAltBox>
<north>37.430419921875</north><south>37.4249267578125</south>
<east>-122.0965576171875</east><west>-122.10205078125</west>
</LatLonAltBox>
</Region>
<Link>
<href>180.kml</href>
<viewRefreshMode>onRegion</viewRefreshMode>
</Link>
</NetworkLink>
<NetworkLink>
<name>001121</name>
<Region>
<Lod>
<minLodPixels>128</minLodPixels><maxLodPixels>-1</maxLodPixels>
</Lod>
<LatLonAltBox>
<north>37.430419921875</north><south>37.4249267578125</south>
<east>-122.091064453125</east><west>-122.0965576171875</west>
</LatLonAltBox>
</Region>
<Link>
<href>185.kml</href>
<viewRefreshMode>onRegion</viewRefreshMode>
</Link>
</NetworkLink>
<NetworkLink>
<name>001122</name>
<Region>
<Lod>
<minLodPixels>128</minLodPixels><maxLodPixels>-1</maxLodPixels>
</Lod>
<LatLonAltBox>
<north>37.4249267578125</north><south>37.41943359375</south>
<east>-122.0965576171875</east><west>-122.10205078125</west>
</LatLonAltBox>
</Region>
<Link>
<href>190.kml</href>
<viewRefreshMode>onRegion</viewRefreshMode>
</Link>
</NetworkLink>
<NetworkLink>
<name>001123</name>
<Region>
<Lod>
<minLodPixels>128</minLodPixels><maxLodPixels>-1</maxLodPixels>
</Lod>
<LatLonAltBox>
<north>37.4249267578125</north><south>37.41943359375</south>
<east>-122.091064453125</east><west>-122.0965576171875</west>
</LatLonAltBox>
</Region>
<Link>
<href>195.kml</href>
<viewRefreshMode>onRegion</viewRefreshMode>
</Link>
</NetworkLink>
<GroundOverlay>
<drawOrder>5</drawOrder>
<Icon>
<href>179.JPEG</href>
</Icon>
<LatLonBox>
<north>37.430419921875</north><south>37.41943359375</south>
<east>-122.091064453125</east><west>-122.10205078125</west>
</LatLonBox>
</GroundOverlay>
</Document>
</kml>