public Node(int id = 0, IPolyline data = null, int depth = 0, double length = 0, Node parent = null, List <Node> children = null, Posi tag = Posi.NONE, Posi exp = Posi.NONE, Boolean eptWnd = false) { this.id = id; this.poly = data; this.parent = parent; this.children = children; this.depth = depth; this.length = length; this.tag = tag; this.exp = exp; this.emptyWindow = eptWnd; }
/// <summary> /// 初始化标签 /// </summary> /// <param name="tag">标签</param> /// <param name="minTreeAngle">树剪枝阈值</param> /// <param name="tree">树结构</param> /// <param name="featClass">要素类</param> private void InitTag(Posi tag, double minTreeAngle, ref Tree tree, IFeatureClass featClass) { //确定tag int polyID = tree.Root().id; //寻找与polyID相接触的Polyline集合 IPolyline polyline = featClass.GetFeature(polyID).ShapeCopy as IPolyline; IPoint touchPoint = null; if (tag == Posi.FROM) { touchPoint = polyline.FromPoint; } else if (tag == Posi.TO) { touchPoint = polyline.ToPoint; } ISpatialFilter sf = new SpatialFilterClass(); sf.Geometry = touchPoint; sf.GeometryField = "SHAPE"; sf.SpatialRel = esriSpatialRelEnum.esriSpatialRelTouches; IFeatureCursor fc = featClass.Search(sf, false); int num = featClass.FeatureCount(sf); IFeature fea = null; while ((fea = fc.NextFeature()) != null) { int id = fea.OID; if (id == polyID) { continue; //忽略自身 } if (Convert.ToInt32(fea.get_Value(Program.linkIndex)) != 1) { continue; //不是link,跳过 } IPolyline poly = fea.ShapeCopy as IPolyline; if (num > 2 && GetPolylineAngle(polyID, id, featClass) < minTreeAngle) { continue; //剪枝 } if (GetRel(id, polyID, featClass) == Posi.FROM) //polyID相接于id的FROM端 { tree.InsertAsChild(tree.Root(), id, poly, poly.Length, tag, Posi.TO); //暴露点exp为TO端 } else if (GetRel(id, polyID, featClass) == Posi.TO) //polyID相接于id的TO端 { tree.InsertAsChild(tree.Root(), id, poly, poly.Length, tag, Posi.FROM); //暴露点exp为FROM端 } } }
public List <Node> GetChildren(Posi tag) { List <Node> children = new List <Node>(); foreach (Node child in this.children) { if (child.tag == tag) { children.Add(child); } } return(children); }
public string path = "C://Users//candi//Desktop//DHT sensor//for output//output.txt"; //Path where the file for sensors is generate void Start() { Debug.Log("Welcome to Detection and Prevention of Forest Fire Hud Space"); num = ReadTextFile(path); //Read from file, which sensor is triggered. for (int i = 0; i < num.Count; i++) { Debug.Log("START: " + num[i]); int numb = (int)num[i]; //get that number Vector3 position = Selectsensor(numb); x = (int)position[0]; y = (int)position[2]; //get the position of that number in x,y,z Debug.Log("Initiate fire"); Instantiate(myPrefab, new Vector3(x, z, y), Quaternion.identity); //start a fire at that position Posi seedPosi = new Posi(x, y); //mark that position as seeen position list.Add(seedPosi); //add that to the list to already present fire positions map[x, y] = "F"; //mark the map as fire present } }
/// <summary> /// 寻找特定颜色的叶子节点 /// </summary> /// <param name="tag">某一侧</param> public List <Node> FindLeaves(Posi tag) { List <Node> leaves = new List <Node>(); if (tag == Posi.NONE) { leaves.Add(_root); return(leaves); } //返回根节点 if (this._root.children == null) { leaves.Add(_root); return(leaves); } //没有孩子,返回根节点 Queue <Node> Q = new Queue <Node>(); //队列 foreach (Node child in _root.children) { if (child.tag == tag) { Q.Enqueue(child); //将该方向的节点放入队列 } } while (Q.Count > 0) //在队列为空之前 { Node currNode = Q.Dequeue(); //当前节点 List <Node> children = currNode.GetChildren(); //获取顶节点的孩子节点 if (children != null) { foreach (Node child in children) { Q.Enqueue(child); } //children.Clear(); } //有孩子:孩子入栈 else { leaves.Add(currNode); } } Q.Clear(); //释放内存 return(leaves); }
/// <summary> /// 获取Polyline之间的夹角(角度) /// </summary> /// <param name="id1">Base Polyline的OID</param> /// <param name="id2">待比较Polyline的OID</param> /// <param name="featureClass">要素类</param> private double GetPolylineAngle(int id1, int id2, IFeatureClass featureClass) { Posi IItoI = GetRel(id1, id2, featureClass); Posi ItoII = GetRel(id2, id1, featureClass); double[] v1 = null; double[] v2 = null; ISegmentCollection sc1 = featureClass.GetFeature(id1).ShapeCopy as ISegmentCollection; ISegmentCollection sc2 = featureClass.GetFeature(id2).ShapeCopy as ISegmentCollection; if (IItoI == Posi.FROM) { ISegment seg = sc1.get_Segment(0); v1 = new double[2] { seg.ToPoint.X - seg.FromPoint.X, seg.ToPoint.Y - seg.FromPoint.Y }; } else { ISegment seg = sc1.get_Segment(sc1.SegmentCount - 1); v1 = new double[2] { seg.FromPoint.X - seg.ToPoint.X, seg.FromPoint.Y - seg.ToPoint.Y }; } if (ItoII == Posi.FROM) { ISegment seg = sc2.get_Segment(0); v2 = new double[2] { seg.ToPoint.X - seg.FromPoint.X, seg.ToPoint.Y - seg.FromPoint.Y }; } else { ISegment seg = sc2.get_Segment(sc2.SegmentCount - 1); v2 = new double[2] { seg.FromPoint.X - seg.ToPoint.X, seg.FromPoint.Y - seg.ToPoint.Y }; } return(getVetorAngle(v1, v2)); }
public Boolean emptyWindow; //空窗期(记录从该节点到达根节点的路径中是否经过选框之外的节点) //构造函数 public Node() { this.id = 0; this.poly = null; this.parent = null; this.children = null; this.depth = 0; this.length = 0; this.tag = Posi.NONE; this.exp = Posi.NONE; this.emptyWindow = false; }
/// <summary> /// 将e作为孩子插入(原无) /// </summary> /// <param name="node">节点</param> /// <param name="id">新节点id</param> /// <param name="polyline">新节点数据</param> /// <param name="length">长度</param> /// <param name="tag">方向</param> /// <param name="exp">暴露端</param> public Node InsertAsChild(Node node, int id, IPolyline polyline, double length, Posi tag = Posi.NONE, Posi exp = Posi.NONE, Boolean empWnd = false) { this._size++; return(node.AddChild(id, polyline, length, tag, exp, empWnd)); }
/// <summary> /// 将e作为节点作为当前节点的孩子 /// </summary> /// <param name="polyline">数据</param> public Node AddChild(int id, IPolyline polyline, double length, Posi tag = Posi.NONE, Posi exp = Posi.NONE, Boolean eptWnd = false) { Node child = new Node(id, polyline, this.depth + 1, this.length + length, this, null, tag, exp, eptWnd); this.AddChild(child); return(child); }
/// <summary> /// 向某一个方向延申 /// </summary> /// <param name="tag">延申的方向</param> /// <param name="selected">选框元素的OID</param> /// <param name="tree">树结构</param> /// <param name="featClass">要素类</param> private void GoForward(Posi tag, double minTreeAngle, ref Tree tree, IFeatureClass featClass) { while (true) { Boolean bUpdate = false; //树是否更新过 List <Node> leaves = tree.FindLeaves(tag); foreach (Node leaf in leaves) { //寻找相接触的Polyline //寻找与polyID相接触的Polyline集合 IPoint touchPoint = null; if (leaf.exp == Posi.FROM) { touchPoint = leaf.poly.FromPoint; } else if (leaf.exp == Posi.TO) { touchPoint = leaf.poly.ToPoint; } ISpatialFilter sf = new SpatialFilterClass(); sf.Geometry = touchPoint; sf.GeometryField = "SHAPE"; sf.SpatialRel = esriSpatialRelEnum.esriSpatialRelTouches; IFeatureCursor fc = featClass.Search(sf, false); int num = featClass.FeatureCount(sf); IFeature fea = null; while ((fea = fc.NextFeature()) != null) { int id = fea.OID; if (id == leaf.id) { continue; //排除自身 } if (Convert.ToInt32(fea.get_Value(Program.linkIndex)) != 1) { continue; //不是link,跳过 } if (tree.FindNode(id)) { continue; //不能是本树的节点 } if (num > 2 && GetPolylineAngle(leaf.id, id, featClass) < minTreeAngle) { continue; //剪枝 } IPolyline poly = fea.ShapeCopy as IPolyline; if (GetRel(id, leaf.id, featClass) == Posi.FROM) { tree.InsertAsChild(leaf, id, poly, poly.Length, tag, Posi.TO); } else if (GetRel(id, leaf.id, featClass) == Posi.TO) { tree.InsertAsChild(leaf, id, poly, poly.Length, tag, Posi.FROM); } bUpdate = true; } } if (!bUpdate) { break; //此次无更新,退出 } } }
/// <summary> /// 从一个段IPolyline找到最匹配的IPolyline(EveryBestFit延申策略) /// </summary> /// <param name="polyID">待延申的polyID</param> /// <param name="currExp">polyID的暴露端</param> /// <param name="featureClass">要素类</param> /// <param name="visited">已访问的要素OID</param> /// <param name="bestPolyID">下一段Polyline的OID</param> /// <param name="nextExp">下一个暴露端</param> static private int EveryBestFit(int polyID, Posi currExp, IFeatureClass featureClass, List <int> visited, out int bestPolyID, out Posi nextExp) { bestPolyID = -1; nextExp = Posi.NONE; int mainCount = 0; //表示该接触点有主要道路 IFeature feature = featureClass.GetFeature(polyID); //临边查询 ISpatialFilter sf = new SpatialFilterClass(); sf.GeometryField = "SHAPE"; sf.SpatialRel = esriSpatialRelEnum.esriSpatialRelTouches; if (currExp == Posi.FROM) { sf.Geometry = (feature.ShapeCopy as IPolyline).FromPoint; } else if (currExp == Posi.TO) { sf.Geometry = (feature.ShapeCopy as IPolyline).ToPoint; } IFeatureCursor fc = featureClass.Search(sf, false); List <int> polySet = new List <int>(); //所有邻接要素的OID IFeature fea = null; while ((fea = fc.NextFeature()) != null) { if (fea.OID != polyID) { polySet.Add(fea.OID); } if (!IsLink(fea, featureClass)) { mainCount++; } } if (polySet.Count == 0) // 无邻接边 { return(0); } else if (polySet.Count == 1) //唯一邻接边 { if (visited.Contains(polySet[0])) //唯一连接路段已名花有主 { return(0); } bestPolyID = polySet[0]; Posi rel = GetRel(bestPolyID, polyID, featureClass); if (rel == Posi.FROM) { nextExp = Posi.TO; } else if (rel == Posi.TO) { nextExp = Posi.FROM; } else { Console.WriteLine("拓扑出错:[ " + polyID + ", " + bestPolyID + " ]"); } if (IsLink(bestPolyID, featureClass)) { return(1); } else { return(2); } } else { //寻找最匹配段 double maxAngle = 0; int cddId = -1; foreach (int id in polySet) { double angle = GetPolylineAngle(polyID, id, featureClass); if (angle > maxAngle) { maxAngle = angle; cddId = id; } } if (visited.Contains(cddId)) //候选段已名花有主 { return(0); } //寻找最佳匹配段的最佳匹配 polySet.Add(polyID); maxAngle = 0; int maxId = -1; foreach (int id in polySet) { if (id == cddId) { continue; } double angle = GetPolylineAngle(cddId, id, featureClass); if (angle > maxAngle) { maxAngle = angle; maxId = id; } } if (maxId == polyID) //配对成功 { if (!IsLink(cddId, featureClass)) //主要道路 { if (mainCount == 1) { return(2); } else { return(3); } } bestPolyID = cddId; Posi rel = GetRel(bestPolyID, polyID, featureClass); if (rel == Posi.FROM) { nextExp = Posi.TO; } else if (rel == Posi.TO) { nextExp = Posi.FROM; } else { Console.WriteLine("拓扑出错:[ " + polyID + ", " + bestPolyID + " ]"); } return(1); } else { return(3); //配对不成功 } } }
/// <summary> /// 获得从某一要素开始延伸的所有要素 /// <summary> /// <param name="feature">要素</param> /// <param name="featClass">要素类</param> static private void DeleteFeatureByStrokeTouching(IFeature feature, IFeatureClass featClass, ref List <int> visited) { //Console.WriteLine("feature id:" + feature.get_Value(id_index).ToString()); List <int> strokeFeature = new List <int>() { feature.OID }; //存储一段stroke的要素 //List<int> fea_id = new List<int>() { Convert.ToInt32(feature.get_Value(id_index))}; //存储一段stroke的要素 //状态码:0(不接触),1(延申到_link),2(延申到唯一的_main),3(其它) int fsc = 1; int tsc = 1; //沿着feature的polyline前后寻找link道路,将其存储在strokeFeature中,这些道路组合成stroke, //如果stroke的两端存在与非link道路的接触,则保留,否则删除 Posi currExp = Posi.FROM; //延申端 while (true) { if (fsc != 1) { break; //两边都无法通行,则退出 } int bestPolyID = -1; Posi nextExp = Posi.NONE; fsc = EveryBestFit(strokeFeature[0], currExp, featClass, visited, out bestPolyID, out nextExp); //寻找from端的最佳延申延申段 if (fsc == 1) { strokeFeature.Insert(0, bestPolyID); visited.Add(bestPolyID); currExp = nextExp; //fea_id.Insert(0, Convert.ToInt32(bestFeature.get_Value(id_index))); } } currExp = Posi.TO; //延申端 while (true) { if (tsc != 1) { break; //两边都无法通行,则退出 } int bestPolyID = -1; Posi nextExp = Posi.NONE; tsc = EveryBestFit(strokeFeature[strokeFeature.Count - 1], currExp, featClass, visited, out bestPolyID, out nextExp); //寻找from端的最佳延申延申段 if (tsc == 1) //延申下去 { strokeFeature.Add(bestPolyID); visited.Add(bestPolyID); currExp = nextExp; //fea_id.Insert(0, Convert.ToInt32(bestFeature.get_Value(id_index))); } } //输出strokeFeature //Console.WriteLine("fea_id:"); //foreach(int id in fea_id) //{ // Console.Write(id + " "); //} //Console.WriteLine(); //删除stroke的条件:任何一端是友好连接的都保留 if ((fsc == 0 || tsc == 0) || (fsc != 2 && tsc != 2)) { foreach (int oid in strokeFeature) //删除stroke的构成元素 { featClass.GetFeature(oid).Delete(); } } strokeFeature.Clear(); }
/// <summary> /// 按实际情况去除连接道路 /// <summary> /// <param name="featClass">要素类</param> static private void RemoveLinkRoad_Tree(IFeatureClass featClass) { string linkWhereClause = "link = 1"; //筛选条件(筛选出所有link) IQueryFilter queryFilter = new QueryFilterClass(); queryFilter.WhereClause = linkWhereClause; IFeatureCursor searchCursor = featClass.Search(queryFilter, false); Dictionary <int, Posi> uniqueTouch = new Dictionary <int, Posi>(); //与link唯一连接的要素ID集合 int featCount = featClass.FeatureCount(queryFilter); //筛选出所有跟link唯一连接的主要道路(即在link的端点处仅存在唯一的main道路) int count = 0; //计数器 IFeature linkFeatrue = null; while ((linkFeatrue = searchCursor.NextFeature()) != null) { Console.WriteLine("探测唯一接触点:" + (++count) + " / " + featCount); UpdateUniqueTouch(linkFeatrue, Posi.FROM, ref uniqueTouch, featClass); //FROM端更新 UpdateUniqueTouch(linkFeatrue, Posi.TO, ref uniqueTouch, featClass); //TO端更新 } Marshal.FinalReleaseComObject(searchCursor); //foreach (KeyValuePair<int, Posi> kvp in uniqueTouch) // Console.WriteLine("id: " + kvp.Key + " posi: " + kvp.Value); //唯一邻接表的所有线段为根节点生成所有的树 Forest forest = new Forest(); //空森林 count = 0; foreach (KeyValuePair <int, Posi> kvp in uniqueTouch) { Console.WriteLine("生成树:" + (++count) + " / " + uniqueTouch.Count); int polyID = kvp.Key; Posi posi = kvp.Value; forest.AddTree(polyID, featClass, uniqueTouch); //往森林里添加树 } //获取应该保留的边 List <int> linkIDStay = forest.QueryLinkID(); //Console.WriteLine("linkIDStay: "); //foreach (int id in linkIDStay) // Console.Write(id + " "); //删除link count = 0; IFeatureCursor searchCursor2 = featClass.Search(queryFilter, false); //迭代器 linkFeatrue = null; while ((linkFeatrue = searchCursor2.NextFeature()) != null) { Console.WriteLine("删除边:" + (++count) + " / " + featCount); if (!linkIDStay.Contains(linkFeatrue.OID)) //如果线段不在应该保留的范围之内,则 { linkFeatrue.Delete(); //删除线段 } } Marshal.FinalReleaseComObject(searchCursor2); //释放内存 linkIDStay.Clear(); forest.Clear(); uniqueTouch.Clear(); }