public List <ContourStructure>[] Slice(double sliceThickness, double tolerance = 0.0001) { if (Facets == null) { return(null); } int numberOfSlices = (int)Math.Ceiling((MaxZ - MinZ) / sliceThickness); var contours = new List <ContourStructure> [numberOfSlices]; IntersectionStructure intersection; LinkedList <IntersectionStructure> contourLinkedList; STLFacet currentFacet; STLEdge e1, e2; for (int i = 0; i < Facets.Count; i++) { 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 { continue; } // slicing facet section below Smid for (int j = currentFacet.Smin; j < currentFacet.Smid; j++) { double slicePosition = (j * sliceThickness) + MinZ; // create intersecting structure intersection = new IntersectionStructure() { ForwardEdgeIntersectionPoint = GetIntersection( e1, slicePosition // slice position ), ForwardEdge = e1, BackwardEdge = e2 }; // The Efficient Contour Construction Algorithm (ECC) // initialise contours array if (contours[j] == null) { contours[j] = new List <ContourStructure>(); } // 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++) { 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 foreach (var node in contourLinkedList) { contours[j][position].IntersectionList.AddLast(node); } // 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) foreach (var node in contours[j][position].IntersectionList) { contourLinkedList.AddLast(node); } // 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 ContourStructure(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 { continue; } // slicing facet section above Smid for (int k = currentFacet.Smid; k < currentFacet.Smax; k++) { double slicePosition = (k * sliceThickness) + MinZ; // create intersecting structure 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 <ContourStructure>(); } // 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++) { 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 foreach (var node in contourLinkedList) { contours[k][position].IntersectionList.AddLast(node); } // 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) foreach (var node in contours[k][position].IntersectionList) { contourLinkedList.AddLast(node); } // 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 ContourStructure(intersection)); } } } return(contours); }
public ConnectionType GetConnectionType(MLinkedList <IntersectionStructure> contourLinkedList, IntersectionStructure intersection, double tolerance = 0.0001) { if (CompareEqual(contourLinkedList.First.Value.ForwardEdge, intersection.BackwardEdge, tolerance)) { return(ConnectionType.START_TO_END); } else if (CompareEqual(contourLinkedList.Last.Value.BackwardEdge, intersection.ForwardEdge, tolerance)) { return(ConnectionType.END_TO_START); } return(ConnectionType.NONE); }