1 场景描述
本文的应用场景,是要通过某市的行政区划,去查询覆盖指定县市的影像数据。其中行政区划采用Xian80地理坐标系,而影像数据则采用了该市的地方平面坐标系,因此需要进行坐标转换。
下文将为您介绍如何在ArcGIS Server开发中进行坐标系转换。
2 关于自定义坐标系
本文所谓的自定义坐标系,是指没有包含在ArcGIS自带的坐标系中的坐标系。比如你通过ArcGIS的坐标系定义工具自定义的,或者从其他部门得到的.prj文件等。
自定义坐标系在国内应用比较普通,通常每个城市都会有自己的地方坐标系,以获得最高的测量精度。这些地方坐标系与其他标准坐标系(WGS84、Xian80、Beijing54或CGCS2000)之间的转换参数(如七参数、三参数)一般都是保密的。3 ArcGISServer中的坐标系
我们知道,在进行ArcGIS Server客户端应用(如Flex、Silverlight、JavaScript、Android、iOS、Windows Phone等)开发的时候,都是通过REST接口,使用的坐标系的时候通常是通过WKID,但这个WKID只包含了ArcGIS自带的那些标准的坐标系,对于自定义的坐标系则无法使用WKID。
在ArcGIS Server 10.0中,推出了新的WKT(Well-KnownText),即可以通过标准的文本来定义坐标系。
另外在ArcGIS 10.1中,对投影函数进行了增强,使之支持自定义的大地基准转换,这样我们就可以完全在ArcGIS Server开发中使用自定义坐标系了。4 示例数据
4.1 自定义坐标系
本文示例为作者根据已有的坐标系,进行微调生成的自定义坐标系,我们姑且叫他“XX市独立坐标系(xx_duli)”吧。坐标系定义(即WKT)如下:
PROJCS["xx_duli",GEOGCS["GCS_Krasovsky_1940",DATUM["D_Krasovsky_1940",SPHEROID["Krasovsky_1940",6378245.0,298.3]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Gauss_Kruger"],PARAMETER["False_Easting",50000.0],PARAMETER["False_Northing",-3202855.272],PARAMETER["Central_Meridian",106.419263889],PARAMETER["Scale_Factor",1.0],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]4.2 自定义大地基准转换
另外定义了一个大地基准转换,用于在该坐标系的大地基准(D_Krasovsky_1940)和Xian80的大地基准(GCS_Xian_1980)之间进行转换,转换定义如下:
GEOGTRAN["GCS_Xian_1980_To_Krasovsky_1940",GEOGCS["GCS_Xian_1980",DATUM["D_Xian_1980",SPHEROID["Xian_1980",6378140.0,298.257]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433],METADATA["China- onshore",73.66,18.04,134.85,53.59,0.0,0.0174532925199433,0.0,3228]],GEOGCS["GCS_Krasovsky_1940",DATUM["D_Krasovsky_1940",SPHEROID["Krasovsky_1940",6378245.0,298.3]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433],METADATA["Notspecified",-180.0,-90.0,180.0,90.0,0.0,0.0174532925199433,0.0,1263]],METHOD["Geocentric_Translation"],PARAMETER["X_Axis_Translation",0.0],PARAMETER["Y_Axis_Translation",0.0],PARAMETER["Z_Axis_Translation",0.0]]4.3 创建空间数据
首先使用Xian80坐标系创建一个行政区划要素类,然后添加几个区划要素,并赋予区县名称属性。
然后使用地方坐标系创建一个影像数据集,本文用矩形框模拟影像范围,绘制几个影像footprint要素。
5 关键代码
接下来就可以进行程序开发了,首先看一下进行坐标转换的代码(本文示例代码使用Silverlight):
SpatialReference outSR = new SpatialReference("PROJCS[\"CQDuli_NEW\",GEOGCS[\"GCS_Krasovsky_1940\",DATUM[\"D_Krasovsky_1940\",SPHEROID[\"Krasovsky_1940\",6378245.0,298.3]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",50000.0],PARAMETER[\"False_Northing\",-3202855.272],PARAMETER[\"Central_Meridian\",106.419263889],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]"); DatumTransform trans = new DatumTransform("GEOGTRAN[\"GCS_Xian_1980_To_Krasovsky_1940\",GEOGCS[\"GCS_Xian_1980\",DATUM[\"D_Xian_1980\",SPHEROID[\"Xian_1980\",6378140.0,298.257]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433],METADATA[\"China - onshore\",73.66,18.04,134.85,53.59,0.0,0.0174532925199433,0.0,3228]],GEOGCS[\"GCS_Krasovsky_1940\",DATUM[\"D_Krasovsky_1940\",SPHEROID[\"Krasovsky_1940\",6378245.0,298.3]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433],METADATA[\"Not specified\",-180.0,-90.0,180.0,90.0,0.0,0.0174532925199433,0.0,1263]],METHOD[\"Geocentric_Translation\"],PARAMETER[\"X_Axis_Translation\",0.0],PARAMETER[\"Y_Axis_Translation\",0.0],PARAMETER[\"Z_Axis_Translation\",0.0]]"); GeometryService projectTask = new GeometryService(geometryUrl); projectTask.ProjectCompleted += new EventHandler<GraphicsEventArgs>(projectTask_ProjectCompleted); projectTask.Failed += new EventHandler<TaskFailedEventArgs>(projectTask_Failed); projectTask.ProjectAsync(e.FeatureSet, outSR, trans, true, null);
请注意在上最新的10.1中,ProjectAsync方法新增了DatumTransform参数,可以在投影中指定大地基准转换。 接下来是利用返回的结果(投影到地方坐标系的行政区划要素),再进行空间查询:
QueryTask spatialQuery = new QueryTask(cqduliUrl); spatialQuery.Failed += new EventHandler<TaskFailedEventArgs>(spatialQuery_Failed); spatialQuery.ExecuteCompleted += new EventHandler<QueryEventArgs>(spatialQuery_ExecuteCompleted); Query query = new Query(); query.ReturnGeometry = true; query.OutFields.Add("OBJECTID"); query.Geometry = e.Results[0].Geometry; query.OutSpatialReference = new SpatialReference(4610); spatialQuery.ExecuteAsync(query);
请注意,在上述代码中,空间查询输入的Geometry,即投影转换的结果,已经是地方平面坐标系了,这样就可以从影像服务中查询到正确的结果。而由于最终返回的结果需要绘制到地图上,所以设置了输出空间参考为4610,即Xian80地理坐标系。 后面的代码无非就是处理返回的查询结果,将其绘制到地图上,以及处理查询失败的结果等,不再赘言,查询结果如下:
通过中间这个县的区划要素,查询到三景影像覆盖。
以上就是如何在客户端开发中使用自定义坐标系和自定义大地基准转换,关键就是要用好WKT,而且该功能是由REST SDK提供的,因此对于Flex、Silverlight、JavaScript、Android、Windows Phone或者iOS都同等支持。