ESRI终于发布了基于Silverlight的地图示例,其中使用了DeepZoom技术,地图的体验很好,地址见
http://resources.esri.com/arcgisserver/adf/dotnet/index.cfm?fa=codeGalleryDetails&scriptID=15746
posted @
2008-08-15 01:08 Ren 阅读(201) |
评论 (1) |
编辑
原文地址
Web地图通常包含底图(提供影像和位置信息)和功能性的专题图层(包含业务信息)。例如提供实时交通信息的在线地图服务,其中街道图是底图,一般情况下不会变化,可以作为其他Web地图应用的底图。交通信息是专题图层,在实时动态更新。本文描述了几种在叠加底图和专题层时常用的模式。
底图和专题层在维护和显示的策略上有很大区别。在创建Web地图时,最好的办法是将二者分开处理。底图不需要经常更新,可以事先缓存成图片存在服务器上,而专题层则需要考虑数据实时更新和加快显示速度。
将底图和专题层分离需要在ArcMap中创建至少两个地图文档(.mxd),并在ArcGIS Server中发布成独立的地图服务,最后在Web地图中成为叠加的两个地图服务层。地图服务层由于是从地图文档发布来的,所以是包含很多图层的容器。
如果你对Web地图比较陌生,可能理解起来有困难。也许你的公司只有一个包含许多许多图层的地图文档要发布,为了性能和灵活性,最好是将其拆分成目的明确的多个地图文档进行发布,然后针对不同的地图服务采用相应的策略。
显示底图的策略
为了追求最快的地图显示速度,底图应该进行缓存,缓存是预先生成好的图片,当用户请求时直接从服务器读取。底图和它的缓存易于维护,因为它们通常不会变化,即使变化了,也可以更新缓存。底图通常包括影像,街道,地形或者其他为专题图层提供背景的图形(示例)。
你的底图可以来自在线的地图服务,也可以是自己的地图文档,在线的地图服务例如ArcGIS Online。通过ESRI提供的Javascript扩展,你也可以在自己的Web地图中使用Google Maps和Microsoft Virtual Earth提供的地图服务。
如果上述地图服务无法满足需求,你可以将自己的高分辨率地图通过ArcMap制作为地图文档,然后用ArcGIS Server发布并建立缓存。建立缓存时,如果选择将所有图层融合,性能将达到最好。但发布后就无法控制单个图层的显示与隐藏了。处理这部分需要隐藏的图层,你应该将它们发布成单独的地图服务作为底图,或者,专题图层。
在建立缓存时,最佳做法是只对需要显示的区域进行缓存。默认设置下,缓存工具会对整个地图文档的全图区域建立缓存。但ArcGIS Server9.3可以通过一个矢量文件指定需要建立缓存的区域,这在地图显示区域是条带状时尤其有用,不需要为大片空白区域浪费系统资源了。
当你的系统资源更加紧张,而要建立缓存的区域非常大时,可以考虑仅在用户请求时建立缓存。更加灵活的策略是对热点区域通过指定矢量文件预先建立缓存,而其他区域在请求时建立缓存,这样只有在第一个用户访问时会感觉到显示的延迟。
当底图的数据被更改时,需要对缓存进行更新,通过只更新修改了数据的区域,可以节省系统资源。这时要注意那些被设置为请求时建立缓存的区域,它们同样需要更新。最简单的办法是删除这些图片,在请求时重新创建缓存。
还可以将建立缓存工作保存为脚本,在半夜或周末,用户访问量较少时进行,减小对网站的影响。
显示专题图层的策略
将专题图层显示为客户端图形
专题图层上的图形是客户端渲染的,服务器端发回的是图形数据。当用户缩放、漫游或点击地图时,可以查看可视区域内的客户端图形,这种方式有几点好处:
保证了只加载用户需要的图形;
对图形的渲染消耗客户端的CPU,而减轻了服务器的负担;
如果数据被修改过,用户能够马上看到最新的数据;
可以将图层渲染的功能交给客户端的JavaScript,从而提供更好的符号和标注功能(示例),并且能够控制图层的隐藏。
这个例子将地块作为客户端图形叠加在底图上,并且只有在放大到一定范围后才显示,这样避免了回传大量的数据,地块没有标注,但点击后可以立即看到相应信息。
你甚至可以选择在用户点击地图前不显示图形,例如这个地图,只有在用户点击影像上的某个位置时才显示该位置的地块形状。
在客户端图形上标注是一个难题,尽管在图形上显示文字很容易实现,但没有很好的客户端标注引擎来决定文字的显示位置,避免标注信息的重叠。由于图形和属性信息都已经加载到客户端,所以响应用户鼠标点击或停放事件,在弹出的信息窗口中显示标注是一个解决之道。更高级的应用是在信息窗口中通过表格、图表或其他方式展示数据。
采用这种客户端图形的显示策略,你需要特别注意避免用户请求过多的图形。这种情况很可能使浏览器抓狂,并且占用大量的带宽。因此,你需要设计你的程序来应对这种问题。
地图服务有一个MaxRecordCount的选项,决定了每次最多请求的图形数量。默认值为500。根据需要你可以调整这个值,或者设定用户在缩放到某个比例尺时才开始请求这些图形,避免超过上限。
ArcGIS Server REST和SOAP Web服务都提供了查询地图服务的功能,通过QueryFeatures、Identify和Find操作实现。Javascript API和Web ADF框架将这些操作封装在QueryTask中。
动态地图服务
展示专题图层的第二种方式是动态地图服务。在动态地图服务中,服务器端根据请求区域绘制好地图,发送给客户端,在浏览器中叠加动态地图和缓存的地图。(译注:由于叠加时动态地图要透明,所以一般是png格式)。
这个例子展示了这种做法。
动态地图服务是处理专题图层的传统做法,这种方式加重了服务器的负担,为了提高性能,对动态地图要尽量减少显示的图层和采用尽可能简单的符号。
动态地图将当前区域内所有可见图层的数据都进行了展示,包括用户不太需要的图层。没有必要将所有这些图层都展示给用户,因此动态地图往往提供用户隐藏某些图层的功能,例如用户只关心电力网络时,对电力节点设施等图层可以隐藏,减轻服务端动态生成地图的压力。
Javascript API通过ArcGISDynamicMapServiceLayer发布动态地图,ADF通过Map Resouce发布动态服务,REST和SOAP Web服务通过ExportMapImage操作提供动态地图。
将专题图层显示为缓存的地图服务
第三种方式是将专题图层也发布为缓存的地图服务,当你的专题数据更新不是很频繁,或者更新只影响很小范围时比较适用。
这个例子是将专题图层进行缓存,然后与缓存的底图进行叠加的效果。但是这个例子同样展示了这种做法的缺点。当你在地图上缩放时,只能在几个级别上看到缓存的专题图层。因为在比例尺较大时,对专题图层的缓存要耗费相当的系统资源,而且频繁的更新数据和缓存会对程序造成较大的影响。
综观以上三种技术,可知缓存可以满足用户最苛刻的性能要求,因为浏览器只需要从服务器获取现成的图片即可。当你浏览一个缓存地图时,不需要等待地图绘制或者数据传输的过程。同时,缓存保证了最佳的制图效果,尽管制图效果在建立缓存时相当耗费服务器资源。
当你为专题图层建立缓存时,选择与底图相同的切图方案是非常必要的。切图方案设定了建立缓存的比例尺和级别,只有在底图和缓存的专题图层比例尺匹配时,才能进行叠加。相同的切图方案还包括相同的投影方式。只需要地图文档的投影相同即可,而单个图层的投影可以不同。
使用PNG 8格式的图片建立缓存是推荐的做法。PNG 24在IE6和之前版本中不能透明化。JPG则根本不提供透明,当考虑相同的切图方案时,图片的格式不必匹配,也可以进行叠加。
与缓存底图相似,对专题图层的缓存也可以脚本化和定期进行,只是比底图的更新频率更高。当第一次建立专题图层的缓存时,建议记录下所需的时间,做到心中有数。如果专题图层在较大比例尺时才进行显示,可以减少建立缓存的级别,并且采用较尽可能简单的渲染方式和标注。
Javascript API通过ArcGISTiledMapServiceLayer发布缓存后的地图服务,Web ADF使用map resource,REST 和SOAP Web 服务也提供了相应接口访问缓存后的地图服务。
posted @
2008-08-09 23:16 Ren 阅读(961) |
评论 (2) |
编辑
不知道算不算bug
今天为了验证REST和ADF方式下是否都会动态生成缓存,于是手工把arcgiscache目录下某个地图服务的缓存删除了,结果REST和ADF两种方式访问该地图服务都显示空白页面,并且firebug报所有发送的请求都找不到资源。窃以为是因为Server将生成的缓存信息记录在了某个位置,请求发送到Server的时候,先在这个位置找是不是有缓存,如果有,就直接GET缓存的图片,如果没有,就生成缓存。但我没有发现这个记录缓存信息的文件。
出现这个错误以后,更令人不能接受的是,Manager显示,这个地图服务始终在运行,就是说,ArcSOC读取缓存发现没有找到缓存,它并没有放弃查找,而是在继续徒劳的寻找早已被我删掉的缓存文件。不知道这个工作会不会超时,反正我是等了半个小时ArcSOC发现还在运行中。

如果这算是Bug的话,大家以后千万别学我手工删除缓存文件,后果很严重,不管是重启SOM,还是重启服务器,都没办法再让这个地图服务正常起来。
posted @
2008-07-17 01:17 Ren 阅读(45) |
评论 (0) |
编辑
ASP.NET AJAX推出也有一段时间了,当初宣称的AJAX客户端脚本可以脱离服务器端脚本,在诸如html,php等平台上使用,但像微软不少其他产品一样,这个肥大的,性能低下,毫无艺术感的框架正在被大家所诟病。越来越多的人想要脱离这个客户端脚本,脱离AJAX提供的客户端控件,用更精炼更高效的框架来调用服务器端方法。很显然,目前最火的js库是JQuery。
但是要很好的将JQuery和ASP.NET AJAX无缝的结合还是需要一点耐心的,建议从这篇文章入手:
http://encosia.com/2008/03/27/using-jquery-to-consume-aspnet-json-web-services/
ASP.NET AJAX转换.net对象和json对象的功能还是很不错的,如何用jquery来接受asp.net服务返回的json对象是关键,这篇文章讲得比较清楚,但是作者很快意识到实际使用两者结合时还有一些问题,于是写了另一篇文章进行了修正:
http://encosia.com/2008/06/05/3-mistakes-to-avoid-when-using-jquery-with-aspnet-ajax/
经过这篇文章的修正,基本上可以很好的掌握两者的结合方法了。
但这两篇文章是将如何用jquery来调用asp.net的web服务的,如果你想调用页面上的方法,则可以看看这两个脚本:
http://plugins.jquery.com/project/ajaxdotnet
http://schotime.net/jMsAjax.aspx
后者还可以将asp.net AJAX的古怪时间格式转换成更常用的格式,非常推荐。
posted @
2008-07-17 00:07 Ren 阅读(350) |
评论 (0) |
编辑
为了节省文件大小,应该把多个Silverlight控件放在一个XAP文件里,例如Page1.xaml和Page2.xaml。第一次加载哪一个可以在App的Startup事件的处理事件中选择性加载。
private void Application_Startup(object sender, StartupEventArgs e)
{
// Load the main control
this.RootVisual = new Page1();
// 或者加载Page2
//this.RootVisual = new Page2();
}
如果要判断,可以通过
StartupEventArgs对象的InitParams集合,这是一个
键/值对集合,向它传入初始化参数。方法如下:
<asp:Silverlight ID="Xaml1" runat="server" ... InitParameters="Author=renji,Url=http://renji.cnblogs.com,Role=User"/>
或在Object里面:
<param name="initParams" value="Author=renji,Url=http://renji.cnblogs.com,Role=User" />
这样在App.xaml.cs中就可以检查值了:
if (!e.InitParams.ContainsKey("Role"))
{
this.RootVisual = new Page1();
}
else
{
switch (e.InitParams["Role"])
{
case "User":
this.RootVisual = new Page1();
break;
case "Admin":
this.RootVisual = new Page2();
break;
default:
throw new Exception("缺少权限信息");
}
}
posted @
2008-03-07 23:25 Ren 阅读(182) |
评论 (1) |
编辑
我们的小组成员之间经常通过网络邻居来拷贝东西,但是很久以来,就有这么一个问题,经常共享了一个文件夹以后,对方却被拒绝访问。这种情况出现是随机的,时而共享就没问题,时而就无论共享什么都拒绝访问。从前我们的土办法是把要共享的文件都拷到一个总是能共享的文件夹里面去。这也不行,有些文件实在太大了。今天我终于开始思考这个终极问题,TM的到底能不能解决这个烦人的东西。
结果这个解决方法就是那么的简单,把everyone添加到那个要共享的文件夹的安全组里面。属性--安全--添加--everyone。之后,整个世界清静了。
posted @
2008-03-06 23:16 Ren 阅读(695) |
评论 (3) |
编辑
在即将到来的MIX08上将有演示S60上的Silverlight,消息来自
Livesino,当Flasher们还在以为这是个1.0的玩意儿的时候,商业的力量已经开始渗透到手机平台厂商了。当然普及手机上网的日子还很漫长,但是这一天终究得到来。即使是脱机的手机游戏,也是个不可估量的市场。
微软是个有钱的对手,你不会愿意跟有钱的对手打仗,因为他玩得起。如果微软还是老一套,拼命的复制你,频繁的升级超过你,直到蚕食掉大部分的份额,那么Adobe真的得当心了。而且几乎没有悬念微软还是会这么干。而且这一次恐怕更快,因为熟悉C#,熟悉Javascript的人实在太多了,门槛太低了。
posted @
2008-03-04 22:24 Ren 阅读(226) |
评论 (1) |
编辑
无论你关心SQL Server 2008版本中的新特性,还是正在开发基于SQL SERVER的应用,那么
这段视频(1GB)是不能错过的,由微软负责SQL Server 2008项目经理演示的在CTP6中的各种新功能。总结如下:
1、在Management Studio中的Intellisense,以前你可能需要一些工具如
SQL Prompt提供的智能完成,现在这个功能集成到了Management Studio中(智能完成业不是多高深的玩意儿,也不知道怎么现在才集成进来)。不过在CTP6中还不完善,只能在SELECT语句中使用。
2、新增了一些数据类型,比如只存储日期和只存储时间的数据类型,并且在与.NetDateTime数据交互时不需要额外的工作,由系统来完成转换,从而提高了索引的性能,降低了转化带来的开销。
3、系统提供了对层级查询的支持,通过IsDescendent(ID)可以方便实现,免去了繁重的递归查询(
这功能慢了Oracle好几拍),以前你常常得
这么做。
4、对GROUP语句的增强(我不care)
5、新的Merge语句,用来同步多个表中的数据,并且性能不错。这也许为同步写入表和查询表提供了一个新的选择。
6、在SQL Server中直接管理文件系统(安全吗),应该要为运行SQL Server的本地帐号授予这个目录的读写权限。可以在备份和恢复的时候与数据库绑定在一起。那不知道如果用了专门的文件服务器会怎么样。
7、为ADO.NET中的DataTable建立对应的类型,通过这个自定义类型,直接将DataTable的数据传入一个真实的数据库表中(看上去狠酷,至少我没这么想过)
8、对地理数据的支持,提供了Geometry类型,遵照OGC标准,对较简单的图形查询速度达到了次秒级(汗),通过将一个字段定义为geometry,可以将点线面数据都存储在这个数据类型中,设置它的值通过GEOMETRY::STGeomFromText方法如:
geometry::STGeomFromText
('POLYGON ((0 0, 150 0, 150 150, 0 150, 0 0))', 0));
通过诸如STUnion,STIntersects,STBuffer等操作来完成传统GIS中的相交,缓冲区等操作,性能不错,与VE的结合也很好。
虽然对空间数据的支持还是比Oracle慢了几拍,但微软若做得足够好,至少对ESRI数据库产品的依赖能够尽量减少,用原生的ADO.NET数据引擎性能肯定也能提升很多。
posted @
2008-03-04 15:00 Ren 阅读(2344) |
评论 (8) |
编辑
面对多位GIS开发界牛人对Web ADF的声讨(
1,
2,
3,
4...),ESRI选择以加快曝光ArcGIS 9.3 Server产品作为回应。前段时间发布了一系列的podcast来讲9.3里面的
REST和
Javascript API,并提供了一个
演示,展示了Javascript API的使用效果(还是不错的,但肯定要加大网络传输量)。并且很快的将
REST API文档上线,不过下午这个网址突然当掉了。也许这周或下周就将面向部分用户,开发商进行测试。
在之前版本的Server产品中,ESRI已经发布了SOAP API,但只局限于进行地图发布,同时由于SOAP协议本身,传输量也不小。这次发布的REST API顾名思义,提供了REST风格的开发接口,可发布json格式的数据。
由于REST风格的Web开发是将全部将资源以URL的方式对外发布,因此构建正确的URL字符串就成为这种开发方式的核心。这次ESRI提供了一个工具来辅助你完成URL的构建,叫做Services Explorer。你使用这个工具的方式就是通过浏览器,这里有一个
示例。
通过这个工具,你可以看到这台GIS服务器发布的所有GIS服务。对每一个GIS服务来说,例如ESRI_Census_USA (MapServer)这个地图发布服务,你看到的每一个链接就是访问这个服务的URL地址,比如在第一行View in: 中链接ArcGIS Javascript指向的URL,就是用Web方式浏览这个地图服务的地址。而Layers中每个图层的链接就表示了访问这个图层元数据的URL。
除了返回地图,还有基本的Identify,Find这类查询操作也以URL的方式发布了。例如URL:
http://myserver/arcgis/rest/services/maps/world/MapServer/export
表示了导出地图这个操作。当某个操作必需要参数时,就把参数写在后面,如:
http://myserver/arcgis/rest/services/maps/world/MapServer/export?bbox=-197.99999664046,-131.792384313038,197.99999664046,125.388423131397
表示导出这个范围内的图片。而如果要返回Json形式的数据,则再加参数f=json在末尾。
对于需要添加参数的操作,Services Explorer也提供了帮助。仍以ESRI_Census_USA (MapServer)为例。在页面最下可以看到Supported Operations,后面跟一些链接,就是这个Map服务提供的操作。打开这些链接,Services Explorer以输入框,单选框,下拉框的形式告诉你这个操作需要哪些参数,都是哪些类型的值有效。你设定好以后,会为你构建正确的请求URL,并返回操作结果。
尽管ESRI的产品总给人以笨重复杂的印象,但从这套REST API来看是蛮轻量的,提供的Services Explorer也很到位。只是不知道操作能不能自己扩展,还是只能使用产品给定的那些基本功能。如果可以扩展,那么这一套机制就比ADF那套高明得多了。即使不行,现有的这些REST风格也可以很容易与ajax技术结合,更方便与Silverlight,Flex这类客户端技术结合,那一定可以极大扩展ESRI产品的应用领域。
posted @
2008-02-28 16:42 Ren 阅读(521) |
评论 (3) |
编辑