public void PrintFacet(STLFacet stlFacet) { switch (stlFacet.OrientationType) { case OrientationType.TypeA: Console.WriteLine($"Orientation Type: TypeA"); break; case OrientationType.TypeB: Console.WriteLine($"Orientation Type: TypeB"); break; case OrientationType.TypeC: Console.WriteLine($"Orientation Type: TypeC"); break; case OrientationType.TypeD: Console.WriteLine($"Orientation Type: TypeD"); break; default: break; } Console.WriteLine(""); PrintEdge("Edge S1", stlFacet.EdgeS1); Console.WriteLine(""); PrintEdge("Edge S2", stlFacet.EdgeS2); Console.WriteLine(""); PrintEdge("Edge S3", stlFacet.EdgeS3); Console.WriteLine(""); PrintVertex("Vmin", stlFacet.Vmin); PrintVertex("Vmid", stlFacet.Vmid); PrintVertex("Vmax", stlFacet.Vmax); Console.WriteLine(""); PrintSliceNumber("Slice Number", stlFacet); Console.WriteLine(""); }
private (List <STLFacet>, double MinZ, double MaxZ) ParseASCII(StreamReader readerIn) { double[] normals; var facets = new List <STLFacet>(); double minZ = double.MaxValue; double maxZ = double.MinValue; while ((normals = GetNextMatch(readerIn, MatchDouble)) != null) { var facet = new STLFacet( normals, GetNextMatch(readerIn, MatchDouble), GetNextMatch(readerIn, MatchDouble), GetNextMatch(readerIn, MatchDouble) ); // ignore facets that are parallel to the slicing plane if ((facet.Vmax.Z - facet.Vmin.Z) <= 0.0001) { continue; } // track the minimum and maximum z coordinate if (facet.Vmax.Z > maxZ) { maxZ = facet.Vmax.Z; } if (facet.Vmin.Z < minZ) { minZ = facet.Vmin.Z; } facets.Add( facet ); } return(facets, minZ, maxZ); }
private (List <STLFacet>, double MinZ, double MaxZ) ParseBinary(BinaryReader readerIn) { // read the header and number of facets. readerIn.ReadBytes(80); double[] normals = new double[3]; double[] vertex1 = new double[3]; double[] vertex2 = new double[3]; double[] vertex3 = new double[3]; double minZ = double.MaxValue; double maxZ = double.MinValue; uint howmany = BitConverter.ToUInt32(readerIn.ReadBytes(4), 0); var facets = new List <STLFacet>((int)howmany); for (int i = 0; i < howmany; i++) { normals[0] = BitConverter.ToSingle(readerIn.ReadBytes(4), 0); normals[1] = BitConverter.ToSingle(readerIn.ReadBytes(4), 0); normals[2] = BitConverter.ToSingle(readerIn.ReadBytes(4), 0); vertex1[0] = BitConverter.ToSingle(readerIn.ReadBytes(4), 0); vertex1[1] = BitConverter.ToSingle(readerIn.ReadBytes(4), 0); vertex1[2] = BitConverter.ToSingle(readerIn.ReadBytes(4), 0); vertex2[0] = BitConverter.ToSingle(readerIn.ReadBytes(4), 0); vertex2[1] = BitConverter.ToSingle(readerIn.ReadBytes(4), 0); vertex2[2] = BitConverter.ToSingle(readerIn.ReadBytes(4), 0); vertex3[0] = BitConverter.ToSingle(readerIn.ReadBytes(4), 0); vertex3[1] = BitConverter.ToSingle(readerIn.ReadBytes(4), 0); vertex3[2] = BitConverter.ToSingle(readerIn.ReadBytes(4), 0); // skip attribute byte count readerIn.ReadBytes(2); var facet = new STLFacet( normals, vertex1, vertex2, vertex3 ); // ignore facets that are parallel to the slicing plane if ((facet.Vmax.Z - facet.Vmin.Z) <= 0.001) { continue; } // track the minimum and maximum z coordinate if (facet.Vmax.Z > maxZ) { maxZ = facet.Vmax.Z; } if (facet.Vmin.Z < minZ) { minZ = facet.Vmin.Z; } facets.Add( facet ); } return(facets, minZ, maxZ); }
public void PrintSliceNumber(string tag, STLFacet stlFacet) { Console.WriteLine($"{tag} Smin: {stlFacet.Smin}, Smid: {stlFacet.Smid}, Smax: {stlFacet.Smax}"); }
public List <MContourStructure>[] SliceParallel(double sliceThickness, double tolerance = 0.0001) { if (Facets == null) { return(null); } int numberOfSlices = (int)Math.Ceiling((MaxZ - MinZ) / sliceThickness); var contours = new List <MContourStructure> [numberOfSlices]; Parallel.For(0, Facets.Count, (i) => { STLEdge e1, e2; STLFacet currentFacet = Facets[i]; // calculating the slice number currentFacet.UpdateSliceNumber(MinZ, sliceThickness); // forward edge and backward edge judgments // use to select edge to use for intersection if ( (currentFacet.OrientationType == OrientationType.TypeA) && // Group A : oriented from min to max (currentFacet.Vmax.Flag > currentFacet.Vmin.Flag) // and flagzmax > flagzmin ) { e1 = currentFacet.EdgeS2; e2 = currentFacet.EdgeS1; } else if ( (currentFacet.OrientationType == OrientationType.TypeB) && // Group B : oriented from min to max (currentFacet.Vmax.Flag < currentFacet.Vmin.Flag) // and flagzmax < flagzmin ) { e1 = currentFacet.EdgeS2; e2 = currentFacet.EdgeS1; } else if ( (currentFacet.OrientationType == OrientationType.TypeC) && // Group C : oriented from max to min (currentFacet.Vmax.Flag < currentFacet.Vmin.Flag) // and flagzmax < flagzmin ) { e1 = currentFacet.EdgeS1; e2 = currentFacet.EdgeS2; } else if ( (currentFacet.OrientationType == OrientationType.TypeD) && // Group D : oriented from max to min (currentFacet.Vmax.Flag > currentFacet.Vmin.Flag) // and flagzmax > flagzmin ) { e1 = currentFacet.EdgeS1; e2 = currentFacet.EdgeS2; } else { return; } // slicing facet section below Smid for (int j = currentFacet.Smin; j < currentFacet.Smid; j++) { double slicePosition = (j * sliceThickness) + MinZ; // create intersecting structure var intersection = new IntersectionStructure() { ForwardEdgeIntersectionPoint = GetIntersection( e1, slicePosition // slice position ), ForwardEdge = e1, BackwardEdge = e2, SlicePosition = slicePosition }; // The Efficient Contour Construction Algorithm (ECC) // initialise contours array if (contours[j] == null) { contours[j] = new List <MContourStructure>(); } lock (contours[j]) { // used to mark whether the forward adjacent intersection structure or // the backward adjacent intersection structure of IS has been found bool foundForward = false; bool foundBackward = false; // used to mark the position where the backward adjacent intersection // structure of IS has been found. int position = -1; for (int l = 0; l < contours[j].Count; l++) { var contourLinkedList = contours[j][l].IntersectionList; var connectionType = GetConnectionType( contourLinkedList, intersection, tolerance ); switch (connectionType) { case ConnectionType.START_TO_START: // these should never happen case ConnectionType.END_TO_END: // must test to make sure case ConnectionType.NONE: continue; } if ( !foundForward && connectionType == ConnectionType.START_TO_END ) { if (foundBackward) { // copy items from current location to position contours[j][position].IntersectionList.AddLast(contourLinkedList); // delete current location contours[j].RemoveAt(l); break; } foundForward = true; position = l; contourLinkedList.AddFirst(intersection); } if ( !foundBackward && connectionType == ConnectionType.END_TO_START ) { if (foundForward && position == l) { break; // contour must be closed since forward edge and backward edge are found in the same list } else if (foundForward) { // copy nodes from position to current location // it's easier than copy from this location to the found location (reverse) contourLinkedList.AddLast(contours[j][position].IntersectionList); // delete current location contours[j].RemoveAt(position); break; } foundBackward = true; position = l; contourLinkedList.AddLast(intersection); } } if (!(foundForward || foundBackward)) // not forward or backward intersection; insert into contours list { contours[j].Add(new MContourStructure(intersection)); } } } // forward edge and backward edge judgments // use to select edge to use for intersection if ( (currentFacet.OrientationType == OrientationType.TypeA) && // Group A : oriented from min to max (currentFacet.Vmax.Flag > currentFacet.Vmin.Flag) // and flagzmax > flagzmin ) { e1 = currentFacet.EdgeS3; e2 = currentFacet.EdgeS1; } else if ( (currentFacet.OrientationType == OrientationType.TypeB) && // Group B : oriented from min to max (currentFacet.Vmax.Flag < currentFacet.Vmin.Flag) // and flagzmax < flagzmin ) { e1 = currentFacet.EdgeS3; e2 = currentFacet.EdgeS1; } else if ( (currentFacet.OrientationType == OrientationType.TypeC) && // Group C : oriented from max to min (currentFacet.Vmax.Flag < currentFacet.Vmin.Flag) // and flagzmax < flagzmin ) { e1 = currentFacet.EdgeS1; e2 = currentFacet.EdgeS3; } else if ( (currentFacet.OrientationType == OrientationType.TypeD) && // Group D : oriented from max to min (currentFacet.Vmax.Flag > currentFacet.Vmin.Flag) // and flagzmax > flagzmin ) { e1 = currentFacet.EdgeS1; e2 = currentFacet.EdgeS3; } else { return; } // slicing facet section above Smid for (int k = currentFacet.Smid; k < currentFacet.Smax; k++) { double slicePosition = (k * sliceThickness) + MinZ; // create intersecting structure var intersection = new IntersectionStructure() { ForwardEdgeIntersectionPoint = GetIntersection( e1, slicePosition // slice position ), ForwardEdge = e1, BackwardEdge = e2 }; // The Efficient Contour Construction Algorithm (ECC) // initialise contours array if (contours[k] == null) { contours[k] = new List <MContourStructure>(); } lock (contours[k]) { // used to mark whether the forward adjacent intersection structure or // the backward adjacent intersection structure of IS has been found bool foundForward = false; bool foundBackward = false; // used to mark the position where the backward adjacent intersection // structure of IS has been found. int position = -1; for (int l = 0; l < contours[k].Count; l++) { var contourLinkedList = contours[k][l].IntersectionList; var connectionType = GetConnectionType( contourLinkedList, intersection ); switch (connectionType) { case ConnectionType.START_TO_START: // these should never happen case ConnectionType.END_TO_END: // must test to make sure case ConnectionType.NONE: continue; } if ( !foundForward && connectionType == ConnectionType.START_TO_END ) { if (foundBackward) { // copy items from current location to position contours[k][position].IntersectionList.AddLast(contourLinkedList); // delete current location contours[k].RemoveAt(l); break; } foundForward = true; position = l; contourLinkedList.AddFirst(intersection); } if ( !foundBackward && connectionType == ConnectionType.END_TO_START ) { if (foundForward && position == l) { break; // contour must be closed since forward edge and backward edge are found in the same list } else if (foundForward) { // copy nodes from position to current location // it's easier than copy from this location to the found location (reverse) contourLinkedList.AddLast(contours[k][position].IntersectionList); // delete current location contours[k].RemoveAt(position); break; } foundBackward = true; position = l; contourLinkedList.AddLast(intersection); } } if (!(foundForward || foundBackward)) // not forward or backward intersection; insert into contours list { contours[k].Add(new MContourStructure(intersection)); } } } }); return(contours); }
public static Triangle ToTriangle(this STLFacet facet) { return(new Triangle(new Point(new Vect3(facet.Vertex1)), new Point(new Vect3(facet.Vertex2)), new Point(new Vect3(facet.Vertex3)), new Vect3(facet.Normal))); }