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); } } }
static void Main(string[] args) { #if false //test code StreamWriter testsw = new StreamWriter("D:\\PersonalProjects\\Bridges 2011\\artshow\\sphere.stl"); testsw.WriteLine("solid sphereshell"); new Sphere(36.128, 5, true).Output(testsw, 1.0); //Torus(5, 1.5, 3).Output(testsw, 1.0); testsw.WriteLine("endsolid"); testsw.Close(); return; #endif ModelType model = ModelType.Outside; if (args.Count() > 1) { try { model = (ModelType)(Int16.Parse(args[1])); } catch { model = ModelType.Outside; } } double dRadius = 50.0; double dHalfLineWidth = 0.5; double dHalfLineHeight = 0.4; if (model == ModelType.Empty) { dHalfLineWidth = 0.5; dHalfLineHeight = 1.0; dRadius = 36.128 + dHalfLineHeight; //inside shell is a little smaller than white plastic ball } string Filename = args[0]; if (model == ModelType.Empty) Filename += "_empty.stl"; else if (model == ModelType.Inside) Filename += "_glow.stl"; else if (model == ModelType.Outside) Filename += ".stl"; StreamWriter sw = new StreamWriter(Filename); if (model == ModelType.Inside || model == ModelType.Outside) { sw.WriteLine("solid sphereshell"); Surface SphereSurface = new Surface(); if (model == ModelType.Inside) { SphereSurface.AddSurface(new Sphere(dRadius + dHalfLineHeight + 1.95, 6, true)); SphereSurface.AddSurface(new Sphere(dRadius + dHalfLineHeight - 0.05, 4, false)); } else if (model == ModelType.Outside) { SphereSurface.AddSurface(new Sphere(dRadius - dHalfLineHeight - 1.95, 4, true)); SphereSurface.AddSurface(new Sphere(dRadius - dHalfLineHeight + 0.05, 6, false)); } Point3D HolePunch = new Point3D(0, -1, 0).ScaledTo(dRadius); SurfaceTools.PunchHole(ref SphereSurface, //surf HolePunch, //center HolePunch, //direction 10, //length 1.2); //radius SphereSurface.Output(sw, 1.0); sw.WriteLine("endsolid"); } sw.WriteLine("solid tour"); Tour newTour = new Tour(args[0] + ".csv", dRadius, dHalfLineWidth, dHalfLineHeight); Surface TourSurface = new Surface(); TourSurface.AddSurface(newTour); TourSurface.Output(sw, 1.0); sw.WriteLine("endsolid"); sw.Close(); }
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); }
public void AddSurface(Surface s2) { int nFaces = mFaces.Count; int nPoints = mPts.Count; mFaces.AddRange(s2.mFaces); mPts.AddRange(s2.mPts); for (int i = nFaces; i < mFaces.Count; i++) { mFaces[i].Offset(nPoints); } }