Beispiel #1
0
        /// <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);
 }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        /// <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());
        }
Beispiel #6
0
        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);
                        }
                    }
                }
            }
        }
Beispiel #7
0
        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);
        }