float SearchWidth(Vertex c, Triangle t, HalfEdge e, float d) { Vertex u = e.Src, v = e.Dest; if (c.Position.dot2(v.Position, u.Position) <= 0 || c.Position.dot2(u.Position, v.Position) <= 0) { return d; } float d2 = MathUtility.MinDistance2Segment(c.Position, e.Src.Position, e.Dest.Position); if (d2 > d) { return d; } if (e.Constrained) { return d2; } Triangle t2 = e.Pair.Face; if (t2 == null) { Debug.LogError("Invalid t2"); return d; } HalfEdge e2 = t2.GetOpposite(e.Src); HalfEdge e3 = t2.GetOpposite(e.Dest); d = SearchWidth(c, t2, e2, d); return SearchWidth(c, t2, e3, d); }
/// <summary> /// 将点插入到三角形中. /// </summary> void InsertToTriangle(Vertex v, Triangle old) { Triangle ab = geomManager.CreateTriangle(); Triangle bc = geomManager.CreateTriangle(); Triangle ca = geomManager.CreateTriangle(); // 分别构造连接v和old的三个顶点的边, 将old一分为三. HalfEdge av = geomManager.CreateEdge(old.A, v); HalfEdge bv = geomManager.CreateEdge(old.B, v); HalfEdge cv = geomManager.CreateEdge(old.C, v); HalfEdge AB = old.AB, BC = old.BC, CA = old.CA; // 更新Face. AB.Face = bv.Face = av.Pair.Face = ab; BC.Face = cv.Face = bv.Pair.Face = bc; CA.Face = av.Face = cv.Pair.Face = ca; // 释放旧三角形. geomManager.ReleaseTriangle(old); // 连接边. ab.Edge = AB.CycleLink(bv, av.Pair); bc.Edge = BC.CycleLink(cv, bv.Pair); ca.Edge = CA.CycleLink(av, cv.Pair); // 映射到格子地图上. geomManager.RasterizeTriangle(ab); geomManager.RasterizeTriangle(bc); geomManager.RasterizeTriangle(ca); Utility.Verify(av.Face == ca); Utility.Verify(av.Pair.Face == ab); Utility.Verify(bv.Face == ab); Utility.Verify(bv.Pair.Face == bc); Utility.Verify(cv.Face == bc); Utility.Verify(cv.Pair.Face == ca); // 维护delaunay特性. FlipTriangles(ab.Edge); FlipTriangles(bc.Edge); FlipTriangles(ca.Edge); }
/// <summary> /// 将点插入到old的边上. /// </summary> void InsertOnEdge(Vertex v, Triangle old, HalfEdge hitEdge) { // 连接v和v所在的边正对的顶点, 将old一分为二. Triangle split1 = geomManager.CreateTriangle(); Triangle split2 = geomManager.CreateTriangle(); Vertex opositeVertex = hitEdge.Next.Dest; HalfEdge ov = geomManager.CreateEdge(opositeVertex, v); HalfEdge v1 = geomManager.CreateEdge(v, hitEdge.Dest); HalfEdge v2 = geomManager.CreateEdge(v, hitEdge.Pair.Dest); HalfEdge sp1Edge0 = hitEdge.Next; HalfEdge sp2Edge0 = hitEdge.Next.Next; HalfEdge sp2Edge1 = v2.Pair; HalfEdge sp2Edge2 = ov.Pair; // 更新Face. sp1Edge0.Face = ov.Face = v1.Face = split1; sp2Edge0.Face = sp2Edge1.Face = sp2Edge2.Face = split2; // 释放旧三角形. geomManager.ReleaseTriangle(old); // 连接边. split1.Edge = sp1Edge0.CycleLink(ov, v1); split2.Edge = sp2Edge0.CycleLink(sp2Edge1, sp2Edge2); // 将新三角形映射到格子地图上. geomManager.RasterizeTriangle(split1); geomManager.RasterizeTriangle(split2); Utility.Verify(ov.Face == split1); Utility.Verify(ov.Pair.Face == split2); Triangle other = hitEdge.Pair.Face; Triangle oposite1 = null; Triangle oposite2 = null; // 分割另一侧的三角形. if (other != null) { Vertex p = hitEdge.Pair.Next.Dest; HalfEdge vp = geomManager.CreateEdge(v, p); oposite1 = geomManager.CreateTriangle(); oposite2 = geomManager.CreateTriangle(); HalfEdge hpn = hitEdge.Pair.Next; HalfEdge op1Edge0 = hpn.Next; HalfEdge op1Edge1 = v1.Pair; HalfEdge op1Edge2 = vp; hpn.Face = vp.Pair.Face = v2.Face = oposite2; op1Edge0.Face = op1Edge1.Face = op1Edge2.Face = oposite1; geomManager.ReleaseTriangle(other); oposite2.Edge = hpn.CycleLink(vp.Pair, v2); oposite1.Edge = op1Edge0.CycleLink(op1Edge1, op1Edge2); geomManager.RasterizeTriangle(oposite1); geomManager.RasterizeTriangle(oposite2); Utility.Verify(vp.Face == oposite1); Utility.Verify(vp.Pair.Face == oposite2); } Utility.Verify(v1.Face == split1); Utility.Verify(v1.Pair.Face == oposite1); Utility.Verify(v2.Face == oposite2); Utility.Verify(v2.Pair.Face == split2); // 维护delaunay特性. FlipTriangles(split1.Edge); FlipTriangles(split2.Edge); if (other != null) { FlipTriangles(oposite1.Edge); FlipTriangles(oposite2.Edge); } }
public bool SharesEdgeWith(Triangle triangle) { var sharedVertices = Vertices.Where(o => triangle.Vertices.Contains(o)).Count(); return(sharedVertices == 2); }
/// <summary> /// 查找与triangle的外接矩形相交的格子. /// </summary> TiledMapRegion FindTriangleBoundingRectOverlappedTiles(Triangle triangle) { float xMin = Mathf.Min(triangle.A.Position.x, triangle.B.Position.x, triangle.C.Position.x); float xMax = Mathf.Max(triangle.A.Position.x, triangle.B.Position.x, triangle.C.Position.x); float zMin = Mathf.Min(triangle.A.Position.z, triangle.B.Position.z, triangle.C.Position.z); float zMax = Mathf.Max(triangle.A.Position.z, triangle.B.Position.z, triangle.C.Position.z); return tiledMap.GetTiles(xMin, xMax, zMin, zMax); }
/// <summary> /// 将triangle的映射从TiledMap上去掉. /// </summary> public void UnrasterizeTriangle(Triangle triangle) { TiledMapRegion tmr = FindTriangleBoundingRectOverlappedTiles(triangle); for (; tmr.MoveNext(); ) { Tile tile = tiledMap[tmr.Current.First, tmr.Current.Second]; if (tile.Face == triangle) { tile.Face = null; } } }
/// <summary> /// 将triangle映射到TiledMap上. /// </summary> public void RasterizeTriangle(Triangle triangle) { Vector3[] list = new Vector3[] { triangle.A.Position, triangle.B.Position, triangle.C.Position }; TiledMapRegion tmr = FindTriangleBoundingRectOverlappedTiles(triangle); for (; tmr.MoveNext(); ) { Tuple2<int, int> current = tmr.Current; Tile tile = tiledMap[current.First, current.Second]; Vector3 center = tiledMap.GetTileCenter(current.First, current.Second); if (MathUtility.PolygonContains(list, center)) { tile.Face = triangle; } } }
/// <summary> /// 释放triangle. /// </summary> public void ReleaseTriangle(Triangle triangle) { UnrasterizeTriangle(triangle); foreach (HalfEdge edge in triangle.BoundingEdges) { if (edge.Face == triangle) { edge.Face = null; edge.Next = null; } if (edge.Face == null && edge.Pair.Face == null) { ReleaseEdge(edge); } } }