public HashSet<TopoTriangle> FindIntersectionCandidates(TopoTriangle triangle) { if (tree == null) PrepareFastSearch(); HashSet<TopoTriangle> result = new HashSet<TopoTriangle>(); tree.FindIntersectionCandidates(triangle, result); return result; }
public TopoTriangle AddTriangle(TopoTriangle triangle) { if (triangle.IsDegenerated()) triangle.Unlink(this); else triangles.Add(triangle); return triangle; }
public TopoTriangle addTriangle(RHVector3 p1,RHVector3 p2,RHVector3 p3,RHVector3 normal) { TopoVertex v1 = addVertex(p1); TopoVertex v2 = addVertex(p2); TopoVertex v3 = addVertex(p3); TopoTriangle triangle = new TopoTriangle(this, v1, v2, v3, normal.x, normal.y, normal.z); return AddTriangle(triangle); }
public TopoTriangle addTriangle(double p1x, double p1y, double p1z, double p2x, double p2y, double p2z, double p3x, double p3y, double p3z, double nx, double ny, double nz) { TopoVertex v1 = addVertex(new RHVector3(p1x, p1y, p1z)); TopoVertex v2 = addVertex(new RHVector3(p2x, p2y, p2z)); TopoVertex v3 = addVertex(new RHVector3(p3x, p3y, p3z)); TopoTriangle triangle = new TopoTriangle(this, v1, v2, v3, nx, ny, nz); return AddTriangle(triangle); }
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 bool containTri(TopoTriangle triangle) { foreach (TopoVertex ver in triangle.vertices) { if (ContainsPoint(ver.pos)) { return(true); } } return(false); }
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); } }
//--- MODEL_SLA // milton public TopoTriangle[] getBoundingTri() { TopoTriangle[] triangles = new TopoTriangle[12]; TopoVertex[] vertices = getVertices(); triangles[0] = new TopoTriangle(vertices[0], vertices[1], vertices[3]); triangles[1] = new TopoTriangle(vertices[0], vertices[3], vertices[2]); triangles[2] = new TopoTriangle(vertices[4], vertices[6], vertices[7]); triangles[3] = new TopoTriangle(vertices[4], vertices[7], vertices[5]); triangles[4] = new TopoTriangle(vertices[2], vertices[3], vertices[7]); triangles[5] = new TopoTriangle(vertices[2], vertices[7], vertices[6]); triangles[6] = new TopoTriangle(vertices[1], vertices[5], vertices[7]); triangles[7] = new TopoTriangle(vertices[1], vertices[7], vertices[3]); triangles[8] = new TopoTriangle(vertices[0], vertices[4], vertices[5]); triangles[9] = new TopoTriangle(vertices[0], vertices[5], vertices[1]); triangles[10] = new TopoTriangle(vertices[0], vertices[2], vertices[6]); triangles[11] = new TopoTriangle(vertices[0], vertices[6], vertices[4]); return(triangles); }
public bool Remove(TopoTriangle triangle) { if (tree != null) tree.RemoveTriangle(triangle); return triangles.Remove(triangle); }
public bool Contains(TopoTriangle test) { return triangles.Contains(test); }
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 Add(TopoTriangle triangle) { triangles.Add(triangle); if (tree != null) tree.AddTriangle(triangle); }
public void disconnectFace(TopoTriangle triangle) { connectedFacesList.Remove(triangle); }
public void removeTriangle(TopoTriangle triangle) { triangle.Unlink(this); triangles.Remove(triangle); }
public void connectFace(TopoTriangle triangle) { connectedFacesList.AddLast(triangle); }
private void FloodFillPlanarRegions(TopoTriangle good, int marker) { good.algHelper = marker; HashSet<TopoTriangle> front = new HashSet<TopoTriangle>(); front.Add(good); HashSet<TopoTriangle> newFront = new HashSet<TopoTriangle>(); int i; while (front.Count > 0) { Application.DoEvents(); foreach (TopoTriangle t in front) { for (i = 0; i < 3; i++) { foreach (TopoTriangle test in t.edges[i].faces) { if (test.algHelper == 0) { if (t.normal.Angle(test.normal) < 1e-6) { test.algHelper = 1; newFront.Add(test); } } } } } front = newFront; newFront = new HashSet<TopoTriangle>(); } }
private bool FloodFillCheckNormals(TopoTriangle good) { good.algHelper = 1; HashSet<TopoTriangle> front = new HashSet<TopoTriangle>(); front.Add(good); HashSet<TopoTriangle> newFront = new HashSet<TopoTriangle>(); int i; int cnt = 0; while (front.Count > 0) { foreach (TopoTriangle t in front) { cnt++; if((cnt % 2000) == 0) Application.DoEvents(); for (i = 0; i < 3; i++) { foreach (TopoTriangle test in t.edges[i].faces) { if (t != test && test.algHelper == 0) { test.algHelper = 1; newFront.Add(test); test.RecomputeNormal(); if (!t.SameNormalOrientation(test)) { return false; } } } } } front = newFront; newFront = new HashSet<TopoTriangle>(); } return true; }
public bool RemoveTriangle(TopoTriangle triangle) { TopoTriangleNode node = FindNodeForTriangle(triangle); if (node != null) return node.triangles.Remove(triangle); return false; }
public bool importObj(string filename) { clear(); bool error = false; try { string[] text = System.IO.File.ReadAllText(filename).Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); int vPos = 0; int vnPos = 0; int count = 0,countMax = text.Length; List<TopoVertex> vList = new List<TopoVertex>(); List<RHVector3> vnList = new List<RHVector3>(); foreach (string currentLine in text) { count++; Progress((double)count / countMax); if (count % 2000 == 0) { Application.DoEvents(); if (IsActionStopped()) return true; } string line = currentLine.Trim().ToLower(); if (line.Length == 0 || line.StartsWith("#")) continue; int p = line.IndexOf(" "); if (p < 0) continue; string cmd = line.Substring(0, p); if (cmd == "v") { RHVector3 vert = extractVector(line.Substring(p + 1)); vList.Add(addVertex(vert)); vPos++; } else if (cmd == "vn") { RHVector3 vert = extractVector(line.Substring(p + 1)); vnList.Add(vert); vnPos++; } else if (cmd == "f") { line = line.Substring(p + 1).Replace(" ", " "); string[] parts = line.Split(new char[] { ' ' }); int[] vidx = new int[parts.Length]; int[] nidx = new int[parts.Length]; RHVector3 norm = null; p = 0; foreach (string part in parts) { string[] sp = part.Split('/'); if (sp.Length > 0) { int.TryParse(sp[0], out vidx[p]); if (vidx[p] < 0) vidx[p] += vPos; else vidx[p]--; if (vidx[p] < 0 || vidx[p] >= vPos) { error = true; break; } } if (sp.Length > 2 && norm == null) { int.TryParse(sp[0], out nidx[p]); if (nidx[p] < 0) nidx[p] += vnPos; else nidx[p]--; if (nidx[p] >= 0 && nidx[p] < vnPos) norm = vnList[nidx[p]]; } p++; } for (int i = 2; i < parts.Length; i++) { TopoTriangle triangle = new TopoTriangle(this, vList[vidx[0]], vList[vidx[1]], vList[vidx[2]]); if (norm != null && norm.ScalarProduct(triangle.normal) < 0) triangle.FlipDirection(); AddTriangle(triangle); } } if (error) break; } } catch { error = true; } if (error) { clear(); } return error; }
public TopoModel Copy() { TopoModel newModel = new TopoModel(); int nOld = vertices.Count; int i = 0; List<TopoVertex> vcopy = new List<TopoVertex>(vertices.Count); foreach (TopoVertex v in vertices) { v.id = i++; TopoVertex newVert = new TopoVertex(v.id, v.pos); newModel.addVertex(newVert); vcopy.Add(newVert); } foreach (TopoTriangle t in triangles) { TopoTriangle triangle = new TopoTriangle(newModel, vcopy[t.vertices[0].id], vcopy[t.vertices[1].id], vcopy[t.vertices[2].id], t.normal.x, t.normal.y, t.normal.z); newModel.triangles.Add(triangle); } UpdateVertexNumbers(); newModel.UpdateVertexNumbers(); newModel.badEdges = 0; newModel.badTriangles = badTriangles; newModel.shells = shells; newModel.updatedNormals = updatedNormals; newModel.loopEdges = loopEdges; newModel.manyShardEdges = 0; newModel.manifold = manifold; newModel.normalsOriented = normalsOriented; return newModel; }
private void FloodFillTriangles(TopoTriangle tri, int value) { tri.algHelper = value; HashSet<TopoTriangle> front = new HashSet<TopoTriangle>(); front.Add(tri); HashSet<TopoTriangle> newFront = new HashSet<TopoTriangle>(); int i; while (front.Count > 0) { foreach (TopoTriangle t in front) { for (i = 0; i < 3; i++) { foreach (TopoTriangle test in t.edges[i].faces) { if (test.algHelper == 0) { test.algHelper = value; newFront.Add(test); } } } } front = newFront; newFront = new HashSet<TopoTriangle>(); } }
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); }
// Milton: Efficient AABB/triangle intersection algoirthm // from http://stackoverflow.com/questions/17458562/efficient-aabb-triangle-intersection-in-c-sharp public bool overlapTri(TopoTriangle triangle) { double triangleMin, triangleMax; double boxMin, boxMax; /*// Test the box normals (x-, y- and z-axes) * var boxNormals = new IVector[] { * new Vector(1,0,0), * new Vector(0,1,0), * new Vector(0,0,1) * };*/ RHVector3[] boxNormals = { new RHVector3(1, 0, 0), new RHVector3(0, 1, 0), new RHVector3(0, 0, 1) }; /* * for (int i = 0; i < 3; i++) * { * RHVector3 n = boxNormals[i]; * Project(triangle.vertices, boxNormals[i], out triangleMin, out triangleMax); * if (triangleMax < box.Start.Coords[i] || triangleMin > box.End.Coords[i]) * return false; // No intersection possible. * }*/ Project(triangle.vertices, boxNormals[0], out triangleMin, out triangleMax); if (triangleMax < minPoint.x || triangleMin > maxPoint.x) { return(false); } Project(triangle.vertices, boxNormals[1], out triangleMin, out triangleMax); if (triangleMax < minPoint.y || triangleMin > maxPoint.y) { return(false); } Project(triangle.vertices, boxNormals[2], out triangleMin, out triangleMax); if (triangleMax < minPoint.z || triangleMin > maxPoint.z) { return(false); } /*// Test the triangle normal * double triangleOffset = triangle.Normal.Dot(triangle.A); * Project(box.Vertices, triangle.Normal, out boxMin, out boxMax); * if (boxMax < triangleOffset || boxMin > triangleOffset) * return false; // No intersection possible.*/ double triangleOffset = triangle.normal.ScalarProduct(triangle.vertices[0].pos); Project(getVertices(), triangle.normal, out boxMin, out boxMax); if (boxMin < triangleOffset || boxMax > triangleOffset) { return(false); // No intersection possible. } /*// Test the nine edge cross-products * IVector[] triangleEdges = new IVector[] { * triangle.A.Minus(triangle.B), * triangle.B.Minus(triangle.C), * triangle.C.Minus(triangle.A) * }; */ RHVector3[] triangleEdges = { triangle.vertices[0].pos.Subtract(triangle.vertices[1].pos), triangle.vertices[1].pos.Subtract(triangle.vertices[2].pos), triangle.vertices[2].pos.Subtract(triangle.vertices[0].pos) }; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { RHVector3 axis = triangleEdges[i].CrossProduct(boxNormals[j]); Project(getVertices(), axis, out boxMin, out boxMax); Project(triangle.vertices, axis, out triangleMin, out triangleMax); if (boxMax < triangleMin || boxMin > triangleMax) { return(false); // No intersection possible } } } return(true); }
public TopoTriangle IntersectsTriangleAnyTriangle(TopoTriangle test) { HashSet<TopoTriangle> candidates = triangles.FindIntersectionCandidates(test); foreach (TopoTriangle candidate in candidates) { if (test.Intersects(candidate)) return candidate; } return null; }
private void FloodFillNormals(TopoTriangle good) { good.algHelper = 1; HashSet<TopoTriangle> front = new HashSet<TopoTriangle>(); front.Add(good); HashSet<TopoTriangle> newFront = new HashSet<TopoTriangle>(); int i; int cnt = 0; while (front.Count > 0) { foreach (TopoTriangle t in front) { cnt++; if((cnt % 2000) == 0) Application.DoEvents(); for (i = 0; i < 3; i++) { foreach (TopoTriangle test in t.edges[i].faces) { if (t != test && test.algHelper == 0) { test.algHelper = 1; newFront.Add(test); if (!t.SameNormalOrientation(test)) { test.FlipDirection(); updatedNormals++; } } } } } front = newFront; newFront = new HashSet<TopoTriangle>(); } }
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 void Merge(TopoModel model, Matrix4 trans) { int nOld = vertices.Count; int i = 0; List<TopoVertex> vcopy = new List<TopoVertex>(model.vertices.Count); foreach (TopoVertex v in model.vertices) { v.id = i++; TopoVertex newVert = new TopoVertex(v.id, v.pos, trans); addVertex(newVert); vcopy.Add(newVert); } foreach (TopoTriangle t in model.triangles) { TopoTriangle triangle = new TopoTriangle(this, vcopy[t.vertices[0].id], vcopy[t.vertices[1].id], vcopy[t.vertices[2].id]); triangle.RecomputeNormal(); triangles.Add(triangle); } RemoveUnusedDatastructures(); intersectionsUpToDate = false; }