123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812 |
- // -----------------------------------------------------------------------
- // <copyright file="SweepLine.cs">
- // Original Triangle code by Jonathan Richard Shewchuk, http://www.cs.cmu.edu/~quake/triangle.html
- // Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
- // </copyright>
- // -----------------------------------------------------------------------
- namespace UnityEngine.U2D.Animation.TriangleNet
- .Meshing.Algorithm
- {
- using System;
- using System.Collections.Generic;
- using Animation.TriangleNet.Topology;
- using Animation.TriangleNet.Geometry;
- using Animation.TriangleNet.Tools;
- /// <summary>
- /// Builds a delaunay triangulation using the sweepline algorithm.
- /// </summary>
- internal class SweepLine : ITriangulator
- {
- static int randomseed = 1;
- static int SAMPLERATE = 10;
- static int randomnation(int choices)
- {
- randomseed = (randomseed * 1366 + 150889) % 714025;
- return randomseed / (714025 / choices + 1);
- }
- IPredicates predicates;
- Mesh mesh;
- double xminextreme; // Nonexistent x value used as a flag in sweepline.
- List<SplayNode> splaynodes;
- public IMesh Triangulate(IList<Vertex> points, Configuration config)
- {
- this.predicates = config.Predicates();
- this.mesh = new Mesh(config);
- this.mesh.TransferNodes(points);
- // Nonexistent x value used as a flag to mark circle events in sweepline
- // Delaunay algorithm.
- xminextreme = 10 * mesh.bounds.Left - 9 * mesh.bounds.Right;
- SweepEvent[] eventheap;
- SweepEvent nextevent;
- SweepEvent newevent;
- SplayNode splayroot;
- Otri bottommost = default(Otri);
- Otri searchtri = default(Otri);
- Otri fliptri;
- Otri lefttri = default(Otri);
- Otri righttri = default(Otri);
- Otri farlefttri = default(Otri);
- Otri farrighttri = default(Otri);
- Otri inserttri = default(Otri);
- Vertex firstvertex, secondvertex;
- Vertex nextvertex, lastvertex;
- Vertex connectvertex;
- Vertex leftvertex, midvertex, rightvertex;
- double lefttest, righttest;
- int heapsize;
- bool check4events, farrightflag = false;
- splaynodes = new List<SplayNode>();
- splayroot = null;
- heapsize = points.Count;
- CreateHeap(out eventheap, heapsize);//, out events, out freeevents);
- mesh.MakeTriangle(ref lefttri);
- mesh.MakeTriangle(ref righttri);
- lefttri.Bond(ref righttri);
- lefttri.Lnext();
- righttri.Lprev();
- lefttri.Bond(ref righttri);
- lefttri.Lnext();
- righttri.Lprev();
- lefttri.Bond(ref righttri);
- firstvertex = eventheap[0].vertexEvent;
- HeapDelete(eventheap, heapsize, 0);
- heapsize--;
- do
- {
- if (heapsize == 0)
- {
- Log.Instance.Error("Input vertices are all identical.", "SweepLine.Triangulate()");
- throw new Exception("Input vertices are all identical.");
- }
- secondvertex = eventheap[0].vertexEvent;
- HeapDelete(eventheap, heapsize, 0);
- heapsize--;
- if ((firstvertex.x == secondvertex.x) &&
- (firstvertex.y == secondvertex.y))
- {
- if (Log.Verbose)
- {
- Log.Instance.Warning("A duplicate vertex appeared and was ignored (ID " + secondvertex.id + ").",
- "SweepLine.Triangulate().1");
- }
- secondvertex.type = VertexType.UndeadVertex;
- mesh.undeads++;
- }
- }
- while ((firstvertex.x == secondvertex.x) &&
- (firstvertex.y == secondvertex.y));
- lefttri.SetOrg(firstvertex);
- lefttri.SetDest(secondvertex);
- righttri.SetOrg(secondvertex);
- righttri.SetDest(firstvertex);
- lefttri.Lprev(ref bottommost);
- lastvertex = secondvertex;
- while (heapsize > 0)
- {
- nextevent = eventheap[0];
- HeapDelete(eventheap, heapsize, 0);
- heapsize--;
- check4events = true;
- if (nextevent.xkey < mesh.bounds.Left)
- {
- fliptri = nextevent.otriEvent;
- fliptri.Oprev(ref farlefttri);
- Check4DeadEvent(ref farlefttri, eventheap, ref heapsize);
- fliptri.Onext(ref farrighttri);
- Check4DeadEvent(ref farrighttri, eventheap, ref heapsize);
- if (farlefttri.Equals(bottommost))
- {
- fliptri.Lprev(ref bottommost);
- }
- mesh.Flip(ref fliptri);
- fliptri.SetApex(null);
- fliptri.Lprev(ref lefttri);
- fliptri.Lnext(ref righttri);
- lefttri.Sym(ref farlefttri);
- if (randomnation(SAMPLERATE) == 0)
- {
- fliptri.Sym();
- leftvertex = fliptri.Dest();
- midvertex = fliptri.Apex();
- rightvertex = fliptri.Org();
- splayroot = CircleTopInsert(splayroot, lefttri, leftvertex, midvertex, rightvertex, nextevent.ykey);
- }
- }
- else
- {
- nextvertex = nextevent.vertexEvent;
- if ((nextvertex.x == lastvertex.x) &&
- (nextvertex.y == lastvertex.y))
- {
- if (Log.Verbose)
- {
- Log.Instance.Warning("A duplicate vertex appeared and was ignored (ID " + nextvertex.id + ").",
- "SweepLine.Triangulate().2");
- }
- nextvertex.type = VertexType.UndeadVertex;
- mesh.undeads++;
- check4events = false;
- }
- else
- {
- lastvertex = nextvertex;
- splayroot = FrontLocate(splayroot, bottommost, nextvertex, ref searchtri, ref farrightflag);
- //bottommost.Copy(ref searchtri);
- //farrightflag = false;
- //while (!farrightflag && RightOfHyperbola(ref searchtri, nextvertex))
- //{
- // searchtri.OnextSelf();
- // farrightflag = searchtri.Equal(bottommost);
- //}
- Check4DeadEvent(ref searchtri, eventheap, ref heapsize);
- searchtri.Copy(ref farrighttri);
- searchtri.Sym(ref farlefttri);
- mesh.MakeTriangle(ref lefttri);
- mesh.MakeTriangle(ref righttri);
- connectvertex = farrighttri.Dest();
- lefttri.SetOrg(connectvertex);
- lefttri.SetDest(nextvertex);
- righttri.SetOrg(nextvertex);
- righttri.SetDest(connectvertex);
- lefttri.Bond(ref righttri);
- lefttri.Lnext();
- righttri.Lprev();
- lefttri.Bond(ref righttri);
- lefttri.Lnext();
- righttri.Lprev();
- lefttri.Bond(ref farlefttri);
- righttri.Bond(ref farrighttri);
- if (!farrightflag && farrighttri.Equals(bottommost))
- {
- lefttri.Copy(ref bottommost);
- }
- if (randomnation(SAMPLERATE) == 0)
- {
- splayroot = SplayInsert(splayroot, lefttri, nextvertex);
- }
- else if (randomnation(SAMPLERATE) == 0)
- {
- righttri.Lnext(ref inserttri);
- splayroot = SplayInsert(splayroot, inserttri, nextvertex);
- }
- }
- }
- if (check4events)
- {
- leftvertex = farlefttri.Apex();
- midvertex = lefttri.Dest();
- rightvertex = lefttri.Apex();
- lefttest = predicates.CounterClockwise(leftvertex, midvertex, rightvertex);
- if (lefttest > 0.0)
- {
- newevent = new SweepEvent();
- newevent.xkey = xminextreme;
- newevent.ykey = CircleTop(leftvertex, midvertex, rightvertex, lefttest);
- newevent.otriEvent = lefttri;
- HeapInsert(eventheap, heapsize, newevent);
- heapsize++;
- lefttri.SetOrg(new SweepEventVertex(newevent));
- }
- leftvertex = righttri.Apex();
- midvertex = righttri.Org();
- rightvertex = farrighttri.Apex();
- righttest = predicates.CounterClockwise(leftvertex, midvertex, rightvertex);
- if (righttest > 0.0)
- {
- newevent = new SweepEvent();
- newevent.xkey = xminextreme;
- newevent.ykey = CircleTop(leftvertex, midvertex, rightvertex, righttest);
- newevent.otriEvent = farrighttri;
- HeapInsert(eventheap, heapsize, newevent);
- heapsize++;
- farrighttri.SetOrg(new SweepEventVertex(newevent));
- }
- }
- }
- splaynodes.Clear();
- bottommost.Lprev();
- this.mesh.hullsize = RemoveGhosts(ref bottommost);
- return this.mesh;
- }
- #region Heap
- void HeapInsert(SweepEvent[] heap, int heapsize, SweepEvent newevent)
- {
- double eventx, eventy;
- int eventnum;
- int parent;
- bool notdone;
- eventx = newevent.xkey;
- eventy = newevent.ykey;
- eventnum = heapsize;
- notdone = eventnum > 0;
- while (notdone)
- {
- parent = (eventnum - 1) >> 1;
- if ((heap[parent].ykey < eventy) ||
- ((heap[parent].ykey == eventy)
- && (heap[parent].xkey <= eventx)))
- {
- notdone = false;
- }
- else
- {
- heap[eventnum] = heap[parent];
- heap[eventnum].heapposition = eventnum;
- eventnum = parent;
- notdone = eventnum > 0;
- }
- }
- heap[eventnum] = newevent;
- newevent.heapposition = eventnum;
- }
- void Heapify(SweepEvent[] heap, int heapsize, int eventnum)
- {
- SweepEvent thisevent;
- double eventx, eventy;
- int leftchild, rightchild;
- int smallest;
- bool notdone;
- thisevent = heap[eventnum];
- eventx = thisevent.xkey;
- eventy = thisevent.ykey;
- leftchild = 2 * eventnum + 1;
- notdone = leftchild < heapsize;
- while (notdone)
- {
- if ((heap[leftchild].ykey < eventy) ||
- ((heap[leftchild].ykey == eventy)
- && (heap[leftchild].xkey < eventx)))
- {
- smallest = leftchild;
- }
- else
- {
- smallest = eventnum;
- }
- rightchild = leftchild + 1;
- if (rightchild < heapsize)
- {
- if ((heap[rightchild].ykey < heap[smallest].ykey) ||
- ((heap[rightchild].ykey == heap[smallest].ykey)
- && (heap[rightchild].xkey < heap[smallest].xkey)))
- {
- smallest = rightchild;
- }
- }
- if (smallest == eventnum)
- {
- notdone = false;
- }
- else
- {
- heap[eventnum] = heap[smallest];
- heap[eventnum].heapposition = eventnum;
- heap[smallest] = thisevent;
- thisevent.heapposition = smallest;
- eventnum = smallest;
- leftchild = 2 * eventnum + 1;
- notdone = leftchild < heapsize;
- }
- }
- }
- void HeapDelete(SweepEvent[] heap, int heapsize, int eventnum)
- {
- SweepEvent moveevent;
- double eventx, eventy;
- int parent;
- bool notdone;
- moveevent = heap[heapsize - 1];
- if (eventnum > 0)
- {
- eventx = moveevent.xkey;
- eventy = moveevent.ykey;
- do
- {
- parent = (eventnum - 1) >> 1;
- if ((heap[parent].ykey < eventy) ||
- ((heap[parent].ykey == eventy)
- && (heap[parent].xkey <= eventx)))
- {
- notdone = false;
- }
- else
- {
- heap[eventnum] = heap[parent];
- heap[eventnum].heapposition = eventnum;
- eventnum = parent;
- notdone = eventnum > 0;
- }
- }
- while (notdone);
- }
- heap[eventnum] = moveevent;
- moveevent.heapposition = eventnum;
- Heapify(heap, heapsize - 1, eventnum);
- }
- void CreateHeap(out SweepEvent[] eventheap, int size)
- {
- Vertex thisvertex;
- int maxevents;
- int i;
- SweepEvent evt;
- maxevents = (3 * size) / 2;
- eventheap = new SweepEvent[maxevents];
- i = 0;
- foreach (var v in mesh.vertices.Values)
- {
- thisvertex = v;
- evt = new SweepEvent();
- evt.vertexEvent = thisvertex;
- evt.xkey = thisvertex.x;
- evt.ykey = thisvertex.y;
- HeapInsert(eventheap, i++, evt);
- }
- }
- #endregion
- #region Splaytree
- SplayNode Splay(SplayNode splaytree, Point searchpoint, ref Otri searchtri)
- {
- SplayNode child, grandchild;
- SplayNode lefttree, righttree;
- SplayNode leftright;
- Vertex checkvertex;
- bool rightofroot, rightofchild;
- if (splaytree == null)
- {
- return null;
- }
- checkvertex = splaytree.keyedge.Dest();
- if (checkvertex == splaytree.keydest)
- {
- rightofroot = RightOfHyperbola(ref splaytree.keyedge, searchpoint);
- if (rightofroot)
- {
- splaytree.keyedge.Copy(ref searchtri);
- child = splaytree.rchild;
- }
- else
- {
- child = splaytree.lchild;
- }
- if (child == null)
- {
- return splaytree;
- }
- checkvertex = child.keyedge.Dest();
- if (checkvertex != child.keydest)
- {
- child = Splay(child, searchpoint, ref searchtri);
- if (child == null)
- {
- if (rightofroot)
- {
- splaytree.rchild = null;
- }
- else
- {
- splaytree.lchild = null;
- }
- return splaytree;
- }
- }
- rightofchild = RightOfHyperbola(ref child.keyedge, searchpoint);
- if (rightofchild)
- {
- child.keyedge.Copy(ref searchtri);
- grandchild = Splay(child.rchild, searchpoint, ref searchtri);
- child.rchild = grandchild;
- }
- else
- {
- grandchild = Splay(child.lchild, searchpoint, ref searchtri);
- child.lchild = grandchild;
- }
- if (grandchild == null)
- {
- if (rightofroot)
- {
- splaytree.rchild = child.lchild;
- child.lchild = splaytree;
- }
- else
- {
- splaytree.lchild = child.rchild;
- child.rchild = splaytree;
- }
- return child;
- }
- if (rightofchild)
- {
- if (rightofroot)
- {
- splaytree.rchild = child.lchild;
- child.lchild = splaytree;
- }
- else
- {
- splaytree.lchild = grandchild.rchild;
- grandchild.rchild = splaytree;
- }
- child.rchild = grandchild.lchild;
- grandchild.lchild = child;
- }
- else
- {
- if (rightofroot)
- {
- splaytree.rchild = grandchild.lchild;
- grandchild.lchild = splaytree;
- }
- else
- {
- splaytree.lchild = child.rchild;
- child.rchild = splaytree;
- }
- child.lchild = grandchild.rchild;
- grandchild.rchild = child;
- }
- return grandchild;
- }
- else
- {
- lefttree = Splay(splaytree.lchild, searchpoint, ref searchtri);
- righttree = Splay(splaytree.rchild, searchpoint, ref searchtri);
- splaynodes.Remove(splaytree);
- if (lefttree == null)
- {
- return righttree;
- }
- else if (righttree == null)
- {
- return lefttree;
- }
- else if (lefttree.rchild == null)
- {
- lefttree.rchild = righttree.lchild;
- righttree.lchild = lefttree;
- return righttree;
- }
- else if (righttree.lchild == null)
- {
- righttree.lchild = lefttree.rchild;
- lefttree.rchild = righttree;
- return lefttree;
- }
- else
- {
- // printf("Holy Toledo!!!\n");
- leftright = lefttree.rchild;
- while (leftright.rchild != null)
- {
- leftright = leftright.rchild;
- }
- leftright.rchild = righttree;
- return lefttree;
- }
- }
- }
- SplayNode SplayInsert(SplayNode splayroot, Otri newkey, Point searchpoint)
- {
- SplayNode newsplaynode;
- newsplaynode = new SplayNode(); //poolalloc(m.splaynodes);
- splaynodes.Add(newsplaynode);
- newkey.Copy(ref newsplaynode.keyedge);
- newsplaynode.keydest = newkey.Dest();
- if (splayroot == null)
- {
- newsplaynode.lchild = null;
- newsplaynode.rchild = null;
- }
- else if (RightOfHyperbola(ref splayroot.keyedge, searchpoint))
- {
- newsplaynode.lchild = splayroot;
- newsplaynode.rchild = splayroot.rchild;
- splayroot.rchild = null;
- }
- else
- {
- newsplaynode.lchild = splayroot.lchild;
- newsplaynode.rchild = splayroot;
- splayroot.lchild = null;
- }
- return newsplaynode;
- }
- SplayNode FrontLocate(SplayNode splayroot, Otri bottommost, Vertex searchvertex,
- ref Otri searchtri, ref bool farright)
- {
- bool farrightflag;
- bottommost.Copy(ref searchtri);
- splayroot = Splay(splayroot, searchvertex, ref searchtri);
- farrightflag = false;
- while (!farrightflag && RightOfHyperbola(ref searchtri, searchvertex))
- {
- searchtri.Onext();
- farrightflag = searchtri.Equals(bottommost);
- }
- farright = farrightflag;
- return splayroot;
- }
- SplayNode CircleTopInsert(SplayNode splayroot, Otri newkey,
- Vertex pa, Vertex pb, Vertex pc, double topy)
- {
- double ccwabc;
- double xac, yac, xbc, ybc;
- double aclen2, bclen2;
- Point searchpoint = new Point(); // TODO: mesh.nextras
- Otri dummytri = default(Otri);
- ccwabc = predicates.CounterClockwise(pa, pb, pc);
- xac = pa.x - pc.x;
- yac = pa.y - pc.y;
- xbc = pb.x - pc.x;
- ybc = pb.y - pc.y;
- aclen2 = xac * xac + yac * yac;
- bclen2 = xbc * xbc + ybc * ybc;
- searchpoint.x = pc.x - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
- searchpoint.y = topy;
- return SplayInsert(Splay(splayroot, searchpoint, ref dummytri), newkey, searchpoint);
- }
- #endregion
- bool RightOfHyperbola(ref Otri fronttri, Point newsite)
- {
- Vertex leftvertex, rightvertex;
- double dxa, dya, dxb, dyb;
- Statistic.HyperbolaCount++;
- leftvertex = fronttri.Dest();
- rightvertex = fronttri.Apex();
- if ((leftvertex.y < rightvertex.y) ||
- ((leftvertex.y == rightvertex.y) &&
- (leftvertex.x < rightvertex.x)))
- {
- if (newsite.x >= rightvertex.x)
- {
- return true;
- }
- }
- else
- {
- if (newsite.x <= leftvertex.x)
- {
- return false;
- }
- }
- dxa = leftvertex.x - newsite.x;
- dya = leftvertex.y - newsite.y;
- dxb = rightvertex.x - newsite.x;
- dyb = rightvertex.y - newsite.y;
- return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
- }
- double CircleTop(Vertex pa, Vertex pb, Vertex pc, double ccwabc)
- {
- double xac, yac, xbc, ybc, xab, yab;
- double aclen2, bclen2, ablen2;
- Statistic.CircleTopCount++;
- xac = pa.x - pc.x;
- yac = pa.y - pc.y;
- xbc = pb.x - pc.x;
- ybc = pb.y - pc.y;
- xab = pa.x - pb.x;
- yab = pa.y - pb.y;
- aclen2 = xac * xac + yac * yac;
- bclen2 = xbc * xbc + ybc * ybc;
- ablen2 = xab * xab + yab * yab;
- return pc.y + (xac * bclen2 - xbc * aclen2 + Math.Sqrt(aclen2 * bclen2 * ablen2)) / (2.0 * ccwabc);
- }
- void Check4DeadEvent(ref Otri checktri, SweepEvent[] eventheap, ref int heapsize)
- {
- SweepEvent deadevent;
- SweepEventVertex eventvertex;
- int eventnum = -1;
- eventvertex = checktri.Org() as SweepEventVertex;
- if (eventvertex != null)
- {
- deadevent = eventvertex.evt;
- eventnum = deadevent.heapposition;
- HeapDelete(eventheap, heapsize, eventnum);
- heapsize--;
- checktri.SetOrg(null);
- }
- }
- /// <summary>
- /// Removes ghost triangles.
- /// </summary>
- /// <param name="startghost"></param>
- /// <returns>Number of vertices on the hull.</returns>
- int RemoveGhosts(ref Otri startghost)
- {
- Otri searchedge = default(Otri);
- Otri dissolveedge = default(Otri);
- Otri deadtriangle = default(Otri);
- Vertex markorg;
- int hullsize;
- bool noPoly = !mesh.behavior.Poly;
- var dummytri = mesh.dummytri;
- // Find an edge on the convex hull to start point location from.
- startghost.Lprev(ref searchedge);
- searchedge.Sym();
- dummytri.neighbors[0] = searchedge;
- // Remove the bounding box and count the convex hull edges.
- startghost.Copy(ref dissolveedge);
- hullsize = 0;
- do
- {
- hullsize++;
- dissolveedge.Lnext(ref deadtriangle);
- dissolveedge.Lprev();
- dissolveedge.Sym();
- // If no PSLG is involved, set the boundary markers of all the vertices
- // on the convex hull. If a PSLG is used, this step is done later.
- if (noPoly)
- {
- // Watch out for the case where all the input vertices are collinear.
- if (dissolveedge.tri.id != Mesh.DUMMY)
- {
- markorg = dissolveedge.Org();
- if (markorg.label == 0)
- {
- markorg.label = 1;
- }
- }
- }
- // Remove a bounding triangle from a convex hull triangle.
- dissolveedge.Dissolve(dummytri);
- // Find the next bounding triangle.
- deadtriangle.Sym(ref dissolveedge);
- // Delete the bounding triangle.
- mesh.TriangleDealloc(deadtriangle.tri);
- }
- while (!dissolveedge.Equals(startghost));
- return hullsize;
- }
- #region Internal classes
- /// <summary>
- /// A node in a heap used to store events for the sweepline Delaunay algorithm.
- /// </summary>
- /// <remarks>
- /// Only used in the sweepline algorithm.
- ///
- /// Nodes do not point directly to their parents or children in the heap. Instead, each
- /// node knows its position in the heap, and can look up its parent and children in a
- /// separate array. To distinguish site events from circle events, all circle events are
- /// given an invalid (smaller than 'xmin') x-coordinate 'xkey'.
- /// </remarks>
- class SweepEvent
- {
- public double xkey, ykey; // Coordinates of the event.
- public Vertex vertexEvent; // Vertex event.
- public Otri otriEvent; // Circle event.
- public int heapposition; // Marks this event's position in the heap.
- }
- /// <summary>
- /// Introducing a new class which aggregates a sweep event is the easiest way
- /// to handle the pointer magic of the original code (casting a sweep event
- /// to vertex etc.).
- /// </summary>
- class SweepEventVertex : Vertex
- {
- public SweepEvent evt;
- public SweepEventVertex(SweepEvent e)
- {
- evt = e;
- }
- }
- /// <summary>
- /// A node in the splay tree.
- /// </summary>
- /// <remarks>
- /// Only used in the sweepline algorithm.
- ///
- /// Each node holds an oriented ghost triangle that represents a boundary edge
- /// of the growing triangulation. When a circle event covers two boundary edges
- /// with a triangle, so that they are no longer boundary edges, those edges are
- /// not immediately deleted from the tree; rather, they are lazily deleted when
- /// they are next encountered. (Since only a random sample of boundary edges are
- /// kept in the tree, lazy deletion is faster.) 'keydest' is used to verify that
- /// a triangle is still the same as when it entered the splay tree; if it has
- /// been rotated (due to a circle event), it no longer represents a boundary
- /// edge and should be deleted.
- /// </remarks>
- class SplayNode
- {
- public Otri keyedge; // Lprev of an edge on the front.
- public Vertex keydest; // Used to verify that splay node is still live.
- public SplayNode lchild, rchild; // Children in splay tree.
- }
- #endregion
- }
- }
|