关于如何根据几何网络进行爆管分析

我的QQ是:732344647,加我记得写备注~


之前写过一篇关于如何建立集合网络流向的文章:如何建立几何网络流向,在这篇文章之中只是介绍如何建立流向,并没有介绍如何实现爆管分析的功能,我在网上也没百度谷歌出相关代码(应该有我没有找到吧),所以自己研究出来了,今天就分享给大家,并感谢给我找相关文献的同门们以及那些分享经验的大神们(本文实现代码并没有根据流向来找到阀门,而是找到所有的相连,但是整体的实现思路不会错,如果你需要根据流向来实现搜索,还需要将流向设置好了以后进一步判断,参考API以后相信根据本文你可以进一步完善)。

———————————————————————————————————————-
首先,我并不会将所有的代码都写出来,但是会介绍最关键的流程与主要代码。
1–找到目标数据的几何网络。因为我们是在这个数据基础上进行分析的,就是QI到这个接口INetworkCollection,通过ArcGIS API的帮助文档,我们可以发现类FeatureDataset实现了这个接口,所以思路就是从操作的图层之中尽享QI转换过去就可以了;

iFeatureLayer = iLayer as IFeatureLayer;
iFeatureDataset = iFeaLayer.FeatureClass.FeatureDataset;
iNetCollec = iDataset as INetworkCollection;

2-找到Edge边。因为爆管分析是我们需要先选中我们确定的已经的爆管的管道,所以需要根据鼠标点击数据找到那条边;这里主要用到了IPointToEID接口的GetNearestEdge方法获取到当前的爆管位置
3-找到Edge首末节点。根据第二步找到Edge以后得到的是该边的EID,在几何网络之中会根据Feature重新生成一个EID对应每个要素;所以我们可以使用INetTopologyEditGEN接口的GetFromToJunctionEIDs方法找到首末节点的EID
4–判断首末节点是否为阀门(爆管分析就是要关闭连通的阀门),如果是阀门,那么这个节点相连的边线就不用继续搜索了,否则根据该节点的EID继续往下搜索所有相连的边线Edges;这里我们使用队列Enqueue数据结构来处理节点EID,所有检索到的非节点的EID全部保存在队列之中,因为队列是先进先出的,而且出列的同时会返回该出列值,适用于当前的数据结构,而检索到的所有Edges全部保存在字典Dictionary之中,其中Key是连接节点,而Value是与该点连接Edges;这样,当我们从队列中取出非阀门节点的EID的时候就可以去字典中找到相连的Edge,然后根据这条连接边继续寻找节点,直到队列为空为止。
这一步相对较为复杂,所以会将所有代码全部贡献出来

while (true)
                {
                    dictionary.Clear();
                    //判断2个起始节点是否为阀门
                    if (IsWaterValue(fromFuncEID, iGeoNetwork) && IsWaterValue(toFuncEID, iGeoNetwork))//首尾皆为阀门
                    {
g_WaterValues.Add(GetFeatureByEID(fromFuncEID, iGeoNetwork));                    g_WaterValues.Add(GetFeatureByEID(toFuncEID, iGeoNetwork));
                        break;//跳出
                    }
                    else if (IsWaterValue(fromFuncEID, iGeoNetwork) && !IsWaterValue(toFuncEID, iGeoNetwork))//起点是阀门
                    {
                        g_WaterValues.Add(GetFeatureByEID(fromFuncEID, iGeoNetwork));
                        juncQueue.Enqueue(toFuncEID);
                        dictionary.Add(toFuncEID, nearestEdgeEID);
                    }
                    else if (!IsWaterValue(fromFuncEID, iGeoNetwork) && IsWaterValue(toFuncEID, iGeoNetwork))//终点是阀门
                    {
                        g_WaterValues.Add(GetFeatureByEID(toFuncEID, iGeoNetwork));
                        juncQueue.Enqueue(fromFuncEID);
                        dictionary.Add(fromFuncEID, nearestEdgeEID);
                    }
                    else//都不是阀门
                    {
                        juncQueue.Enqueue(fromFuncEID);
                        juncQueue.Enqueue(toFuncEID);
                        dictionary.Add(fromFuncEID, nearestEdgeEID);
                        dictionary.Add(toFuncEID, nearestEdgeEID);
                    }

                    IForwardStarGEN iForwardStarGEN = iGeoNetwork.Network.CreateForwardStar(true, null, null, null, null) as IForwardStarGEN;//这个接口主要负责根据EID查找连通的要素EID
                    while (juncQueue.Count != 0)//判断队列是否为空,递归...
                    {
                        int adgacentEdgesCount = 0;//指定的搜索节点连接的除源edge以外的邻接边线个数
                        int eid = (int)juncQueue.Dequeue();//队列移除eid并获取eid

                        iForwardStarGEN.FindAdjacent(dictionary[eid], eid, out adgacentEdgesCount);//首次判断使用起始边线作为输入参数
                        if (adgacentEdgesCount != 0)//如果邻接线为0
                        {
                            int[] refEdgesEIDs = new int[adgacentEdgesCount];//查询到的边线集合
                            bool[] refReverseOrirntation = new bool[adgacentEdgesCount];//默认为false
                            object[] refWeightValue = new object[adgacentEdgesCount];
                            iForwardStarGEN.QueryAdjacentEdges(ref refEdgesEIDs, ref refReverseOrirntation, ref refWeightValue);//获得与指定节点的边线EID集合
                            //遍历边线集合
                            for (int i = 0; i < refEdgesEIDs.Length; i++)
                            {
                                int adgacentJunc;
                                object weight;
                                iForwardStarGEN.QueryAdjacentJunction(i, out adgacentJunc, out weight);
                                //判断这个输出的节点EID是否为阀门
                                if (IsWaterValue(adgacentJunc, iGeoNetwork))
                                {//如果是阀门加入到集合中
                                    g_WaterValues.Add(GetFeatureByEID(adgacentJunc, iGeoNetwork));
                                }
                                else
                                {
                                    if (!dictionary.ContainsKey(adgacentJunc))//因为没有设置流向,所以是双向查找,所以要判断是否已经查过了
                                    {
                                        dictionary.Add(adgacentJunc, refEdgesEIDs[i]); //成对添加到字典中去
                                        juncQueue.Enqueue(adgacentJunc);//如果不是阀门,那么将该节点加入到队列中去
                                    }
                                }
                            }
                        }
                    }
                    //最后需要break
                    break;
                }

———————————————————————————————————————-
这就是主要的流程逻辑与代码了,希望可以帮到大家,另外有什么不足之处请大家不吝指教!

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值