Vertex *InsertPointInEdge(float2 point, Edge *edge) { _flipStack.Push(edge->ONext->Sym); _flipStack.Push(edge->DPrev->Sym); _flipStack.Push(edge->OPrev); _flipStack.Push(edge->DNext); for (var i = 0; i < _flipStack.Count; i++) { Assert.IsTrue(Math.Ccw(_flipStack[i]->Org->Point, _flipStack[i]->Dest->Point, point)); } DestroyedTriangle(edge->TriangleId); DestroyedTriangle(edge->Sym->TriangleId); var crep = edge->QuadEdge->Crep; var e = edge->OPrev; C.Remove((IntPtr)edge); RemoveEdge(edge, false); var result = CreateVertex(point); V.TryAdd((IntPtr)result); V.TryAdd((IntPtr)e->Org); var newEdge = CreateEdge(e->Org, result); newEdge->QuadEdge->Crep = GetCrep(crep); Splice(newEdge, e); V.TryAdd((IntPtr)e->Dest); V.TryAdd((IntPtr)newEdge->Sym->Org); newEdge = Connect(e, newEdge->Sym); e = newEdge->OPrev; V.TryAdd((IntPtr)e->Dest); V.TryAdd((IntPtr)newEdge->Sym->Org); newEdge = Connect(e, newEdge->Sym); newEdge->QuadEdge->Crep = crep; e = newEdge->OPrev; V.TryAdd((IntPtr)e->Dest); V.TryAdd((IntPtr)newEdge->Sym->Org); Connect(e, newEdge->Sym); var te = result->Edge; NewTriangle(te); te = te->ONext; NewTriangle(te); te = te->ONext; NewTriangle(te); te = te->ONext; NewTriangle(te); FlipEdges(point); return(result); }
void IsCdt(Navmesh *lct, int constraint = -1, int vertex = -1) { var e = lct->GetEdgeEnumerator(true); while (e.MoveNext()) { if (e.Current->Constrained) { continue; } var o = e.Current->Org->Point; var d = e.Current->Dest->Point; if (Math.Contains(o, -lct->Extent, lct->Extent) && Math.Contains(d, -lct->Extent, lct->Extent)) { var on = e.Current->ONext->Dest->Point; var dn = e.Current->DNext->Org->Point; if (Math.CircumcircleContains(o, d, on, dn) && Math.Ccw(dn, d, on) && Math.Ccw(on, o, dn)) { Debug.Log($"delaunay fail, constraint: {constraint}, vertex:{vertex}, from: {o}, to: {d}"); throw new Exception(); } } } }
// https://www.researchgate.net/publication/2478154_Fully_Dynamic_Constrained_Delaunay_Triangulations void FlipEdges(float2 p) { while (_flipStack.Count > 0) { var e = _flipStack.Pop(); Assert.IsTrue(Math.Ccw(e->Org->Point, e->Dest->Point, p)); if (!e->Constrained && Math.CircumcircleContains(e->Org->Point, e->Dest->Point, p, e->DNext->Org->Point)) { _flipStack.Push(e->OPrev); _flipStack.Push(e->DNext); Assert.IsTrue(Math.Ccw(e->OPrev->Org->Point, e->OPrev->Dest->Point, p)); Assert.IsTrue(Math.Ccw(e->DNext->Org->Point, e->DNext->Dest->Point, p)); Swap(e); } } }
static Edge *GetLeftEdge(Vertex *a, float2 p) { var result = a->Edge; var o = result->Org->Point; InfiniteLoopDetection.Reset(); while (!Math.Ccw(o, p, result->Dest->Point)) { InfiniteLoopDetection.Register(1000, "GetLeftEdge 0"); result = result->ONext; } InfiniteLoopDetection.Reset(); while (Math.Ccw(o, p, result->OPrev->Dest->Point)) { InfiniteLoopDetection.Register(1000, "GetLeftEdge 1"); result = result->OPrev; } return(result); }
Vertex *InsertPointInFace(float2 p, Edge *edge) { _flipStack.Push(edge->ONext->Sym); _flipStack.Push(edge); _flipStack.Push(edge->DPrev->Sym); for (var i = 0; i < _flipStack.Count; i++) { Assert.IsTrue(Math.Ccw(_flipStack[i]->Org->Point, _flipStack[i]->Dest->Point, p)); } DestroyedTriangle(edge->TriangleId); var result = CreateVertex(p); V.TryAdd((IntPtr)result); V.TryAdd((IntPtr)edge->Org); V.TryAdd((IntPtr)edge->Dest); V.TryAdd((IntPtr)edge->LNext->Dest); var newEdge = CreateEdge(edge->Org, result); Splice(newEdge, edge); newEdge = Connect(edge, newEdge->Sym); Connect(newEdge->OPrev, newEdge->Sym); var te = result->Edge; NewTriangle(te); te = te->ONext; NewTriangle(te); te = te->ONext; NewTriangle(te); FlipEdges(p); return(result); }
// http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.61.3862&rep=rep1&type=pdf // TriangulatePseudopolygonDelaunay() void RetriangulateFace(Edge *edge) { Assert.IsTrue(edge != null); Assert.IsTrue(edge != edge->LNext->LNext); if (edge->LNext->LNext->LNext == edge) { NewTriangle(edge); return; } InfiniteLoopDetection.Reset(); while (!Math.Ccw(edge->Org->Point, edge->Dest->Point, edge->LNext->Dest->Point)) { InfiniteLoopDetection.Register(1000, "RetriangulateFace 0"); edge = edge->LNext; } var c = edge->LNext; var e = c; InfiniteLoopDetection.Reset(); while (true) { InfiniteLoopDetection.Register(1000, "RetriangulateFace 1"); e = e->LNext; if (e->LNext == edge) { break; } if (Math.CircumcircleContains(edge->Org->Point, edge->Dest->Point, c->Dest->Point, e->Dest->Point)) { c = e; } } Assert.IsTrue(c != edge); var connected = false; if (c->LNext->LNext != edge) { V.TryAdd((IntPtr)edge->LPrev->Dest); V.TryAdd((IntPtr)c->LNext->Org); var b = Connect(edge->LPrev, c->LNext); RetriangulateFace(b); connected = true; } if (c != edge->LNext) { V.TryAdd((IntPtr)c->Dest); V.TryAdd((IntPtr)edge->LNext->Org); var a = Connect(c, edge->LNext); RetriangulateFace(a); connected = true; } if (connected) { NewTriangle(edge); } }