/// <summary> /// Gets the contour segments. /// </summary> /// <param name="mesh"> /// The mesh. /// </param> /// <param name="plane"> /// The plane origin. /// </param> /// <param name="normal"> /// The plane normal. /// </param> /// <returns> /// The segments of the contour. /// </returns> public static IList <Point3D> GetContourSegments(this MeshGeometry3D mesh, Point3D plane, Vector3D normal) { var segments = new List <Point3D>(); var contourHelper = new ContourHelper(plane, normal, mesh); for (int i = 0; i < mesh.TriangleIndices.Count; i += 3) { Point3D[] positions; Vector3D[] normals; Point[] textureCoordinates; int[] triangleIndices; contourHelper.ContourFacet( mesh.TriangleIndices[i], mesh.TriangleIndices[i + 1], mesh.TriangleIndices[i + 2], out positions, out normals, out textureCoordinates, out triangleIndices); segments.AddRange(positions); } return(segments); }
private void Contour(MeshGeometry3D mesh) { var ch = new ContourHelper(origin, normal, mesh); ch.ContourFacet(0, 1, 2, out newPositions, out newNormals, out newTextureCoordinates, out triangleIndices); }
/// <summary> /// Cuts the mesh with the specified plane. /// </summary> /// <param name="mesh"> /// The mesh. /// </param> /// <param name="plane"> /// The plane origin. /// </param> /// <param name="normal"> /// The plane normal. /// </param> /// <returns> /// The <see cref="MeshGeometry3D"/>. /// </returns> public static MeshGeometry3D Cut(this MeshGeometry3D mesh, Point3D plane, Vector3D normal) { var hasTextureCoordinates = mesh.TextureCoordinates != null && mesh.TextureCoordinates.Count > 0; var hasNormals = mesh.Normals != null && mesh.Normals.Count > 0; var meshBuilder = new MeshBuilder(hasNormals, hasTextureCoordinates); var contourHelper = new ContourHelper(plane, normal, mesh); foreach (var position in mesh.Positions) { meshBuilder.Positions.Add(position); } if (hasTextureCoordinates) { foreach (var textureCoordinate in mesh.TextureCoordinates) { meshBuilder.TextureCoordinates.Add(textureCoordinate); } } if (hasNormals) { foreach (var n in mesh.Normals) { meshBuilder.Normals.Add(n); } } for (var i = 0; i < mesh.TriangleIndices.Count; i += 3) { var index0 = mesh.TriangleIndices[i]; var index1 = mesh.TriangleIndices[i + 1]; var index2 = mesh.TriangleIndices[i + 2]; Point3D[] positions; Vector3D[] normals; Point[] textureCoordinates; int[] triangleIndices; contourHelper.ContourFacet(index0, index1, index2, out positions, out normals, out textureCoordinates, out triangleIndices); foreach (var p in positions) { meshBuilder.Positions.Add(p); } foreach (var tc in textureCoordinates) { meshBuilder.TextureCoordinates.Add(tc); } foreach (var n in normals) { meshBuilder.Normals.Add(n); } foreach (var ti in triangleIndices) { meshBuilder.TriangleIndices.Add(ti); } } return(meshBuilder.ToMesh()); }
/// <summary> /// Cuts the mesh with the specified plane. /// </summary> /// <param name="mesh"> /// The mesh. /// </param> /// <param name="p"> /// The plane origin. /// </param> /// <param name="n"> /// The plane normal. /// </param> /// <returns> /// The <see cref="MeshGeometry3D"/>. /// </returns> public static MeshGeometry3D Cut(MeshGeometry3D mesh, Point3D p, Vector3D n) { var ch = new ContourHelper(p, n); var mb = new MeshBuilder(false, false); foreach (var pos in mesh.Positions) { mb.Positions.Add(pos); } int j = mb.Positions.Count; for (int i = 0; i < mesh.TriangleIndices.Count; i += 3) { int i0 = mesh.TriangleIndices[i]; int i1 = mesh.TriangleIndices[i + 1]; int i2 = mesh.TriangleIndices[i + 2]; var p0 = mesh.Positions[i0]; var p1 = mesh.Positions[i1]; var p2 = mesh.Positions[i2]; Point3D s0, s1; int r = ch.ContourFacet(p0, p1, p2, out s0, out s1); switch (r) { case -1: mb.TriangleIndices.Add(i0); mb.TriangleIndices.Add(i1); mb.TriangleIndices.Add(i2); break; case 0: mb.Positions.Add(s1); mb.Positions.Add(s0); mb.TriangleIndices.Add(i0); mb.TriangleIndices.Add(j++); mb.TriangleIndices.Add(j++); break; case 1: mb.Positions.Add(s0); mb.Positions.Add(s1); mb.TriangleIndices.Add(i1); mb.TriangleIndices.Add(j++); mb.TriangleIndices.Add(j++); break; case 2: mb.Positions.Add(s0); mb.Positions.Add(s1); mb.TriangleIndices.Add(i2); mb.TriangleIndices.Add(j++); mb.TriangleIndices.Add(j++); break; case 10: mb.Positions.Add(s0); mb.Positions.Add(s1); mb.TriangleIndices.Add(i1); mb.TriangleIndices.Add(i2); mb.TriangleIndices.Add(j); mb.TriangleIndices.Add(j++); mb.TriangleIndices.Add(j++); mb.TriangleIndices.Add(i1); break; case 11: mb.Positions.Add(s1); mb.Positions.Add(s0); mb.TriangleIndices.Add(i2); mb.TriangleIndices.Add(i0); mb.TriangleIndices.Add(j); mb.TriangleIndices.Add(j++); mb.TriangleIndices.Add(j++); mb.TriangleIndices.Add(i2); break; case 12: mb.Positions.Add(s1); mb.Positions.Add(s0); mb.TriangleIndices.Add(i0); mb.TriangleIndices.Add(i1); mb.TriangleIndices.Add(j); mb.TriangleIndices.Add(j++); mb.TriangleIndices.Add(j++); mb.TriangleIndices.Add(i0); break; } } // begin bonghi: this is different from the original HelixToolkit version if (mb.TriangleIndices.Count == 0) { return(new MeshGeometry3D()); } // end bonghi return(mb.ToMesh()); }
internal void CalcSlicesContours(Material selectedMaterial, AtumPrinter selectedPrinter) { var resultAB = new SortedDictionary <float, PolyTree>(); var abSegmentAsSTLModel = new SupportCone(); abSegmentAsSTLModel.Triangles = this.ASegment.Triangles; //abSegmentAsSTLModel.Triangles[0].AddRange(this.ASegmentCap[0]); abSegmentAsSTLModel.Triangles[0].AddRange(this.BSegment[0]); abSegmentAsSTLModel.Triangles[0].AddRange(this.BSegmentCap[0]); foreach (var triangle in abSegmentAsSTLModel.Triangles[0]) { triangle.CalcMinMaxZ(); } abSegmentAsSTLModel.UpdateBoundries(); abSegmentAsSTLModel.CalcSliceIndexes(selectedMaterial, false); var sliceIndex = 0; foreach (var sliceHeight in abSegmentAsSTLModel.SliceIndexes.Keys) { resultAB.Add(sliceHeight, STLModel3D.GetSliceContoursForSupportConeV2(abSegmentAsSTLModel, sliceIndex, sliceHeight, selectedPrinter)); sliceIndex++; } //c segment var cSegmentAsSTLModel = new SupportCone(); cSegmentAsSTLModel.Triangles = this.CSegment.Triangles; foreach (var triangle in cSegmentAsSTLModel.Triangles[0]) { triangle.CalcMinMaxZ(); triangle.CalcMinMaxX(); triangle.CalcMinMaxY(); triangle.CalcCenter(); } cSegmentAsSTLModel.UpdateBoundries(); cSegmentAsSTLModel.CalcSliceIndexes(selectedMaterial, false); var resultC = new SortedDictionary <float, PolyTree>(); sliceIndex = 0; foreach (var sliceHeight in cSegmentAsSTLModel.SliceIndexes.Keys) { resultC.Add(sliceHeight, STLModel3D.GetSliceContoursForSupportConeV2(cSegmentAsSTLModel, sliceIndex, sliceHeight, selectedPrinter)); sliceIndex++; } //defg segment var defgSegmentAsSTLModel = new SupportCone(); defgSegmentAsSTLModel.Triangles = this.DSegment; defgSegmentAsSTLModel.Triangles[0].AddRange(this.TopSupportCone[0]); defgSegmentAsSTLModel.Triangles[0].AddRange(this.MiddleSupportCone[0]); defgSegmentAsSTLModel.Triangles[0].AddRange(this.BottomSupportCone[0]); foreach (var triangle in defgSegmentAsSTLModel.Triangles[0]) { triangle.CalcMinMaxZ(); } defgSegmentAsSTLModel.UpdateBoundries(); defgSegmentAsSTLModel.CalcSliceIndexes(selectedMaterial, false); var resultDEFG = new SortedDictionary <float, PolyTree>(); sliceIndex = 0; foreach (var sliceHeight in defgSegmentAsSTLModel.SliceIndexes.Keys) { resultDEFG.Add(sliceHeight, STLModel3D.GetSliceContoursForSupportConeV2(defgSegmentAsSTLModel, sliceIndex, sliceHeight, selectedPrinter)); sliceIndex++; } //combine all foreach (var sliceHeight in resultC.Keys) { if (!resultAB.ContainsKey(sliceHeight)) { resultAB.Add(sliceHeight, resultC[sliceHeight]); } else { resultAB[sliceHeight] = ContourHelper.UnionModelSliceLayer(resultAB[sliceHeight], resultC[sliceHeight]); } } foreach (var sliceHeight in resultDEFG.Keys) { if (!resultAB.ContainsKey(sliceHeight)) { resultAB.Add(sliceHeight, resultDEFG[sliceHeight]); } else { resultAB[sliceHeight] = ContourHelper.UnionModelSliceLayer(resultAB[sliceHeight], resultDEFG[sliceHeight]); } } this.SliceContours = resultAB; foreach (var interlinkConnectionIndex in this.InterlinkConnections) { if (interlinkConnectionIndex.Value != null) { foreach (var interlinkConnection in interlinkConnectionIndex.Value) { if (interlinkConnection != null) { interlinkConnection.CalcSlicesContours(selectedMaterial, selectedPrinter); } } } } }
public static StructureSetMeta ParseDICOM(string file) { var sm = new StructureSetMeta(); var dcm = DICOMObject.Read(file); var sel = dcm.GetSelector(); var metas = sel.StructureSetROISequence.Items.Select(i => { var meta = new StructureMeta(); meta.StructureId = i.GetSelector().ROIName?.Data; meta.ROINumber = i.GetSelector().ROINumber.Data; return(meta); }); foreach (var meta in metas) { try { var comatch = sel.ROIContourSequence.Items.FirstOrDefault(i => i.GetSelector().ReferencedROINumber.Data == meta.ROINumber); var romatch = sel.RTROIObservationsSequence.Items.FirstOrDefault(i => i.GetSelector().ReferencedROINumber.Data == meta.ROINumber); var colorValues = comatch.GetSelector().ROIDisplayColor.Data_; var color = new Vec3b((byte)colorValues[0], (byte)colorValues[1], (byte)colorValues[2]); var dicomType = romatch.GetSelector().RTROIInterpretedType.Data; var name = romatch.GetSelector().ROIObservationLabel.Data; meta.StructureName = name; meta.Color = new Scalar(colorValues[0], colorValues[1], colorValues[2]); var hasContours = comatch.GetSelector().ContourSequence != null; if (!hasContours) { continue; } //HAS CONTOURS - SET COLOR BYTES IN MATRIX foreach (var slice in comatch.GetSelector().ContourSequence.Items) { var contours = slice.GetSelector().ContourData.Data_; if (contours.Count % 3 != 0) { _logger.LogWarning($"Slice for structure {meta.StructureId} has {contours.Count} contour points. Not divisible by 3! Can't process."); continue; } try { var contour = new SliceContourMeta(); for (int i = 0; i < contours.Count; i += 3) { var contourPt = new OpenCvSharp.Point3f((float)contours[i + 0], (float)contours[i + 1], (float)contours[i + 2]); contour.AddPoint(contourPt); } meta.SliceContours.Add(contour); meta.DICOMType = dicomType; } catch (Exception e) { _logger.LogError(e.ToString()); } } //OrganizeContours - contours containing other contours (holes and fills) will be organized //into children. All other contours are outermost contours and not children of any other var slices = meta.SliceContours.GroupBy(s => s.Z).ToList(); foreach (var slice in slices) { var sliceContours = slice.OrderByDescending(s => s.CalculateArea()).ToList(); ContourHelper.OrganizeIntoChildren(sliceContours[0], sliceContours.Skip(1)); } sm.Structures.Add(meta.StructureId, meta); } catch (Exception e) { _logger.LogError(e, $"Could not add structure {meta.StructureId}"); } } return(sm); }
internal Dictionary <IntPoint, MagsAISurfaceIntersectionData> CalcSupportPoints(SortedDictionary <float, PolyTree> modelLayers, ConcurrentDictionary <float, ConcurrentDictionary <MagsAIIntersectionData, bool> > currentModelSupportPoints, float firstSurfaceAngleDistanceFactor, SupportProfile selectedMaterialProfile, float overhangFactor, ConcurrentDictionary <float, ConcurrentDictionary <float, ConcurrentDictionary <IntPoint, MagsAISurfaceIntersectionData> > > previousOverhangDistanceFactorBasedSupportPoints, STLModel3D stlModel, TriangleSurfaceInfo surface) { this.AddedSupportPoints = new Dictionary <IntPoint, MagsAISurfaceIntersectionData>(); this.AddedSupportPointsByLayer = new Dictionary <float, Dictionary <IntPoint, MagsAISurfaceIntersectionData> >(); //create support cones that exists in each layer var previousSliceHeight = float.MaxValue; foreach (var sliceHeight in this.ModelContours.Keys.OrderBy(s => s)) { var sliceContours = this.ModelContours[sliceHeight]; sliceContours = ContourHelper.IntersectModelSliceLayer(sliceContours, modelLayers[sliceHeight]); //create contour offset using max border as model contour instead of extrude contour if (!this.AddedSupportPointsByLayer.ContainsKey(sliceHeight)) { this.AddedSupportPointsByLayer.Add(sliceHeight, new Dictionary <IntPoint, MagsAISurfaceIntersectionData>()); } if (previousSliceHeight != float.MaxValue) { var supportedLayerAsPolyTree = new PolyTree(); if (this.AddedSupportPointsByLayer.ContainsKey(previousSliceHeight)) { foreach (var supportIntersectionData in this.AddedSupportPointsByLayer[previousSliceHeight].Values) { if (supportIntersectionData.UnsupportedContour) { this.AddedSupportPointsByLayer[sliceHeight].Add(supportIntersectionData.TopPoint, supportIntersectionData); } } } //added support circles from current diff layer with overhang distance foreach (var overhangDistanceFactor in previousOverhangDistanceFactorBasedSupportPoints) { var previousAngleBasedSupportPointsAsCircles = new List <List <IntPoint> >(); if (overhangDistanceFactor.Value.ContainsKey(sliceHeight)) { foreach (var previousAngleBasedSupportPoint in overhangDistanceFactor.Value[sliceHeight].Values) { AddPointToCurrentLayerWhenExistsInContour(sliceContours, previousAngleBasedSupportPoint, sliceHeight); } } } //check if supportcones where allready added using other algorithms var supportSliceHeightsWithinRange = new List <float>() { (float)Math.Round(previousSliceHeight - (sliceHeight - previousSliceHeight), 2), sliceHeight }; var supportSliceHeightsWithinRangeMin = supportSliceHeightsWithinRange[0]; var supportSliceHeightsWithinRangeMax = supportSliceHeightsWithinRange[1]; foreach (var supportPointIndex in currentModelSupportPoints) { foreach (var supportPointValue in supportPointIndex.Value.Keys) { if (supportPointValue.SliceHeight <= sliceHeight && supportPointValue.LastSupportSliceHeight >= supportSliceHeightsWithinRangeMin) { var supportSlicePointAsIntPoint = new IntPoint(supportPointValue.TopPoint); if (!this.AddedSupportPointsByLayer[sliceHeight].ContainsKey(supportSlicePointAsIntPoint)) { var supportConePoint2 = new MagsAISurfaceIntersectionData(); supportConePoint2.TopPoint = supportSlicePointAsIntPoint; supportConePoint2.SliceHeight = sliceHeight; supportConePoint2.OverhangDistanceFactor = firstSurfaceAngleDistanceFactor; supportConePoint2.ModelIntersection = supportPointValue.ModelIntersection; supportConePoint2.LastSupportSliceHeight = supportPointValue.LastSupportSliceHeight; this.AddedSupportPointsByLayer[sliceHeight].Add(supportConePoint2.TopPoint, supportConePoint2); } } } } //combine all previous found points supportedLayerAsPolyTree = new PolyTree(); if (AddedSupportPointsByLayer.ContainsKey(sliceHeight)) { var supportCircles = new List <List <IntPoint> >(); foreach (var addedSupportPointByLayer in AddedSupportPointsByLayer[sliceHeight].Values) { var outlineCirclePoints = MagsAIEngine.ConvertSupportPointsToCircles(addedSupportPointByLayer.TopPoint, selectedMaterialProfile.SupportOverhangDistance); supportCircles.Add(outlineCirclePoints); var outlineCirclePolygon = MagsAIEngine.MergeSupportCircles(new List <List <IntPoint> >() { outlineCirclePoints }); var intersectedPolygons = ContourHelper.IntersectModelSliceLayer(ModelContours[sliceHeight], outlineCirclePolygon); var intersectedPolygonFound = false; foreach (var intersectedPolygon in intersectedPolygons._allPolys.Where(s => !s.IsHole)) { if (ContourHelper.PointExistsInNotHolePolygon(intersectedPolygon, addedSupportPointByLayer.TopPoint)) { supportedLayerAsPolyTree._allPolys.Add(intersectedPolygon); break; } } //check if intersected triangle is part of angle surface if (!intersectedPolygonFound) { //check if triangle index is in surface var pointFound = false; foreach (var surfaceConnection in surface.Keys) { if (addedSupportPointByLayer.ModelIntersection != null) { if (surfaceConnection.ArrayIndex == addedSupportPointByLayer.ModelIntersection.Index.ArrayIndex && surfaceConnection.TriangleIndex == addedSupportPointByLayer.ModelIntersection.Index.TriangleIndex) { foreach (var intersectedPolygon in intersectedPolygons._allPolys.Where(s => !s.IsHole)) { supportedLayerAsPolyTree._allPolys.Add(intersectedPolygon); pointFound = true; } break; } } } if (!pointFound) { } } } // TriangleHelper.SavePolyNodesContourToPng(ModelContours[sliceHeight]._allPolys, surface.Id.ToString("00") + "-" + sliceHeight.ToString("0.00") + "-" + overhangFactor.ToString(".00") + "-model"); // TriangleHelper.SavePolyNodesContourToPng(intersectedPolygons._allPolys, surface.Id.ToString("00") + "-" + sliceHeight.ToString("0.00") + "-" + overhangFactor.ToString(".00") + "-intersected"); //TriangleHelper.SavePolyNodesContourToPng(MagsAIEngine.MergeSupportCircles(supportCircles)._allPolys, surface.Id.ToString("00") + "-" + sliceHeight.ToString("0.00") + "-" + overhangFactor.ToString(".00") + "-supportcircles"); supportedLayerAsPolyTree = UnionModelSliceLayer(new PolyTree(), supportedLayerAsPolyTree); //TriangleHelper.SavePolyNodesContourToPng(supportedLayerAsPolyTree._allPolys, surface.Id.ToString("00") + "-" + sliceHeight.ToString("0.00") + "-" + overhangFactor.ToString(".00") + "-supportedlayer"); } // this.SupportedLayers.Add(sliceHeight, supportedLayerAsPolyTree); var unsupportedLayer = DifferenceModelSliceLayer(sliceContours, supportedLayerAsPolyTree); ////if (sliceHeight >= 15f && sliceHeight <= 16f) // { foreach (var verticalSurface in stlModel.Triangles.MagsAIVerticalSurfaces) { verticalSurface.UpdateBoundries(stlModel.Triangles); if (verticalSurface.BottomPoint <= this.BottomPoint) { foreach (var workingSliceHeight in verticalSurface.VerticalSurfaceModelPolygons.Keys) { if (workingSliceHeight >= previousSliceHeight - 0.4f && workingSliceHeight <= sliceHeight) { //TriangleHelper.SavePolyNodesContourToPng(verticalSurface.VerticalSurfaceModelPolygons[workingSliceHeight]._allPolys, sliceHeight.ToString("0.00") + "-" + workingSliceHeight + "-subtract-vertical-contour"); unsupportedLayer = DifferenceModelSliceLayer(unsupportedLayer, verticalSurface.VerticalSurfaceModelPolygons[workingSliceHeight]); // TriangleHelper.SavePolyNodesContourToPng(unsupportedLayer._allPolys, sliceHeight.ToString("0.00") + "-unsupported-vertical-contour"); } } } } //} //remove supportedLayer from current diff layer and previous found support points //TriangleHelper.SavePolyNodesContourToPng(unsupportedLayer._allPolys, surface.Id.ToString("00") + "-" + sliceHeight.ToString(".00") + "-" + overhangFactor.ToString(".00") + "-surface-unsupported"); if (unsupportedLayer._allPolys.Count > 0) { while (unsupportedLayer._allPolys.Where(s => !s.IsHole).Count() > 0) { var skippedUnsupportedLayerPolyNodes = new List <PolyNode>(); foreach (var unsupportLayerHole in unsupportedLayer._allPolys.Where(s => s.IsHole)) { skippedUnsupportedLayerPolyNodes.Add(unsupportLayerHole); } foreach (var areaToSmallPolygon in unsupportedLayer._allPolys.Where(s => !s.IsHole)) { if ((Clipper.Area(areaToSmallPolygon.Contour) / (CONTOURPOINT_TO_VECTORPOINT_FACTOR * CONTOURPOINT_TO_VECTORPOINT_FACTOR)) < 2) { skippedUnsupportedLayerPolyNodes.Add(areaToSmallPolygon); } } foreach (var removePolygon in skippedUnsupportedLayerPolyNodes) { unsupportedLayer._allPolys.Remove(removePolygon); } skippedUnsupportedLayerPolyNodes.Clear(); foreach (var unsupportedLayerPolyNode in unsupportedLayer._allPolys) { var contourPolyTree = new PolyTree(); contourPolyTree._allPolys.Add(unsupportedLayerPolyNode); //TriangleHelper.SavePolyNodesContourToPng(contourPolyTree._allPolys, "b"); var supportConeIntersections = MagsAIEngine.CalcContourSupportStructure(contourPolyTree, null, null, selectedMaterialProfile, sliceHeight, this, true, false); if (supportConeIntersections.Count > 0) { var supportConeIntersectionPolyTree = new PolyTree(); foreach (var supportConeIntersection in supportConeIntersections) { if (supportConeIntersection.LowestPoints.Count == 0) { skippedUnsupportedLayerPolyNodes.Add(unsupportedLayerPolyNode); } else { var k = 0; foreach (var supportConeIntersectionPoint in supportConeIntersection.LowestPoints) { var supportConeIntersectionPointAsIntPoint = supportConeIntersectionPoint.Point; supportConeIntersectionPointAsIntPoint.Z = (int)(sliceHeight * CONTOURPOINT_TO_VECTORPOINT_FACTOR); var addedSupportPoint = new MagsAISurfaceIntersectionData() { TopPoint = supportConeIntersectionPointAsIntPoint, SliceHeight = sliceHeight }; addedSupportPoint.OverhangDistanceFactor = selectedMaterialProfile.SupportOverhangDistance * overhangFactor; var outlineCirclePoints = MagsAIEngine.ConvertSupportPointsToCircles(supportConeIntersectionPointAsIntPoint, selectedMaterialProfile.SupportOverhangDistance * overhangFactor); var outlineCirclePolygon = MagsAIEngine.MergeSupportCircles(new List <List <IntPoint> >() { outlineCirclePoints }); var intersectedPolygons = ContourHelper.IntersectModelSliceLayer(ModelContours[sliceHeight], outlineCirclePolygon); var intersectionPointFound = false; foreach (var intersectedPolygon in intersectedPolygons._allPolys.Where(s => !s.IsHole)) { if (ContourHelper.PointExistsInNotHolePolygon(intersectedPolygon, addedSupportPoint.TopPoint)) { supportConeIntersectionPolyTree._allPolys.Add(intersectedPolygon); intersectionPointFound = true; } } if (!intersectionPointFound) { foreach (var intersectedPolygon in intersectedPolygons._allPolys.Where(s => !s.IsHole)) { supportConeIntersectionPolyTree._allPolys.Add(intersectedPolygon); } } // TriangleHelper.SavePolyNodesContourToPng(outlineCirclePolygon._allPolys, sliceHeight.ToString("0.00") + "-" + k.ToString()); addedSupportPoint.UpdateLastSupportedHeight(stlModel); addedSupportPoint.UpdateTriangleReference(stlModel); if (!this.AddedSupportPoints.ContainsKey(addedSupportPoint.TopPoint)) { this.AddedSupportPoints.Add(addedSupportPoint.TopPoint, addedSupportPoint); } if (!this.AddedSupportPointsByLayer[sliceHeight].ContainsKey(addedSupportPoint.TopPoint)) { addedSupportPoint.UnsupportedContour = true; this.AddedSupportPointsByLayer[sliceHeight].Add(addedSupportPoint.TopPoint, addedSupportPoint); } k++; } } if (supportConeIntersectionPolyTree._allPolys.Count > 0) { unsupportedLayer = DifferenceModelSliceLayer(unsupportedLayer, supportConeIntersectionPolyTree); // TriangleHelper.SavePolyNodesContourToPng(unsupportedLayer._allPolys, "s"); break; } } } } if (skippedUnsupportedLayerPolyNodes.Count > 0) { foreach (var skippedUnsuppertedLayerPolyNode in skippedUnsupportedLayerPolyNodes) { unsupportedLayer._allPolys.Remove(skippedUnsuppertedLayerPolyNode); } } } } previousSliceHeight = sliceHeight; } if (previousSliceHeight == float.MaxValue) { previousSliceHeight = sliceHeight; } } return(this.AddedSupportPoints); }