ArcGIS客户端API中加载大量数据的几种解决办法
2011-03-25 18:17

REST风格的一切事物方兴未艾,ArcGIS Server的客户端API(Javascript/Flex/Silverlight API)也逐渐站上了GIS舞台的中央。虽然客户端API给我们带来了更快捷的开发体验,更丰富的展现效果,但有些(奇怪的)需求还不能直接解决。比如要求在客户端API程序中显示大量图形(上万个),乍看之下,受到平台本身的性能制约无法完成,但我们的思维和时间一样,只要挤一挤,总还是有的。本文就来讨论一下如何在客户端API程序中显示大数据量图形的问题。以Silverlight API为例。

要将几何对象显示在客户端程序中,一般我们首先想到的办法就是GraphicsLayer。将服务器端的要素通过查询或者其他方式创建成客户端的Graphic用以显示,从而进一步交互。于是有了下面几种方法。

1、Cluster

比较成熟和理智的做法是,利用Cluster效果来处理大量的Graphic。对于这种办法,ArcGIS Server中的Javascript APIFlex APISilverlight API均能做到。下图是Silverlight API中300,000个点的展示效果。(忽略数据从服务器到客户端的传输时间)

Google MapsBing Maps等也都采取了这种做法。

但是,不论什么原因,就是不想采用Cluster的办法,而要看到大量密密麻麻的点时心里才觉得踏实该怎么办?对于这种需求,也有对应的解决方案。

2、直接在前台绘制Graphic

但这种办法直接受到平台性能的限制。以Flex和Silverlight为例,在不影响地图操作的情况下,视图范围内一次性能够承受的Graphic数量大约是4000-5000个。注意,相对于绘制Graphic对象的操作来说,Geometry节点的个数可以忽略,也就是说这几千个Graphic既可以是点,也可以是面。这时候你的地图看起来是这样的(4000个Graphic):

3、用ElementLayer(Silverlight API独有)来模拟GraphicsLayer

ElementLayer是Silverlight API中独有的一种图层类型,直接继承自ESRI.ArcGIS.Client.Layer,用来承载Silverlight本身的一些布局控件(Framework Element)。它的最主要的用途是使得Silverlight本身的控件能够随着地图的放大缩小而自动变化。利用它我们可以在一定程度上模拟GraphicsLayer。比如Silverlight API中的InfoWindow

GraphicsLayer之所以只能承载一定数目的Graphic,就是因为Graphic对象本身封装的内容比较多。如果我们仅需要展示这些点,并只在上面做一些简单查询,那么可以完全用ElementLayer来替代之。直接的好处就是,可以在客户端显示更多的数据。比如一个点,我们可以用更基本的Ellipse来代替Graphic。将Graphic的Attributes存储在Ellipse.Tag中,依然可以用上面提到的InfoWindow做DataBinding。初步做了一下试验,如果用ElementLayer来模拟GraphicsLayer,在不影响地图操作的情况下,视图范围内一次性能承载的图形个数大约是20,000-25,000个。这时候你的地图看起来像是这样(20,000个Ellipse):

顺便提一下,如果想在ElementLayer中来模拟动态的地图符号,甚至是时态图层也是可以的。对于Graphic,你可以定义Symbol的ControlTemplate;对于ElementLayer,则可以直接将带有任何动画的对象直接加入其中。

上面提到的3种方法都是纯客户端的,尤其第三种办法,再没有更多工作量的情况下已经基本将客户端的性能用到了极致。但对于想看到密密麻麻点的人来说,五位数的数量级很有可能并不能满足要求。要想将展示的图形个数再提高一个或两个数量级,达到几十万甚至上百万,那么只有来借用服务器端的性能了。

4、ArcGISDynamicMapServiceLayer

直接将所要展示的数据在服务器端发布成一个MapService,在客户端通过ArcGISDynamicMapServiceLayer来加载。这样的话客户端需要展示的仅仅是一张图片,没有任何压力。功能上,如果想查询的话可以使用Identify/Find/Query Task来达到目的。下图加载了一个本机的ArcGISDynamicMapServiceLayer(AGS10,msd发布,1个实例,core i7 2.6GHz,4g内存,win7 x64),服务只有一个点图层,记录数大约650,000条:

服务器端生成这张图片的时间大约13s,进行一次IdentifyTask操作时间是0.2s。这里大部分时间都花在了服务器端对数据的绘制上,因此局域网传输图片等因素可以暂不考虑。服务器端的绘制速度受硬件和软件两个方面的影响。以ArcGIS Server 10已经无法改变,理论上只能通过提高硬件配置来达到加快出图速度的目的。

ps:采用ArcGISDynamicMapServiceLayer时可结合服务器端的点抽希办法来一起使用(抽稀方法1抽稀方法2)。但这样就失去了密密麻麻数据带给我们的“成就感”,不在赘述。

这种办法中,客户端的压力已经完全没有了,功能上也能通过变通来实现,但展现上有两个缺点:1、数据过多的话绘制速度太慢(40w条数据大约是6.7s,12w条数据大约是2.3s,3w条数据大约是0.6s,);2、出图过程中该服务一片空白,且移动过程中也会出现“白边”的现象。如果硬件配置也无法提高,还有没有更好的办法呢?办法是有的。

5、继承TiledMapServiceLayer来达到“动态切图”的目的

Google Fusion Tables的例子中,我们可以看到,所有的点数据都是以切片的方式展现,这样的好处是,即使出图速度较慢,用户也能看到切片一个一个的加载过程,不至于长时间一片空白;移动过程中也不会有白边现象;且浏览过的地方都会被客户端缓存,不需要再次向服务器请求,既减少了服务器压力,也加快了显示速度。但明显Google不可能为上传的每张表格都去做切片处理,ArcGIS Server中如何能达到这种效果?

首先想到的是服务切图时的“Cache On Demand”设置。但第一个用户等待的时间就是服务器完成该比例尺下切图的时间,显然太长;并且切图后如果数据有变化,那么看到的切图就和实际数据不一致了。这条路走不通。

通过继承TiledMapServiceLayer,可以利用GetUrl方法来控制如何获取每一个切片。此时如果我们以动态地图服务为资源,利用REST SDK的ExportMap操作来生成每一个切片,就达到了“动态切图”的目的。不仅如此,我们还可以在服务器端发布多个相同的服务,在GetUrl方法中轮询使用这些服务,便可以达到“并行”出图的目的。此时每个服务生成的图片都是256*256大小,所包含的记录数会少很多,速度会明显加快。本机发布3个服务时,同样比例尺下的650,000条记录,所有“切片”加载完成大约需要6s,考虑到缓存服务的加载效果,用户完全可以接受。这种方法相比ArcGISDynamicMapServiceLayer,大大提高了出图的速度和效果。

关于此方法的几点说明:如何利用比例尺、行/列号来计算一个切片的范围,可以参考《ArcGIS Server的切图原理深入》;默认情况下,浏览过的“切片”会缓存在客户端,再次浏览时服务器端就不用动态出图了。如果不想在客户端缓存“切片”,保证服务器端数据发生变化后,客户端也能随时更新,则可以在请求后面加上时间戳,达到DisableClientCache的功能;对于这种数量级的数据展示来说,一般是局域网应用,因此Identify/Find/Query与服务器端的交互完全可以接受;而且通常拥有这种数据量的用户硬件资源一般都是可充分扩展的,因此多发布几个服务来加速出图完全可行。

无图无真相,看看这种办法的效果。别忘了,在服务器端你发布的仅仅是普通的动态地图服务。

好了,这几种方法各有千秋,供各位朋友按需选择。

ArcGIS客户端API中加载大量数据的几种解决办法的更多相关文章

  1. 在Spring Boot中加载初始化数据

    文章目录 依赖条件 data.sql文件 schema.sql 文件 @sql注解 @SqlConfig 注解 在Spring Boot中加载初始化数据 在Spring Boot中,Spring Bo ...

  2. ios网络学习------4 UIWebView的加载本地数据的三种方式

    ios网络学习------4 UIWebView的加载本地数据的三种方式 分类: IOS2014-06-27 12:56 959人阅读 评论(0) 收藏 举报 UIWebView是IOS内置的浏览器, ...

  3. Velocity中加载vm文件的三种方式

    Velocity中加载vm文件的三种方式: a.  加载classpath目录下的vm文件 /** * 初始化Velocity引擎 * --VelocityEngine是单例模式,线程安全 * @th ...

  4. 转 Velocity中加载vm文件的三种方式

    Velocity中加载vm文件的三种方式   velocitypropertiespath Velocity中加载vm文件的三种方式:    方式一:加载classpath目录下的vm文件 Prope ...

  5. BadImageFormatException,未能加载正确的程序集XXX的解决办法

    BadImageFormatException,未能加载正确的程序集XXX的解决办法 IDE:VS2010 语言:C# 异常:System.BadImageFormatException,未能加载正确 ...

  6. iOS --- UIWebView的加载本地数据的三种方式

    UIWebView是IOS内置的浏览器,可以浏览网页,打开文档  html/htm  pdf   docx  txt等格式的文件.  safari浏览器就是通过UIWebView做的. 服务器将MIM ...

  7. ExtJS4加载FormPanel数据的几种方式

    我们做web应用最多的就是处理表单,extjs为我们提供了很多处理表单的功能,很多初学者疑惑怎么加载表单数据,到底能用什么方式加载?本文中,我将我自己实验过的进行一下总结,自己备忘,也希望能帮助到其他 ...

  8. arcgis三维球中加载2000坐标系出现错误(The tiling scheme of this layer is not supported by SceneView)

    目前我们国家测绘地理信息的坐标体系基准是国家2000坐标系CGCS2000.各类地图组件如OpenLayers.Mapbox.Cesuim和ArcGIS Javascrip等都主要是支持WGS84(w ...

  9. javascript innerHTML 大数据量加载 导致IE 内存溢出 的解决办法

    在做 ajax 滚动加载的时候,越到后面 数据量越大,使用obj.innerHTML+=row添加到页面的时候,出现ie内存不足的情况,此时使用createDocumentFragment,创建一个文 ...

随机推荐

  1. pathlib:处理文件路径的瑞士军刀

    pathlib是python3.4中引入的模块,专门用来处理路径的.个人觉得这是一个非常非常强大的模块,可以说是处理路径的一把瑞士军刀,下面我们就来看看它的功能. 在pathlib中有一个Path这个 ...

  2. Winform Global exception and task parallel library exception;

    static class Program { /// <summary> /// 应用程序的主入口点. /// </summary> [STAThread] static vo ...

  3. string::erase

    sequence (1) string& erase (size_t pos = 0, size_t len = npos);两个参数都有默认值,传递的唯一参数匹配第一个 character ...

  4. 【转载】关于java 的InputStream和OutputStream的理解

    关于InputStream和OutputStream的输入输出方向的理解 InputStream输入类,首先需要读取的内容转化成输入流,再从它那里进行读取,先关联源:之后过程中关联目的,这样形成了流: ...

  5. 权限和ACL练习题

    1.在/testdir/dir里创建的新文件自动属于g1组,组 g2的成员如:alice能对这些新文件有读写权限,组g3 的成员如:tom只能对新文件有读权限,其它用户(不 属于g1,g2,g3)不能 ...

  6. Java分级考试

    石家庄铁道大学选课管理系统 1.项目需求: 本项目所开发的学生选课系统完成学校对学生的选课信息的统计与管理,减少数据漏掉的情况,同时也节约人力.物力和财力.告别以往的人工统计. 2.系统要求与功能设计 ...

  7. Ubuntu 安装matlab2013b

    下载软件包: 链接:http://pan.baidu.com/s/1bHoFHc 密码:lugc 还要注意软件的解压的问题: 链接:http://pan.baidu.com/s/1geBEQyf 密码 ...

  8. printf计算参数是从右到左压栈的(a++和++a的压栈的区别)

    一.问题 c++代码: #include <iostream> #include <stdio.h> using namespace std; int main(){ ; co ...

  9. 如何在输入命令行npm run dev 之后vue项目自动在浏览器打开

    使用代码编辑器打开vue项目代码,在config文件夹里面找到index.js 将里面的:autoOpenBrowser: false, 修改为 :autoOpenBrowser: true, 这个方 ...

  10. 字典树Trie--实现敏感词过滤

    序言 Trie树 资料 https://blog.csdn.net/m0_37907797/article/details/103272967?utm_source=apphttps://blog.c ...