据我所知,通过画布,SVG和Flash可以实现3种特定的选择。
如果Flash可以在Apple上运行,它似乎是最好的解决方案iphones / ipads似乎提供了最快的渲染和最干净的显示。画布似乎是第二好的选择,但是如果在地图上显示数百个多边形,则花很长时间,而SVG需要更长的渲染时间。
我几乎没有希望找到解决这个问题的方法了但今天我遇到了一家名为GISCloud的公司http://www.giscloud.com(目前处于免费注册测试阶段)。
这家公司的SOMEHOW设法找出了一种惊人的方式来渲染数百个地图上的实时向量。我对他们的方法感到惊讶,我对社区的疑问涉及我们如何复制他们的方法以与现有技术一起使用,例如传单,开放层,蜡...
通过查看来看看自己这个惊人的演示:
http://www.giscloud.com/map/284/africa
确保将鼠标悬停在页面上的任何多边形上,并测试缩放控件以查看这些多边形确实是矢量。
通过查看带有Firebug的请求,我注意到,该地图正在请求特定的json文件。似乎根据缩放级别/区域,有多个json文件被请求。
我还要在这里提到,一旦giscloud将数据加载到页面上,将鼠标悬停在矢量上会立即更改颜色而不创建新请求。
示例:
http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/ 3 / 3.json
http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/5/3.json
http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/4/4.json
http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/3 /4.json
http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/5/4.json
我假设url结构遵循标准平铺服务逻辑(例如,第3个到最后一个文件夹为缩放级别...)。
无论如何,我已经分析了这些json文件的实际数据,似乎它们使用的逻辑如下它们仅根据以下数据值创建矢量的某种逻辑:
width / height:它们定义每个数据中所服务数据的宽度和高度
json请求
pixels:在这里它们定义了我正在定义的像素值
假设与某种通用的x / y像素坐标有关,这些像素值是广义点级别的?我猜他们会以某种方式根据缩放级别自动简化区域。我
假设他们使用像素坐标,我猜它们正在
与经纬度数据相比,大大减少了需要加载的数据大小。
/>样式:这里定义了两个RGB css
值。 “ F”代表多边形文件的颜色,“ S”代表多边形的边界颜色。
geom:这是我猜测它们
定义特定多边形的地方在正在加载的
切片中,根据地图
容器窗口定义此类数据。有趣的是,每个条目都有一个“ S”
值,我假设该值用作可选属性或要素
链接值,并且在每个条目的末尾都有一个
似乎定义了特定的每个矢量ID以及层ID
,我猜这是用来以某种方式将来自每个被调用的
我还假设他们以某种方式找到了一种方法,可以根据需要为请求的图块加载的数据大小,自动确定并拆分每个图块需要加载的数据。
以下是其中一个请求的摘要:
{"width":256,"height":256,"tile":
{"pixels":
[0,6461,-1,0,5,148,0,509,-1,10715,-1,1,-1,251,-1,1,-1,1,-1,251,-2,3,-1,255,-1,249,-2,5,-2,247,-1,509,-3,251,-1,2,-2,253,-2,252,-2,254,-1,255,-1,254,-1,255,-1,1276,-2,13,-1,233,-1,2,-1,253,-1,1,-1,255,-1,247,-1,1306,-1,1533,-1,1269,-1,1276,-1,2303,-1]},
"styles":
[{"f":"rgb(99,230,101)","s":"rgb(5,148,0)","lw":"0"}],
"geom":
[
{"s":0,"p":[4,143,5,144,3,146,1,146,2,143,4,143],"c":"layer1156_5098"},
{"s":0,"p":[-2,143,0,140,2,141,2,144,1,146,-2,144,-2,143],"c":"layer1156_5067"},
{"s":0,"p":[7,143,5,144,4,143,2,143,2,141,5,138,6,139,5,141,7,143],"c":"layer1156_5051"},
{"s":0,"p":[10,141,11,137,12,137,14,137,12,142,9,143,9,142,10,141],"c":"layer1156_5041"},
{"s":0,"p":[1,136,0,140,-2,143,-2,136,1,136],"c":"layer1156_5038"},
{"s":0,"p":[8,143,5,141,5,137,8,136,10,137,10,141,8,143],"c":"layer1156_5033"},
{"s":0,"p":[5,137,2,141,0,140,1,136,1,136,2,135,3,136,5,137],"c":"layer1156_5028"},
{"s":0,"p":[10,134,12,136,11,138,8,135,10,134],"c":"layer1156_5020"},
{"s":0,"p":[-2,133,0,136,-2,136,-2,133],"c":"layer1156_5005"},
{...}
...
]
}
我们如何使用Postgis复制相同(或相似)速度类型(我该怎么做?他们似乎也在使用)?
#1 楼
我已经看到了过去使用的这种技术。 Zain Memon(来自Trulia)向我解释了这一点,他在Michal Migurski创建TileStache时提供了一些帮助。 Zain在一次较早的SF GeoMeetup会议中解释了使用此技术的Trulia演示时,仔细研究了它。实际上,如果您下周在SF(这是我la脚的尝试,他会尝试解决,请随时露面:)确定,现在开始解释。
首先,当您查看上面的json文件时,您看上去在错误的位置。
让我解释一下(为什么可以),为什么。
这些瓦片正像常规渲染的瓦片一样通过,在那里没什么大不了的,我们知道该怎么做,所以我不需要解释。
如果您在Firebug,您会看到还得到了一堆看起来像是空白的图像,就像这样。
为什么空白?它不是。像素包含数据-只是不包含传统的可见图像数据。他们正在使用一种非常聪明的技术来传递像素本身编码的数据。
过去十年来,人们一直在以牺牲格式的可读性和可移植性数据为代价来取舍存储效率。
以xml示例数据的示例为例:
<data>
<feature>
<point>
<x> -32.1231 </x>
<y> 10.31243 </y>
</point>
<type>
sold
</type>
</feature>
<feature>
<point>
<x> -33.1231 </x>
<y> 11.31243 </y>
</point>
<type>
available
</type>
</feature>
</data>
好,要传输多少位?前提是我们是utf8(处理此内容时每个字符1个字节)。好吧,我们大约有176个字符(不包括制表符或空格),这使这176个字节(出于各种原因,我对此很乐观,为简单起见,我将省略它)。请注意,这是2分!
仍然,一些不懂他在说什么的聪明驴子,在某处会声称“ json给您更高的压缩率”。
好吧,让我们将与json相同的xml废话放进去:
{ "data": [
"feature" : { "x" : -32.1231, "y" : 10.31243 , "type": "sold" },
"feature" : { "x" : -33.1231, "y" :11.31243, "type": "avail" },
]
}
这里有多少字节?说约115个字符。我什至作弊了一点,然后变小了。
说我的区域覆盖256x256像素,并且我处于较高的缩放级别,以至于每个要素渲染为一个像素,而且我拥有如此多的要素,它已经满了。我需要多少数据才能显示65,536个功能?
每个“功能”条目的54个字符(或utf字节-我什至忽略了其他东西)乘以x 65,536 = 3,538,944或大约3.3MB
我想您已经明白了。
但这就是我们在面向服务的体系结构中传输数据的方式。可读的肿废话。
如果我想以自己发明的二进制方案传输所有内容,该怎么办?说相反,我将该信息编码为单波段图像(即黑白图像)。我决定0表示已售出,1表示可用,2表示我不知道。哎呀,在1个字节中,我有256个可以使用的选项-在此示例中,我仅使用其中的2个或3个。
那的存储成本是多少? 256x256x 1(仅一个频段)。 65,536字节或0.06MB。而且这甚至都没有考虑到我从数十年的图像压缩研究中免费获得的其他压缩技术。
此时,您应该问自己,为什么人们不仅仅发送数据编码为二进制格式,而不是序列化为json?嗯,首先,事实证明,JavaScript在传输二进制数据上花了很多时间,因此这就是为什么人们从历史上就没有这样做过。
当HTML5的新功能出现时,一些人已经使用了很棒的解决方法出来了,特别是帆布。那么,这是什么很棒的解决方法?事实证明,您可以通过编码在看起来像图像上的电线来发送数据,然后可以将该图像推送到HTML5 Canvas中,从而可以直接操作像素!现在,您可以获取数据,在客户端将其解码并在客户端中生成json对象。
停下来思考一下。
您有一种方法可以以高度压缩的格式编码大量有意义的地理参考数据,其大小比Web应用程序中传统上做的其他任何事情都要小,并在javascript中对其进行操作。
甚至不需要使用HTML canvas进行绘制,它仅用作二进制解码机制!
这就是全部您在Firebug中看到的那些图像是关于的。一个图像,其中包含为下载的每个单个图块编码的数据。它们非常小,但它们具有有意义的数据。
那么如何在服务器端对它们进行编码?好吧,您确实需要在服务器端对数据进行概括,并为每个已编码数据的缩放级别创建一个有意义的图块。当前,要执行此操作,您必须自己动手-不存在现成的开源解决方案,但是您拥有执行此操作所需的所有工具。 PostGIS将通过GEOS进行归纳,TileCache可用于缓存并帮助您触发图块的生成。在客户端,您将需要使用HTML5 Canvas传递特殊的“假图块”,然后您可以使用OpenLayers创建真正的客户端javascript对象,这些对象代表具有鼠标悬停效果的矢量。
如果需要编码更多数据,请记住,您始终可以为每个像素生成RGBA图像(这样可以为每个像素提供4个字节,或者每个像素可以代表4,294,967,296个数字)。我可以想到几种使用方法:)
更新:回答以下QGIS问题。
与大多数其他桌面GIS一样,QGIS没有固定的缩放级别集。它们具有任意缩放比例和仅渲染的灵活性。他们可以显示来自WMS或基于图块的来源的数据吗?当然可以,但是在大多数情况下,它们确实是愚蠢的:缩放到不同程度,计算边界框,计算所需的平铺,抓取并显示它们。在大多数情况下,他们会忽略其他事情,例如将使之成为标头的HTTP标头缓存,因此他们不必进行重新提取。有时,他们实现了一种简单的缓存机制(存储磁贴,如果您要的话,请检查磁贴,而不要使用它)。但这还不够。
使用这种技术,需要在每个缩放级别重新提取图块和矢量。为什么?因为矢量已被通用化以适应缩放级别。
就将图块放到HTML5画布上以便您可以访问缓冲区的整个技巧而言,整个过程不是必需的。 QGIS允许您使用Python和C ++编写代码,这两种语言都对处理二进制缓冲区提供了出色的支持,因此,此解决方案对于此平台而言确实无关紧要。
* UPDATE 2 **:
首先存在一个关于如何创建通用矢量图块的问题(在将结果序列化为图像之前,请先进行第1步)。也许我还不够澄清。 Tilestache将允许您在每个缩放级别上为数据创建有效的“矢量图块”(它甚至具有一个选项,允许您在通过图块边界时剪切或不剪切数据)。这需要将向量分成各种缩放级别的图块。我会选择“不剪辑”选项(但是它将选择覆盖更多区域的任意图块)。然后,您可以通过GEOS一般化选项为每个向量提供大量的数字,实际上,您希望它足够大,以使折线和多边形折叠到其自身上,因为如果这样做,则可以将它们从缩放级别中移除,因为在该阶段它们是不相关的。 Tilestache甚至允许您编写简单的pythonic数据提供程序,您可以在其中放置此逻辑。在那个阶段,您可以选择将它们作为json文件(就像它们对某些非洲地图样本所做的那样)或作为序列化的几何图形服务到png中,就像它们在我上面给出的其他样本(或Trulia样本)中一样。 br />
评论
到目前为止,我见过的使用此技术的每个人都尚未发布代码。恕我直言,因为重要的部分实际上是在服务器上发生的,因此没有“标准”,并且因为选择每个像素的含义(1 =已售,2 =可用等)对于您的当前地图而言是如此特定,因此此代码是最有可能不是“通用”。
–拉吉·亚瑟(Ragi Yaser Burhum)
2011-10-20 15:21
至于QGIS,答案涉及更多,我将在工作方式上更新我的答案。不要害怕,我坐火车,所以在为我回复GIS.SE时不要开车:)
–拉吉·亚瑟(Ragi Yaser Burhum)
2011-10-20 15:34
+1感谢您不压缩此可读性很强的响应:)
– Kirk Kuykendall
2011年10月20日16:49
您可以确定使用Silverlight或Flash进行此操作。不过,请记住,重要的部分正在服务器上发生,因此Flash或Silverlight不会有太大帮助。
–拉吉·亚瑟(Ragi Yaser Burhum)
2011年10月20日在20:44
四年后,发生了许多事情,这个文本框只有500个字符来解释。总结是,WebGL是成熟的,并且除了序列化技术之外,人们还一直在以Topojson之类的格式应用固定精度的增量编码(就像我们在60年代使用的那样)。这是一件好事。我很乐意以OGC的标准来查看其中的一些内容……不过,最近OGC周围的政治非常复杂。这是我两年前的感受:blog.burhum.com/post/50036141569/the-ogc-is-stuck-in-1999
–拉吉·亚瑟(Ragi Yaser Burhum)
15年11月20日在19:56
#2 楼
直接由开发人员Dino Ravnic在最近的邮件列表中发布的:我们如何做到这不是一个秘密,所以我很乐意与您分享。关键在于两件事:
从图块中删除所有较小的可见矢量
,即,以像素为单位计算的面积小于1px。因此,我们
删除了这样的向量,而不是放置一个像素,因此在我们的json磁贴中有
“ pixels”属性
可以实际看到的向量得到了一般化,
然后将其坐标以像素为单位写入图块
在客户端,我们在画布上渲染这些静态像素和可见的
向量。在向量之上,我们实现了鼠标事件处理以实现悬停(即交互)。就是这样。
我们的后端地图引擎完成了所有繁重的工作,因为我们不使用任何预缓存,并且所有瓦片都在实时生成。拥有可以快速刷新的地图对我们来说非常重要。
因此,听起来客户端很容易。令人印象深刻的是,无需任何缓存即可呈现数据。
他还提到了您可能感兴趣的托管服务。您可能要权衡尝试重新创建它的成本和使用现成服务的成本。
评论
让我感到困惑的部分是,似乎请求被发送到了postgis,而不是获得带有经纬度值的标准geojson,它们似乎是(实时地)将经纬度值转换为xyz坐标并将其吐出根据所需的缩放级别和地图图块。你们认为用来获得这些速度的是什么?
– NetConstructor.com
2011年10月9日14:47
@netconstructor也许几何体已经存储在xyz几何体中,所以不需要转换?
– geoographika
2011-10-12 18:58
相对xyz坐标可能比需要较少带宽的相对纬度/经度短。
–马修·斯内普(Matthew Snape)
2011年10月19日在17:28
是的,但是他们正在即时转换数据
– NetConstructor.com
2011-10-25 9:25
#3 楼
正如我在OSGeo列表中所述,关键是将数据作为矢量JSON切片传递,这些切片具有用于子像素几何的像素和用于那些在特定级别上实际可见的特征的广义几何。性能非常好,因为该技术消除了所有不必要的矢量信息,只保留了那些实际上会对地图产生视觉影响的矢量。像素在那里填补空白并被放置,而不是放置那些子像素向量。关于图块格式就是这样。后端是真正的重物。我们没有使用TileStache或任何其他地图引擎,因为我们编写了自己的引擎,可以进行许多优化,以实时生成此类矢量图形。
首先,我们开始将地图图块作为SWF交付。最近,我们仅启用了对JSON的输出,因此我们可以使用HTML5 Canvas渲染图形。您可以找到一个基准,将这种矢量技术与栅格技术(mapnik)进行比较。为了公平比较,请仅在CGI模式下查找结果。
http://www.giscloud.com/blog/realtime-map-tile-rendering-benchmark-rasters-vs-vectors/
我们正计划提供这项技术,作为地图图块托管服务。想法是将您的地理数据托管在云上,并通过HTML5将其高速传输到任何地图客户端中,而无需预先缓存图块。如果您有兴趣加入此Beta,请随时与我们联系:http://www.giscloud.com/contact/
评论
将图块用于矢量数据的想法非常有趣(它看起来像是“空间索引”的另一种说法)。您如何处理跨越多个图块的要素?他们被割了吗?
–朱利安
2011年10月21日10:10
是的,矢量贴在瓷砖上
–迪诺·拉夫尼奇(Dino Ravnic)
2011年10月21日在10:22
#4 楼
看起来最近在OSGeo开放层论坛上提出了一个非常相似的问题,GIS云开发人员描述了他们的方法,这是GeoJSON几何形状和静态像素的有趣组合。实际上,它们实际上是在动态生成所有矢量图块,而不是使用预先构建的GeoJSON文件缓存。Esri使用ArcGIS Server和要素图层实现了类似的方法,可以在飞行并将其作为JSON通过网络发送。
对于现在可以实际实现的简单方法,您可以使用Tilestache(支持PostGIS)构建矢量图块,然后将其使用在Polymap中。 Polymaps使用SVG,但是性能非常好,并且CSS规则可以对地图元素进行样式设置,因此要素渲染完全取决于您。这是一篇博客文章,其内容与您的要求类似。
评论
@wwnick-感谢您的回答,但是GisCloud.com似乎正在利用一些其他方法,这些方法使他们具有惊人的处理能力,而不必缓存元素,这意味着一切都是实时的。我为这个问题添加了一笔赏金,希望您可能愿意参与提供深入的解决方案。到目前为止,感谢您的回复!
– NetConstructor.com
2011年10月19日下午4:13
#5 楼
我在使用Canvas的OpenLayers上玩了游戏,并获得了合理的结果。如其他答案中所述:实时传递和显示矢量-需要针对每个缩放级别和每个数据集将其通用化。另外,您可以使用Google折线编码来大幅缩减尺寸。
我使用了一种简单的投放机制。每个几何都是JavaScript HTTP响应中的JavaScript函数。
,它不像基于图块的矢量交付那样先进,而是简单且开源!我没有尝试使用Canvas尝试使用Google Maps v3,但是看到了《纽约时报》的几个演示给人留下了深刻的印象。 br />
评论
这种方法的问题在于,在处理500,000个多边形时,它的速度通常不及其解决方案的速度,即性能确实很差
– NetConstructor.com
2011年10月9日14:49
请注意增加的赏金,如果可以的话,请提供详细的解决方案。顺便说一句,《纽约时报》非常酷,但是却利用giscloud.com使用的解决方案来利用闪存。
– NetConstructor.com
2011年10月19日下午4:30
您的链接离线
– NetConstructor.com
2012年3月28日在7:38
是的,对此感到抱歉-经过4年的多边形修补后,我的“爱好”已经结束! GISCloud向您展示了自几年前进行人口普查演示以来该技术已经走了多远...在上面的评论中,我已删除了对该技术的引用。
–减34
2012年4月3日,下午1:36
迟到总比不到好!我已将事情更新为尽可能“开箱即用”,并将客户端代码发布在GitHub上。新代码的设置已发布。现在,它可以直接从PostGIS中直接读取多边形,并通过PostGIS RESTful Web服务框架(PRWSF)即时将细化应用到Leaflet Javascript API客户端。几乎不需要后端编码!
–减34
2012年6月4日10:12
#6 楼
我不确定该公司使用哪种解决方案(您可能会直接问他们),但我有个主意。提高矢量数据网络传输和渲染速度的关键解决方案是根据缩放级别对其进行归纳:在高缩放级别下传输和渲染成千上万个为低缩放级别设计的对象通常非常耗时(并且也无用,因为最终的显示效果通常不清晰-例如,参见此图) 。为此,您的postgis服务器数据库必须是多尺度的:对于每个缩放级别,应该有一个适合该缩放级别的对象表示。可以使用归纳技术自动计算这些不同的表示形式。此外,服务器发送给客户端的矢量数据不仅应取决于空间范围,还应取决于缩放级别:服务器根据缩放级别发送合适的数据。这就是这篇优秀论文所捍卫的方法:-)
#7 楼
由Stanford Visualization Group开发的有趣的论文,演示和软件源代码,每个数据块都使用datacube,以便可视化和探索大型地理数据集。它只能用于点数据集,但可以是一种有趣的方式。
http://vis.stanford.edu/papers/immens
Vizzuality的CartoDB平台和名为Torque的库也在尝试如何绘制大量数据。
http://cartodb.github.io/torque/https://github.com/CartoDB/torque/tree/new_torque
评论
啊!不要查看JSON文件,而是查看其他似乎无关紧要的图像:)请参阅下面的答案。“有3种特定的选择” ...那么,切碎的肝是Silverlight吗?
Silverlight需要它的插件才能工作,我认为它实际上没有比giscloud使用的解决方案快,但是我没有做任何直接比较。
这个问题提出了很多有趣的问题,这些问题与通常的问答形式不符。让我们在“在Web Map World中使用向量”中讨论它们
@RagiYaserBurhum对于如何使用类似技术将其用于旅行等时线映射进行了很好的解释:mysociety.org/2012/11/08/…