public static void ConvexHull(ref Surface surf) { if (surf.NumPoints < 4) return; //add the middle point to make a tetrahedron for some numerical stability Point3D Middle = new Point3D(); for (int i = 0; i < surf.NumPoints; i++) { Middle += surf.Point(i); } Middle /= surf.NumPoints; int mid = surf.AddPoint(Middle); //clean out the faces, and add faces of a tetrahedron using the first 3 pts and the middle. Point3D inside = (surf.Point(0) + surf.Point(1) + surf.Point(2) + surf.Point(mid)) / 4.0; while (surf.NumFaces > 0) surf.RemoveFace(0); surf.AddFace(0, 1, 2, inside); surf.AddFace(0, 1, mid, inside); surf.AddFace(0, 2, mid, inside); surf.AddFace(1, 2, mid, inside); // add in points one at a time, remove and replace faces as necessary for (int i = 3; i < surf.NumPoints; i++) { List<Edge> Edges = new List<Edge>(); //for the ith point... //go through the each existing face, for (int j = surf.NumFaces - 1; j >= 0; j--) { //if a triangle is facing our new point, remove the face, add its edges to a list. double tmp = Point3D.Dot(surf.FaceNormal(j), surf.Point(i) - surf.Point(surf.Face(j).I)); if (Point3D.Dot(surf.FaceNormal(j), (surf.Point(i) - surf.Point(surf.Face(j).I)).Normalized) > -DMS.EPSILON) { Edges.Add(new Edge(surf.Face(j).I, surf.Face(j).J)); Edges.Add(new Edge(surf.Face(j).J, surf.Face(j).K)); Edges.Add(new Edge(surf.Face(j).K, surf.Face(j).I)); surf.RemoveFace(j); } } //now add a triangle using any non duplicated edges together with our new point. Edges.Sort(Edge.Comparison); for (int j = 0; j < Edges.Count(); j++) { if (j != Edges.Count() - 1 && Edges[j] == Edges[j + 1]) { //this edge is a duplicate, do nothing. j++; //we'll skip the next one which is a duplicate too. continue; } surf.AddFace(Edges[j].I, Edges[j].J, i, inside); } } }
public static void PunchHole(ref Surface surf, Point3D center, Point3D direction, double Length, double Radius) { Surface HoleWall = new Surface(); List<int> HoleIdxs = new List<int>(); Point3D dir = direction.Normalized; for (int i = 0; i < surf.NumPoints; i++) { if (!IsInCylinder(surf.Point(i), center, dir, Length, Radius)) continue; for (int j = surf.NumFaces - 1; j >= 0; j--) { if (surf.Face(j).I == i || surf.Face(j).J == i || surf.Face(j).K == i) { if (!IsInCylinder(surf.Point(surf.Face(j).I), center, dir, Length, Radius)) HoleIdxs.Add(surf.Face(j).I); if (!IsInCylinder(surf.Point(surf.Face(j).J), center, dir, Length, Radius)) HoleIdxs.Add(surf.Face(j).J); if (!IsInCylinder(surf.Point(surf.Face(j).K), center, dir, Length, Radius)) HoleIdxs.Add(surf.Face(j).K); surf.RemoveFace(j); } } } //make sure points in hole wall are unique for (int j = HoleIdxs.Count() - 1; j >= 0; j--) { Point3D NewPt = surf.Point(HoleIdxs[j]); //check that existing points in HoleWall surface don't match int k; for (k = 0; k < HoleWall.NumPoints; k++) { if (NewPt == HoleWall.Point(k)) break; } //add if we haven't found it. if (k == HoleWall.NumPoints) HoleWall.AddPoint(NewPt); } //get the convex hull faces, then either remove them if they're pointing in our direction, or reverse them ConvexHull(ref HoleWall); for (int i = HoleWall.NumFaces - 1; i >= 0; i--) { double IR = HoleWall.Point(HoleWall.Face(i).I).R; double JR = HoleWall.Point(HoleWall.Face(i).J).R; double KR = HoleWall.Point(HoleWall.Face(i).K).R; if ( IR > center.R && JR > center.R && KR > center.R || IR < center.R && JR < center.R && KR < center.R ) { HoleWall.RemoveFace(i); } else { HoleWall.Face(i).Reverse(); } } //add in the new hole wall surf.AddSurface(HoleWall); }