public void FindIntersectionCandidates(TopoTriangle triangle, HashSet <TopoTriangle> resultList) { if (triangles != null) // end leaf, test all boxes for intersection { foreach (TopoTriangle test in triangles) { if (test != triangle && test.boundingBox.IntersectsBox(triangle.boundingBox)) { resultList.Add(test); } } return; } if (left == null) { return; } if (triangle.boundingBox.minPoint[dimension] < middlePosition) { left.FindIntersectionCandidates(triangle, resultList); } if (triangle.boundingBox.maxPoint[dimension] > middlePosition) { right.FindIntersectionCandidates(triangle, resultList); } if (triangle.boundingBox.minPoint[dimension] < middlePosition && triangle.boundingBox.maxPoint[dimension] > middlePosition) { middle.FindIntersectionCandidates(triangle, resultList); } }
public void AddTriangle(TopoTriangle triangle) { if (left == null && triangles == null) { triangles = new HashSet <TopoTriangle>(); } if (triangles != null) { triangles.Add(triangle); box.Add(triangle.boundingBox); if (triangles.Count > nextTrySplit) { TrySplit(); } } else { if (triangle.boundingBox.maxPoint[dimension] < middlePosition) { left.AddTriangle(triangle); } else if (triangle.boundingBox.minPoint[dimension] > middlePosition) { right.AddTriangle(triangle); } else { middle.AddTriangle(triangle); } } }
public void disconnectFace(TopoTriangle face, TopoModel model) { faces.Remove(face); if (faces.Count == 0) { model.edges.Remove(this); } }
public void Add(TopoTriangle triangle) { triangles.Add(triangle); if (tree != null) { tree.AddTriangle(triangle); } }
public bool Remove(TopoTriangle triangle) { if (tree != null) { tree.RemoveTriangle(triangle); } return(triangles.Remove(triangle)); }
public bool RemoveTriangle(TopoTriangle triangle) { TopoTriangleNode node = FindNodeForTriangle(triangle); if (node != null) { return(node.triangles.Remove(triangle)); } return(false); }
public HashSet <TopoTriangle> FindIntersectionCandidates(TopoTriangle triangle) { if (tree == null) { PrepareFastSearch(); } HashSet <TopoTriangle> result = new HashSet <TopoTriangle>(); tree.FindIntersectionCandidates(triangle, result); return(result); }
public TopoTriangle GetFaceExcept(TopoTriangle notThis) { foreach (TopoTriangle test in faces) { if (test != notThis) { return(test); } } return(null); }
public List <TopoEdge> FindNeighbourEdgesWithOneFace() { List <TopoEdge> list = null; TopoTriangle thisFace = faces.First.Value; foreach (TopoTriangle face in v1.connectedFacesList) { if (face == thisFace) { continue; } for (int e = 0; e < 3; e++) { TopoEdge testEdge = face.edges[e]; if (testEdge.connectedFaces != 1) { continue; } if (testEdge.ContainsVertex(v1)) { if (list == null) { list = new List <TopoEdge>(); } list.Add(testEdge); } } } foreach (TopoTriangle face in v2.connectedFacesList) { if (face == thisFace) { continue; } for (int e = 0; e < 3; e++) { TopoEdge testEdge = face.edges[e]; if (testEdge.connectedFaces != 1) { continue; } if (testEdge.ContainsVertex(v2)) { if (list == null) { list = new List <TopoEdge>(); } list.Add(testEdge); } } } return(list); }
public bool SameNormalOrientation(TopoTriangle test) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (vertices[i] == test.vertices[j] && vertices[(i + 1) % 3] == test.vertices[(j + 2) % 3]) { return(true); } } } return(false); }
public int testTriangleSide(TopoTriangle triangle) { double d1 = VertexDistance(triangle.vertices[0].pos); double d2 = VertexDistance(triangle.vertices[1].pos); double d3 = VertexDistance(triangle.vertices[2].pos); if (d1 >= 0 && d2 >= 0 && d3 >= 0) { return(1); } if (d1 <= 0 && d2 <= 0 && d3 <= 0) { return(-1); } return(0); }
public int testTriangleSideFast(TopoTriangle triangle) { bool d1 = VertexDistance(triangle.vertices[0].pos) > 0; bool d2 = VertexDistance(triangle.vertices[1].pos) > 0; bool d3 = VertexDistance(triangle.vertices[2].pos) > 0; if (d1 && d2 && d3) { return(1); } if (d1 == d2 && d2 == d3) { return(-1); } return(0); }
public int NumberOfSharedVertices(TopoTriangle tri) { int sameVertices = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (vertices[i] == tri.vertices[j]) { sameVertices++; break; } } } return(sameVertices); }
void TestInplaneOutside() { TopoModel model = new TopoModel(); TopoVertex v1 = model.addVertex(new RHVector3(0, 0, 0)); TopoVertex v2 = model.addVertex(new RHVector3(10, 0, 0)); TopoVertex v3 = model.addVertex(new RHVector3(10, 10, 0)); TopoVertex v4 = model.addVertex(new RHVector3(11, 1, 0)); TopoVertex v5 = model.addVertex(new RHVector3(17, 1, 0)); TopoVertex v6 = model.addVertex(new RHVector3(11, 7, 0)); TopoTriangle t1 = model.AddTriangle(new TopoTriangle(model, v1, v2, v3)); TopoTriangle t2 = model.AddTriangle(new TopoTriangle(model, v4, v5, v6)); if (t1.Intersects(t2)) { faildTests++; Console.WriteLine("Failed test:TestInplaneOutside"); } }
void TestInplaneInsideSameEdgeIntersects() { TopoModel model = new TopoModel(); TopoVertex v1 = model.addVertex(new RHVector3(0, 0, 0)); TopoVertex v2 = model.addVertex(new RHVector3(10, 0, 0)); TopoVertex v3 = model.addVertex(new RHVector3(10, 10, 0)); TopoVertex v4 = model.addVertex(new RHVector3(1, 1, 0)); TopoVertex v5 = model.addVertex(new RHVector3(7, 1, 0)); TopoVertex v6 = model.addVertex(new RHVector3(5, 3, 0)); TopoTriangle t1 = model.AddTriangle(new TopoTriangle(model, v1, v2, v3)); TopoTriangle t2 = model.AddTriangle(new TopoTriangle(model, v1, v2, v6)); if (!t1.Intersects(t2)) { faildTests++; Console.WriteLine("Failed test:TestInplaneInsideSameEdgeIntersects"); } }
void TestInplane3D_1() { TopoModel model = new TopoModel(); TopoVertex v1 = model.addVertex(new RHVector3(3.67848944664001, -2.6547646522522, 1.38814495312454E-14)); TopoVertex v2 = model.addVertex(new RHVector3(1.62981510162354, -1.05116808414459, 1.83297828141877E-14)); TopoVertex v3 = model.addVertex(new RHVector3(2.29873323440552, -0.79055267572403, 2.11497486191092E-14)); TopoVertex v4 = model.addVertex(new RHVector3(1.63205575942993, -1.05116808414459, 2.78849697113037)); TopoVertex v5 = model.addVertex(new RHVector3(0.916237592697144, -1.1297744512558, 1.83297828141877E-14)); TopoVertex v6 = model.addVertex(new RHVector3(1.38571500778198, -1.07829427719116, 2.67316389083862)); TopoTriangle t1 = model.AddTriangle(new TopoTriangle(model, v1, v2, v3)); TopoTriangle t2 = model.AddTriangle(new TopoTriangle(model, v4, v5, v6)); if (t1.Intersects(t2)) { faildTests++; Console.WriteLine("Failed test:TestInplane3D_1"); } }
void TestSharedPointIntersect() { TopoModel model = new TopoModel(); TopoVertex v1 = model.addVertex(new RHVector3(0, 0, 0)); TopoVertex v2 = model.addVertex(new RHVector3(10, 0, 0)); TopoVertex v3 = model.addVertex(new RHVector3(5, 5, 0)); TopoVertex v4 = model.addVertex(new RHVector3(0, 0, -5)); TopoVertex v5 = model.addVertex(new RHVector3(10, 0, -5)); TopoVertex v6 = model.addVertex(new RHVector3(5, 0, 5)); TopoTriangle t1 = model.AddTriangle(new TopoTriangle(model, v1, v2, v3)); TopoTriangle t2 = model.AddTriangle(new TopoTriangle(model, v1, v5, v6)); if (!t1.Intersects(t2)) { faildTests++; Console.WriteLine("Failed test:TestSharedPointIntersect"); } }
public TopoTriangleNode FindNodeForTriangle(TopoTriangle triangle) { if (triangles != null) { return(this); } if (triangle.boundingBox.maxPoint[dimension] < middlePosition) { return(left.FindNodeForTriangle(triangle)); } else if (triangle.boundingBox.minPoint[dimension] > middlePosition) { return(right.FindNodeForTriangle(triangle)); } else { return(middle.FindNodeForTriangle(triangle)); } }
public TopoTriangle BuildTriangle(TopoModel model) { TopoVertex sharedPoint = null; TopoVertex p1 = null, p2 = null; if (edgeA.v1 == edgeB.v1) { sharedPoint = edgeA.v1; p1 = edgeA.v2; p2 = edgeB.v2; } else if (edgeA.v1 == edgeB.v2) { sharedPoint = edgeA.v1; p1 = edgeA.v2; p2 = edgeB.v1; } else if (edgeA.v2 == edgeB.v1) { sharedPoint = edgeA.v1; p1 = edgeA.v1; p2 = edgeB.v2; } else if (edgeA.v2 == edgeB.v2) { sharedPoint = edgeA.v2; p1 = edgeA.v1; p2 = edgeB.v1; } TopoTriangle faceA = edgeA.faces.First.Value; TopoTriangle newTriangle = new TopoTriangle(model, sharedPoint, p1, p2, 0, 0, 1); if (newTriangle.SameNormalOrientation(faceA) == false) { newTriangle.FlipDirection(); } newTriangle.RecomputeNormal(); model.AddTriangle(newTriangle); return(newTriangle); }
public bool Contains(TopoTriangle test) { return(triangles.Contains(test)); }
private bool IntersectsSharedVertex(TopoVertex shared, TopoVertex[] a, TopoVertex[] b, TopoTriangle tri) { double d1 = DistanceToPlane(b[0].pos); double d2 = DistanceToPlane(b[1].pos); // Compute intersection point with plane int idx1, idx2; DominantAxis(out idx1, out idx2); if (Math.Abs(d1) < 1e-8 && Math.Abs(d2) < 1e-8) // In plane { if (InPlanePointInside(idx1, idx2, b[0].pos)) { return(true); } if (InPlanePointInside(idx1, idx2, b[1].pos)) { return(true); } if (InPlaneIntersectLineSmall(idx1, idx2, a[0].pos, a[1].pos, shared.pos, b[0].pos)) { return(true); } if (InPlaneIntersectLineSmall(idx1, idx2, a[0].pos, a[1].pos, shared.pos, b[1].pos)) { return(true); } return(false); } if (d1 * d2 > 0) { return(false); // Both points on same side, no intersection possible } double factor = Math.Abs(d1 / (d1 - d2)); RHVector3 p1 = b[0].pos; // new RHVector3(normal); RHVector3 p2 = b[1].pos; // new RHVector3(normal); /*p1.Scale(-d1); * p2.Scale(-d2); * p1.AddInternal(b[0].pos); * p2.AddInternal(b[1].pos);*/ RHVector3 inter = new RHVector3((1 - factor) * p1.x + factor * p2.x, (1 - factor) * p1.y + factor * p2.y, (1 - factor) * p1.z + factor * p2.z); if (inter.Subtract(shared.pos).Length < epsilonZero) { if (Math.Abs(d1) < epsilonZero || Math.Abs(d2) < epsilonZero) { return(false); // Connection ends at shared vertex - does not count as intersection } } if (InPlanePointInside(idx1, idx2, inter)) { return(true); } if (InPlaneIntersectLineSmall(idx1, idx2, a[0].pos, a[1].pos, shared.pos, inter)) { return(true); } return(false); }
private bool IntersectsSharedEdge(TopoVertex[] shared, TopoVertex a, TopoVertex b, TopoTriangle tri) { // Test if coplanar. If not no intersection is possible if (Math.Abs(DistanceToPlane(b.pos)) > epsilonZero) { return(false); } int idx2, idx1; DominantAxis(out idx1, out idx2); if (InPlanePointInside(idx1, idx2, b.pos)) { return(true); } if (tri.InPlanePointInside(idx1, idx2, a.pos)) { return(true); } return(false); }
public bool Intersects(TopoTriangle tri) { // First detect shared edges for more reliable and faster tests TopoVertex[] shared = new TopoVertex[3]; TopoVertex[] uniqueA = new TopoVertex[3]; TopoVertex[] uniqueB = new TopoVertex[3]; int nShared = 0, nUniqueA = 0, nUniqueB = 0; for (int i = 0; i < 3; i++) { bool isDouble = false; for (int j = 0; j < 3; j++) { if (vertices[i] == tri.vertices[j]) { shared[nShared++] = vertices[i]; isDouble = true; break; } } if (!isDouble) { uniqueA[nUniqueA++] = vertices[i]; } } if (nShared > 0) { for (int i = 0; i < 3; i++) { bool isDouble = false; for (int j = 0; j < nShared; j++) { if (tri.vertices[i] == shared[j]) { isDouble = true; break; } } if (!isDouble) { uniqueB[nUniqueB++] = tri.vertices[i]; } } if (nShared == 1) { return(IntersectsSharedVertex(shared[0], uniqueA, uniqueB, tri)); } if (nShared == 2) { return(IntersectsSharedEdge(shared, uniqueA[0], uniqueB[0], tri)); } return(true); } // Nice to read but unoptimized intersection computation RHMatrix3 A = new RHMatrix3(); RHVector3 p1 = vertices[1].pos.Subtract(vertices[0].pos); RHVector3 p2 = vertices[2].pos.Subtract(vertices[0].pos); A.SetXColumn(p1); A.SetYColumn(p2); RHVector3 P = new RHVector3(vertices[0].pos); RHVector3 q1 = tri.vertices[1].pos.Subtract(tri.vertices[0].pos); RHVector3 q2 = tri.vertices[2].pos.Subtract(tri.vertices[0].pos); RHVector3 r1 = tri.vertices[0].pos.Subtract(P); // r2 == r1! RHVector3 r3 = tri.vertices[2].pos.Subtract(P); A.SetZColumn(q1); double detAq1 = A.Determinant; A.SetZColumn(q2); double detAq2 = A.Determinant; //A.SetZColumn(q3); double detAq3 = detAq1 - detAq2; // A.Determinant; A.SetZColumn(r1); double detAr1 = A.Determinant; //A.SetZColumn(r3); double detAr3 = detAr1 + detAq2; // A.Determinant; int intersect = 0; if (detAq1 == 0 && detAq2 == 0 && detAq3 == 0) // same plane case { if (detAr1 != 0) { return(false); // other parallel plance } // Select plane for computation x-y or x-z based on normal int idx1, idx2; DominantAxis(out idx1, out idx2); if (InPlaneIntersectLine(idx1, idx2, vertices[0].pos, vertices[1].pos, tri.vertices[0].pos, tri.vertices[1].pos)) { return(true); } if (InPlaneIntersectLine(idx1, idx2, vertices[0].pos, vertices[1].pos, tri.vertices[1].pos, tri.vertices[2].pos)) { return(true); } if (InPlaneIntersectLine(idx1, idx2, vertices[0].pos, vertices[1].pos, tri.vertices[2].pos, tri.vertices[0].pos)) { return(true); } if (InPlaneIntersectLine(idx1, idx2, vertices[1].pos, vertices[2].pos, tri.vertices[0].pos, tri.vertices[1].pos)) { return(true); } if (InPlaneIntersectLine(idx1, idx2, vertices[1].pos, vertices[2].pos, tri.vertices[1].pos, tri.vertices[2].pos)) { return(true); } if (InPlaneIntersectLine(idx1, idx2, vertices[1].pos, vertices[2].pos, tri.vertices[2].pos, tri.vertices[0].pos)) { return(true); } if (InPlaneIntersectLine(idx1, idx2, vertices[2].pos, vertices[0].pos, tri.vertices[0].pos, tri.vertices[1].pos)) { return(true); } if (InPlaneIntersectLine(idx1, idx2, vertices[2].pos, vertices[0].pos, tri.vertices[1].pos, tri.vertices[2].pos)) { return(true); } if (InPlaneIntersectLine(idx1, idx2, vertices[2].pos, vertices[0].pos, tri.vertices[2].pos, tri.vertices[0].pos)) { return(true); } // Test if point inside. 1 test per triangle is enough if (InPlanePointInside(idx1, idx2, tri.vertices[0].pos)) { return(true); } if (InPlanePointInside(idx1, idx2, tri.vertices[1].pos)) { return(true); } if (InPlanePointInside(idx1, idx2, tri.vertices[2].pos)) { return(true); } if (tri.InPlanePointInside(idx1, idx2, vertices[0].pos)) { return(true); } if (tri.InPlanePointInside(idx1, idx2, vertices[1].pos)) { return(true); } if (tri.InPlanePointInside(idx1, idx2, vertices[2].pos)) { return(true); } return(false); } double beta1 = -1, beta2 = -1, beta3 = -1; if (detAq1 != 0) { beta1 = -detAr1 / detAq1; if (beta1 >= epsilonZeroMinus && beta1 <= epsilonOnePlus) { intersect = 1; } } if (detAq2 != 0) { beta2 = -detAr1 / detAq2; if (beta2 >= epsilonZeroMinus && beta2 <= epsilonOnePlus) { intersect |= 2; } } if (detAq3 != 0) { beta3 = -detAr3 / detAq3; if (beta3 >= epsilonZeroMinus && beta3 <= epsilonOnePlus) { intersect |= 4; } } if (intersect == 7) { // Special case intersection in one point caused 3 valid betas if (Math.Abs(beta1) < epsilonZero) { intersect = 6; } else if (Math.Abs(beta3) < epsilonZero) { intersect = 3; } else { intersect = 5; } } //if (intersect == 0) return false; // Lies on wrong side RHVector3 T = null, t = null; if ((intersect & 1) == 1) { T = new RHVector3(q1); T.Scale(beta1); T.AddInternal(tri.vertices[0].pos); } if ((intersect & 2) == 2) { if (T == null) { T = new RHVector3(q2); T.Scale(beta2); T.AddInternal(tri.vertices[0].pos); } else { q2.Scale(beta2); q2.AddInternal(tri.vertices[0].pos); t = q2.Subtract(T); } } if ((intersect & 4) == 4 && T != null && (t == null || t.Length < epsilonZero)) { RHVector3 q3 = tri.vertices[1].pos.Subtract(tri.vertices[2].pos); q3.Scale(beta3); q3.AddInternal(tri.vertices[2].pos); t = q3.Subtract(T); } if (t == null) { return(false); } if (t.Length < epsilonZero) { // Only one point touches the plane int idx1, idx2; DominantAxis(out idx1, out idx2); return(InPlanePointInside(idx1, idx2, T)); } // Compute intersection points with this triangle double d1 = p1.x * t.y - p1.y * t.x; double d2 = p1.x * t.z - p1.z * t.x; double delta1 = -1, delta2 = -1, delta3 = -1, gamma1 = -1, gamma2 = -1, gamma3 = -1; if (Math.Abs(d1) > epsilonZero || Math.Abs(d2) > epsilonZero) { if (Math.Abs(d1) > Math.Abs(d2)) { delta1 = -(t.x * T.y - t.y * T.x + P.x * t.y - P.y * t.x) / d1; gamma1 = -(p1.x * T.y - p1.y * T.x - p1.x * P.y + p1.y * P.x) / d1; } else { delta1 = -(t.x * T.z - t.z * T.x + P.x * t.z - P.z * t.x) / d2; gamma1 = -(p1.x * T.z - p1.z * T.x - p1.x * P.z + p1.z * P.x) / d2; } } d1 = p2.x * t.y - p2.y * t.x; d2 = p2.x * t.z - p2.z * t.x; if (Math.Abs(d1) > epsilonZero || Math.Abs(d2) > epsilonZero) { if (Math.Abs(d1) > Math.Abs(d2)) { delta2 = -(t.x * T.y - t.y * T.x + P.x * t.y - P.y * t.x) / d1; gamma2 = -(p2.x * T.y - p2.y * T.x - p2.x * P.y + p2.y * P.x) / d1; } else { delta2 = -(t.x * T.z - t.z * T.x + P.x * t.z - P.z * t.x) / d2; gamma2 = -(p2.x * T.z - p2.z * T.x - p2.x * P.z + p2.z * P.x) / d2; } } P.AddInternal(p1); p2.SubtractInternal(p1); // p2 is now p3! d1 = p2.x * t.y - p2.y * t.x; d2 = p2.x * t.z - p2.z * t.x; if (Math.Abs(d1) > epsilonZero || Math.Abs(d2) > epsilonZero) { if (Math.Abs(d1) > Math.Abs(d2)) { delta3 = -(t.x * T.y - t.y * T.x + P.x * t.y - P.y * t.x) / d1; gamma3 = -(p2.x * T.y - p2.y * T.x - p2.x * P.y + p2.y * P.x) / d1; } else { delta3 = -(t.x * T.z - t.z * T.x + P.x * t.z - P.z * t.x) / d2; gamma3 = -(p2.x * T.z - p2.z * T.x - p2.x * P.z + p2.z * P.x) / d2; } } // Check for line intersection inside the line. Hits at the vertices to not count! if (delta1 >= epsilonZero && delta1 <= epsilonOneMinus && gamma1 >= epsilonZero && gamma1 <= epsilonOneMinus) { return(true); } if (delta2 >= epsilonZero && delta2 <= epsilonOneMinus && gamma2 >= epsilonZero && gamma2 <= epsilonOneMinus) { return(true); } if (delta3 >= epsilonZero && delta3 <= epsilonOneMinus && gamma3 >= epsilonZero && gamma3 <= epsilonOneMinus) { return(true); } // Test if intersection is inside triangle intersect = 0; if (delta1 >= epsilonZeroMinus && delta1 <= epsilonOnePlus) { intersect |= 1; } if (delta2 >= epsilonZeroMinus && delta2 <= epsilonOnePlus) { intersect |= 2; } if (delta3 >= epsilonZeroMinus && delta3 <= epsilonOnePlus) { intersect |= 4; } /* if (gamma1 == 0) gamma1 = -1; * if (gamma2 == 0) gamma2 = -1; * if (gamma3 == 0) gamma3 = -1;*/ if (gamma1 == 0) { intersect &= ~1; } if (gamma2 == 0) { intersect &= ~2; } if (gamma3 == 0) { intersect &= ~4; } /* if ((intersect & 3) == 3) return gamma1 * gamma2 < 0; * if ((intersect & 5) == 5) return gamma1 * gamma3 < 0; * if ((intersect & 6) == 6) return gamma3 * gamma2 < 0;*/ if ((intersect & 3) == 3) { if (gamma1 * gamma2 < 0) { return(true); } else { return(false); } } if ((intersect & 5) == 5) { if (gamma1 * gamma3 < 0) { return(true); } else { return(false); } } if ((intersect & 6) == 6) { if (gamma3 * gamma2 < 0) { return(true); } else { return(false); } } // if (intersect!=0) happens only with numeric problems // return true; return(false); // No intersection found :-) }
public void connectFace(TopoTriangle face) { faces.AddLast(face); }
/// <summary> /// Splits an edge and changes the connected triangles to maintain /// a topological correct system. /// </summary> /// <param name="model"></param> /// <param name="vertex"></param> public void InsertVertex(TopoModel model, TopoVertex vertex) { LinkedList <TopoTriangle> delList = new LinkedList <TopoTriangle>(); LinkedList <TopoTriangle> testFaces = new LinkedList <TopoTriangle>(); foreach (TopoTriangle oldTriangle in faces) { testFaces.AddLast(oldTriangle); } foreach (TopoTriangle oldTriangle in testFaces) { delList.AddLast(oldTriangle); for (int i = 0; i < 3; i++) { if (oldTriangle.vertices[i] != v1 && oldTriangle.vertices[i] != v2) { TopoTriangle newTriangle = new TopoTriangle(model, v1, vertex, oldTriangle.vertices[i]); if (newTriangle.IsDegenerated()) { newTriangle.Unlink(model); } else { // Test orientation for (int e = 0; e < 3; e++) { TopoTriangle neigbour = newTriangle.edges[i].GetFaceExcept(newTriangle); if (neigbour != null) { if (!newTriangle.SameNormalOrientation(neigbour)) { newTriangle.FlipDirection(); } break; } } model.AddTriangle(newTriangle); } newTriangle = new TopoTriangle(model, vertex, v2, oldTriangle.vertices[i]); if (newTriangle.IsDegenerated()) { newTriangle.Unlink(model); } else { // Test orientation for (int e = 0; e < 3; e++) { TopoTriangle neigbour = newTriangle.edges[i].GetFaceExcept(newTriangle); if (neigbour != null) { if (!newTriangle.SameNormalOrientation(neigbour)) { newTriangle.FlipDirection(); } break; } } model.AddTriangle(newTriangle); } } } } foreach (TopoTriangle tri in delList) { tri.Unlink(model); model.removeTriangle(tri); } }
public void connectFace(TopoTriangle triangle) { connectedFacesList.AddLast(triangle); }
public void addIntersectionToSubmesh(Submesh mesh, TopoTriangle triangle, bool addEdges, int color) { int[] outside = new int[3]; int[] inside = new int[3]; int nOutside = 0, nInside = 0; int i; for (i = 0; i < 3; i++) { if (VertexDistance(triangle.vertices[i].pos) > 0) { outside[nOutside++] = i; } else { inside[nInside++] = i; } } if (nOutside != 1 && nOutside != 2) { return; } RHVector3[] intersections = new RHVector3[3]; int nIntersections = 0; for (int iInside = 0; iInside < nInside; iInside++) { for (int iOutside = 0; iOutside < nOutside; iOutside++) { RHVector3 v1 = triangle.vertices[inside[iInside]].pos; RHVector3 v2 = triangle.vertices[outside[iOutside]].pos; double dist1 = VertexDistance(v1); double dist2 = VertexDistance(v2); double pos = Math.Abs(dist1) / Math.Abs(dist2 - dist1); intersections[nIntersections++] = new RHVector3( v1.x + pos * (v2.x - v1.x), v1.y + pos * (v2.y - v1.y), v1.z + pos * (v2.z - v1.z) ); } } if (nInside == 2) { if (outside[0] == 1) { mesh.AddTriangle(triangle.vertices[inside[1]].pos, triangle.vertices[inside[0]].pos, intersections[1], color); mesh.AddTriangle(triangle.vertices[inside[0]].pos, intersections[0], intersections[1], color); } else { mesh.AddTriangle(triangle.vertices[inside[0]].pos, triangle.vertices[inside[1]].pos, intersections[0], color); mesh.AddTriangle(triangle.vertices[inside[1]].pos, intersections[1], intersections[0], color); } } else { if (inside[0] == 1) { mesh.AddTriangle(triangle.vertices[inside[0]].pos, intersections[1], intersections[0], color); } else { mesh.AddTriangle(triangle.vertices[inside[0]].pos, intersections[0], intersections[1], color); } } if (addEdges) { if (nInside == 2) { mesh.AddEdge(triangle.vertices[inside[0]].pos, triangle.vertices[inside[1]].pos, triangle.edges[0].connectedFaces == 2 ? Submesh.MESHCOLOR_EDGE : Submesh.MESHCOLOR_ERROREDGE); mesh.AddEdge(triangle.vertices[inside[0]].pos, intersections[0], triangle.edges[1].connectedFaces == 2 ? Submesh.MESHCOLOR_EDGE : Submesh.MESHCOLOR_ERROREDGE); mesh.AddEdge(triangle.vertices[inside[1]].pos, intersections[1], triangle.edges[2].connectedFaces == 2 ? Submesh.MESHCOLOR_EDGE : Submesh.MESHCOLOR_ERROREDGE); } else { for (int iInter = 0; iInter < nIntersections; iInter++) { mesh.AddEdge(triangle.vertices[inside[0]].pos, intersections[iInter], triangle.edges[(inside[0] + 2 * iInter) % 3].connectedFaces == 2 ? Submesh.MESHCOLOR_EDGE : Submesh.MESHCOLOR_ERROREDGE); } } } if (nIntersections == 2) { mesh.AddEdge(intersections[0], intersections[1], Submesh.MESHCOLOR_CUT_EDGE); } }
public void disconnectFace(TopoTriangle triangle) { connectedFacesList.Remove(triangle); }
public TopoTriangleDistance(double dist, TopoTriangle tri) { triangle = tri; distance = dist; }