コード例 #1
0
		public static PathStorage PolygonToPathStorage(Polygons polygons)
		{
			PathStorage output = new PathStorage();

			foreach (Polygon polygon in polygons)
			{
				bool first = true;
				foreach (IntPoint point in polygon)
				{
					if (first)
					{
						output.Add(point.X, point.Y, ShapePath.FlagsAndCommand.CommandMoveTo);
						first = false;
					}
					else
					{
						output.Add(point.X, point.Y, ShapePath.FlagsAndCommand.CommandLineTo);
					}
				}

				output.ClosePolygon();
			}
			output.Add(0, 0, ShapePath.FlagsAndCommand.CommandStop);

			return output;
		}
コード例 #2
0
		public static void AddAll(this Polygons polygons, Polygons other)
		{
			for (int n = 0; n < other.Count; n++)
			{
				polygons.Add(other[n]);
			}
		}
コード例 #3
0
		public AvoidCrossingPerimeters(Polygons bounderyPolygons)
		{
			this.bounderyPolygons = bounderyPolygons;
			minXPosition = new long[bounderyPolygons.Count];
			maxXPosition = new long[bounderyPolygons.Count];
			indexOfMinX = new int[bounderyPolygons.Count];
			indexOfMaxX = new int[bounderyPolygons.Count];
		}
コード例 #4
0
ファイル: Program.cs プロジェクト: caomw/elementdiscovery
 public void AddPolygons(Polygons poly)
 {
     if (poly.Count == 0) return;
     PolyInfo pi = new PolyInfo();
     pi.polygons = poly;
     pi.si = style.Clone();
     PolyInfoList.Add(pi);
 }
コード例 #5
0
ファイル: 3DToyForm.cs プロジェクト: qqzh002/3DToy
 private void LoadButton_Click(object sender, EventArgs e)
 {
     if (openFileDialog.ShowDialog() == DialogResult.OK)
     {
         pathText.Text = openFileDialog.FileName;
         _polygons = DataLoader.LoadPolygons(openFileDialog.OpenFile());
     }
 }
コード例 #6
0
ファイル: PolygonHelper.cs プロジェクト: broettge/MatterSlice
		public void Calculate(Polygons polys)
		{
			min = new IntPoint(long.MaxValue, long.MaxValue);
			max = new IntPoint(long.MinValue, long.MinValue);
			for (int i = 0; i < polys.Count; i++)
			{
				for (int j = 0; j < polys[i].Count; j++)
				{
					if (min.X > polys[i][j].X) min.X = polys[i][j].X;
					if (min.Y > polys[i][j].Y) min.Y = polys[i][j].Y;
					if (max.X < polys[i][j].X) max.X = polys[i][j].X;
					if (max.Y < polys[i][j].Y) max.Y = polys[i][j].Y;
				}
			}
		}
コード例 #7
0
ファイル: infill.cs プロジェクト: GearWalker/MatterSlice
		public static void GenerateLinePaths(Polygons polygonToInfill, ref Polygons infillLinesToPrint, int lineSpacing, int infillExtendIntoPerimeter_um, double rotation, long rotationOffset = 0)
		{
			if (polygonToInfill.Count > 0)
			{
				Polygons outlines = polygonToInfill.Offset(infillExtendIntoPerimeter_um);
				if (outlines.Count > 0)
				{
					PointMatrix matrix = new PointMatrix(-(rotation + 90)); // we are rotating the part so we rotate by the negative so the lines go the way we expect

					outlines.ApplyMatrix(matrix);

					Aabb boundary = new Aabb(outlines);

					boundary.min.X = ((boundary.min.X / lineSpacing) - 1) * lineSpacing - rotationOffset;
					int xLineCount = (int)((boundary.max.X - boundary.min.X + (lineSpacing - 1)) / lineSpacing);
					Polygons unclipedPatern = new Polygons();

					long firstX = boundary.min.X / lineSpacing * lineSpacing;
					for (int lineIndex = 0; lineIndex < xLineCount; lineIndex++)
					{
						Polygon line = new Polygon();
						line.Add(new IntPoint(firstX + lineIndex * lineSpacing, boundary.min.Y));
						line.Add(new IntPoint(firstX + lineIndex * lineSpacing, boundary.max.Y));
						unclipedPatern.Add(line);
					}

					PolyTree ret = new PolyTree();
					Clipper clipper = new Clipper();
					clipper.AddPaths(unclipedPatern, PolyType.ptSubject, false);
					clipper.AddPaths(outlines, PolyType.ptClip, true);
					clipper.Execute(ClipType.ctIntersection, ret, PolyFillType.pftPositive, PolyFillType.pftEvenOdd);

					Polygons newSegments = Clipper.OpenPathsFromPolyTree(ret);
					PointMatrix inversematrix = new PointMatrix((rotation + 90));
					newSegments.ApplyMatrix(inversematrix);

					infillLinesToPrint.AddRange(newSegments);
				}
			}
		}
コード例 #8
0
ファイル: clipper.cs プロジェクト: caomw/elementdiscovery
        //------------------------------------------------------------------------------

        public static void ReversePolygons(Polygons polys)
        {
            polys.ForEach(delegate(Polygon poly) { poly.Reverse(); });
        }
コード例 #9
0
        public IEnumerable <Polygon> GetBackwardsPolygons(float epsilon = 0.001f)
        {
            var origin = Origin;

            return(Polygons.Where(x => x.Plane.OnPlane(origin, epsilon) > 0));
        }
コード例 #10
0
        public FestaMapRootPageViewModel(INavigationService navigationService, IEventAggregator eventAggregator, IShowFestaMap showFesta, IMapAssociated mapParam)
        {
            _eventAggregator   = eventAggregator;
            _navigationService = navigationService;
            showFestaUsecase   = showFesta;
            _mapParams         = mapParam;

            InfoWindowClickedCommand = new DelegateCommand <InfoWindowClickedEventArgs>(async(pin) =>
            {
                var region = pin.Pin.Tag as MapRegion;
                if (region == null)
                {
                    return;
                }
                if (IsGlobalMap)
                {
                    if (region.MapObjectType.HasFlag(MapObjectEnum.STAGE))
                    {
                        await _navigationService.NavigateAsync(
                            nameof(StageEventListRootPageViewModel).GetViewNameFromRule(),
                            StageEventListRootPageViewModel.GetNavigationParameter(region.Id, region.Name));
                    }
                    else
                    {
                        var type = region.MapObjectType.HasFlag(MapObjectEnum.EXHIBITION) ? PlanningTypeEnum.EXHIBITION : PlanningTypeEnum.STALL;
                        await _navigationService.NavigateAsync(
                            "RegionSpecificPlanningListPage",
                            PlanningListRootPageViewModel.GetNavigationParameter(region.Id, region.Name, type));
                    }
                }
            });

            _eventAggregator.GetEvent <PolygonClickedEvent>().Subscribe((pin) =>
            {
                SelectedPin.Value = pin.Tag as Pin;
                MoveToRegionRequest.MoveToRegion(
                    MapSpan.FromCenterAndRadius(SelectedPin.Value.Position, Distance.FromMeters(100)));
            }).AddTo(this.Disposable);

            showFesta.Pins.ToCollectionChanged <Pin>()
            .Subscribe(change =>
            {
                switch (change.Action)
                {
                case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                    Pins?.Add(change.Value);
                    break;

                case System.Collections.Specialized.NotifyCollectionChangedAction.Move:
                    break;

                case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                    Pins?.Remove(change.Value);
                    break;

                case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
                    break;

                case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                    Pins?.Clear();
                    break;
                }
            }).AddTo(this.Disposable);

            showFesta.Polygons.ToCollectionChanged <Polygon>()
            .Subscribe(change =>
            {
                switch (change.Action)
                {
                case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                    Polygons?.Add(change.Value);
                    break;

                case System.Collections.Specialized.NotifyCollectionChangedAction.Move:
                    break;

                case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                    Polygons?.Remove(change.Value);
                    break;

                case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
                    break;

                case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                    Polygons?.Clear();
                    break;
                }
            }).AddTo(this.Disposable);

            // For iOS
            _eventAggregator.GetEvent <TabbedPageOpendEvent>().Subscribe((ev) =>
            {
                if (ev.Name != this.GetType().Name.Replace("ViewModel", ""))
                {
                    return;
                }

                IsShowingUser.Value = true;
                showFestaUsecase.InitializeAllMapObjects();
                if (IsGlobalMap)
                {
                    MoveToRegionRequest.MoveToRegion(
                        MapSpan.FromCenterAndRadius(
                            new Position(_mapParams.MapCenterLangitude, _mapParams.MapCenterLongitude),
                            Distance.FromMeters(185)));
                }
            }).AddTo(this.Disposable);

            _eventAggregator.GetEvent <LocationPermissionRequestResultEvent>()
            .Subscribe((ev) =>
            {
                IsShowingUser.Value = ev.Granted;
            });

            Title.AddTo(this.Disposable);
            SelectedPin.AddTo(this.Disposable);
            IsShowingUser.AddTo(this.Disposable);
        }
コード例 #11
0
		public static Polygons ProcessEvenOdd(this Polygons polygons)
		{
			Polygons ret = new Polygons();
			Clipper clipper = new Clipper();
			clipper.AddPaths(polygons, PolyType.ptSubject, true);
			clipper.Execute(ClipType.ctUnion, ret);
			return ret;
		}
コード例 #12
0
		public static Polygons DeepCopy(this Polygons polygons)
		{
			Polygons deepCopy = new Polygons();
			foreach (Polygon poly in polygons)
			{
				deepCopy.Add(new Polygon(poly));
			}

			return deepCopy;
		}
コード例 #13
0
		public static Polygons CreateFromString(string polygonsPackedString)
		{
			Polygons output = new Polygons();
			string[] polygons = polygonsPackedString.Split('|');
			foreach (string polygonString in polygons)
			{
				Polygon nextPoly = PolygonHelper.CreateFromString(polygonString);
				if (nextPoly.Count > 0)
				{
					output.Add(nextPoly);
				}
			}
			return output;
		}
コード例 #14
0
ファイル: clipper.cs プロジェクト: caomw/elementdiscovery
        //------------------------------------------------------------------------------

        public static void PolyTreeToPolygons(PolyTree polytree, Polygons polygons)
        {
            polygons.Clear();
            polygons.Capacity = polytree.Total;
            AddPolyNodeToPolygons(polytree, polygons);
        }
コード例 #15
0
ファイル: Example_Clipper.cs プロジェクト: CrazyLiu00/GMap
        bool LoadFromFile(string filename, Polygons ppg, double scale // = 0
                          , int xOffset                               // = 0
                          , int yOffset)                              // = 0)
        {
            double scaling = Math.Pow(10, scale);

            ppg.Clear();
            if (!Alt.IO.File.Exists(filename))
            {
                return(false);
            }
            System.IO.StreamReader sr = new System.IO.StreamReader(filename);
            if (sr == null)
            {
                return(false);
            }
            string line;

            if ((line = sr.ReadLine()) == null)
            {
                return(false);
            }
            int polyCnt, vertCnt;

            if (!Int32.TryParse(line, out polyCnt) || polyCnt < 0)
            {
                return(false);
            }
            ppg.Capacity = polyCnt;
            for (int i = 0; i < polyCnt; i++)
            {
                if ((line = sr.ReadLine()) == null)
                {
                    return(false);
                }
                if (!Int32.TryParse(line, out vertCnt) || vertCnt < 0)
                {
                    return(false);
                }
                Polygon pg = new Polygon(vertCnt);
                ppg.Add(pg);
                for (int j = 0; j < vertCnt; j++)
                {
                    double x, y;
                    if ((line = sr.ReadLine()) == null)
                    {
                        return(false);
                    }
                    char[]   delimiters = new char[] { ',', ' ' };
                    string[] vals       = line.Split(delimiters);
                    if (vals.Length < 2)
                    {
                        return(false);
                    }
                    if (!double.TryParse(vals[0], out x))
                    {
                        return(false);
                    }
                    if (!double.TryParse(vals[1], out y))
                    {
                        if (vals.Length < 2 || !double.TryParse(vals[2], out y))
                        {
                            return(false);
                        }
                    }
                    x = x * scaling + xOffset;
                    y = y * scaling + yOffset;
                    pg.Add(new IntPoint((int)Math.Round(x), (int)Math.Round(y)));
                }
            }
            return(true);
        }
コード例 #16
0
ファイル: Example_Clipper.cs プロジェクト: CrazyLiu00/GMap
        void DrawingPanel_Paint(object sender, GUI.PaintEventArgs e)
        {
            GUI.Cursor.Current = GUI.Cursors.WaitCursor;

            Graphics      graphics            = e.Graphics;
            SmoothingMode fillSmoothingMode   = graphics is SoftwareGraphics ? SmoothingMode.AntiAlias : SmoothingMode.None;
            SmoothingMode strokeSmoothingMode = SmoothingMode.AntiAlias;

            graphics.SmoothingMode = fillSmoothingMode;

            graphics.Clear(Color.White);


            GraphicsPath path = new GraphicsPath();

            if (rbNonZero.IsChecked)
            {
                path.FillMode = FillMode.Winding;
            }

            //draw subjects ...
            foreach (Polygon pg in subjects)
            {
                Point[] pts = PolygonToPointArray(pg, scale);
                path.AddPolygon(pts);
                pts = null;
            }

            Pen myPen = new Pen(
                //Color.FromArgb(196, 0xC3, 0xC9, 0xCF),
                Color.FromArgb(128, 0, 0, 255),
                0.6);
            SolidColorBrush myBrush = new SolidColorBrush(
                //Color.FromArgb(127, 0xDD, 0xDD, 0xF0));
                //Color.FromArgb(255, 210, 210, 255));
                Color.FromArgb(127, Color.LightBlue));

            graphics.SmoothingMode = fillSmoothingMode;
            graphics.FillPath(myBrush, path);
            graphics.SmoothingMode = strokeSmoothingMode;
            graphics.DrawPath(myPen, path);
            path.Reset();

            //draw clips ...
            if (rbNonZero.IsChecked)
            {
                path.FillMode = FillMode.Winding;
            }
            foreach (Polygon pg in clips)
            {
                Point[] pts = PolygonToPointArray(pg, scale);
                path.AddPolygon(pts);
                pts = null;
            }
            myPen.Color   = Color.FromArgb(128, Color.Red); //0xF9, 0xBE, 0xA6);
            myBrush.Color =                                 //Color.FromArgb(127, 0xFF, 0xE0, 0xE0);
                            Color.FromArgb(50, 255, 0, 0);

            graphics.SmoothingMode = fillSmoothingMode;
            graphics.FillPath(myBrush, path);
            graphics.SmoothingMode = strokeSmoothingMode;
            graphics.DrawPath(myPen, path);

            //do the clipping ...
            if ((clips.Count > 0 || subjects.Count > 0) &&
                !rbNone.IsChecked)
            {
                Polygons solution2 = new Polygons();
                Clipper  c         = new Clipper(0);
                c.AddPaths(subjects, PolyType.ptSubject, true);
                c.AddPaths(clips, PolyType.ptClip, true);
                solution.Clear();
                bool succeeded = c.Execute(GetClipType(), solution, GetPolyFillType(), GetPolyFillType());
                if (succeeded)
                {
                    myBrush.Color = Color.Black;
                    path.Reset();

                    //It really shouldn't matter what FillMode is used for solution
                    //polygons because none of the solution polygons overlap.
                    //However, FillMode.Winding will show any orientation errors where
                    //holes will be stroked (outlined) correctly but filled incorrectly  ...
                    path.FillMode = FillMode.Winding;

                    //or for something fancy ...
                    if (nudOffset.Value != 0)
                    {
                        //old   solution2 = Clipper.OffsetPolygons(solution, (double)nudOffset.Value * scale, JoinType.jtMiter);
                        ClipperOffset co = new ClipperOffset(2, 0.25);
                        co.AddPaths(solution, JoinType.jtMiter, EndType.etClosedPolygon);
                        co.Execute(ref solution2, (double)nudOffset.Value * scale);
                    }
                    else
                    {
                        solution2 = new Polygons(solution);
                    }

                    foreach (Polygon pg in solution2)
                    {
                        Point[] pts = PolygonToPointArray(pg, scale);
                        if (pts.Length//Count()
                            > 2)
                        {
                            path.AddPolygon(pts);
                        }
                        pts = null;
                    }
                    //myBrush.Color = Color.FromArgb(127, 0x66, 0xEF, 0x7F);
                    myBrush.Color = Color.FromArgb(100, 0, 255, 0);
                    myPen.Color   = Color.FromArgb(255, 0, 0x33, 0);
                    myPen.Width   = 1;

                    graphics.SmoothingMode = fillSmoothingMode;
                    graphics.FillPath(myBrush, path);
                    graphics.SmoothingMode = strokeSmoothingMode;
                    graphics.DrawPath(myPen, path);

                    //now do some fancy testing ...
                    Font   f = new Font("Arial", 8);
                    Brush  b = Brushes.Navy;
                    double subj_area = 0, clip_area = 0, int_area = 0, union_area = 0;
                    c.Clear();
                    c.AddPaths(subjects, PolyType.ptSubject, true);
                    c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType());
                    foreach (Polygon pg in solution2)
                    {
                        subj_area += Clipper.Area(pg);
                    }
                    c.Clear();
                    c.AddPaths(clips, PolyType.ptClip, true);
                    c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType());
                    foreach (Polygon pg in solution2)
                    {
                        clip_area += Clipper.Area(pg);
                    }
                    c.AddPaths(subjects, PolyType.ptSubject, true);
                    c.Execute(ClipType.ctIntersection, solution2, GetPolyFillType(), GetPolyFillType());
                    foreach (Polygon pg in solution2)
                    {
                        int_area += Clipper.Area(pg);
                    }
                    c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType());
                    foreach (Polygon pg in solution2)
                    {
                        union_area += Clipper.Area(pg);
                    }

                    StringFormat lftStringFormat = new StringFormat();
                    lftStringFormat.Alignment     = StringAlignment.Near;
                    lftStringFormat.LineAlignment = StringAlignment.Near;
                    StringFormat rtStringFormat = new StringFormat();
                    rtStringFormat.Alignment     = StringAlignment.Far;
                    rtStringFormat.LineAlignment = StringAlignment.Near;
                    RectI rec = new RectI(WorkArea.Width - 114, WorkArea.Height - 116, 104, 106);
                    graphics.FillRectangle(new SolidColorBrush(Color.FromArgb(196, Color.WhiteSmoke)), rec);
                    graphics.DrawRectangle(myPen, rec);
                    rec.Inflate(new SizeI(-2, 0));

                    //  because of Alt.Sketch smaller top offset
                    rec += new PointI(0, 1);
                    rec -= new SizeI(0, 1);

                    graphics.DrawString("Areas", f, b, rec, rtStringFormat);
                    rec.Offset(new PointI(0, 14));
                    graphics.DrawString("subj: ", f, b, rec, lftStringFormat);
                    graphics.DrawString((subj_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new PointI(0, 12));
                    graphics.DrawString("clip: ", f, b, rec, lftStringFormat);
                    graphics.DrawString((clip_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new PointI(0, 12));
                    graphics.DrawString("intersect: ", f, b, rec, lftStringFormat);
                    graphics.DrawString((int_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new PointI(0, 12));
                    graphics.DrawString("---------", f, b, rec, rtStringFormat);
                    rec.Offset(new PointI(0, 10));
                    graphics.DrawString("s + c - i: ", f, b, rec, lftStringFormat);
                    graphics.DrawString(((subj_area + clip_area - int_area) / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new PointI(0, 10));
                    graphics.DrawString("---------", f, b, rec, rtStringFormat);
                    rec.Offset(new PointI(0, 10));
                    graphics.DrawString("union: ", f, b, rec, lftStringFormat);
                    graphics.DrawString((union_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new PointI(0, 10));
                    graphics.DrawString("---------", f, b, rec, rtStringFormat);
                } //end if succeeded
            }     //end if something to clip

            //TEMP  pictureBox1.Image = mybitmap;
            graphics.Dispose();
            GUI.Cursor.Current = GUI.Cursors.Default;
        }
コード例 #17
0
ファイル: Example_Clipper.cs プロジェクト: CrazyLiu00/GMap
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);


            /*TEMP
             * saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
             * saveFileDialog1.DefaultExt = "svg";
             * saveFileDialog1.Filter = "SVG Files (*.svg)|*.svg";*/


            //  Refresh
            bRefresh        = new Alt.GUI.Temporary.Gwen.Control.Button(m_RightPanel);
            bRefresh.Text   = "Refresh";
            bRefresh.Dock   = Pos.Bottom;
            bRefresh.Margin = new Margin(0, 20, 5, GUI.Config.Logo.PixelHeight);

            bRefresh.Click += new EventHandler(bRefresh_Click);


            //  Save
            bSave          = new Alt.GUI.Temporary.Gwen.Control.Button(m_RightPanel);
            bSave.Text     = "Save as SVG File";
            bSave.Dock     = Pos.Top;
            bSave.Margin   = new Margin(0, 20, 0, 0);
            bSave.IsHidden = true;


            //  Drawing Panel
            Base DrawingPanelHolder = new Base(m_Splitter);

            m_DrawingPanel = new DoubleBufferedControl(DrawingPanelHolder);
            m_DrawingPanel.UseTransparentBackground = false;
            m_DrawingPanel.Dock        = Pos.Fill;
            m_DrawingPanel.Paint      += new GUI.PaintEventHandler(DrawingPanel_Paint);
            m_DrawingPanel.MouseWheel += new GUI.MouseEventHandler(DrawingPanel_MouseWheel);
            m_DrawingPanel.Resize     += new EventHandler(DrawingPanel_Resize);
            m_DrawingPanel.Margin      = new Margin(0, GUI.Config.Logo.PixelHeight, 0, GUI.Config.Logo.PixelHeight);
            m_DrawingPanel.DrawBorder  = true;
            m_DrawingPanel.BorderColor = Color.DodgerBlue * 0.6;


            //
            m_Splitter.SetPanel(1, m_RightPanel);
            m_Splitter.SetPanel(0, DrawingPanelHolder);
            m_Splitter.SetHValue(0.83f);


            //  Neet to correct groupBoxes
            groupBox_Geometry.AutoSizeToContents         = false;
            groupBox_BooleanOperation.AutoSizeToContents = false;
            groupBox_Options.AutoSizeToContents          = false;


            //  Core
            subjects = new Polygons();
            clips    = new Polygons();
            solution = new Polygons();


            this.Focus();
        }
コード例 #18
0
ファイル: fffProcessor.cs プロジェクト: wpmyj/AndroidDemo
        private void WriteSupportPolygons(SliceDataStorage storage, GCodePlanner gcodeLayer, int layerIndex, ConfigSettings config, Polygons supportPolygons, SupportType interfaceLayer)
        {
            for (int volumeIndex = 0; volumeIndex < storage.volumes.Count; volumeIndex++)
            {
                SliceLayer layer = storage.volumes[volumeIndex].layers[layerIndex];
                for (int partIndex = 0; partIndex < layer.parts.Count; partIndex++)
                {
                    supportPolygons = supportPolygons.CreateDifference(layer.parts[partIndex].TotalOutline.Offset(config.supportXYDistance_um));
                }
            }

            //Contract and expand the support polygons so small sections are removed and the final polygon is smoothed a bit.
            supportPolygons = supportPolygons.Offset(-config.extrusionWidth_um * 1);
            supportPolygons = supportPolygons.Offset(config.extrusionWidth_um * 1);

            List <Polygons>    supportIslands       = supportPolygons.CreateLayerOutlines(PolygonsHelper.LayerOpperation.EvenOdd);
            PathOrderOptimizer islandOrderOptimizer = new PathOrderOptimizer(gcode.GetPositionXY());

            for (int islandIndex = 0; islandIndex < supportIslands.Count; islandIndex++)
            {
                islandOrderOptimizer.AddPolygon(supportIslands[islandIndex][0]);
            }
            islandOrderOptimizer.Optimize();

            for (int islandIndex = 0; islandIndex < supportIslands.Count; islandIndex++)
            {
                Polygons island       = supportIslands[islandOrderOptimizer.bestPolygonOrderIndex[islandIndex]];
                Polygons supportLines = new Polygons();
                if (config.supportLineSpacing_um > 0)
                {
                    switch (interfaceLayer)
                    {
                    case SupportType.Interface:
                        Infill.GenerateLineInfill(config, island, ref supportLines, config.supportInfillStartingAngle + 90, config.extrusionWidth_um);
                        break;

                    case SupportType.General:
                        switch (config.supportType)
                        {
                        case ConfigConstants.SUPPORT_TYPE.GRID:
                            Infill.GenerateGridInfill(config, island, ref supportLines, config.supportInfillStartingAngle, config.supportLineSpacing_um);
                            break;

                        case ConfigConstants.SUPPORT_TYPE.LINES:
                            Infill.GenerateLineInfill(config, island, ref supportLines, config.supportInfillStartingAngle, config.supportLineSpacing_um);
                            break;
                        }
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                }

                if (config.avoidCrossingPerimeters)
                {
                    gcodeLayer.SetOuterPerimetersToAvoidCrossing(island);
                }

                switch (interfaceLayer)
                {
                case SupportType.Interface:
                    gcodeLayer.WritePolygonsByOptimizer(supportLines, supportInterfaceConfig);
                    break;

                case SupportType.General:
                    if (config.supportType == ConfigConstants.SUPPORT_TYPE.GRID)
                    {
                        gcodeLayer.WritePolygonsByOptimizer(island, supportNormalConfig);
                    }
                    gcodeLayer.WritePolygonsByOptimizer(supportLines, supportNormalConfig);
                    break;

                default:
                    throw new NotImplementedException();
                }

                gcodeLayer.SetOuterPerimetersToAvoidCrossing(null);
            }
        }
コード例 #19
0
ファイル: fffProcessor.cs プロジェクト: wpmyj/AndroidDemo
        private void CalculateInfillData(SliceDataStorage storage, int volumeIndex, int layerIndex, SliceLayerPart part, ref Polygons fillPolygons, ref Polygons topFillPolygons, ref Polygons bridgePolygons)
        {
            // generate infill the bottom layer including bridging
            foreach (Polygons outline in part.SolidBottomOutlines.CreateLayerOutlines(PolygonsHelper.LayerOpperation.EvenOdd))
            {
                if (layerIndex > 0)
                {
                    double bridgeAngle;
                    if (Bridge.BridgeAngle(outline, storage.volumes[volumeIndex].layers[layerIndex - 1], out bridgeAngle))
                    {
                        Infill.GenerateLinePaths(outline, ref bridgePolygons, config.extrusionWidth_um, config.infillExtendIntoPerimeter_um, bridgeAngle);
                    }
                    else
                    {
                        Infill.GenerateLinePaths(outline, ref fillPolygons, config.extrusionWidth_um, config.infillExtendIntoPerimeter_um, config.infillStartingAngle);
                    }
                }
                else
                {
                    Infill.GenerateLinePaths(outline, ref fillPolygons, config.firstLayerExtrusionWidth_um, config.infillExtendIntoPerimeter_um, config.infillStartingAngle);
                }
            }

            // generate infill for the top layer
            foreach (Polygons outline in part.SolidTopOutlines.CreateLayerOutlines(PolygonsHelper.LayerOpperation.EvenOdd))
            {
                Infill.GenerateLinePaths(outline, ref topFillPolygons, config.extrusionWidth_um, config.infillExtendIntoPerimeter_um, config.infillStartingAngle);
            }

            // generate infill intermediate layers
            foreach (Polygons outline in part.SolidInfillOutlines.CreateLayerOutlines(PolygonsHelper.LayerOpperation.EvenOdd))
            {
                if (true)                 // use the old infill method
                {
                    Infill.GenerateLinePaths(outline, ref fillPolygons, config.extrusionWidth_um, config.infillExtendIntoPerimeter_um, config.infillStartingAngle + 90 * (layerIndex % 2));
                }
                else                 // use the new concentric infill (not tested enough yet) have to handle some bad casses better
                {
                    double oldInfillPercent = config.infillPercent;
                    config.infillPercent = 100;
                    Infill.GenerateConcentricInfill(config, outline, ref fillPolygons);
                    config.infillPercent = oldInfillPercent;
                }
            }

            double fillAngle = config.infillStartingAngle;

            // generate the sparse infill for this part on this layer
            if (config.infillPercent > 0)
            {
                switch (config.infillType)
                {
                case ConfigConstants.INFILL_TYPE.LINES:
                    if ((layerIndex & 1) == 1)
                    {
                        fillAngle += 90;
                    }
                    Infill.GenerateLineInfill(config, part.InfillOutlines, ref fillPolygons, fillAngle);
                    break;

                case ConfigConstants.INFILL_TYPE.GRID:
                    Infill.GenerateGridInfill(config, part.InfillOutlines, ref fillPolygons, fillAngle);
                    break;

                case ConfigConstants.INFILL_TYPE.TRIANGLES:
                    Infill.GenerateTriangleInfill(config, part.InfillOutlines, ref fillPolygons, fillAngle);
                    break;

                case ConfigConstants.INFILL_TYPE.HEXAGON:
                    Infill.GenerateHexagonInfill(config, part.InfillOutlines, ref fillPolygons, fillAngle, layerIndex);
                    break;

                case ConfigConstants.INFILL_TYPE.CONCENTRIC:
                    Infill.GenerateConcentricInfill(config, part.InfillOutlines, ref fillPolygons);
                    break;

                default:
                    throw new NotImplementedException();
                }
            }
        }
コード例 #20
0
ファイル: fffProcessor.cs プロジェクト: wpmyj/AndroidDemo
        //Add a single layer from a single mesh-volume to the GCode
        private void AddVolumeLayerToGCode(SliceDataStorage storage, GCodePlanner gcodeLayer, int volumeIndex, int layerIndex, int extrusionWidth_um, int fanSpeedPercent)
        {
            int  prevExtruder    = gcodeLayer.getExtruder();
            bool extruderChanged = gcodeLayer.SetExtruder(volumeIndex);

            SliceLayer layer = storage.volumes[volumeIndex].layers[layerIndex];

            if (extruderChanged)
            {
                addWipeTower(storage, gcodeLayer, layerIndex, prevExtruder, extrusionWidth_um);
            }

            if (storage.wipeShield.Count > 0 && storage.volumes.Count > 1)
            {
                gcodeLayer.SetAlwaysRetract(true);
                gcodeLayer.WritePolygonsByOptimizer(storage.wipeShield[layerIndex], skirtConfig);
                gcodeLayer.SetAlwaysRetract(!config.avoidCrossingPerimeters);
            }

            PathOrderOptimizer partOrderOptimizer = new PathOrderOptimizer(new IntPoint());

            for (int partIndex = 0; partIndex < layer.parts.Count; partIndex++)
            {
                if (config.continuousSpiralOuterPerimeter && partIndex > 0)
                {
                    continue;
                }

                partOrderOptimizer.AddPolygon(layer.parts[partIndex].Insets[0][0]);
            }
            partOrderOptimizer.Optimize();

            for (int partIndex = 0; partIndex < partOrderOptimizer.bestPolygonOrderIndex.Count; partIndex++)
            {
                if (config.continuousSpiralOuterPerimeter && partIndex > 0)
                {
                    continue;
                }

                SliceLayerPart part = layer.parts[partOrderOptimizer.bestPolygonOrderIndex[partIndex]];

                if (config.avoidCrossingPerimeters)
                {
                    gcodeLayer.SetOuterPerimetersToAvoidCrossing(part.AvoidCrossingBoundery);
                }
                else
                {
                    gcodeLayer.SetAlwaysRetract(true);
                }

                Polygons fillPolygons    = new Polygons();
                Polygons topFillPolygons = new Polygons();
                Polygons bridgePolygons  = new Polygons();

                CalculateInfillData(storage, volumeIndex, layerIndex, part, ref fillPolygons, ref topFillPolygons, ref bridgePolygons);

                // Write the bridge polgons out first so the perimeter will have more to hold to while bridging the gaps.
                // It would be even better to slow down the perimeters that are part of bridges but that is a bit harder.
                if (bridgePolygons.Count > 0)
                {
                    gcode.WriteFanCommand(config.bridgeFanSpeedPercent);
                    gcodeLayer.WritePolygonsByOptimizer(bridgePolygons, bridgConfig);
                    gcode.WriteFanCommand(fanSpeedPercent);
                }

                if (config.numberOfPerimeters > 0)
                {
                    if (partIndex != lastPartIndex)
                    {
                        // force a retract if changing islands
                        gcodeLayer.ForceRetract();
                        lastPartIndex = partIndex;
                    }

                    if (config.continuousSpiralOuterPerimeter)
                    {
                        if (layerIndex >= config.numberOfBottomLayers)
                        {
                            inset0Config.spiralize = true;
                        }
                    }

                    // If we are on the very first layer we start with the outside in so that we can stick to the bed better.
                    if (config.outsidePerimetersFirst || layerIndex == 0 || inset0Config.spiralize)
                    {
                        // First the outside (this helps with accuracy)
                        if (part.Insets.Count > 0)
                        {
                            gcodeLayer.WritePolygonsByOptimizer(part.Insets[0], inset0Config);
                        }

                        if (!inset0Config.spiralize)
                        {
                            for (int perimeterIndex = 1; perimeterIndex < part.Insets.Count; perimeterIndex++)
                            {
                                gcodeLayer.WritePolygonsByOptimizer(part.Insets[perimeterIndex], insetXConfig);
                            }
                        }
                    }
                    else                     // This is so we can do overhanges better (the outside can stick a bit to the inside).
                    {
                        // Print everything but the first perimeter from the outside in so the little parts have more to stick to.
                        for (int perimeterIndex = 1; perimeterIndex < part.Insets.Count; perimeterIndex++)
                        {
                            gcodeLayer.WritePolygonsByOptimizer(part.Insets[perimeterIndex], insetXConfig);
                        }
                        // then 0
                        if (part.Insets.Count > 0)
                        {
                            gcodeLayer.WritePolygonsByOptimizer(part.Insets[0], inset0Config);
                        }
                    }
                }

                gcodeLayer.WritePolygonsByOptimizer(fillPolygons, fillConfig);
                gcodeLayer.WritePolygonsByOptimizer(topFillPolygons, topFillConfig);

                //After a layer part, make sure the nozzle is inside the comb boundary, so we do not retract on the perimeter.
                if (!config.continuousSpiralOuterPerimeter || layerIndex < config.numberOfBottomLayers)
                {
                    gcodeLayer.MoveInsideTheOuterPerimeter(extrusionWidth_um * 2);
                }
            }
            gcodeLayer.SetOuterPerimetersToAvoidCrossing(null);
        }
コード例 #21
0
        /// <summary>
        /// Remove a region
        /// </summary>
        /// <param name="index"></param>
        public void Remove(int index)
        {
            Polygons.RemoveAt(index);

            Removed?.Invoke(this, new EventArgs());
        }
コード例 #22
0
ファイル: clipper.cs プロジェクト: caomw/elementdiscovery
            public PolyOffsetBuilder(Polygons pts, Polygons solution, double delta, 
                JoinType jointype, double MiterLimit = 2, bool AutoFix = true)
            {
                //precondtion: solution != pts

                if (delta == 0)
                {
                    solution = pts;
                    return;
                }

                this.pts = pts;
                this.delta = delta;

                //AutoFix - fixes polygon orientation if necessary and removes 
                //duplicate vertices. Can be set false when you're sure that polygon
                //orientation is correct and that there are no duplicate vertices.
                if (AutoFix)
                {
                    int Len = pts.Count, botI = 0;
                    while (botI < Len && pts[botI].Count == 0) botI++;
                    if (botI == Len) return;

                    //botPt: used to find the lowermost (in inverted Y-axis) & leftmost point
                    //This point (on pts[botI]) must be on an outer polygon ring and if 
                    //its orientation is false (counterclockwise) then assume all polygons 
                    //need reversing ...
                    IntPoint botPt = pts[botI][0];
                    for (int i = botI; i < Len; ++i)
                    {
                        if (pts[i].Count == 0) continue;
                        if (UpdateBotPt(pts[i][0], ref botPt)) botI = i;
                        for (int j = pts[i].Count -1; j > 0; j--)
                        {
                            if (PointsEqual(pts[i][j], pts[i][j -1]))
                                pts[i].RemoveAt(j);
                            else if (UpdateBotPt(pts[i][j], ref botPt))
                                botI = i;
                        }
                    }
                    if (!Orientation(pts[botI]))
                        ReversePolygons(pts);
                }

                if (MiterLimit <= 1) MiterLimit = 1;
                double RMin = 2.0 / (MiterLimit*MiterLimit);

                normals = new List<DoublePoint>();

                double deltaSq = delta*delta;
                solution.Clear();
                solution.Capacity = pts.Count;
                for (m_i = 0; m_i < pts.Count; m_i++)
                {
                    int len = pts[m_i].Count;
                    if (len > 1 && pts[m_i][0].X == pts[m_i][len - 1].X &&
                        pts[m_i][0].Y == pts[m_i][len - 1].Y) len--;

                    if (len == 0 || (len < 3 && delta <= 0)) 
                        continue;
                    else if (len == 1)
                    {
                        Polygon arc;
                        arc = BuildArc(pts[m_i][len - 1], 0, 2 * Math.PI, delta);
                        solution.Add(arc);
                        continue;
                    }

                    //build normals ...
                    normals.Clear();
                    normals.Capacity = len;
                    for (int j = 0; j < len -1; ++j)
                        normals.Add(GetUnitNormal(pts[m_i][j], pts[m_i][j+1]));
                    normals.Add(GetUnitNormal(pts[m_i][len - 1], pts[m_i][0]));

                    currentPoly = new Polygon();
                    m_k = len - 1;
                    for (m_j = 0; m_j < len; ++m_j)
                    {
                        switch (jointype)
                        {
                            case JoinType.jtMiter:
                            {
                                m_R = 1 + (normals[m_j].X*normals[m_k].X + 
                                    normals[m_j].Y*normals[m_k].Y);
                                if (m_R >= RMin) DoMiter(); else DoSquare(MiterLimit);
                                break;
                            }
                            case JoinType.jtRound: 
                                DoRound();
                                break;
                            case JoinType.jtSquare:
                                DoSquare(1);
                                break;
                        }
                        m_k = m_j;
                    }
                    solution.Add(currentPoly);
                }

                //finally, clean up untidy corners ...
                Clipper clpr = new Clipper();
                clpr.AddPolygons(solution, PolyType.ptSubject);
                if (delta > 0)
                {
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
                }
                else
                {
                    IntRect r = clpr.GetBounds();
                    Polygon outer = new Polygon(4);

                    outer.Add(new IntPoint(r.left - 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.top - 10));
                    outer.Add(new IntPoint(r.left - 10, r.top - 10));

                    clpr.AddPolygon(outer, PolyType.ptSubject);
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                    if (solution.Count > 0)
                    {
                        solution.RemoveAt(0);
                        for (int i = 0; i < solution.Count; i++)
                            solution[i].Reverse();
                    }
                }
            }
コード例 #23
0
ファイル: clipper.cs プロジェクト: caomw/elementdiscovery
        //------------------------------------------------------------------------------

        public static Polygons OffsetPolygons(Polygons poly, double delta)
        {
            Polygons result = new Polygons(poly.Count);
            new PolyOffsetBuilder(poly, result, delta, JoinType.jtSquare, 2.0, true);
            return result;
        }
コード例 #24
0
 public static bool FindThinLines(Polygon polygon, long overlapMergeAmount_um, long minimumRequiredWidth_um, out Polygons onlyMergeLines, bool pathIsClosed = true)
 {
     return(FindThinLines(new Polygons {
         polygon
     }, overlapMergeAmount_um, minimumRequiredWidth_um, out onlyMergeLines, pathIsClosed));
 }
コード例 #25
0
ファイル: clipper.cs プロジェクト: caomw/elementdiscovery
        //------------------------------------------------------------------------------

        public bool AddPolygons(Polygons ppg, PolyType polyType)
        {
            bool result = false;
            for (int i = 0; i < ppg.Count; ++i)
                if (AddPolygon(ppg[i], polyType)) result = true;
            return result;
        }
コード例 #26
0
        public static bool FindThinLines(Polygons polygons, long overlapMergeAmount_um, long minimumRequiredWidth_um, out Polygons onlyMergeLines, bool pathIsClosed = true)
        {
            bool pathHasMergeLines = false;

            polygons = MakeCloseSegmentsMergable(polygons, overlapMergeAmount_um, pathIsClosed);

            // make a copy that has every point duplicated (so that we have them as segments).
            List <Segment> polySegments = Segment.ConvertToSegments(polygons);

            Altered[] markedAltered = new Altered[polySegments.Count];

            int segmentCount = polySegments.Count;

            // now walk every segment and check if there is another segment that is similar enough to merge them together
            for (int firstSegmentIndex = 0; firstSegmentIndex < segmentCount; firstSegmentIndex++)
            {
                for (int checkSegmentIndex = firstSegmentIndex + 1; checkSegmentIndex < segmentCount; checkSegmentIndex++)
                {
                    // The first point of start and the last point of check (the path will be coming back on itself).
                    long startDelta = (polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length();
                    // if the segments are similar enough
                    if (startDelta < overlapMergeAmount_um)
                    {
                        // The last point of start and the first point of check (the path will be coming back on itself).
                        long endDelta = (polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length();
                        if (endDelta < overlapMergeAmount_um)
                        {
                            // move the first segments points to the average of the merge positions
                            long startEndWidth = Math.Abs((polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length());
                            long endStartWidth = Math.Abs((polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length());
                            long width         = Math.Min(startEndWidth, endStartWidth);

                            if (width > minimumRequiredWidth_um)
                            {
                                // We need to check if the new start position is on the inside of the curve. We can only add thin lines on the insides of our exisiting curves.
                                IntPoint newStartPosition  = (polySegments[firstSegmentIndex].Start + polySegments[checkSegmentIndex].End) / 2;                                // the start;
                                IntPoint newStartDirection = newStartPosition - polySegments[firstSegmentIndex].Start;
                                IntPoint normalLeft        = (polySegments[firstSegmentIndex].End - polySegments[firstSegmentIndex].Start).GetPerpendicularLeft();
                                long     dotProduct        = normalLeft.Dot(newStartDirection);
                                if (dotProduct > 0)
                                {
                                    pathHasMergeLines = true;

                                    polySegments[firstSegmentIndex].Start       = newStartPosition;
                                    polySegments[firstSegmentIndex].Start.Width = width;
                                    polySegments[firstSegmentIndex].End         = (polySegments[firstSegmentIndex].End + polySegments[checkSegmentIndex].Start) / 2;                             // the end
                                    polySegments[firstSegmentIndex].End.Width   = width;

                                    markedAltered[firstSegmentIndex] = Altered.merged;
                                    // mark this segment for removal
                                    markedAltered[checkSegmentIndex] = Altered.remove;
                                    // We only expect to find one match for each segment, so move on to the next segment
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            // remove the marked segments
            for (int segmentIndex = segmentCount - 1; segmentIndex >= 0; segmentIndex--)
            {
                // remove every segment that has not been merged
                if (markedAltered[segmentIndex] != Altered.merged)
                {
                    polySegments.RemoveAt(segmentIndex);
                }
            }

            // go through the polySegments and create a new polygon for every connected set of segments
            onlyMergeLines = new Polygons();
            Polygon currentPolygon = new Polygon();

            onlyMergeLines.Add(currentPolygon);
            // put in the first point
            for (int segmentIndex = 0; segmentIndex < polySegments.Count; segmentIndex++)
            {
                // add the start point
                currentPolygon.Add(polySegments[segmentIndex].Start);

                // if the next segment is not connected to this one
                if (segmentIndex < polySegments.Count - 1 &&
                    polySegments[segmentIndex].End != polySegments[segmentIndex + 1].Start)
                {
                    // add the end point
                    currentPolygon.Add(polySegments[segmentIndex].End);

                    // create a new polygon
                    currentPolygon = new Polygon();
                    onlyMergeLines.Add(currentPolygon);
                }
            }

            // add the end point
            if (polySegments.Count > 0)
            {
                currentPolygon.Add(polySegments[polySegments.Count - 1].End);
            }

            long cleanDistance_um = overlapMergeAmount_um / 40;

            //Clipper.CleanPolygons(onlyMergeLines, cleanDistance_um);

            return(pathHasMergeLines);
        }
コード例 #27
0
		public static Polygons CreateLineIntersections(this Polygons polygons, Polygons other)
		{
			Clipper clipper = new Clipper();

			clipper.AddPaths(other, PolyType.ptSubject, false);
			clipper.AddPaths(polygons, PolyType.ptClip, true);

			PolyTree clippedLines = new PolyTree();

			clipper.Execute(ClipType.ctIntersection, clippedLines);

			return Clipper.OpenPathsFromPolyTree(clippedLines);
		}
コード例 #28
0
        public static bool MergePerimeterOverlaps(Polygon perimeter, long overlapMergeAmount_um, out Polygons separatedPolygons, bool pathIsClosed = true)
        {
            separatedPolygons = new Polygons();

            long cleanDistance_um = overlapMergeAmount_um / 40;

            Polygons cleanedPolygs = Clipper.CleanPolygons(new Polygons()
            {
                perimeter
            }, cleanDistance_um);

            perimeter = cleanedPolygs[0];

            if (perimeter.Count == 0)
            {
                return(false);
            }
            bool pathWasOptomized = false;

            for (int i = 0; i < perimeter.Count; i++)
            {
                perimeter[i] = new IntPoint(perimeter[i])
                {
                    Width = overlapMergeAmount_um
                };
            }

            perimeter = MakeCloseSegmentsMergable(perimeter, overlapMergeAmount_um, pathIsClosed);

            // make a copy that has every point duplicated (so that we have them as segments).
            List <Segment> polySegments = Segment.ConvertToSegments(perimeter, pathIsClosed);

            Altered[] markedAltered = new Altered[polySegments.Count];

            int segmentCount = polySegments.Count;

            // now walk every segment and check if there is another segment that is similar enough to merge them together
            for (int firstSegmentIndex = 0; firstSegmentIndex < segmentCount; firstSegmentIndex++)
            {
                //polySegments[firstSegmentIndex].Start.Width = overlapMergeAmount_um;
                //polySegments[firstSegmentIndex].End.Width = overlapMergeAmount_um;

                for (int checkSegmentIndex = firstSegmentIndex + 1; checkSegmentIndex < segmentCount; checkSegmentIndex++)
                {
                    // The first point of start and the last point of check (the path will be coming back on itself).
                    long startDelta = (polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length();
                    // if the segments are similar enough
                    if (startDelta < overlapMergeAmount_um)
                    {
                        // The last point of start and the first point of check (the path will be coming back on itself).
                        long endDelta = (polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length();
                        if (endDelta < overlapMergeAmount_um)
                        {
                            // only considre the merge if the directions of the lines are towards eachother
                            var firstSegmentDirection = polySegments[firstSegmentIndex].End - polySegments[firstSegmentIndex].Start;
                            var checkSegmentDirection = polySegments[checkSegmentIndex].End - polySegments[checkSegmentIndex].Start;
                            if (firstSegmentDirection.Dot(checkSegmentDirection) > 0)
                            {
                                continue;
                            }
                            pathWasOptomized = true;
                            // move the first segments points to the average of the merge positions
                            long startEndWidth = Math.Abs((polySegments[firstSegmentIndex].Start - polySegments[checkSegmentIndex].End).Length());
                            long endStartWidth = Math.Abs((polySegments[firstSegmentIndex].End - polySegments[checkSegmentIndex].Start).Length());
                            long width         = Math.Min(startEndWidth, endStartWidth) + overlapMergeAmount_um;
                            polySegments[firstSegmentIndex].Start       = (polySegments[firstSegmentIndex].Start + polySegments[checkSegmentIndex].End) / 2;                     // the start
                            polySegments[firstSegmentIndex].Start.Width = width;
                            polySegments[firstSegmentIndex].End         = (polySegments[firstSegmentIndex].End + polySegments[checkSegmentIndex].Start) / 2;                     // the end
                            polySegments[firstSegmentIndex].End.Width   = width;

                            markedAltered[firstSegmentIndex] = Altered.merged;
                            // mark this segment for removal
                            markedAltered[checkSegmentIndex] = Altered.remove;
                            // We only expect to find one match for each segment, so move on to the next segment
                            break;
                        }
                    }
                }
            }

            // remove the marked segments
            for (int segmentIndex = segmentCount - 1; segmentIndex >= 0; segmentIndex--)
            {
                if (markedAltered[segmentIndex] == Altered.remove)
                {
                    polySegments.RemoveAt(segmentIndex);
                }
            }

            // go through the polySegments and create a new polygon for every connected set of segments
            Polygon currentPolygon = new Polygon();

            separatedPolygons.Add(currentPolygon);
            // put in the first point
            for (int segmentIndex = 0; segmentIndex < polySegments.Count; segmentIndex++)
            {
                // add the start point
                currentPolygon.Add(polySegments[segmentIndex].Start);

                // if the next segment is not connected to this one
                if (segmentIndex < polySegments.Count - 1 &&
                    polySegments[segmentIndex].End != polySegments[segmentIndex + 1].Start)
                {
                    // add the end point
                    currentPolygon.Add(polySegments[segmentIndex].End);

                    // create a new polygon
                    currentPolygon = new Polygon();
                    separatedPolygons.Add(currentPolygon);
                }
            }

            // add the end point
            currentPolygon.Add(polySegments[polySegments.Count - 1].End);

            return(pathWasOptomized);
        }
コード例 #29
0
		public static bool polygonCollidesWithlineSegment(Polygons polys, IntPoint transformed_startPoint, IntPoint transformed_endPoint, PointMatrix transformation_matrix)
		{
			foreach (Polygon poly in polys)
			{
				if (poly.size() == 0) { continue; }
				if (PolygonHelper.polygonCollidesWithlineSegment(poly, transformed_startPoint, transformed_endPoint, transformation_matrix))
				{
					return true;
				}
			}

			return false;
		}
コード例 #30
0
        public void WriteQueuedGCode(int layerThickness, int fanSpeedPercent = -1, int bridgeFanSpeedPercent = -1)
        {
            GCodePathConfig lastConfig    = null;
            int             extruderIndex = gcodeExport.GetExtruderIndex();

            for (int pathIndex = 0; pathIndex < paths.Count; pathIndex++)
            {
                GCodePath path = paths[pathIndex];
                if (extruderIndex != path.extruderIndex)
                {
                    extruderIndex = path.extruderIndex;
                    gcodeExport.SwitchExtruder(extruderIndex);
                }
                else if (path.Retract)
                {
                    gcodeExport.WriteRetraction();
                }
                if (path.config != travelConfig && lastConfig != path.config)
                {
                    if (path.config.gcodeComment == "BRIDGE" && bridgeFanSpeedPercent != -1)
                    {
                        gcodeExport.WriteFanCommand(bridgeFanSpeedPercent);
                    }
                    else if (lastConfig?.gcodeComment == "BRIDGE" && bridgeFanSpeedPercent != -1)
                    {
                        gcodeExport.WriteFanCommand(fanSpeedPercent);
                    }

                    gcodeExport.WriteComment("TYPE:{0}".FormatWith(path.config.gcodeComment));
                    lastConfig = path.config;
                }

                double speed = path.config.speed;

                if (path.config.lineWidth_um != 0)
                {
                    // Prevent cooling overrides from affecting bridge moves
                    if (path.config.gcodeComment != "BRIDGE")
                    {
                        speed = speed * extrudeSpeedFactor / 100;
                    }
                }
                else
                {
                    speed = speed * travelSpeedFactor / 100;
                }

                if (path.points.Count == 1 &&
                    path.config != travelConfig &&
                    (gcodeExport.GetPositionXY() - path.points[0]).ShorterThen(path.config.lineWidth_um * 2))
                {
                    //Check for lots of small moves and combine them into one large line
                    IntPoint nextPosition = path.points[0];
                    int      i            = pathIndex + 1;
                    while (i < paths.Count && paths[i].points.Count == 1 && (nextPosition - paths[i].points[0]).ShorterThen(path.config.lineWidth_um * 2))
                    {
                        nextPosition = paths[i].points[0];
                        i++;
                    }
                    if (paths[i - 1].config == travelConfig)
                    {
                        i--;
                    }

                    if (i > pathIndex + 2)
                    {
                        nextPosition = gcodeExport.GetPosition();
                        for (int x = pathIndex; x < i - 1; x += 2)
                        {
                            long     oldLen   = (nextPosition - paths[x].points[0]).Length();
                            IntPoint newPoint = (paths[x].points[0] + paths[x + 1].points[0]) / 2;
                            long     newLen   = (gcodeExport.GetPosition() - newPoint).Length();
                            if (newLen > 0)
                            {
                                gcodeExport.WriteMove(newPoint, speed, (int)(path.config.lineWidth_um * oldLen / newLen));
                            }

                            nextPosition = paths[x + 1].points[0];
                        }

                        long lineWidth_um = path.config.lineWidth_um;
                        if (paths[i - 1].points[0].Width != 0)
                        {
                            lineWidth_um = paths[i - 1].points[0].Width;
                        }

                        gcodeExport.WriteMove(paths[i - 1].points[0], speed, lineWidth_um);
                        pathIndex = i - 1;
                        continue;
                    }
                }


                bool spiralize = path.config.spiralize;
                if (spiralize)
                {
                    //Check if we are the last spiralize path in the list, if not, do not spiralize.
                    for (int m = pathIndex + 1; m < paths.Count; m++)
                    {
                        if (paths[m].config.spiralize)
                        {
                            spiralize = false;
                        }
                    }
                }

                if (spiralize)                 // if we are still in spiralize mode
                {
                    //If we need to spiralize then raise the head slowly by 1 layer as this path progresses.
                    double   totalLength     = 0;
                    long     z               = gcodeExport.GetPositionZ();
                    IntPoint currentPosition = gcodeExport.GetPositionXY();
                    for (int pointIndex = 0; pointIndex < path.points.Count; pointIndex++)
                    {
                        IntPoint nextPosition = path.points[pointIndex];
                        totalLength    += (currentPosition - nextPosition).LengthMm();
                        currentPosition = nextPosition;
                    }

                    double length = 0.0;
                    currentPosition = gcodeExport.GetPositionXY();
                    for (int i = 0; i < path.points.Count; i++)
                    {
                        IntPoint nextPosition = path.points[i];
                        length         += (currentPosition - nextPosition).LengthMm();
                        currentPosition = nextPosition;
                        IntPoint nextExtrusion = path.points[i];
                        nextExtrusion.Z = (int)(z + layerThickness * length / totalLength + .5);
                        gcodeExport.WriteMove(nextExtrusion, speed, path.config.lineWidth_um);
                    }
                }
                else
                {
                    // This is test code to remove double drawn small perimeter lines.
                    Polygons pathsWithOverlapsRemoved = null;
                    bool     pathHadOverlaps          = false;
                    bool     pathIsClosed             = true;
                    if (mergeOverlappingLines &&
                        (path.config.gcodeComment == "WALL-OUTER" || path.config.gcodeComment == "WALL-INNER"))
                    {
                        //string perimeterString = Newtonsoft.Json.JsonConvert.SerializeObject(path);
                        if (perimeterStartEndOverlapRatio < 1)
                        {
                            path = TrimPerimeter(path, perimeterStartEndOverlapRatio);
                            //string trimmedString = Newtonsoft.Json.JsonConvert.SerializeObject(path);
                            // it was closed but now it isn't
                            pathIsClosed = false;
                        }

                        if (path.config.lineWidth_um > 0 &&
                            path.points.Count > 2)
                        {
                            // have to add in the position we are currently at
                            path.points.Insert(0, gcodeExport.GetPosition());
                            //string openPerimeterString = Newtonsoft.Json.JsonConvert.SerializeObject(path);
                            pathHadOverlaps = MergePerimeterOverlaps(path.points, path.config.lineWidth_um, out pathsWithOverlapsRemoved, pathIsClosed) &&
                                              pathsWithOverlapsRemoved.Count > 0;
                            //string trimmedString = Newtonsoft.Json.JsonConvert.SerializeObject(pathsWithOverlapsRemoved);
                        }
                    }

                    if (pathHadOverlaps)
                    {
                        for (int polygonIndex = 0; polygonIndex < pathsWithOverlapsRemoved.Count; polygonIndex++)
                        {
                            Polygon polygon = pathsWithOverlapsRemoved[polygonIndex];

                            if (polygon.Count == 2)
                            {
                                // make sure the path is ordered with the first point the closest to where we are now
                                IntPoint currentPosition = gcodeExport.GetPosition();
                                // if the second point is closer swap them
                                if ((polygon[1] - currentPosition).LengthSquared() < (polygon[0] - currentPosition).LengthSquared())
                                {
                                    // swap them
                                    IntPoint temp = polygon[0];
                                    polygon[0] = polygon[1];
                                    polygon[1] = temp;
                                }
                            }

                            // move to the start of this polygon
                            gcodeExport.WriteMove(polygon[0], travelConfig.speed, 0);

                            // write all the data for the polygon
                            for (int pointIndex = 1; pointIndex < polygon.Count; pointIndex++)
                            {
                                gcodeExport.WriteMove(polygon[pointIndex], speed, polygon[pointIndex - 1].Width);
                            }
                        }
                    }
                    else
                    {
                        int outputCount = path.points.Count;
                        for (int i = 0; i < outputCount; i++)
                        {
                            long lineWidth_um = path.config.lineWidth_um;
                            if (path.points[i].Width != 0)
                            {
                                lineWidth_um = path.points[i].Width;
                            }

                            gcodeExport.WriteMove(path.points[i], speed, lineWidth_um);
                        }
                    }
                }
            }

            gcodeExport.UpdateTotalPrintTime();
        }
コード例 #31
0
        public static void GenerateConcentricInfill(ConfigSettings config, Polygons partOutline, Polygons fillPolygons, long extrusionWidthOverride_um = 0)
        {
            if (extrusionWidthOverride_um == 0)
            {
                extrusionWidthOverride_um = config.ExtrusionWidth_um;
            }

            Polygons outlineCopy = new Polygons(partOutline);

            foreach (Polygon outline in outlineCopy)
            {
                if (outline.Count > 0)
                {
                    outline.Add(outline[0]);
                }
            }
            int linespacing_um = (int)(extrusionWidthOverride_um / (config.InfillPercent / 100));

            while (outlineCopy.Count > 0)
            {
                for (int outlineIndex = 0; outlineIndex < outlineCopy.Count; outlineIndex++)
                {
                    Polygon r = outlineCopy[outlineIndex];
                    fillPolygons.Add(r);
                }
                outlineCopy = outlineCopy.Offset(-linespacing_um);
                foreach (Polygon outline in outlineCopy)
                {
                    if (outline.Count > 0)
                    {
                        outline.Add(outline[0]);
                    }
                }
            }
        }
コード例 #32
0
        private static Polygons GetSkirtBounds(ConfigSettings config, LayerDataStorage storage, bool externalOnly, int distance, int extrusionWidth_um, int brimCount)
        {
            Polygons allOutlines = new Polygons();

            // Loop over every extruder
            for (int extrudeIndex = 0; extrudeIndex < storage.Extruders.Count; extrudeIndex++)
            {
                // Only process the first extruder on spiral vase or
                // skip extruders that have empty layers
                if (config.ContinuousSpiralOuterPerimeter)
                {
                    SliceLayer layer0 = storage.Extruders[extrudeIndex].Layers[0];
                    allOutlines.AddAll(layer0.Islands[0]?.IslandOutline);

                    break;
                }

                // Add the layers outline to allOutlines
                SliceLayer layer = storage.Extruders[extrudeIndex].Layers[0];
                allOutlines.AddAll(layer.AllOutlines);
            }

            bool hasWipeTower = storage.wipeTower.PolygonLength() > 0;

            Polygons skirtPolygons = hasWipeTower ? new Polygons(storage.wipeTower) : new Polygons();

            if (brimCount > 0)
            {
                Polygons brimLoops = new Polygons();

                // Loop over the requested brimCount creating and unioning a new perimeter for each island
                for (int brimIndex = 0; brimIndex < brimCount; brimIndex++)
                {
                    int offsetDistance = extrusionWidth_um * brimIndex + extrusionWidth_um / 2;

                    Polygons unionedIslandOutlines = new Polygons();

                    // Grow each island by the current brim distance
                    foreach (var island in allOutlines)
                    {
                        var polygons = new Polygons();
                        polygons.Add(island);

                        // Union the island brims
                        unionedIslandOutlines = unionedIslandOutlines.CreateUnion(polygons.Offset(offsetDistance));
                    }

                    // Extend the polygons to account for the brim (ensures convex hull takes this data into account)
                    brimLoops.AddAll(unionedIslandOutlines);
                }

                // TODO: This is a quick hack, reuse the skirt data to stuff in the brim. Good enough from proof of concept
                storage.skirt.AddAll(brimLoops);

                skirtPolygons = skirtPolygons.CreateUnion(brimLoops);
            }
            else
            {
                skirtPolygons = skirtPolygons.CreateUnion(allOutlines);
            }

            if (storage.support != null)
            {
                skirtPolygons = skirtPolygons.CreateUnion(storage.support.GetBedOutlines());
            }

            return(skirtPolygons);
        }
コード例 #33
0
 private static Mesh CreateTop(Polygons path, double topHeight, double scaling)
 {
     return(path.CreateVertexStorage(scaling).TriangulateFaces(zHeight: topHeight));
 }
コード例 #34
0
        public void WriteRaftGCodeIfRequired(GCodeExport gcode, ConfigSettings config)
        {
            LayerDataStorage storage = this;

            if (config.ShouldGenerateRaft())
            {
                GCodePathConfig raftBaseConfig = new GCodePathConfig("raftBaseConfig");
                raftBaseConfig.SetData(config.FirstLayerSpeed, config.RaftBaseExtrusionWidth_um, "SUPPORT");

                GCodePathConfig raftMiddleConfig = new GCodePathConfig("raftMiddleConfig");
                raftMiddleConfig.SetData(config.RaftPrintSpeed, config.RaftInterfaceExtrusionWidth_um, "SUPPORT");

                GCodePathConfig raftSurfaceConfig = new GCodePathConfig("raftMiddleConfig");
                raftSurfaceConfig.SetData((config.RaftSurfacePrintSpeed > 0) ? config.RaftSurfacePrintSpeed : config.RaftPrintSpeed, config.RaftSurfaceExtrusionWidth_um, "SUPPORT");

                // create the raft base
                {
                    gcode.WriteComment("LAYER:-3");
                    gcode.WriteComment("RAFT BASE");
                    GCodePlanner gcodeLayer = new GCodePlanner(gcode, config.TravelSpeed, config.MinimumTravelToCauseRetraction_um);
                    if (config.RaftExtruder >= 0)
                    {
                        // if we have a specified raft extruder use it
                        gcodeLayer.SetExtruder(config.RaftExtruder);
                    }
                    else if (config.SupportExtruder >= 0)
                    {
                        // else preserve the old behavior of using the support extruder if set.
                        gcodeLayer.SetExtruder(config.SupportExtruder);
                    }

                    gcode.setZ(config.RaftBaseThickness_um);
                    gcode.SetExtrusion(config.RaftBaseThickness_um, config.FilamentDiameter_um, config.ExtrusionMultiplier);

                    // write the skirt around the raft
                    gcodeLayer.QueuePolygonsByOptimizer(storage.skirt, raftBaseConfig);

                    List <Polygons> raftIslands = storage.raftOutline.ProcessIntoSeparatIslands();
                    foreach (var raftIsland in raftIslands)
                    {
                        // write the outline of the raft
                        gcodeLayer.QueuePolygonsByOptimizer(raftIsland, raftBaseConfig);

                        Polygons raftLines = new Polygons();
                        Infill.GenerateLinePaths(raftIsland, raftLines, config.RaftBaseLineSpacing_um, config.InfillExtendIntoPerimeter_um, 0);

                        // write the inside of the raft base
                        gcodeLayer.QueuePolygonsByOptimizer(raftLines, raftBaseConfig);

                        if (config.RetractWhenChangingIslands)
                        {
                            gcodeLayer.ForceRetract();
                        }
                    }

                    gcodeLayer.WriteQueuedGCode(config.RaftBaseThickness_um);
                }

                if (config.RaftFanSpeedPercent > 0)
                {
                    gcode.WriteFanCommand(config.RaftFanSpeedPercent);
                }

                // raft middle layers
                {
                    gcode.WriteComment("LAYER:-2");
                    gcode.WriteComment("RAFT MIDDLE");
                    GCodePlanner gcodeLayer = new GCodePlanner(gcode, config.TravelSpeed, config.MinimumTravelToCauseRetraction_um);
                    gcode.setZ(config.RaftBaseThickness_um + config.RaftInterfaceThicknes_um);
                    gcode.SetExtrusion(config.RaftInterfaceThicknes_um, config.FilamentDiameter_um, config.ExtrusionMultiplier);

                    Polygons raftLines = new Polygons();
                    Infill.GenerateLinePaths(storage.raftOutline, raftLines, config.RaftInterfaceLineSpacing_um, config.InfillExtendIntoPerimeter_um, 45);
                    gcodeLayer.QueuePolygonsByOptimizer(raftLines, raftMiddleConfig);

                    gcodeLayer.WriteQueuedGCode(config.RaftInterfaceThicknes_um);
                }

                for (int raftSurfaceIndex = 1; raftSurfaceIndex <= config.RaftSurfaceLayers; raftSurfaceIndex++)
                {
                    gcode.WriteComment("LAYER:-1");
                    gcode.WriteComment("RAFT SURFACE");
                    GCodePlanner gcodeLayer = new GCodePlanner(gcode, config.TravelSpeed, config.MinimumTravelToCauseRetraction_um);
                    gcode.setZ(config.RaftBaseThickness_um + config.RaftInterfaceThicknes_um + config.RaftSurfaceThickness_um * raftSurfaceIndex);
                    gcode.SetExtrusion(config.RaftSurfaceThickness_um, config.FilamentDiameter_um, config.ExtrusionMultiplier);

                    Polygons raftLines = new Polygons();
                    if (raftSurfaceIndex == config.RaftSurfaceLayers)
                    {
                        // make sure the top layer of the raft is 90 degrees offset to the first layer of the part so that it has minimum contact points.
                        Infill.GenerateLinePaths(storage.raftOutline, raftLines, config.RaftSurfaceLineSpacing_um, config.InfillExtendIntoPerimeter_um, config.InfillStartingAngle + 90);
                    }
                    else
                    {
                        Infill.GenerateLinePaths(storage.raftOutline, raftLines, config.RaftSurfaceLineSpacing_um, config.InfillExtendIntoPerimeter_um, 90 * raftSurfaceIndex);
                    }
                    gcodeLayer.QueuePolygonsByOptimizer(raftLines, raftSurfaceConfig);

                    gcodeLayer.WriteQueuedGCode(config.RaftInterfaceThicknes_um);
                }
            }
        }
コード例 #35
0
 public Aabb(Polygons polys)
 {
     min = new IntPoint(long.MinValue, long.MinValue);
     max = new IntPoint(long.MinValue, long.MinValue);
     Calculate(polys);
 }
コード例 #36
0
 public static double TotalArea(this Polygons polygons)
 {
     return(polygons.Sum(polygon => polygon.Area()));
 }
コード例 #37
0
ファイル: clipper.cs プロジェクト: caomw/elementdiscovery
        //------------------------------------------------------------------------------

        private void BuildResult(Polygons polyg)
        {
            polyg.Clear();
            polyg.Capacity = m_PolyOuts.Count;
            for (int i = 0; i < m_PolyOuts.Count; i++)
            {
                OutRec outRec = m_PolyOuts[i];
                if (outRec.pts == null) continue;
                OutPt p = outRec.pts;
                int cnt = PointCount(p);
                if (cnt < 3) continue;
                Polygon pg = new Polygon(cnt);
                for (int j = 0; j < cnt; j++)
                {
                    pg.Add(p.pt);
                    p = p.prev;
                }
                polyg.Add(pg);
            }
        }
コード例 #38
0
        private static Polygons IntersectWithSparsePolygons(List <LayerIsland> islands, Aabb boundsToConsider, Polygons polysToIntersect)
        {
            Polygons polysFromIslands = new Polygons();

            for (int islandIndex = 0; islandIndex < islands.Count; islandIndex++)
            {
                if (boundsToConsider.Hit(islands[islandIndex].BoundingBox))
                {
                    if (islands[islandIndex].InsetToolPaths.Count > 0)
                    {
                        polysFromIslands = polysFromIslands.CreateUnion(islands[islandIndex].SparseInfillPaths);
                        polysFromIslands = Clipper.CleanPolygons(polysFromIslands, cleanDistance_um);
                    }
                }
            }

            polysToIntersect = polysToIntersect.CreateIntersection(polysFromIslands);

            return(polysToIntersect);
        }
コード例 #39
0
ファイル: clipper.cs プロジェクト: caomw/elementdiscovery
        //------------------------------------------------------------------------------

        public static Polygons OffsetPolygons(Polygons poly, double delta,
            JoinType jointype, double MiterLimit)
        {
            Polygons result = new Polygons(poly.Count);
            new PolyOffsetBuilder(poly, result, delta, jointype, MiterLimit, true);
            return result;
        }
コード例 #40
0
        private static Polygons RemoveIslandsFromPolygons(List <LayerIsland> islands, Aabb boundsToConsider, Polygons polygonsToSubtractFrom)
        {
            for (int islandIndex = 0; islandIndex < islands.Count; islandIndex++)
            {
                if (boundsToConsider.Hit(islands[islandIndex].BoundingBox))
                {
                    if (islands[islandIndex].InsetToolPaths.Count > 0)
                    {
                        polygonsToSubtractFrom = polygonsToSubtractFrom.CreateDifference(islands[islandIndex].InsetToolPaths[0]);
                        polygonsToSubtractFrom = Clipper.CleanPolygons(polygonsToSubtractFrom, cleanDistance_um);
                    }
                }
            }

            return(polygonsToSubtractFrom);
        }
コード例 #41
0
ファイル: clipper.cs プロジェクト: caomw/elementdiscovery
        //------------------------------------------------------------------------------

        public static Polygons SimplifyPolygons(Polygons polys,
            PolyFillType fillType = PolyFillType.pftEvenOdd)
        {
            Polygons result = new Polygons();
            Clipper c = new Clipper();
            c.AddPolygons(polys, PolyType.ptSubject);
            c.Execute(ClipType.ctUnion, result, fillType, fillType);
            return result;
        }
コード例 #42
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];

            for (int islandIndex = 0; islandIndex < layer.Islands.Count; islandIndex++)
            {
                LayerIsland island = layer.Islands[islandIndex];
                if (island.InsetToolPaths.Count == 0)
                {
                    continue;
                }
                // 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;

                        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 = layerIndex - 1;
                        int downEnd   = layerIndex - downLayerCount;

                        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;
                }
            }
        }
コード例 #43
0
ファイル: clipper.cs プロジェクト: caomw/elementdiscovery
        //------------------------------------------------------------------------------

        public static void AddPolyNodeToPolygons(PolyNode polynode, Polygons polygons)
        {
            if (polynode.Contour.Count > 0) 
                polygons.Add(polynode.Contour);
            foreach (PolyNode pn in polynode.Childs)
                AddPolyNodeToPolygons(pn, polygons);
        }
コード例 #44
0
        public static Polygons CreateLineIntersections(this Polygons areaToIntersect, Polygons lines)
        {
            Clipper clipper = new Clipper();

            clipper.AddPaths(lines, PolyType.ptSubject, false);
            clipper.AddPaths(areaToIntersect, PolyType.ptClip, true);

            PolyTree clippedLines = new PolyTree();

            clipper.Execute(ClipType.ctIntersection, clippedLines);

            return(Clipper.OpenPathsFromPolyTree(clippedLines));
        }
コード例 #45
0
		public static Polygons CreateLineDifference(this Polygons linePolygons, Polygons removePolygons)
		{
			Clipper clipper = new Clipper();

			clipper.AddPaths(linePolygons, PolyType.ptSubject, false);
			clipper.AddPaths(removePolygons, PolyType.ptClip, true);

			PolyTree clippedLines = new PolyTree();

			clipper.Execute(ClipType.ctDifference, clippedLines);

			return Clipper.OpenPathsFromPolyTree(clippedLines);
		}
コード例 #46
0
 public static int size(this Polygons polygons)
 {
     return(polygons.Count);
 }
コード例 #47
0
		public static Polygons CreateIntersection(this Polygons polygons, Polygons other)
		{
			Polygons ret = new Polygons();
			Clipper clipper = new Clipper();
			clipper.AddPaths(polygons, PolyType.ptSubject, true);
			clipper.AddPaths(other, PolyType.ptClip, true);
			clipper.Execute(ClipType.ctIntersection, ret);
			return ret;
		}
コード例 #48
0
		private static void ProcessPolyTreeNodeIntoSeparatIslands(this Polygons polygonsIn, PolyNode node, List<Polygons> ret)
		{
			for (int n = 0; n < node.ChildCount; n++)
			{
				PolyNode child = node.Childs[n];
				Polygons polygons = new Polygons();
				polygons.Add(child.Contour);
				for (int i = 0; i < child.ChildCount; i++)
				{
					polygons.Add(child.Childs[i].Contour);
					polygonsIn.ProcessPolyTreeNodeIntoSeparatIslands(child.Childs[i], ret);
				}
				ret.Add(polygons);
			}
		}
コード例 #49
0
		public static Polygons CreateUnion(this Polygons polygons, Polygons other)
		{
			Clipper clipper = new Clipper();
			clipper.AddPaths(polygons, PolyType.ptSubject, true);
			clipper.AddPaths(other, PolyType.ptSubject, true);

			Polygons ret = new Polygons();
			clipper.Execute(ClipType.ctUnion, ret, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
			return ret;
		}
コード例 #50
0
		public static Mesh[] SplitIntoMeshesOnOrthographicZ(Mesh meshToSplit, Vector3 buildVolume, ReportProgressRatio reportProgress)
		{
			// check if the part is bigger than the build plate (if it is we need to use that as our size)
			AxisAlignedBoundingBox partBounds = meshToSplit.GetAxisAlignedBoundingBox();

			buildVolume.x = Math.Max(buildVolume.x, partBounds.XSize + 2);
			buildVolume.y = Math.Max(buildVolume.y, partBounds.YSize + 2);
			buildVolume.z = Math.Max(buildVolume.z, partBounds.ZSize + 2);

			// Find all the separate objects that are on the plate
			// Create a 2D image the size of the printer bed at some scale with the parts draw on it top down

			double scaleFactor = 5;
			ImageBuffer partPlate = new ImageBuffer((int)(buildVolume.x * scaleFactor), (int)(buildVolume.y * scaleFactor), 32, new BlenderBGRA());
			Vector2 renderOffset = new Vector2(buildVolume.x / 2, buildVolume.y / 2) - new Vector2(partBounds.Center.x, partBounds.Center.y);

			PolygonMesh.Rendering.OrthographicZProjection.DrawTo(partPlate.NewGraphics2D(), meshToSplit, renderOffset, scaleFactor, RGBA_Bytes.White);

			bool continueProcessin = true;
			if (reportProgress != null)
			{
				reportProgress(.2, "", out continueProcessin);
			}

			//ImageIO.SaveImageData("test part plate 0.png", partPlate);
			// expand the bounds a bit so that we can collect all the vertices and polygons within each bound
			Dilate.DoDilate3x3Binary(partPlate, 1);
			//ImageIO.SaveImageData("test part plate 1.png", partPlate);

			// trace all the bounds of the objects on the plate
			PolyTree polyTreeForPlate = FindDistictObjectBounds(partPlate);
			if (polyTreeForPlate == null)
			{
				Mesh[] singleMesh = new Mesh[1];
				singleMesh[0] = meshToSplit;
				return singleMesh;
			}

			// get all the discrete areas that are polygons so we can search them
			Polygons discreteAreas = new Polygons();
			GetAreasRecursive(polyTreeForPlate, discreteAreas);
			if (discreteAreas.Count == 0)
			{
				return null;
			}
			else if (discreteAreas.Count == 1)
			{
				Mesh[] singleMesh = new Mesh[1];
				singleMesh[0] = meshToSplit;
				return singleMesh;
			}

			Graphics2D graphics2D = partPlate.NewGraphics2D();
			graphics2D.Clear(RGBA_Bytes.Black);
			Random rand = new Random();
			foreach (Polygon polygon in discreteAreas)
			{
				graphics2D.Render(PlatingHelper.PolygonToPathStorage(polygon), new RGBA_Bytes(rand.Next(128, 255), rand.Next(128, 255), rand.Next(128, 255)));
			}
			if (reportProgress != null)
			{
				reportProgress(.5, "", out continueProcessin);
			}
			//ImageIO.SaveImageData("test part plate 2.png", partPlate);

			// add each of the separate bounds polygons to new meshes
			Mesh[] discreteMeshes = new Mesh[discreteAreas.Count];
			for (int i = 0; i < discreteAreas.Count; i++)
			{
				discreteMeshes[i] = new Mesh();
			}

			foreach (Face face in meshToSplit.Faces)
			{
				bool faceDone = false;
				// figure out which area one or more of the vertices are in add the face to the right new mesh
				foreach (FaceEdge faceEdge in face.FaceEdges())
				{
					Vector2 position = new Vector2(faceEdge.firstVertex.Position.x, faceEdge.firstVertex.Position.y);
					position += renderOffset;
					position *= scaleFactor;

					for (int areaIndex = discreteAreas.Count - 1; areaIndex >= 0; areaIndex--)
					{
						if (PointInPolygon(discreteAreas[areaIndex], new IntPoint((int)position.x, (int)position.y)))
						{
							List<Vertex> faceVertices = new List<Vertex>();
							foreach (FaceEdge faceEdgeToAdd in face.FaceEdges())
							{
								Vertex newVertex = discreteMeshes[areaIndex].CreateVertex(faceEdgeToAdd.firstVertex.Position);
								faceVertices.Add(newVertex);
							}

							discreteMeshes[areaIndex].CreateFace(faceVertices.ToArray());
							faceDone = true;
							break;
						}
					}

					if (faceDone)
					{
						break;
					}
				}
			}

			if (reportProgress != null)
			{
				reportProgress(.8, "", out continueProcessin);
			}

			for (int i = 0; i < discreteMeshes.Count(); i++)
			{
				Mesh mesh = discreteMeshes[i];
			}

			return discreteMeshes;
		}
コード例 #51
0
		public static Polygons Offset(this Polygons polygons, long distance)
		{
			ClipperOffset offseter = new ClipperOffset();
			offseter.AddPaths(polygons, JoinType.jtMiter, EndType.etClosedPolygon);
			Paths solution = new Polygons();
			offseter.Execute(ref solution, distance);
			return solution;
		}
コード例 #52
0
        private static List <Polygons> AccumulateDownPolygons(ConfigSettings config, List <Polygons> inputPolys, List <Polygons> allPartOutlines)
        {
            int numLayers = inputPolys.Count;

            long nozzleSize     = config.ExtrusionWidth_um;
            long areaToTryAndBe = 20 * 20 * nozzleSize * nozzleSize;             // 10 x 10 mm approximately (assuming .5 nozzle)

            List <Polygons> allDownOutlines = CreateEmptyPolygons(numLayers);

            for (int layerIndex = numLayers - 2; layerIndex >= 0; layerIndex--)
            {
                Polygons aboveRequiredSupport = inputPolys[layerIndex + 1];

                // get all the polygons above us
                Polygons accumulatedAbove = allDownOutlines[layerIndex + 1].CreateUnion(aboveRequiredSupport);

                // experimental and not working well enough yet
                if (config.MinimizeSupportColumns)
                {
                    // reduce the amount of support material used
                    for (int i = accumulatedAbove.Count - 1; i >= 0; i--)
                    {
                        Polygon polygon  = accumulatedAbove[i];
                        double  polyArea = polygon.Area();
                        if (polyArea > areaToTryAndBe)
                        {
                            Polygons offsetPolygons = new Polygons()
                            {
                                polygon
                            }.Offset(-config.ExtrusionWidth_um / 2);
                            accumulatedAbove.RemoveAt(i);
                            foreach (Polygon polyToAdd in offsetPolygons)
                            {
                                accumulatedAbove.Insert(i, polyToAdd);
                            }
                        }
                        else if (polyArea < areaToTryAndBe * .9)
                        {
                            Polygons offsetPolygons = new Polygons()
                            {
                                polygon
                            }.Offset(config.ExtrusionWidth_um / 2);
                            accumulatedAbove.RemoveAt(i);
                            foreach (Polygon polyToAdd in offsetPolygons)
                            {
                                accumulatedAbove.Insert(i, polyToAdd);
                            }
                        }
                    }
                }

                // add in the support on this level
                Polygons curRequiredSupport = inputPolys[layerIndex];

                Polygons totalSupportThisLayer = accumulatedAbove.CreateUnion(curRequiredSupport);

                // remove the solid polygons on this level
                Polygons remainingAbove = totalSupportThisLayer.CreateDifference(allPartOutlines[layerIndex]);

                allDownOutlines[layerIndex] = Clipper.CleanPolygons(remainingAbove, cleanDistance_um);
            }

            return(allDownOutlines);
        }
コード例 #53
0
		public static bool polygonCollidesWithlineSegment(Polygons polys, IntPoint startPoint, IntPoint endPoint)
		{
			IntPoint diff = endPoint - startPoint;

			PointMatrix transformation_matrix = new PointMatrix(diff);
			IntPoint transformed_startPoint = transformation_matrix.apply(startPoint);
			IntPoint transformed_endPoint = transformation_matrix.apply(endPoint);

			return polygonCollidesWithlineSegment(polys, transformed_startPoint, transformed_endPoint, transformation_matrix);
		}
コード例 #54
0
ファイル: infill.cs プロジェクト: qwinner/MatterSlice
        public static void GenerateGridInfill(ConfigSettings config, Polygons partOutline, Polygons fillPolygons, double fillAngle, int linespacing_um = 0)
        {
            if (linespacing_um == 0)
            {
                if (config.InfillPercent <= 0)
                {
                    throw new Exception("infillPercent must be greater than 0.");
                }
                linespacing_um = (int)(config.ExtrusionWidth_um / (config.InfillPercent / 100) * 2);
            }

            Infill.GenerateLinePaths(partOutline, fillPolygons, linespacing_um, config.InfillExtendIntoPerimeter_um, fillAngle);

            fillAngle += 90;
            if (fillAngle > 360)
            {
                fillAngle -= 360;
            }

            Infill.GenerateLinePaths(partOutline, fillPolygons, linespacing_um, config.InfillExtendIntoPerimeter_um, fillAngle);
        }
コード例 #55
0
 /// <summary>
 /// Return a list of polygons of this polygon split into triangles
 /// </summary>
 /// <param name="polygons"></param>
 /// <returns></returns>
 public static Polygons Triangulate(this Polygons polygons)
 {
     throw new NotImplementedException();
 }
コード例 #56
0
        public static void GenerateHexagonInfill(ConfigSettings config, Polygons partOutline, Polygons fillPolygons, double fillAngle, int layerIndex)
        {
            if (config.InfillPercent <= 0)
            {
                throw new Exception("infillPercent must be greater than 0.");
            }

            int linespacing_um = (int)(config.ExtrusionWidth_um / (config.InfillPercent / 100) * 3 * .66);

            Infill.GenerateHexLinePaths(partOutline, fillPolygons, linespacing_um, config.InfillExtendIntoPerimeter_um, fillAngle, layerIndex);
        }
コード例 #57
0
		public static Polygons ConvertToLines(Polygons polygons)
		{
			Polygons linePolygons = new Polygons();
			foreach(Polygon polygon in polygons)
			{
				if (polygon.Count > 2)
				{
					for (int vertexIndex = 0; vertexIndex < polygon.Count; vertexIndex++)
					{
						linePolygons.Add(new Polygon() { polygon[vertexIndex], polygon[(vertexIndex + 1) % polygon.Count] });
					}
				}
				else
				{
					linePolygons.Add(polygon);
				}
			}

			return linePolygons;
		}
コード例 #58
0
 public static Polygon CreateConvexHull(this Polygons polygons)
 {
     return(polygons.SelectMany(s => s).ToList().CreateConvexHull());
 }
コード例 #59
0
		static private void GetAreasRecursive(PolyNode polyTreeForPlate, Polygons discreteAreas)
		{
			if (!polyTreeForPlate.IsHole)
			{
				discreteAreas.Add(polyTreeForPlate.Contour);
			}

			foreach (PolyNode child in polyTreeForPlate.Childs)
			{
				GetAreasRecursive(child, discreteAreas);
			}
		}
コード例 #60
0
ファイル: infill.cs プロジェクト: qwinner/MatterSlice
        public static void GenerateHexLinePaths(Polygons in_outline, Polygons result, int lineSpacing, int infillExtendIntoPerimeter_um, double rotationDegrees, int layerIndex)
        {
            int extraRotationAngle = 0;

            if (in_outline.Count > 0)
            {
                Polygons outlines = in_outline.Offset(infillExtendIntoPerimeter_um);
                if (outlines.Count > 0)
                {
                    int         perIncrementOffset = (int)(lineSpacing * Math.Sqrt(3) / 2 + .5);
                    PointMatrix matrix             = new PointMatrix(-(rotationDegrees + extraRotationAngle));         // we are rotating the part so we rotate by the negative so the lines go the way we expect

                    outlines.ApplyMatrix(matrix);

                    Aabb boundary = new Aabb(outlines);

                    boundary.min.X  = ((boundary.min.X / lineSpacing) - 1) * lineSpacing;
                    boundary.min.Y  = ((boundary.min.Y / perIncrementOffset) - 2) * perIncrementOffset;
                    boundary.max.X += lineSpacing;
                    boundary.max.Y += perIncrementOffset;
                    Polygons unclipedPatern = new Polygons();

                    foreach (IntPoint startPoint in StartPositionIterator(boundary, lineSpacing, layerIndex))
                    {
                        Polygon attachedLine = new Polygon();
                        foreach (IntPoint center in IncrementPositionIterator(startPoint, boundary, lineSpacing, layerIndex))
                        {
                            // what we are adding are the little pluses that define the points
                            //        | top
                            //        |
                            //        /\ center
                            //   left/  \ right
                            //
                            IntPoint left  = center + new IntPoint(-lineSpacing / 2, -perIncrementOffset / 3);
                            IntPoint right = center + new IntPoint(lineSpacing / 2, -perIncrementOffset / 3);
                            IntPoint top   = center + new IntPoint(0, perIncrementOffset * 2 / 3);

                            switch (layerIndex % 3)
                            {
                            case 0:                                     // left to right
                                attachedLine.Add(left); attachedLine.Add(center);
                                attachedLine.Add(center); attachedLine.Add(right);
                                unclipedPatern.Add(new Polygon()
                                {
                                    top, center
                                });
                                break;

                            case 1:                                     // left to top
                                attachedLine.Add(left); attachedLine.Add(center);
                                attachedLine.Add(center); attachedLine.Add(top);
                                unclipedPatern.Add(new Polygon()
                                {
                                    center, right
                                });
                                break;

                            case 2:                                     // top to right
                                attachedLine.Add(top); attachedLine.Add(center);
                                attachedLine.Add(center); attachedLine.Add(right);
                                unclipedPatern.Add(new Polygon()
                                {
                                    left, center
                                });
                                break;
                            }
                        }
                        if (attachedLine.Count > 0)
                        {
                            unclipedPatern.Add(attachedLine);
                        }
                    }

                    PolyTree ret     = new PolyTree();
                    Clipper  clipper = new Clipper();
                    clipper.AddPaths(unclipedPatern, PolyType.ptSubject, false);
                    clipper.AddPaths(outlines, PolyType.ptClip, true);
                    clipper.Execute(ClipType.ctIntersection, ret, PolyFillType.pftPositive, PolyFillType.pftEvenOdd);

                    Polygons    newSegments   = Clipper.OpenPathsFromPolyTree(ret);
                    PointMatrix inversematrix = new PointMatrix((rotationDegrees + extraRotationAngle));
                    newSegments.ApplyMatrix(inversematrix);

                    result.AddRange(newSegments);
                }
            }
        }