// ----------------------------------------------------------------------- // // 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/ // // ----------------------------------------------------------------------- namespace UnityEngine.U2D.Animation.TriangleNet .Topology { using System; using Animation.TriangleNet.Geometry; /// /// An oriented triangle. /// /// /// Includes a pointer to a triangle and orientation. The orientation denotes an edge /// of the triangle. Hence, there are three possible orientations. By convention, each /// edge always points counterclockwise about the corresponding triangle. /// internal struct Otri { internal Triangle tri; internal int orient; // Ranges from 0 to 2. public Triangle Triangle { get { return tri; } set { tri = value; } } public override string ToString() { if (tri == null) { return "O-TID [null]"; } return String.Format("O-TID {0}", tri.hash); } #region Otri primitives (public) // For fast access static readonly int[] plus1Mod3 = { 1, 2, 0 }; static readonly int[] minus1Mod3 = { 2, 0, 1 }; // The following primitives are all described by Guibas and Stolfi. // However, Guibas and Stolfi use an edge-based data structure, // whereas I use a triangle-based data structure. // // lnext: finds the next edge (counterclockwise) of a triangle. // // onext: spins counterclockwise around a vertex; that is, it finds // the next edge with the same origin in the counterclockwise direction. This // edge is part of a different triangle. // // oprev: spins clockwise around a vertex; that is, it finds the // next edge with the same origin in the clockwise direction. This edge is // part of a different triangle. // // dnext: spins counterclockwise around a vertex; that is, it finds // the next edge with the same destination in the counterclockwise direction. // This edge is part of a different triangle. // // dprev: spins clockwise around a vertex; that is, it finds the // next edge with the same destination in the clockwise direction. This edge // is part of a different triangle. // // rnext: moves one edge counterclockwise about the adjacent // triangle. (It's best understood by reading Guibas and Stolfi. It // involves changing triangles twice.) // // rprev: moves one edge clockwise about the adjacent triangle. // (It's best understood by reading Guibas and Stolfi. It involves // changing triangles twice.) /// /// Find the abutting triangle; same edge. [sym(abc) -> ba*] /// /// Note that the edge direction is necessarily reversed, because the handle specified /// by an oriented triangle is directed counterclockwise around the triangle. /// public void Sym(ref Otri ot) { ot.tri = tri.neighbors[orient].tri; ot.orient = tri.neighbors[orient].orient; } /// /// Find the abutting triangle; same edge. [sym(abc) -> ba*] /// public void Sym() { int tmp = orient; orient = tri.neighbors[tmp].orient; tri = tri.neighbors[tmp].tri; } /// /// Find the next edge (counterclockwise) of a triangle. [lnext(abc) -> bca] /// public void Lnext(ref Otri ot) { ot.tri = tri; ot.orient = plus1Mod3[orient]; } /// /// Find the next edge (counterclockwise) of a triangle. [lnext(abc) -> bca] /// public void Lnext() { orient = plus1Mod3[orient]; } /// /// Find the previous edge (clockwise) of a triangle. [lprev(abc) -> cab] /// public void Lprev(ref Otri ot) { ot.tri = tri; ot.orient = minus1Mod3[orient]; } /// /// Find the previous edge (clockwise) of a triangle. [lprev(abc) -> cab] /// public void Lprev() { orient = minus1Mod3[orient]; } /// /// Find the next edge counterclockwise with the same origin. [onext(abc) -> ac*] /// public void Onext(ref Otri ot) { //Lprev(ref ot); ot.tri = tri; ot.orient = minus1Mod3[orient]; //ot.SymSelf(); int tmp = ot.orient; ot.orient = ot.tri.neighbors[tmp].orient; ot.tri = ot.tri.neighbors[tmp].tri; } /// /// Find the next edge counterclockwise with the same origin. [onext(abc) -> ac*] /// public void Onext() { //LprevSelf(); orient = minus1Mod3[orient]; //SymSelf(); int tmp = orient; orient = tri.neighbors[tmp].orient; tri = tri.neighbors[tmp].tri; } /// /// Find the next edge clockwise with the same origin. [oprev(abc) -> a*b] /// public void Oprev(ref Otri ot) { //Sym(ref ot); ot.tri = tri.neighbors[orient].tri; ot.orient = tri.neighbors[orient].orient; //ot.LnextSelf(); ot.orient = plus1Mod3[ot.orient]; } /// /// Find the next edge clockwise with the same origin. [oprev(abc) -> a*b] /// public void Oprev() { //SymSelf(); int tmp = orient; orient = tri.neighbors[tmp].orient; tri = tri.neighbors[tmp].tri; //LnextSelf(); orient = plus1Mod3[orient]; } /// /// Find the next edge counterclockwise with the same destination. [dnext(abc) -> *ba] /// public void Dnext(ref Otri ot) { //Sym(ref ot); ot.tri = tri.neighbors[orient].tri; ot.orient = tri.neighbors[orient].orient; //ot.LprevSelf(); ot.orient = minus1Mod3[ot.orient]; } /// /// Find the next edge counterclockwise with the same destination. [dnext(abc) -> *ba] /// public void Dnext() { //SymSelf(); int tmp = orient; orient = tri.neighbors[tmp].orient; tri = tri.neighbors[tmp].tri; //LprevSelf(); orient = minus1Mod3[orient]; } /// /// Find the next edge clockwise with the same destination. [dprev(abc) -> cb*] /// public void Dprev(ref Otri ot) { //Lnext(ref ot); ot.tri = tri; ot.orient = plus1Mod3[orient]; //ot.SymSelf(); int tmp = ot.orient; ot.orient = ot.tri.neighbors[tmp].orient; ot.tri = ot.tri.neighbors[tmp].tri; } /// /// Find the next edge clockwise with the same destination. [dprev(abc) -> cb*] /// public void Dprev() { //LnextSelf(); orient = plus1Mod3[orient]; //SymSelf(); int tmp = orient; orient = tri.neighbors[tmp].orient; tri = tri.neighbors[tmp].tri; } /// /// Find the next edge (counterclockwise) of the adjacent triangle. [rnext(abc) -> *a*] /// public void Rnext(ref Otri ot) { //Sym(ref ot); ot.tri = tri.neighbors[orient].tri; ot.orient = tri.neighbors[orient].orient; //ot.LnextSelf(); ot.orient = plus1Mod3[ot.orient]; //ot.SymSelf(); int tmp = ot.orient; ot.orient = ot.tri.neighbors[tmp].orient; ot.tri = ot.tri.neighbors[tmp].tri; } /// /// Find the next edge (counterclockwise) of the adjacent triangle. [rnext(abc) -> *a*] /// public void Rnext() { //SymSelf(); int tmp = orient; orient = tri.neighbors[tmp].orient; tri = tri.neighbors[tmp].tri; //LnextSelf(); orient = plus1Mod3[orient]; //SymSelf(); tmp = orient; orient = tri.neighbors[tmp].orient; tri = tri.neighbors[tmp].tri; } /// /// Find the previous edge (clockwise) of the adjacent triangle. [rprev(abc) -> b**] /// public void Rprev(ref Otri ot) { //Sym(ref ot); ot.tri = tri.neighbors[orient].tri; ot.orient = tri.neighbors[orient].orient; //ot.LprevSelf(); ot.orient = minus1Mod3[ot.orient]; //ot.SymSelf(); int tmp = ot.orient; ot.orient = ot.tri.neighbors[tmp].orient; ot.tri = ot.tri.neighbors[tmp].tri; } /// /// Find the previous edge (clockwise) of the adjacent triangle. [rprev(abc) -> b**] /// public void Rprev() { //SymSelf(); int tmp = orient; orient = tri.neighbors[tmp].orient; tri = tri.neighbors[tmp].tri; //LprevSelf(); orient = minus1Mod3[orient]; //SymSelf(); tmp = orient; orient = tri.neighbors[tmp].orient; tri = tri.neighbors[tmp].tri; } /// /// Origin [org(abc) -> a] /// public Vertex Org() { return tri.vertices[plus1Mod3[orient]]; } /// /// Destination [dest(abc) -> b] /// public Vertex Dest() { return tri.vertices[minus1Mod3[orient]]; } /// /// Apex [apex(abc) -> c] /// public Vertex Apex() { return tri.vertices[orient]; } /// /// Copy an oriented triangle. /// public void Copy(ref Otri ot) { ot.tri = tri; ot.orient = orient; } /// /// Test for equality of oriented triangles. /// public bool Equals(Otri ot) { return ((tri == ot.tri) && (orient == ot.orient)); } #endregion #region Otri primitives (internal) /// /// Set Origin /// internal void SetOrg(Vertex v) { tri.vertices[plus1Mod3[orient]] = v; } /// /// Set Destination /// internal void SetDest(Vertex v) { tri.vertices[minus1Mod3[orient]] = v; } /// /// Set Apex /// internal void SetApex(Vertex v) { tri.vertices[orient] = v; } /// /// Bond two triangles together at the resepective handles. [bond(abc, bad)] /// internal void Bond(ref Otri ot) { tri.neighbors[orient].tri = ot.tri; tri.neighbors[orient].orient = ot.orient; ot.tri.neighbors[ot.orient].tri = this.tri; ot.tri.neighbors[ot.orient].orient = this.orient; } /// /// Dissolve a bond (from one side). /// /// Note that the other triangle will still think it's connected to /// this triangle. Usually, however, the other triangle is being deleted /// entirely, or bonded to another triangle, so it doesn't matter. /// internal void Dissolve(Triangle dummy) { tri.neighbors[orient].tri = dummy; tri.neighbors[orient].orient = 0; } /// /// Infect a triangle with the virus. /// internal void Infect() { tri.infected = true; } /// /// Cure a triangle from the virus. /// internal void Uninfect() { tri.infected = false; } /// /// Test a triangle for viral infection. /// internal bool IsInfected() { return tri.infected; } /// /// Finds a subsegment abutting a triangle. /// internal void Pivot(ref Osub os) { os = tri.subsegs[orient]; } /// /// Bond a triangle to a subsegment. /// internal void SegBond(ref Osub os) { tri.subsegs[orient] = os; os.seg.triangles[os.orient] = this; } /// /// Dissolve a bond (from the triangle side). /// internal void SegDissolve(SubSegment dummy) { tri.subsegs[orient].seg = dummy; } /// /// Check a triangle's deallocation. /// internal static bool IsDead(Triangle tria) { return tria.neighbors[0].tri == null; } /// /// Set a triangle's deallocation. /// internal static void Kill(Triangle tri) { tri.neighbors[0].tri = null; tri.neighbors[2].tri = null; } #endregion } }