ArcGIS Server之扩展几何网络分析

1.引言

      在看博客之前,首先重点说明,本博客中使用的软件版本:

  • ArcGIS Server10.2
  • ArcGIS Object10.2

      如果你的版本是10.0,本博客中的代码肯定不可以用(10.0版本到10.1版本是一个大的提升)
      如果你的版本是10.1,本博客中的代码需要稍微修改(10.1版本到10.2版本会有小部分的修改)

      在本篇博客中主要以几何网络分析为例,介绍一下如果使用SOE来扩展我们的WebGIS应用。想要使用SOE扩展我们的WebGIS应用,需要对ArcGIS Object有一定的掌握。

2.在ArcGIS Object中进行几何网络分析。

在SOE扩展几何网络之前,先回顾一下如何使用ArcGIS Object来进行几何网络分析。

  • 首先在MapControl中绘制四类点(点标记listJunctionFlags,线标记listEdgeFlags,点障碍listJunctionBarrier,线障碍listEdgeBarrier)。

这里写图片描述

  • 使用IPointToEID接口,将我们的点转换成网络中的节点(其实就是寻找网络中满足容差最近的节点),转换成功之后的数组为:junctionFlags,edgeFlags,junctionBarrier,edgeBarrier
  • 然后设置网络的四个参数(点标记,线标记,点障碍,线障碍),选择合适的方法分析,比如我们使用公共祖先分析(FindCommonAncestors),分析之后得到结果,得到的结果是网络中的节点id(有节点id,也有线id)
  • 通过网络中的节点id获得相应的Feature,然后就可以在地图中显示。

3.SOE扩展几何网络分析难点

      在上面我们用文字简单的介绍了一下如何使用ArcGIS Object去分析几何网络,如果你熟悉AO,那么上面的过程你应该非常熟悉了。接下来我们就说一下在SOE中扩展WebGIS会遇到哪一些难点。

  • 难点一:假设我们要设置点标记(json数组),前台传来的是一个json数据,我们需要将json数组转换成List<IPoint>,然后通过IPointToEID,去查找网络中与改点最近的节点(在一定容差内)
  • 难点二:前面我们曾经说过,在ArcGIS 10.1之后,SOE开发中不可能获得IMap,ILayer对象,但是呢?IPointToEID这个接口需要传入IMap对象,所以IPointToEID这个接口在ArcGIS Server10.1之后不能使用了(SOE开发中不能用,AO中是可以使用的),但是这个接口的功能是我们必须要用到的,所以这个功能需要我们自己写代码实现。
  • 难点三:我们查询出来的结果,需要传给前台显示,这就需要我们将查询出来的结果序列化成json字符串,然后传给前台。

4.SOE扩展几何网络分析

      在前面我们说了,自己扩展几何网络分析会遇到哪一些困难,接下来,我们就扩展一个几何网络服务,然后解决掉上述遇到的问题。

4.1 获得地图服务中的几何网络

IMapServer3 mapServer = this.serverObjectHelper.ServerObject as IMapServer3;
IMapServerDataAccess dataAccess = (IMapServerDataAccess)mapServer;
IFeatureClass featureclass = (IFeatureClass)dataAccess.GetDataSource(mapServer.DefaultMapName, 0);
IFeatureDataset ds = featureclass.FeatureDataset;
INetworkCollection2 networkCollection2 = ds as INetworkCollection2;
//获得所需要的几何网络
IGeometricNetwork geometricNetwork = networkCollection2.get_GeometricNetwork(0);

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4.2 接受前台传来的数据(以点标记为例)

//定义一个点标记数据
object[] listJunctionFlags;
//读取前台传来的数据(json数组)
operationInput.TryGetArray("listJunctionFlags", out listJunctionFlags);
//我们要将json数据转换成List<IPoint>对象
List<IPoint> junctionFlags = new List<IPoint>();
foreach (JsonObject jo in listJunctionFlags.Cast<JsonObject>().ToArray())
{
                IPoint location = Conversion.ToGeometry(jo, esriGeometryType.esriGeometryPoint) as IPoint;
                junctionFlags.Add(location);
}

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

4.3 自定义IPointToEID所具备的功能


/*
searchTolerance:搜索容差
point:搜索的点,也就是上面我们转换得到的 List<IPoint> junctionFlags
elementType:搜索的类型,(搜索节点,还是搜索线)
geometricNetwork:搜索哪一个网络?
EID:搜索得到的节点id
geometry:搜索得到的几何形状
*/
public void GetEIDFromPoint(double searchTolerance, IPoint point, esriElementType elementType, IGeometricNetwork geometricNetwork, out int EID, out IGeometry geometry)
        {
            EID = -1;
            geometry = null;
            IEnumFeatureClass enumFeatureClassSimple = null;
            IEnumFeatureClass enumFeatureClassComlex = null;
            if (elementType == esriElementType.esriETEdge)
            {
                enumFeatureClassSimple = geometricNetwork.get_ClassesByType(esriFeatureType.esriFTSimpleEdge);
                enumFeatureClassComlex = geometricNetwork.get_ClassesByType(esriFeatureType.esriFTComplexEdge);
            }
            else if (elementType == esriElementType.esriETJunction)
            {
                enumFeatureClassSimple = geometricNetwork.get_ClassesByType(esriFeatureType.esriFTSimpleJunction);
                enumFeatureClassComlex = geometricNetwork.get_ClassesByType(esriFeatureType.esriFTComplexJunction);
            }
            double distance = double.PositiveInfinity;
            int featureClassID = -1;
            FindNearestDistance(enumFeatureClassSimple, point, searchTolerance, ref distance, ref featureClassID, ref geometry);
            FindNearestDistance(enumFeatureClassComlex, point, searchTolerance, ref distance, ref featureClassID, ref geometry);
            if (featureClassID == -1)
            {
                EID = -1;
                return;
            }
            IProximityOperator proximityPoint = geometry as IProximityOperator;
            IPoint p = proximityPoint.ReturnNearestPoint(point, esriSegmentExtension.esriNoExtension);
            if (elementType == esriElementType.esriETEdge)
            {
                EID = geometricNetwork.get_EdgeElement(p);
                return;
            }
            else if (elementType == esriElementType.esriETJunction)
            {
                EID = geometricNetwork.get_JunctionElement(p);
                return;
            }
        return;
    }
    private void FindNearestDistance(IEnumFeatureClass enumFeatureClass, IPoint point, double searchTolerance, ref double distance, ref int featureClassID, ref IGeometry featureGeometry)
    {
        enumFeatureClass.Reset();
        IFeatureClass featureClass = enumFeatureClass.Next();
        while (featureClass != null)
        {
            string shapeFieldName = featureClass.ShapeFieldName;
            ITopologicalOperator topologicalOperator = point as ITopologicalOperator;
            ISpatialFilter spatialFilter = new SpatialFilterClass();
            spatialFilter.Geometry = topologicalOperator.Buffer(searchTolerance);
            spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
            spatialFilter.GeometryField = shapeFieldName;

            IFeatureCursor featureCursor = featureClass.Search(spatialFilter, true);
            IFeature feature = featureCursor.NextFeature();
            while (feature != null)
            {
               IProximityOperator proximityOperator = feature.ShapeCopy as IProximityOperator;
               double distanceCurrent = proximityOperator.ReturnDistance(point);
               if (distance &gt; distanceCurrent)
               {
                 distance = distanceCurrent;
                 featureClassID = featureClass.FeatureClassID;
                 featureGeometry = feature.ShapeCopy;
               }

               feature = featureCursor.NextFeature();
            }             
            featureClass = enumFeatureClass.Next();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80

4.4 使用自定义的方法得到点标记id

			int eid;
            IGeometry geo;
            //points 是我们在4.2中转换得到的List<IPoint>对象
            for (int i = 0; i < points.Count; i++)
            {
                GetEIDFromPoint(tol, points[i], esriElementType.esriETJunction, this.geometricNetwork, out eid, out geo);
                if (geo != null)
                {
                    INetElements netElements = geometricNetwork.Network as INetElements;
                    int userClassID = 0;
                    int userID = 0;
                    int userSubID = 0;
                    netElements.QueryIDs(eid, esriElementType.esriETJunction, out userClassID, out userID, out userSubID);
                    INetFlag junctionFlag = new JunctionFlagClass() as INetFlag;
                    junctionFlag.UserClassID = userClassID;
                    junctionFlag.UserID = userID;
                     //jFlags类型为List<IJunctionFlag>,是我们分析真正用到的节点id
                    jFlags.Add(junctionFlag as IJunctionFlag);
                }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

4.5 设置网络的各种参数

//几何网络分析的具体接口
traceFlowSolverGEN = new TraceFlowSolverClass();
netSolver = traceFlowSolverGEN as INetSolver;
//设置几何网络
netSolver.SourceNetwork = geometricNetwork.Network;
//设置几何网络的点标记
IJunctionFlag[] arrayJunctionFlag = new IJunctionFlag[jFlags.Count];
for (int i = 0; i < listJunctionFlags.Count; i++)
     arrayJunctionFlag[i] = listJunctionFlags[i];
traceFlowSolverGEN.PutJunctionOrigins(ref arrayJunctionFlag);
//同理设置线标记,点障碍,和线障碍
//进行几何网络分析(以公共祖先为例)
//junctionEIDs是分析结果的 节点id
//edgeEIDs是分析结果的 线id
traceFlowSolverGEN.FindCommonAncestors(esriFlowElements.esriFEJunctionsAndEdges,
                        out junctionEIDs, out edgeEIDs);

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

4.6 将分析的结果转换成json字符串

INetElements netElements = geometricNetwork.Network as INetElements;
int userClassID = -1;
int userID = -1;
int userSubID = -1;
int eid = -1;
IFeature feature;
IFeatureClass featureClass = null;
objectJson = new JsonObject();
//没有查找到线
if (edgeEIDs.Count == 0)
{
        objectJson.AddArray("edges", (new List<JsonObject>()).ToArray());
}
else
{
		//如果有查询到线,将线的geometry和属性封装成json对象
        JsonObject[] featureSet = new JsonObject[edgeEIDs.Count];
        for (int i = 0; i < edgeEIDs.Count; i++)
        {
               eid = edgeEIDs.Next();
               netElements.QueryIDs(eid, esriElementType.esriETEdge, out userClassID, out userID, out userSubID);
               featureClass = GetFeatureClassByUserID(userClassID);
               if (featureClass != null)
               {
                      feature = featureClass.GetFeature(userID);
                      featureSet[i] = new JsonObject();
                      featureSet[i].AddJsonObject("geometry", Conversion.ToJsonObject(feature.Shape));
                      JsonObject[] arr = new JsonObject[feature.Fields.FieldCount];
                      for (int j = 0; j < feature.Fields.FieldCount; j++)
                      {
                             IField field=feature.Fields.Field[j];
				             arr[j] = new JsonObject();
			                 arr[j].AddObject(field.AliasName, feature.get_Value(j));
					  }
                                featureSet[i].AddArray("attr",arr);
           }
     }
     objectJson.AddArray("edges", featureSet);

}
//没有查找到点
if (junctionEIDs.Count == 0)
{
objectJson.AddArray(“junctions”, (new List<JsonObject>()).ToArray());
}
else
{
//如果有查询到点,将点的geometry和属性封装成json对象
JsonObject[] featureSet = new JsonObject[junctionEIDs.Count];
for (int i = 0; i < junctionEIDs.Count; i++)
{
eid = junctionEIDs.Next();
netElements.QueryIDs(eid, esriElementType.esriETJunction, out userClassID, out userID, out userSubID);
featureClass = GetFeatureClassByUserID(userClassID);
if (featureClass != null)
{
feature = featureClass.GetFeature(userID);
featureSet[i] = new JsonObject();
featureSet[i].AddJsonObject(“geometry”, Conversion.ToJsonObject(feature.Shape));
JsonObject[] arr = new JsonObject[feature.Fields.FieldCount];
for (int j = 0; j < feature.Fields.FieldCount; j++)
{
IField field = feature.Fields.Field[j];
arr[j] = new JsonObject();
arr[j].AddObject(field.AliasName, feature.get_Value(j));
}
featureSet[i].AddArray(“attr”, arr);

       }
   }
   objectJson.AddArray("junctions", featureSet);

}
//GetFeatureClassByUserID方法
private IFeatureClass GetFeatureClassByUserID(int userClassID)
{
IMapServer3 serverObject = this.serverObjectHelper.ServerObject as IMapServer3;
IMapLayerInfos mapLayerInfos = serverObject.GetServerInfo(serverObject.DefaultMapName).MapLayerInfos;

 for (int i = 0; i &lt; mapLayerInfos.Count; i++)
 {
      IMapLayerInfo mapLayerInfo = mapLayerInfos.get_Element(i);
      if (mapLayerInfo.IsFeatureLayer)
      {
          IFeatureClass featureClass = this.GetFeatureClass(mapLayerInfo.ID);
          if (featureClass.FeatureClassID == userClassID)
              return featureClass;
      }
 }
 return null;

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90

4.7 将结果返回给客户端

return Encoding.UTF8.GetBytes(objectJson.ToJson());

 
 
  • 1

4.8 运行结果

这里写图片描述

5.数据及代码下载地址

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值