示例#1
0
        public void Optimize(IntPoint startPosition, PathFinder pathFinder, int layerIndex, bool addMovePolys, GCodePathConfig pathConfig = null)
        {
            // pathFinder = null;

            this.OptimizedPaths.Clear();

            bool doSeamHiding = pathConfig != null && pathConfig.DoSeamHiding && !pathConfig.Spiralize;
            bool canTravelForwardOrBackward = pathConfig != null && !pathConfig.ClosedLoop;
            // Find the point that is closest to our current position (start position)

            var completedPolygons = new HashSet <int>();

            var polygonAccelerator = Polygons.GetQuadTree();

            IntPoint currentPosition = startPosition;

            while (completedPolygons.Count < Polygons.Count)
            {
                var closestPolyPoint = FindClosestPolyAndPoint(currentPosition,
                                                               polygonAccelerator,
                                                               completedPolygons,
                                                               doSeamHiding,
                                                               layerIndex,
                                                               pathConfig != null ? pathConfig.LineWidth_um : 0,
                                                               canTravelForwardOrBackward,
                                                               out IntPoint endPosition);

                // if we have a path finder check if we have actually found the shortest path
                if (pathFinder != null &&
                    closestPolyPoint.SourcePolyIndex != -1 &&
                    closestPolyPoint.PointIndex != -1 &&
                    closestPolyPoint.FoundPath)
                {
                    // the position that we are going to move to to begin the next polygon (the other side of the endPosition)
                    var nextStartPosition = Polygons[closestPolyPoint.SourcePolyIndex][closestPolyPoint.PointIndex];
                    var pathPolygon       = new Polygon();
                    // path find the start and end that we found to find out how far it is
                    if (pathFinder.CreatePathInsideBoundary(currentPosition, nextStartPosition, pathPolygon, true, layerIndex))
                    {
                        var pathLength   = pathPolygon.PolygonLength();
                        var directLength = (nextStartPosition - currentPosition).Length();

                        var center = pathPolygon.GetPositionAllongPath(.5, pathConfig != null ? pathConfig.ClosedLoop : false);

                        var tryAgain = false;
                        do
                        {
                            tryAgain = false;
                            if (pathLength > config.MinimumTravelToCauseRetraction_um / 10 &&
                                pathLength > directLength * 2)
                            {
                                // try to find a closer place to go to by looking at the center of the returned path
                                var midPolyPoint = FindClosestPolyAndPoint(center,
                                                                           polygonAccelerator,
                                                                           completedPolygons,
                                                                           doSeamHiding,
                                                                           layerIndex,
                                                                           pathConfig != null ? pathConfig.LineWidth_um : 0,
                                                                           canTravelForwardOrBackward,
                                                                           out IntPoint midEndPosition);

                                if (midPolyPoint.SourcePolyIndex != -1 &&
                                    midPolyPoint.PointIndex != -1 &&
                                    closestPolyPoint.FoundPath)
                                {
                                    var midStartPosition = Polygons[midPolyPoint.SourcePolyIndex][midPolyPoint.PointIndex];

                                    if (pathFinder.CreatePathInsideBoundary(currentPosition, midStartPosition, pathPolygon, true, layerIndex))
                                    {
                                        var midPathLength = pathPolygon.PolygonLength();
                                        if (midPathLength < pathLength)
                                        {
                                            closestPolyPoint = midPolyPoint;
                                            endPosition      = midEndPosition;
                                            pathLength       = midPathLength;
                                            center           = pathPolygon.GetPositionAllongPath(.5, pathConfig != null ? pathConfig.ClosedLoop : false);
                                            tryAgain         = true;
                                        }
                                    }
                                }
                            }
                        } while (tryAgain);
                    }
                }

                if (closestPolyPoint.SourcePolyIndex == -1)
                {
                    // could not find any next point
                    break;
                }

                OptimizedPaths.Add(closestPolyPoint);
                completedPolygons.Add(closestPolyPoint.SourcePolyIndex);

                currentPosition = endPosition;
            }
        }
        public void Optimize(IntPoint startPosition, PathFinder pathFinder, int layerIndex, bool addMovePolys, GCodePathConfig pathConfig = null)
        {
            // pathFinder = null;

            this.OptimizedPaths.Clear();

            bool doSeamHiding = pathConfig != null && pathConfig.DoSeamHiding && !pathConfig.Spiralize;
            bool canTravelForwardOrBackward = pathConfig != null && !pathConfig.ClosedLoop;
            // Find the point that is closest to our current position (start position)

            var completedPolygons = new HashSet <int>();

            var polygonAccelerator = Polygons.GetQuadTree();

            IntPoint currentPosition = startPosition;

            while (completedPolygons.Count < Polygons.Count)
            {
                var closestPolyPoint = FindClosestPolyAndPoint(currentPosition,
                                                               polygonAccelerator,
                                                               completedPolygons,
                                                               doSeamHiding,
                                                               config.SeamPlacement,
                                                               layerIndex,
                                                               pathConfig != null ? pathConfig.LineWidth_um : 0,
                                                               canTravelForwardOrBackward,
                                                               out IntPoint endPosition);

                // if we have a path finder check if we have actually found the shortest path
                if (pathFinder != null &&
                    closestPolyPoint.SourcePolyIndex != -1 &&
                    closestPolyPoint.PointIndex != -1 &&
                    closestPolyPoint.FoundPath)
                {
                    // the position that we are going to move to to begin the next polygon (the other side of the endPosition)
                    var nextStartPosition = Polygons[closestPolyPoint.SourcePolyIndex][closestPolyPoint.PointIndex];
                    var pathPolygon       = new Polygon();
                    // path find the start and end that we found to find out how far it is
                    if (pathFinder.CreatePathInsideBoundary(currentPosition, nextStartPosition, pathPolygon, true, layerIndex))
                    {
                        var pathLength   = pathPolygon.PolygonLength();
                        var directLength = (nextStartPosition - currentPosition).Length();

                        var center = pathPolygon.GetPositionAllongPath(.5, pathConfig != null ? pathConfig.ClosedLoop : false);

                        var tryAgain = false;
                        do
                        {
                            tryAgain = false;
                            if (pathLength > config.MinimumTravelToCauseRetraction_um / 10 &&
                                pathLength > directLength * 2)
                            {
                                // try to find a closer place to go to by looking at the center of the returned path
                                var midPolyPoint = FindClosestPolyAndPoint(center,
                                                                           polygonAccelerator,
                                                                           completedPolygons,
                                                                           doSeamHiding,
                                                                           config.SeamPlacement,
                                                                           layerIndex,
                                                                           pathConfig != null ? pathConfig.LineWidth_um : 0,
                                                                           canTravelForwardOrBackward,
                                                                           out IntPoint midEndPosition);

                                if (midPolyPoint.SourcePolyIndex != -1 &&
                                    midPolyPoint.PointIndex != -1 &&
                                    closestPolyPoint.FoundPath)
                                {
                                    var midStartPosition = Polygons[midPolyPoint.SourcePolyIndex][midPolyPoint.PointIndex];

                                    if (pathFinder.CreatePathInsideBoundary(currentPosition, midStartPosition, pathPolygon, true, layerIndex))
                                    {
                                        var midPathLength = pathPolygon.PolygonLength();
                                        if (midPathLength < pathLength)
                                        {
                                            closestPolyPoint = midPolyPoint;
                                            endPosition      = midEndPosition;
                                            pathLength       = midPathLength;
                                            center           = pathPolygon.GetPositionAllongPath(.5, pathConfig != null ? pathConfig.ClosedLoop : false);
                                            tryAgain         = true;
                                        }
                                    }
                                }
                            }
                        }while (tryAgain);
                    }
                }

                if (closestPolyPoint.SourcePolyIndex == -1)
                {
                    // could not find any next point
                    break;
                }

                OptimizedPaths.Add(closestPolyPoint);
                completedPolygons.Add(closestPolyPoint.SourcePolyIndex);

                currentPosition = endPosition;
            }

            if (pathConfig?.Name.Contains("inset") == true &&
                Polygons.Count > 1)
            {
                // we have a subdivided perimeter make sure it is wound in the right direction
                // create a polygon that is all the points in the output order
                var polygon = new Polygon();
                foreach (var optimizedPath in OptimizedPaths)
                {
                    var sourcePoly = Polygons[optimizedPath.SourcePolyIndex];
                    polygon.Add(sourcePoly[optimizedPath.PointIndex]);
                    var endIndex = (optimizedPath.PointIndex - 1 + sourcePoly.Count) % sourcePoly.Count;
                    polygon.Add(sourcePoly[endIndex]);
                }

                // find the winding of all ponits
                if (polygon.GetWindingDirection() == -1)
                {
                    var newPaths = new List <OptimizedPath>();
                    // if -1 reverse the order so they will be ccw
                    foreach (var optimizedPath in ((IEnumerable <OptimizedPath>)OptimizedPaths).Reverse())
                    {
                        var sourcePoly = Polygons[optimizedPath.SourcePolyIndex];
                        var endIndex   = optimizedPath.PointIndex == 0 ? sourcePoly.Count - 1 : 0;
                        newPaths.Add(new OptimizedPath(optimizedPath.SourcePolyIndex, endIndex, optimizedPath.IsExtrude, optimizedPath.FoundPath));
                    }

                    OptimizedPaths = newPaths;
                }
            }
        }