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); } } }
void FlipQuad() { while (_flipStack.Count > 0) { var edge = _flipStack.Pop(); if (!edge->Constrained && Math.CircumcircleContains(edge->Org->Point, edge->Dest->Point, edge->ONext->Dest->Point, edge->DNext->Org->Point)) { _flipStack.Push(edge->OPrev); _flipStack.Push(edge->DNext); _flipStack.Push(edge->Sym->OPrev); _flipStack.Push(edge->Sym->DNext); Swap(edge); } } }
// 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); } }