예제 #1
0
        public NewSupport(ConfigSettings config, List <ExtruderLayers> Extruders, ExtruderLayers userGeneratedSupport, long grabDistance_um)
        {
            cleanDistance_um = config.ExtrusionWidth_um / 10;
            long supportWidth_um = (long)(config.ExtrusionWidth_um * (100 - config.SupportPercent) / 100);
            // create starting support outlines
            List <Polygons> allPartOutlines = CalculateAllPartOutlines(config, Extruders);

            _InsetPartOutlines = CreateInsetPartOutlines(allPartOutlines, config.ExtrusionWidth_um / 2);

            int numSupportLayers = userGeneratedSupport.Layers.Count;

            SparseSupportOutlines = CreateEmptyPolygons(numSupportLayers);

            // calculate the combined outlines for everything
            for (int layerIndex = 0; layerIndex < numSupportLayers; layerIndex++)
            {
                SparseSupportOutlines[layerIndex] = userGeneratedSupport.Layers[layerIndex].AllOutlines.DeepCopy();
            }

            SparseSupportOutlines = ExpandToEasyGrabDistance(SparseSupportOutlines, grabDistance_um - supportWidth_um);

            // remove the actual parts from the support data
            SparseSupportOutlines = ClipToXyDistance(SparseSupportOutlines, _InsetPartOutlines, config);

            // create the interface layers
            InterfaceLayers = CreateInterfaceLayers(SparseSupportOutlines, config.SupportInterfaceLayers);

            // and the bottom support layers
            AirGappedBottomOutlines = CreateAirGappedBottomLayers(SparseSupportOutlines, _InsetPartOutlines);

            // remove the interface layers from the normal support layers
            SparseSupportOutlines = CalculateDifferencePerLayer(SparseSupportOutlines, InterfaceLayers);
            // remove the airGappedBottomOutlines layers from the normal support layers
            SparseSupportOutlines = CalculateDifferencePerLayer(SparseSupportOutlines, AirGappedBottomOutlines);
        }
예제 #2
0
        public SupportLayers(ConfigSettings config, List <ExtruderLayers> extruders, ExtruderLayers userGeneratedSupport)
        {
            cleanDistance_um = config.ExtrusionWidth_um / 10;
            // create starting support outlines
            List <Polygons> allPartOutlines = CalculateAllPartOutlines(config, extruders);

            _InsetPartOutlines = CreateInsetPartOutlines(allPartOutlines, config.ExtrusionWidth_um / 2);

            if (userGeneratedSupport == null)
            {
                long supportWidth_um = (long)(config.ExtrusionWidth_um * (100 - config.SupportPercent) / 100);

                _AllUnsupportedAreas = FindAllUnsupportedAreas(_InsetPartOutlines, supportWidth_um);

                _RequiredSupportAreas = RemoveSelfSupportedAreas(_AllUnsupportedAreas, supportWidth_um);

                if (!config.GenerateInternalSupport)
                {
                    _RequiredSupportAreas = RemoveSupportFromInternalSpaces(_RequiredSupportAreas, _InsetPartOutlines);
                }

                SparseSupportOutlines = AccumulateDownPolygons(config, _RequiredSupportAreas, _InsetPartOutlines);

                SparseSupportOutlines = ExpandToEasyGrabDistance(SparseSupportOutlines, config.SupportGrabDistance_um - supportWidth_um);
            }
            else
            {
                int numSupportLayers = userGeneratedSupport.Layers.Count;
                SparseSupportOutlines = CreateEmptyPolygons(numSupportLayers);

                // calculate the combined outlines for everything
                for (int layerIndex = 0; layerIndex < numSupportLayers; layerIndex++)
                {
                    SparseSupportOutlines[layerIndex] = userGeneratedSupport.Layers[layerIndex].AllOutlines.DeepCopy();
                }
            }

            // remove the actual parts from the support data
            SparseSupportOutlines = ClipToXyDistance(SparseSupportOutlines, _InsetPartOutlines, config);

            // create the interface layers
            InterfaceLayers = CreateInterfaceLayers(SparseSupportOutlines, config.SupportInterfaceLayers);

            // and the bottom support layers
            AirGappedBottomOutlines = CreateAirGappedBottomLayers(SparseSupportOutlines, _InsetPartOutlines);

            // remove the interface layers from the normal support layers
            SparseSupportOutlines = CalculateDifferencePerLayer(SparseSupportOutlines, InterfaceLayers);
            // remove the airGappedBottomOutlines layers from the normal support layers
            SparseSupportOutlines = CalculateDifferencePerLayer(SparseSupportOutlines, AirGappedBottomOutlines);
            // make sure we don't print an interface layer where there is a bottom layer
            InterfaceLayers = CalculateDifferencePerLayer(InterfaceLayers, AirGappedBottomOutlines);
        }
예제 #3
0
        public void CreateWipeTower(int totalLayers, ConfigSettings config, ExtruderLayers wipeTowerLayers)
        {
            if (wipeTowerLayers != null &&
                wipeTowerLayers.Layers.Count > 0 &&
                wipeTowerLayers.Layers[0].AllOutlines.Count > 0)
            {
                for (int i = 0; i < wipeTowerLayers.Layers.Count; i++)
                {
                    var layer = wipeTowerLayers.Layers[i];

                    if (layer.AllOutlines.PolygonLength() > 0)
                    {
                        this.WipeTower.Add(layer.AllOutlines);
                    }
                    else
                    {
                        this.WipeTower.Add(this.WipeTower[i - 1]);
                    }
                }
            }
            else if (config.WipeTowerSize_um < 1 ||
                     LastLayerWithChange(config) == -1)
            {
                return;
            }
            else
            {
                var wipeTowerShape = new Polygon();

                var size = config.WipeTowerSize_um;
                WipeCenter_um = new IntPoint(this.modelMin.X - 3000 - size / 2,
                                             this.modelMax.Y + 3000 + size / 2);

                var points = 100;
                for (int i = 0; i < points; i++)
                {
                    var angle = Math.PI * 2 * i / points;
                    wipeTowerShape.Add(WipeCenter_um + new IntPoint(Math.Cos(angle) * size / 2, Math.Sin(angle) * size / 2));
                }

                this.WipeTower.Add(new Polygons()
                {
                    wipeTowerShape
                });
            }

            var wipeTowerBounds = this.WipeTower[0].GetBounds();

            WipeCenter_um = new IntPoint(
                wipeTowerBounds.minX + (wipeTowerBounds.maxX - wipeTowerBounds.minX) / 2,
                wipeTowerBounds.minY + (wipeTowerBounds.maxY - wipeTowerBounds.minY) / 2);
        }
예제 #4
0
        public void GenerateTopAndBottoms(ConfigSettings config, int layerIndex, long extrusionWidth_um, long outerPerimeterWidth_um, int downLayerCount, int upLayerCount, long infillExtendIntoPerimeter_um)
        {
            var clippingOffset = infillExtendIntoPerimeter_um * 2;

            ExtruderLayers extruder = this;
            SliceLayer     layer    = extruder.Layers[layerIndex];

            Agg.Parallel.For(0, layer.Islands.Count, (islandIndex) =>
                             // for (int islandIndex = 0; islandIndex < layer.Islands.Count; islandIndex++)
            {
                LayerIsland island = layer.Islands[islandIndex];
                if (island.InsetToolPaths.Count == 0)
                {
                    return;
                }

                // this is the entire extrusion width to make sure we are outside of the extrusion line
                Polygons lastInset         = island.InsetToolPaths[island.InsetToolPaths.Count - 1];
                Polygons infillRegionPath  = lastInset.Offset(-extrusionWidth_um);
                Polygons sparseInfillPaths = new Polygons(infillRegionPath);

                // calculate the bottom outlines
                if (downLayerCount > 0)
                {
                    Polygons bottomOutlines = new Polygons(infillRegionPath);

                    if (layerIndex - 1 >= 0)
                    {
                        var previousLayer = extruder.Layers[layerIndex - 1];

                        bottomOutlines = RemoveIslandsFromPolygons(previousLayer.Islands, island.BoundingBox, bottomOutlines);
                        bottomOutlines.RemoveSmallAreas(extrusionWidth_um);
                    }

                    sparseInfillPaths = sparseInfillPaths.CreateDifference(bottomOutlines);
                    sparseInfillPaths = Clipper.CleanPolygons(sparseInfillPaths, cleanDistance_um);

                    island.BottomPaths = bottomOutlines;
                }

                // calculate the top outlines
                if (upLayerCount > 0)
                {
                    Polygons topOutlines = new Polygons(infillRegionPath);
                    topOutlines          = topOutlines.CreateDifference(island.BottomPaths.Offset(clippingOffset));
                    topOutlines          = Clipper.CleanPolygons(topOutlines, cleanDistance_um);

                    if (layerIndex + 1 < extruder.Layers.Count)
                    {
                        // Remove the top layer that is above this one to get only the data that is a top layer on this layer.
                        topOutlines = RemoveIslandsFromPolygons(extruder.Layers[layerIndex + 1].Islands, island.BoundingBox, topOutlines);
                    }

                    topOutlines.RemoveSmallAreas(extrusionWidth_um);

                    sparseInfillPaths = sparseInfillPaths.CreateDifference(topOutlines.Offset(clippingOffset));
                    sparseInfillPaths = Clipper.CleanPolygons(sparseInfillPaths, cleanDistance_um);

                    island.TopPaths = topOutlines;
                }

                if (upLayerCount <= 0 && downLayerCount <= 0)
                {
                    // Assign infill directly if no top/bottom solid layers
                    island.SparseInfillPaths = sparseInfillPaths;
                }
                else
                {
                    // calculate the solid infill outlines
                    Polygons solidInfillPaths = new Polygons(infillRegionPath);

                    // remove all the top layers
                    solidInfillPaths = solidInfillPaths.CreateDifference(island.BottomPaths.Offset(clippingOffset));
                    solidInfillPaths = Clipper.CleanPolygons(solidInfillPaths, cleanDistance_um);

                    // remove all the bottom layers
                    solidInfillPaths = solidInfillPaths.CreateDifference(island.TopPaths.Offset(clippingOffset));
                    solidInfillPaths = Clipper.CleanPolygons(solidInfillPaths, cleanDistance_um);

                    int upEnd = layerIndex + upLayerCount + 1;
                    if (upEnd <= extruder.Layers.Count && layerIndex - downLayerCount >= 0)
                    {
                        // find all the regions that have more top and bottom layers than should be solid (will remain sparse)
                        Polygons regionsThatWillBeSparse = new Polygons(infillRegionPath);

                        int upStart = layerIndex + 2;

                        Agg.Parallel.For(upStart, upEnd, (layerToTest) =>
                                         // for (int layerToTest = upStart; layerToTest < upEnd; layerToTest++)
                        {
                            regionsThatWillBeSparse = IntersectWithPolygons(extruder.Layers[layerToTest].Islands, island.BoundingBox, regionsThatWillBeSparse);
                            regionsThatWillBeSparse = Clipper.CleanPolygons(regionsThatWillBeSparse, cleanDistance_um);
                        });

                        // find all the solid infill bottom layers
                        int downStart = Math.Max(0, layerIndex - 1);
                        int downEnd   = Math.Max(0, layerIndex - downLayerCount);

                        Agg.Parallel.For(downStart, downEnd, (layerToTest) =>
                                         // for (int layerToTest = downStart; layerToTest >= downEnd; layerToTest--)
                        {
                            regionsThatWillBeSparse = IntersectWithPolygons(extruder.Layers[layerToTest].Islands, island.BoundingBox, regionsThatWillBeSparse);
                            regionsThatWillBeSparse = Clipper.CleanPolygons(regionsThatWillBeSparse, cleanDistance_um);
                        });

                        solidInfillPaths = solidInfillPaths.CreateDifference(regionsThatWillBeSparse);
                        solidInfillPaths.RemoveSmallAreas(extrusionWidth_um);
                        solidInfillPaths = Clipper.CleanPolygons(solidInfillPaths, cleanDistance_um);
                    }

                    // remove the solid infill from the sparse infill
                    sparseInfillPaths = sparseInfillPaths.CreateDifference(solidInfillPaths.Offset(clippingOffset));
                    sparseInfillPaths.RemoveSmallAreas(extrusionWidth_um);
                    sparseInfillPaths        = Clipper.CleanPolygons(sparseInfillPaths, cleanDistance_um);
                    island.SparseInfillPaths = sparseInfillPaths;

                    if (config == null ||                   // this is to make our tests test the bridgeOverInfill
                        config.BridgeOverInfill)
                    {
                        // now figure out what part of the solid infill is actually first top layers and switch it to that
                        // we can only have a first top y layer at the bottom of the top layers
                        if (layerIndex == extruder.Layers.Count - upLayerCount)
                        {
                            // all of it is first top layers
                            island.FirstTopPaths = solidInfillPaths;
                            solidInfillPaths     = new Polygons();
                        }
                        else if (layerIndex > 0 &&
                                 layerIndex < extruder.Layers.Count - upLayerCount)
                        {
                            // Intersect the current solid layer with the previous spars layer
                            // that will be all of the new solid layers that are currently on sparse layer

                            var firstTopPaths = new Polygons(solidInfillPaths);
                            firstTopPaths     = IntersectWithSparsePolygons(extruder.Layers[layerIndex - 1].Islands, island.BoundingBox, firstTopPaths);
                            firstTopPaths.RemoveSmallAreas(extrusionWidth_um);
                            firstTopPaths = Clipper.CleanPolygons(firstTopPaths, cleanDistance_um);

                            if (firstTopPaths.Count > 0)
                            {
                                solidInfillPaths = solidInfillPaths.CreateDifference(firstTopPaths.Offset(clippingOffset));
                                solidInfillPaths.RemoveSmallAreas(extrusionWidth_um);
                                solidInfillPaths = Clipper.CleanPolygons(solidInfillPaths, cleanDistance_um);

                                island.FirstTopPaths = firstTopPaths;
                            }
                        }
                    }

                    island.SolidInfillPaths = solidInfillPaths;
                }
            });
        }
예제 #5
0
        public void GenerateTopAndBottoms(int layerIndex, int extrusionWidth_um, int outerPerimeterWidth_um, int downLayerCount, int upLayerCount)
        {
            ExtruderLayers extruder = this;
            SliceLayer     layer    = extruder.Layers[layerIndex];

            for (int islandIndex = 0; islandIndex < layer.Islands.Count; islandIndex++)
            {
                LayerIsland island = layer.Islands[islandIndex];
                // this is the entire extrusion width to make sure we are outside of the extrusion line
                Polygons lastInset       = island.InsetToolPaths[island.InsetToolPaths.Count - 1];
                Polygons insetWithOffset = lastInset.Offset(-extrusionWidth_um);
                Polygons infillOutlines  = new Polygons(insetWithOffset);

                // calculate the bottom outlines
                if (downLayerCount > 0)
                {
                    Polygons bottomOutlines = new Polygons(insetWithOffset);

                    if (layerIndex - 1 >= 0)
                    {
                        bottomOutlines = RemoveIslandsFromPolygons(extruder.Layers[layerIndex - 1].Islands, island.BoundingBox, bottomOutlines);
                        bottomOutlines.RemoveSmallAreas(extrusionWidth_um);
                    }

                    infillOutlines = infillOutlines.CreateDifference(bottomOutlines);
                    infillOutlines = Clipper.CleanPolygons(infillOutlines, cleanDistance_um);

                    island.SolidBottomToolPaths = bottomOutlines;
                }

                // calculate the top outlines
                if (upLayerCount > 0)
                {
                    Polygons topOutlines = new Polygons(insetWithOffset);
                    topOutlines = topOutlines.CreateDifference(island.SolidBottomToolPaths);
                    topOutlines = Clipper.CleanPolygons(topOutlines, cleanDistance_um);

                    for (int insetIndex = 0; insetIndex < island.InsetToolPaths.Count - 1; insetIndex++)
                    {
                        // Add thin wall filling by taking the area between the insets.
                        Polygons largerInset  = island.InsetToolPaths[insetIndex].Offset(-extrusionWidth_um / 2);
                        Polygons smallerInset = island.InsetToolPaths[insetIndex + 1].Offset(extrusionWidth_um / 2);

                        Polygons thinWalls = largerInset.CreateDifference(smallerInset).Offset(-extrusionWidth_um / 4);
                        if (thinWalls.Count > 0)
                        {
                            topOutlines.AddAll(thinWalls);
                        }
                    }

                    if (layerIndex + 1 < extruder.Layers.Count)
                    {
                        // Remove the top layer that is above this one to get only the data that is a top layer on this layer.
                        topOutlines = RemoveIslandsFromPolygons(extruder.Layers[layerIndex + 1].Islands, island.BoundingBox, topOutlines);
                    }

                    topOutlines.RemoveSmallAreas(extrusionWidth_um);

                    infillOutlines = infillOutlines.CreateDifference(topOutlines);
                    infillOutlines = Clipper.CleanPolygons(infillOutlines, cleanDistance_um);

                    island.SolidTopToolPaths = topOutlines;
                }

                // calculate the solid infill outlines
                if (upLayerCount > 1 || downLayerCount > 1)
                {
                    Polygons solidInfillOutlines = new Polygons(insetWithOffset);
                    solidInfillOutlines = solidInfillOutlines.CreateDifference(island.SolidBottomToolPaths);
                    solidInfillOutlines = Clipper.CleanPolygons(solidInfillOutlines, cleanDistance_um);
                    solidInfillOutlines = solidInfillOutlines.CreateDifference(island.SolidTopToolPaths);

                    solidInfillOutlines = Clipper.CleanPolygons(solidInfillOutlines, cleanDistance_um);

                    int upEnd = layerIndex + upLayerCount + 1;
                    if (upEnd <= extruder.Layers.Count && layerIndex - downLayerCount >= 0)
                    {
                        Polygons totalPartsToRemove = new Polygons(insetWithOffset);

                        int upStart = layerIndex + 2;

                        for (int layerToTest = upStart; layerToTest < upEnd; layerToTest++)
                        {
                            totalPartsToRemove = AddIslandsToPolygons(extruder.Layers[layerToTest].Islands, island.BoundingBox, totalPartsToRemove);
                            totalPartsToRemove = Clipper.CleanPolygons(totalPartsToRemove, cleanDistance_um);
                        }

                        int downStart = layerIndex - 1;
                        int downEnd   = layerIndex - downLayerCount;

                        for (int layerToTest = downStart; layerToTest >= downEnd; layerToTest--)
                        {
                            totalPartsToRemove = AddIslandsToPolygons(extruder.Layers[layerToTest].Islands, island.BoundingBox, totalPartsToRemove);
                            totalPartsToRemove = Clipper.CleanPolygons(totalPartsToRemove, cleanDistance_um);
                        }

                        solidInfillOutlines = solidInfillOutlines.CreateDifference(totalPartsToRemove);
                        solidInfillOutlines.RemoveSmallAreas(extrusionWidth_um);

                        solidInfillOutlines = Clipper.CleanPolygons(solidInfillOutlines, cleanDistance_um);
                    }

                    island.SolidInfillToolPaths = solidInfillOutlines;
                    infillOutlines = infillOutlines.CreateDifference(solidInfillOutlines);
                }

                infillOutlines.RemoveSmallAreas(extrusionWidth_um);
                infillOutlines         = Clipper.CleanPolygons(infillOutlines, cleanDistance_um);
                island.InfillToolPaths = infillOutlines;
            }
        }
예제 #6
0
		private static ExtruderLayers CreateLayerData(List<Polygons> totalLayerOutlines)
		{
			int numLayers = totalLayerOutlines.Count;
			ExtruderLayers layerData = new ExtruderLayers();
			layerData.Layers = new List<SliceLayer>();
			for (int layerIndex = 0; layerIndex < numLayers; layerIndex++)
			{
				SliceLayer layer = new SliceLayer();
				layer.AllOutlines = totalLayerOutlines[layerIndex];
				layerData.Layers.Add(layer);
			}
			return layerData;
		}