2009年1月4日星期日

扩展 ArcGIS Server 在移动平台/互联网应用的可达性补遗 —— 使用WFS-T

姊妹篇《扩展 ArcGIS Server 在移动平台/互联网应用的可达性

上个月写过一篇文章《扩展 ArcGIS Server 在移动平台/互联网应用的可达性》,谈了谈在ArcGIS Server提供的ADF和API之外,进行数据获取和提交的话题。该文的主要内容是围绕REST,利用REST易于访问,调用服务简便的特点进行功能延展。本文则将对该文中没有涉及的另外一个口子进入,主要谈谈通过WFS-T服务向服务器提交数据的方法。注意,虽然本文的环境是ArcGIS Server 9.3和Flex,但是使用其它空间数据服务器(如GeoServer)或其它客户端(比如智能设备等),这个方法同样适用。

让我们首先了解一下WFS-T,简而言之它就是WFS with Transaction,提供数据交互(插入、删除、编辑)的WFS服务。你可以从http://www.opengeospatial.org/standards/wfs下载到WFS(1.1)的标准文档。

通过ArcGIS Server发布WFS-T服务对数据源的要求比较多一点,主要是数据源必须是注册成版本的SDE,并且不能使用default版本,需要新建一个其它版本来发布服务。具体细节可以参考http://webhelp.esri.com/arcgisserver/9.3/dotNet/tutorial_wfst_service.htm

好了,现在我们已经发布了一个WFS-T服务,那么我们可以在任何可以触及互联网的地方通过HTTP协议来想服务器发送信息,并通过WFS-T保存到数据库中去了。在Flex中,HTTP请求通过HTTPService对象来发送。

这是在MXML中定义了一个HTTPService对象,它用来向我的服务发送请求,请求方式为POST,我们需要通过POST来提交包含操作信息的XML对象。
<mx:HTTPService id="hs" result="onResult(event);" fault="onFault(event);"
url="http://192.168.200.157/arcgis/services/bj_traffic_mssql_sde/MapServer/WFSServer"
method="POST"
contentType="application/xml"
/>


当我在地图上点击鼠标的时候,从这个点击事件可以获得坐标点,这个时候你就可以构造XML对象并向服务器发送了,看一下我的鼠标事件响应:
private function startGeoProcess( event:MouseEvent ) : void
{
this.cursorManager.setBusyCursor();

var mp:MapPoint = myMap.toMapFromStage(event.stageX, event.stageY);

var insert:XML=
<wfs:Transaction
version="1.1.0"
service="WFS"
xmlns="http://192.168.200.157/arcgis"
xmlns:gml="http://www.opengis.net/gml"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:wfs="http://www.opengis.net/wfs"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://192.168.200.157/arcgis/services/bj_traffic_mssql_sde/MapServer/WFSServer http://192.168.200.157/arcgis/services/bj_traffic_mssql_sde/MapServer/WFSServer?request=describefeaturetype&typename=TrafficCase http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
<wfs:Insert>
<TrafficCase>
<SHAPE>
<gml:Point srsName="urn:ogc:def:crs:EPSG:6.9:4326">
<gml:pos>{mp.x} {mp.y}</gml:pos>
</gml:Point>
</SHAPE>
<PoliceNum>307</PoliceNum>
<CaseDetail>这是WFS提交的</CaseDetail>
<CaseStatus>0</CaseStatus>
</TrafficCase>
</wfs:Insert>
</wfs:Transaction>;
hs.send(insert);
}


简单说明一下,这个XML对象定义的是一个Transaction对象,具体的操作是Insert。Insert元素下的“TrafficCase”是我要提交数据的图层,在这个元素下的是不同的字段赋值。所有这些信息你都可以在http://192.168.200.157/arcgis/services/bj_traffic_mssql_sde/MapServer/WFSServer?request=describefeaturetype&typename=TrafficCase这个XML中找到。

在返回结果中我们判断一下提交操作有没有完成:
private function onResult(event:ResultEvent) : void
{
var result:Object = event.result;

var numInserted:int = result.TransactionResponse.TransactionSummary.totalInserted;
if( numInserted>0 )
{
Alert.show("共"+numInserted+"个数据提交成功");
}

this.cursorManager.removeBusyCursor();
}


看一下执行效果吧:


通过WFS-T方法提交数据比使用GP服务要简单的多,也灵活很多——虽然它对提交来的数据进行处理、过滤的能力则不如前者。同时,这种方法的普适性很好,只要支持WFS-T的空间数据服务器就都可以采用这种方法;而且,它对客户端要求也非常低,只要有互联网、可以POST数据就可以使用,其应用范围可想而知。

2009年1月1日星期四

在Flex中进行三维建模

这个题目起得有点不好,事实上并非在Flex中进行建模,而是通过Flex在浏览器中使用三维模型。本文主要涉及Google SketchUp的建模和Flex中使用开源(MIT许可)的Papervision3D库进行模型加载和使用。

这是一个对“水立方”进行建模表现的例子,当然,这个模型不是我做的,而是从在线模型库中下载的。事实上,使用SketchUp可以用比3DS Max等专业建模软件简单得多的操作来进行建模,同时,你也可以导入其它建模软件的模型(3ds、dwg等)。而使用SketchUp的主要目的在于其特殊的导出功能——KMZ格式。

看一下SketchUp建模的效果:

建模以后导出的格式是个问题,我采用了KMZ方案,一方面将纹理和模型全部包含在一个ZIP文件中,很清爽,Flex中也能很方便地加载;另一方面,KMZ的模型可以直接在Google Earth中打开。

把“WaterCube.kmz”放到Flex项目的bin目录下,下面就是如何在Flex中使用它了。Flex的Papervision3D库可以从 http://code.google.com/p/papervision3d/ 获得,可以导入swc库,抑或直接导入源代码都可。

对于一个KMZ的模型来说,Papervision3D的处理出奇简单,几行代码就可以搞定,免了你使用单纯顶点模型再加载纹理进行贴图的诸多麻烦:
var model:KMZ = new KMZ();
model.load("WaterCube.kmz");

this._scene.addChild(model);


具体的代码就不赘述了,看一下浏览器中的效果: