/// <summary> /// Find triangle in which falls <code>node</code>. /// </summary> /// <param name="T"> /// Initial triangle for search algorithm. /// Works faster with triangles located closer to node. /// </param> /// <returns>Triangle in which falls passed node.</returns> private static Triangle FindTriangleBySeparatingRibs(Point node, Triangle T) { Rib separatingRib = GetSeparatingRib(T, node); while (separatingRib != null) { T = separatingRib.GetAdjacent(T); separatingRib = GetSeparatingRib(T, node); } return(T); }
/// <summary> /// Returns index of passed rib in array of ribs. /// </summary> /// <returns>Index of passed rib.</returns> public int GetIndex(Rib rib) { for (int i = 0; i < 3; ++i) { if (Ribs[i] == rib) { return(i); } } throw new ArgumentException(); }
/// <summary> /// Update triangle's internal representation. /// Sorting ribs and vertices in such way that first rib would match rib that lays on first & second /// vertices, second rib would match rib that lays on second & third vertices, and third rib would match /// rib that lays on firs & third vertices. /// </summary> public unsafe void Update() { Rib a = Ribs[0]; Rib b = null; Rib c = null; var A = a.A; var B = a.B; Point C = new Point(); var r1 = Ribs[1]; if (r1.A.Equals(A)) { b = Ribs[2]; c = r1; C = r1.B; } else if (r1.B.Equals(A)) { b = Ribs[2]; c = r1; C = r1.A; } else if (r1.A.Equals(B)) { b = r1; c = Ribs[2]; C = r1.B; } else if (r1.B.Equals(B)) { b = r1; c = Ribs[2]; C = r1.A; } fixed(Point *points = Vertices) { points[0] = A; points[1] = B; points[2] = C; } Ribs[0] = a; Ribs[1] = b; Ribs[2] = c; }
/// <summary> /// Put node on rib that located somewhere in the bounds of superstructure /// and it has adjacent triangles from both sides. /// </summary> /// <param name="newTriangles">Collection of new triangles.</param> /// <returns>Modified triangles.</returns> private static IEnumerable <Triangle> PutPointOnInnerRib(Rib rib, Point node, out IEnumerable <Triangle> newTriangles) { // Triangles. var LT = rib.T1; var RT = rib.T2; var NLT = new Triangle(); var NRT = new Triangle(); // Vertices of rib. var A = rib.A; var B = rib.B; // Third vertex of left triangle. var C = LT.GetOppositeNode(rib); // Third vertex of right triangle. var D = RT.GetOppositeNode(rib); // Ribs that requires update. var BC = LT.GetOppositeRib(A); var BD = RT.GetOppositeRib(A); // New ribs. var OC = new Rib(node, C, LT, NLT); var OD = new Rib(node, D, RT, NRT); var OB = new Rib(node, B, NLT, NRT); // Update ribs links. BC.Update(LT, NLT); BD.Update(RT, NRT); // Set ribs to new triangles. NLT.SetRibs(OC, OB, BC); NRT.SetRibs(OD, OB, BD); // Update ribs of existing triangles. LT.UpdateRib(BC, OC); RT.UpdateRib(BD, OD); // Change vertex B of old adjacent rib to passed node. rib.B = node; // Update triangles. LT.Update(); RT.Update(); NLT.Update(); NRT.Update(); // Set newTriangles out parameter. newTriangles = new Triangle[] { NLT, NRT }; // Return modified triangles. return(new Triangle[] { LT, RT }); }
/// <summary> /// Updates rib <code>oldRib</code> with a <code>newRib</code>. /// </summary> public void UpdateRib(Rib oldRib, Rib newRib) { if (Ribs[0] == oldRib) { Ribs[0] = newRib; } else if (Ribs[1] == oldRib) { Ribs[1] = newRib; } else if (Ribs[2] == oldRib) { Ribs[2] = newRib; } else { throw new ArgumentException(); } }
/// <summary> /// Puts node in triangle. /// Split this triangle in three new. /// </summary> /// <returns>New and modified triangles.</returns> private IEnumerable <Triangle> PutPointInTriangle(Triangle T, Point node, out IEnumerable <Triangle> newTriangles) { // Vertices. // node == O var A = T.Vertices[0]; var B = T.Vertices[1]; var C = T.Vertices[2]; // Triangles. var LT = new Triangle(); var RT = new Triangle(); // Set new triangles. newTriangles = new Triangle[] { LT, RT }; // Ribs. var AB = T.GetRib(A, B); var BC = T.GetRib(B, C); var AC = T.GetRib(A, C); // New ribs. var OA = new Rib(node, A, LT, T); var OB = new Rib(node, B, LT, RT); var OC = new Rib(node, C, RT, T); // Update links to triangles of old ribs of triangle T. AB.Update(T, LT); BC.Update(T, RT); // Upadte ribs of triangle T. T.UpdateRib(AB, OA); T.UpdateRib(BC, OC); // Set ribs to new triangles. LT.SetRibs(AB, OB, OA); RT.SetRibs(BC, OB, OC); // Add new triangles to triangulation. triangles.Add(LT); triangles.Add(RT); // Update triangles. T.Update(); LT.Update(); RT.Update(); // Return new and modified triangles. return(new Triangle[] { T, LT, RT }); }
/// <summary> /// Puts node on triangles rib. /// Rib splits on two new, and each triangle adjacent with this rib also splits in two new /// </summary> /// <returns>New and modified triangles.</returns> private IEnumerable <Triangle> PutPointOnRib(Rib rib, Point node, out IEnumerable <Triangle> newTriangles) { newTriangles = null; IEnumerable <Triangle> modifiedTriangles = null; if (rib.Triangles.Contains(null)) { modifiedTriangles = PutPointOnOutsideRib(rib, node, out newTriangles); } else { modifiedTriangles = PutPointOnInnerRib(rib, node, out newTriangles); } // Add new triangles to triangulation. foreach (var t in newTriangles) { triangles.Add(t); } // Return new and modified triangles. return(newTriangles.Union(modifiedTriangles)); }
/// <summary> /// Returns opposite to passsed rib node. /// </summary> /// <param name="rib">Rib that belongs to this triangle.</param> /// <returns>Opposite to passed rib vertex.</returns> public Point GetOppositeNode(Rib rib) { int i = 0; for (; i < 3; ++i) { if (Ribs[i] == rib) { break; } } switch (i) { case 0: return(Vertices[2]); case 1: return(Vertices[0]); case 2: return(Vertices[1]); } throw new ArgumentException(); }
/// <summary> /// Set ribs to triangle. /// </summary> public void SetRibs(Rib R1, Rib R2, Rib R3) { Ribs[0] = R1; Ribs[1] = R2; Ribs[2] = R3; }
/// <summary> /// Update link to rib by index <code>index</code> with a link to rib <code>newRib</code>. /// </summary> /// <param name="index">Index of updated rib.</param> /// <param name="newRib"> /// New rib that will be accessible by index <code>index</code> ufter update. /// </param> public void UpdateRib(int index, Rib newRib) { Ribs[index] = newRib; }