public List <GeoPoint2D> GetReduced(double precision) { QuadTree <GeoPoint2DQt> qt = new QuadTree <GeoPoint2DQt>(); for (int i = 0; i < list.Count; i++) { GeoPoint2DQt p = new GeoPoint2DQt(list[i]); GeoPoint2DQt[] close = qt.GetObjectsCloseTo(p); bool found = false; for (int j = 0; j < close.Length; j++) { if ((close[j].p | list[i]) <= precision) { found = true; break; } } if (!found) { qt.AddObject(p); } } GeoPoint2DQt[] all = qt.GetAllObjects(); List <GeoPoint2D> res = new List <GeoPoint2D>(all.Length); for (int i = 0; i < all.Length; i++) { res.Add(all[i].p); } return(res); }
/// <summary> /// 案例1:添加N个圆形区域 /// </summary> void Case1() { _case = 1; _quadTree.Init(new Rect(0, 0, MapSize, MapSize)); for (var i = 0; i < ObjectCount; i++) { var radius = Random.Range(1, ObjectSize); var pos = new float2(Random.Range(-MapSize / 2, MapSize / 2), Random.Range(-MapSize / 2, MapSize / 2)); _quadTree.AddObject(new TestQuadTreeData(), new Circle(radius, pos)); if (Debug) { var obj = Instantiate(Sphere); obj.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector; obj.name = "Sphere:" + i; obj.transform.position = new Vector3(pos.x, 0, pos.y); obj.transform.localScale = new Vector3(radius, radius, radius); } } if (Debug) { _quadTree.Output(10); } _quadTree.FakeClear(); }
public void Subdivide() { if (objectList.Count > maxObjs && childern == null && width > minSize && height > minSize) { float x1 = bbox.xmin; float x2 = bbox.xmin + 0.5f * width; float x3 = bbox.xmax; float y1 = bbox.ymin; float y2 = bbox.ymin + height * 0.5f; float y3 = bbox.ymax; childern = new QuadTree[4]; BBox tlBBox = new BBox(x1, x2, y2, y3); BBox trBBox = new BBox(x2, x3, y2, y3); BBox brBBox = new BBox(x2, x3, y1, y2); BBox blBBox = new BBox(x1, x2, y1, y2); QuadTree tl = new QuadTree(this, tlBBox, level + 1); QuadTree tr = new QuadTree(this, trBBox, level + 1); QuadTree br = new QuadTree(this, brBBox, level + 1); QuadTree bl = new QuadTree(this, blBBox, level + 1); foreach (PPObject obj in objectList) { tl.AddObject(obj); tr.AddObject(obj); br.AddObject(obj); bl.AddObject(obj); } childern[0] = tl; childern[1] = tr; childern[2] = br; childern[3] = bl; objectList = new List <PPObject>(); leaf = false; } else if (childern != null) { PushToChildern(); } }
/// <summary> /// 案例8:添加N个任意朝向的矩形区域 /// 删除随机区域内的矩形 /// 调用FindNearObject方法获取Start节点附近的对象 /// (拖动StartPos可以颜色发生变化的就是查询结果) /// </summary> void Case8() { _case = 8; _quadTree2.Init(new Rect(0, 0, MapSize, MapSize)); for (var i = 0; i < ObjectCount; i++) { var size = new float2(Random.Range(1, ObjectSize), Random.Range(1, ObjectSize)); var pos = new float2(Random.Range(-MapSize / 2, MapSize / 2), Random.Range(-MapSize / 2, MapSize / 2)); var forward = math.normalizesafe(new float2(Random.Range(-1f, 1f), Random.Range(-1f, 1f))); if (math.lengthsq(forward) < 0.1f) { forward = new float2(0, 1); } //if (Debug) { var obj = Instantiate(Cube); obj.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector; obj.name = "Cube:" + i; obj.transform.position = new Vector3(pos.x, 0, pos.y); obj.transform.localScale = new Vector3(size.x * 2, 1, size.y * 2); obj.transform.rotation = quaternion.LookRotation(new float3(forward.x, 0, forward.y), new float3(0, 1, 0)); _quadTree2.AddObject(new TestData2() { Obstacle = obj }, new AnyForwardRect(size, pos, forward)); } } for (var i = 0; i < ObjectCount; i++) { var size = new float2(Random.Range(1, ObjectSize), Random.Range(1, ObjectSize)); var pos = new float2(Random.Range(-MapSize / 2, MapSize / 2), Random.Range(-MapSize / 2, MapSize / 2)); _quadTree2.RemoveAllObjectsInRect(pos - size, pos + size); } _startPos = new GameObject("StartPos"); if (Debug) { _quadTree2.Output(1000); } }
private void Insert(ICurve2D curve) { // der Start- bzw. Endpunkt einer Kurve kommt in die Cluster Liste Joint lp = new Joint(); lp.curve = curve; GeoPoint2D p = curve.StartPoint; BoundingRect CheckSp = new BoundingRect(p, clusterSize, clusterSize); ICollection StartCluster = clusterTree.GetObjectsFromRect(CheckSp); Cluster InsertInto = null; foreach (Cluster cl in StartCluster) { if (Geometry.Dist(cl.center, p) < clusterSize) { InsertInto = cl; clusterTree.RemoveObject(cl); // rausnehmen, da er u.U. größer wird und unten wieder eingefügt wird break; } } if (InsertInto == null) { InsertInto = new Cluster(); clusterSet.Add(InsertInto); } InsertInto.Joints.Add(lp); lp.StartCluster = InsertInto; double x = 0.0; double y = 0.0; for (int i = 0; i < InsertInto.Joints.Count; ++i) { GeoPoint2D pp; if ((InsertInto.Joints[i]).StartCluster == InsertInto) { pp = (InsertInto.Joints[i]).curve.StartPoint; } else { pp = (InsertInto.Joints[i]).curve.EndPoint; } x += pp.x; y += pp.y; } InsertInto.center = new GeoPoint2D(x / InsertInto.Joints.Count, y / InsertInto.Joints.Count); clusterTree.AddObject(InsertInto); // desgleichen mit dem Endpunkt: p = curve.EndPoint; CheckSp = new BoundingRect(p, clusterSize, clusterSize); StartCluster = clusterTree.GetObjectsFromRect(CheckSp); InsertInto = null; foreach (Cluster cl in StartCluster) { if (Geometry.Dist(cl.center, p) < clusterSize) { InsertInto = cl; clusterTree.RemoveObject(cl); // rausnehmen, da er u.U. größer wird und unten wieder eingefügt wird break; } } if (InsertInto == null) { InsertInto = new Cluster(); clusterSet.Add(InsertInto); } InsertInto.Joints.Add(lp); lp.EndCluster = InsertInto; x = 0.0; y = 0.0; for (int i = 0; i < InsertInto.Joints.Count; ++i) { GeoPoint2D pp; if ((InsertInto.Joints[i]).StartCluster == InsertInto) { pp = (InsertInto.Joints[i]).curve.StartPoint; } else { pp = (InsertInto.Joints[i]).curve.EndPoint; } x += pp.x; y += pp.y; } InsertInto.center = new GeoPoint2D(x / InsertInto.Joints.Count, y / InsertInto.Joints.Count); clusterTree.AddObject(InsertInto); }
static public CurveGraph CrackCurves(GeoObjectList l, Plane plane, double maxGap) { // alle Kurven in l werden in die Ebene plane projiziert. Das ist mal ein erster Ansatz // Man könnte auch gemeinsame Ebenen finden u.s.w. ArrayList curves = new ArrayList(); BoundingRect ext = BoundingRect.EmptyBoundingRect; foreach (IGeoObject go in l) { ICurve cv = go as ICurve; if (cv != null) { ICurve2D cv2 = cv.GetProjectedCurve(plane); if (cv2 != null) { // "3d" wird nur verwendet um hinterher aus den Originalkurven die Ebene zu bestimmen // in die alles zurücktranformiert wird. Besser würde man vermutlich mit "plane" arbeiten // so wie es hier reinkommt. if (cv2 is Path2D && (cv2 as Path2D).GetSelfIntersections().Length > 0) { // ein sich selbst überschneidender Pfad muss aufgelöst werden ICurve2D[] sub = (cv2 as Path2D).SubCurves; curves.AddRange(sub); for (int i = 0; i < sub.Length; ++i) { sub[i].UserData.Add("3d", cv); } ext.MinMax(cv2.GetExtent()); } else { cv2.UserData.Add("3d", cv); curves.Add(cv2); ext.MinMax(cv2.GetExtent()); } } } } if (curves.Count == 0) { return(null); } QuadTree qt = new QuadTree(ext); qt.MaxDeepth = 8; qt.MaxListLen = 3; for (int i = 0; i < curves.Count; ++i) { qt.AddObject(curves[i] as ICurve2D); } // jetzt alle mit allen schneiden und die Schnipsel in eine weitere Liste stecken ArrayList snippet = new ArrayList(); for (int i = 0; i < curves.Count; ++i) { ICurve2D cv1 = curves[i] as ICurve2D; ArrayList intersectionPoints = new ArrayList(); // double ICollection closecurves = qt.GetObjectsCloseTo(cv1); foreach (ICurve2D cv2 in closecurves) { if (cv2 != cv1) { //if ((cv1 is Line2D && (cv1 as Line2D).Length > 10 && (cv1 as Line2D).Length < 15) || // (cv2 is Line2D && (cv2 as Line2D).Length > 10 && (cv2 as Line2D).Length < 15)) //{ //} GeoPoint2DWithParameter[] isp = cv1.Intersect(cv2); for (int k = 0; k < isp.Length; ++k) { if (cv2.IsParameterOnCurve(isp[k].par2) && 0.0 < isp[k].par1 && isp[k].par1 < 1.0) { intersectionPoints.Add(isp[k].par1); } } } } if (intersectionPoints.Count == 0) { snippet.Add(cv1); } else { intersectionPoints.Add(0.0); intersectionPoints.Add(1.0); // damit sinds mindesten 3 double[] pps = (double[])intersectionPoints.ToArray(typeof(double)); Array.Sort(pps); for (int ii = 1; ii < pps.Length; ++ii) { if (pps[ii - 1] < pps[ii]) { ICurve2D cv3 = cv1.Trim(pps[ii - 1], pps[ii]); if (cv3 != null) { #if DEBUG GeoPoint2D dbg1 = cv1.PointAt(pps[ii - 1]); GeoPoint2D dbg2 = cv1.PointAt(pps[ii]); GeoPoint2D dbg3 = cv3.StartPoint; GeoPoint2D dbg4 = cv3.EndPoint; double d1 = dbg1 | dbg3; double d2 = dbg2 | dbg4; #endif cv3.UserData.Add("3d", cv1.UserData.GetData("3d")); snippet.Add(cv3); } } } } } // snippet ist jetzt die Liste aller Schnipsel return(new CurveGraph((ICurve2D[])snippet.ToArray(typeof(ICurve2D)), maxGap)); }
public void Add(IQuadTreeInsertableZ toAdd) { allObjects.AddObject(toAdd); extent.MinMax(toAdd.GetExtent()); }