예제 #1
0
        public void ClipSegmentTests()
        {
            {
                GCodePath inPath = Newtonsoft.Json.JsonConvert.DeserializeObject <GCodePath>("{\"config\":{\"closedLoop\":true,\"lineWidth_um\":500,\"gcodeComment\":\"WALL-OUTER\",\"speed\":18.9,\"spiralize\":false,\"doSeamHiding\":true,\"Name\":\"inset0Config\"},\"points\":[{\"x\":105366,\"y\":108976,\"z\":300},{\"x\":105743,\"y\":109188,\"z\":300},{\"x\":106352,\"y\":109582,\"z\":300},{\"x\":106606,\"y\":109674,\"z\":300},{\"x\":107513,\"y\":110120,\"z\":300},{\"x\":107766,\"y\":110836,\"z\":300},{\"x\":107804,\"y\":110986,\"z\":300},{\"x\":107806,\"y\":111124,\"z\":300},{\"x\":106720,\"y\":116034,\"z\":300},{\"x\":106669,\"y\":116205,\"z\":300},{\"x\":106345,\"y\":116505,\"z\":300},{\"x\":103152,\"y\":117619,\"z\":300},{\"x\":102975,\"y\":117661,\"z\":300},{\"x\":102749,\"y\":117546,\"z\":300},{\"x\":101132,\"y\":116186,\"z\":300},{\"x\":100997,\"y\":115990,\"z\":300},{\"x\":100845,\"y\":115704,\"z\":300},{\"x\":100673,\"y\":114777,\"z\":300},{\"x\":100959,\"y\":109833,\"z\":300},{\"x\":101785,\"y\":109149,\"z\":300},{\"x\":101836,\"y\":109129,\"z\":300},{\"x\":101976,\"y\":109137,\"z\":300},{\"x\":102415,\"y\":109277,\"z\":300},{\"x\":102712,\"y\":108910,\"z\":300},{\"x\":103239,\"y\":108477,\"z\":300},{\"x\":103355,\"y\":108453,\"z\":300},{\"x\":103710,\"y\":108924,\"z\":300},{\"x\":104116,\"y\":108883,\"z\":300},{\"x\":104330,\"y\":108371,\"z\":300},{\"x\":104867,\"y\":108245,\"z\":300},{\"x\":104888,\"y\":108273,\"z\":300},{\"x\":104980,\"y\":109145,\"z\":300}]}");

                GCodePath controlPath = Newtonsoft.Json.JsonConvert.DeserializeObject <GCodePath>("{\"config\":{\"closedLoop\":true,\"lineWidth_um\":500,\"gcodeComment\":\"WALL-OUTER\",\"speed\":18.9,\"spiralize\":false,\"doSeamHiding\":true,\"Name\":\"inset0Config\"},\"points\":[{\"x\":105366,\"y\":108976,\"z\":300},{\"x\":105743,\"y\":109188,\"z\":300},{\"x\":106352,\"y\":109582,\"z\":300},{\"x\":106606,\"y\":109674,\"z\":300},{\"x\":107513,\"y\":110120,\"z\":300},{\"x\":107766,\"y\":110836,\"z\":300},{\"x\":107804,\"y\":110986,\"z\":300},{\"x\":107806,\"y\":111124,\"z\":300},{\"x\":106720,\"y\":116034,\"z\":300},{\"x\":106669,\"y\":116205,\"z\":300},{\"x\":106345,\"y\":116505,\"z\":300},{\"x\":103152,\"y\":117619,\"z\":300},{\"x\":102975,\"y\":117661,\"z\":300},{\"x\":102749,\"y\":117546,\"z\":300},{\"x\":101132,\"y\":116186,\"z\":300},{\"x\":100997,\"y\":115990,\"z\":300},{\"x\":100845,\"y\":115704,\"z\":300},{\"x\":100673,\"y\":114777,\"z\":300},{\"x\":100959,\"y\":109833,\"z\":300},{\"x\":101785,\"y\":109149,\"z\":300},{\"x\":101836,\"y\":109129,\"z\":300},{\"x\":101976,\"y\":109137,\"z\":300},{\"x\":102415,\"y\":109277,\"z\":300},{\"x\":102712,\"y\":108910,\"z\":300},{\"x\":103239,\"y\":108477,\"z\":300},{\"x\":103355,\"y\":108453,\"z\":300},{\"x\":103710,\"y\":108924,\"z\":300},{\"x\":104116,\"y\":108883,\"z\":300},{\"x\":104330,\"y\":108371,\"z\":300},{\"x\":104867,\"y\":108245,\"z\":300},{\"x\":104888,\"y\":108273,\"z\":300},{\"x\":104927,\"y\":108647,\"z\":300}]}");

                long      targetDistance = (long)(inPath.Config.LineWidthUM);
                GCodePath testPath       = LayerGCodePlanner.TrimGCodePathEnd(inPath, targetDistance);

                Assert.IsTrue(controlPath.Polygon.Count == testPath.Polygon.Count);
                for (int i = 0; i < controlPath.Polygon.Count; i++)
                {
                    Assert.IsTrue(controlPath.Polygon[i] == testPath.Polygon[i]);
                }
            }

            {
                var path     = new Polygon(new IntPoint[] { new IntPoint(0, 0), new IntPoint(0, 10000) });
                var trimPath = path.CutToLength(7000);
                Assert.AreEqual(2, trimPath.Count);
                Assert.IsTrue(trimPath[1] == new IntPoint(0, 7000));
            }

            {
                var path     = new Polygon(new IntPoint[] { new IntPoint(0, 0), new IntPoint(0, 10000) });
                var trimPath = path.TrimEnd(3000);
                Assert.AreEqual(2, trimPath.Count);
                Assert.IsTrue(trimPath[1] == new IntPoint(0, 7000));
            }

            {
                var path     = new Polygon(new IntPoint[] { new IntPoint(0, 0), new IntPoint(0, 5000), new IntPoint(0, 10000) });
                var trimPath = path.TrimEnd(3000);
                Assert.AreEqual(3, trimPath.Count);
                Assert.IsTrue(trimPath[1] == new IntPoint(0, 5000));
                Assert.IsTrue(trimPath[2] == new IntPoint(0, 7000));
            }

            {
                var path     = new Polygon(new IntPoint[] { new IntPoint(0, 0), new IntPoint(0, 5000), new IntPoint(0, 10000) });
                var trimPath = path.TrimEnd(7000);
                Assert.AreEqual(2, trimPath.Count);
                Assert.IsTrue(trimPath[1] == new IntPoint(0, 3000));
            }

            {
                var path     = new Polygon(new IntPoint[] { new IntPoint(0, 0), new IntPoint(0, 10000) });
                var trimPath = path.CutToLength(0);
                Assert.AreEqual(1, trimPath.Count);
            }

            {
                var path     = new Polygon(new IntPoint[] { new IntPoint(0, 0), new IntPoint(0, 10000) });
                var trimPath = path.CutToLength(20000);
                Assert.AreEqual(2, trimPath.Count);
                Assert.IsTrue(trimPath[1] == new IntPoint(0, 10000));
            }
        }
예제 #2
0
        public void MergePathsIgnoringCollinearLines()
        {
            //GCodePath path = Newtonsoft.Json.JsonConvert.DeserializeObject<GCodePath>("{\"config\":{\"closedLoop\":true,\"lineWidth_um\":500,\"gcodeComment\":\"WALL-OUTER\",\"speed\":15.0,\"spiralize\":false,\"doSeamHiding\":true,\"Name\":\"inset0Config\"},\"points\":[{\"X\":0,\"Y\":6290,\"Width\":0,\"Z\":200},{\"X\":0,\"Y\":6290,\"Width\":0,\"Z\":200},{\"X\":0,\"Y\":6290,\"Width\":0,\"Z\":200},{\"X\":401,\"Y\":6277,\"Width\":0,\"Z\":200},{\"X\":787,\"Y\":6240,\"Width\":0,\"Z\":200},{\"X\":1185,\"Y\":6177,\"Width\":0,\"Z\":200},{\"X\":1564,\"Y\":6092,\"Width\":0,\"Z\":200},{\"X\":1944,\"Y\":5982,\"Width\":0,\"Z\":200},{\"X\":2315,\"Y\":5848,\"Width\":0,\"Z\":200},{\"X\":2671,\"Y\":5693,\"Width\":0,\"Z\":200},{\"X\":3036,\"Y\":5508,\"Width\":0,\"Z\":200},{\"X\":3369,\"Y\":5310,\"Width\":0,\"Z\":200},{\"X\":3691,\"Y\":5093,\"Width\":0,\"Z\":200}]}");
            GCodePath path = Newtonsoft.Json.JsonConvert.DeserializeObject <GCodePath>("{\"config\":{\"closedLoop\":true,\"lineWidth_um\":500,\"gcodeComment\":\"WALL-OUTER\",\"speed\":15.0,\"spiralize\":false,\"doSeamHiding\":true,\"Name\":\"inset0Config\"},\"points\":[{\"X\":0,\"Y\":6290,\"Width\":0,\"Z\":200},{\"X\":0,\"Y\":6290,\"Width\":0,\"Z\":200},{\"X\":0,\"Y\":6290,\"Width\":0,\"Z\":200}]}");

            bool pathIsClosed = false;

            var pathsWithOverlapsRemoved = path.Polygon.MergePerimeterOverlaps(path.Config.LineWidth_um, pathIsClosed);

            Assert.IsFalse(pathsWithOverlapsRemoved == null);
        }
예제 #3
0
        public void ClipSegmentTests()
        {
            GCodePath inPath = Newtonsoft.Json.JsonConvert.DeserializeObject <GCodePath>("{\"config\":{\"closedLoop\":true,\"lineWidth_um\":500,\"gcodeComment\":\"WALL-OUTER\",\"speed\":18.9,\"spiralize\":false,\"doSeamHiding\":true,\"Name\":\"inset0Config\"},\"points\":[{\"x\":105366,\"y\":108976,\"z\":300},{\"x\":105743,\"y\":109188,\"z\":300},{\"x\":106352,\"y\":109582,\"z\":300},{\"x\":106606,\"y\":109674,\"z\":300},{\"x\":107513,\"y\":110120,\"z\":300},{\"x\":107766,\"y\":110836,\"z\":300},{\"x\":107804,\"y\":110986,\"z\":300},{\"x\":107806,\"y\":111124,\"z\":300},{\"x\":106720,\"y\":116034,\"z\":300},{\"x\":106669,\"y\":116205,\"z\":300},{\"x\":106345,\"y\":116505,\"z\":300},{\"x\":103152,\"y\":117619,\"z\":300},{\"x\":102975,\"y\":117661,\"z\":300},{\"x\":102749,\"y\":117546,\"z\":300},{\"x\":101132,\"y\":116186,\"z\":300},{\"x\":100997,\"y\":115990,\"z\":300},{\"x\":100845,\"y\":115704,\"z\":300},{\"x\":100673,\"y\":114777,\"z\":300},{\"x\":100959,\"y\":109833,\"z\":300},{\"x\":101785,\"y\":109149,\"z\":300},{\"x\":101836,\"y\":109129,\"z\":300},{\"x\":101976,\"y\":109137,\"z\":300},{\"x\":102415,\"y\":109277,\"z\":300},{\"x\":102712,\"y\":108910,\"z\":300},{\"x\":103239,\"y\":108477,\"z\":300},{\"x\":103355,\"y\":108453,\"z\":300},{\"x\":103710,\"y\":108924,\"z\":300},{\"x\":104116,\"y\":108883,\"z\":300},{\"x\":104330,\"y\":108371,\"z\":300},{\"x\":104867,\"y\":108245,\"z\":300},{\"x\":104888,\"y\":108273,\"z\":300},{\"x\":104980,\"y\":109145,\"z\":300}]}");

            GCodePath controlPath = Newtonsoft.Json.JsonConvert.DeserializeObject <GCodePath>("{\"config\":{\"closedLoop\":true,\"lineWidth_um\":500,\"gcodeComment\":\"WALL-OUTER\",\"speed\":18.9,\"spiralize\":false,\"doSeamHiding\":true,\"Name\":\"inset0Config\"},\"points\":[{\"x\":105366,\"y\":108976,\"z\":300},{\"x\":105743,\"y\":109188,\"z\":300},{\"x\":106352,\"y\":109582,\"z\":300},{\"x\":106606,\"y\":109674,\"z\":300},{\"x\":107513,\"y\":110120,\"z\":300},{\"x\":107766,\"y\":110836,\"z\":300},{\"x\":107804,\"y\":110986,\"z\":300},{\"x\":107806,\"y\":111124,\"z\":300},{\"x\":106720,\"y\":116034,\"z\":300},{\"x\":106669,\"y\":116205,\"z\":300},{\"x\":106345,\"y\":116505,\"z\":300},{\"x\":103152,\"y\":117619,\"z\":300},{\"x\":102975,\"y\":117661,\"z\":300},{\"x\":102749,\"y\":117546,\"z\":300},{\"x\":101132,\"y\":116186,\"z\":300},{\"x\":100997,\"y\":115990,\"z\":300},{\"x\":100845,\"y\":115704,\"z\":300},{\"x\":100673,\"y\":114777,\"z\":300},{\"x\":100959,\"y\":109833,\"z\":300},{\"x\":101785,\"y\":109149,\"z\":300},{\"x\":101836,\"y\":109129,\"z\":300},{\"x\":101976,\"y\":109137,\"z\":300},{\"x\":102415,\"y\":109277,\"z\":300},{\"x\":102712,\"y\":108910,\"z\":300},{\"x\":103239,\"y\":108477,\"z\":300},{\"x\":103355,\"y\":108453,\"z\":300},{\"x\":103710,\"y\":108924,\"z\":300},{\"x\":104116,\"y\":108883,\"z\":300},{\"x\":104330,\"y\":108371,\"z\":300},{\"x\":104867,\"y\":108245,\"z\":300},{\"x\":104888,\"y\":108273,\"z\":300},{\"x\":104927,\"y\":108647,\"z\":300}]}");

            GCodePath testPath = GCodePlanner.TrimPerimeter(inPath, 0);

            Assert.IsTrue(controlPath.points.Count == testPath.points.Count);
            for (int i = 0; i < controlPath.points.Count; i++)
            {
                Assert.IsTrue(controlPath.points[i] == testPath.points[i]);
            }
        }
예제 #4
0
        private bool RemovePerimetersThatOverlap(GCodePath path, double speed, out List<PathAndWidth> pathsWithOverlapsRemoved, bool pathIsClosed)
        {
            pathsWithOverlapsRemoved = null;
            if (path.config.lineWidth_um > 0
                && path.points.Count > 2 // If the count is not greater than 2 there is no way it can overlap itself.
                && gcodeExport.GetPosition() == path.points[path.points.Count - 1])
            {
                if (RemovePerimeterOverlaps(path.points, path.config.lineWidth_um, out pathsWithOverlapsRemoved, pathIsClosed)
                    && pathsWithOverlapsRemoved.Count > 0)
                {
                    return true;
                }
            }

            return false;
        }
예제 #5
0
        private static bool TrimPerimeterIfNeeded(GCodePath path, double perimeterStartEndOverlapRatio)
        {
            if (path.config.gcodeComment == "WALL-OUTER" || path.config.gcodeComment == "WALL-INNER")
            {
                long currentDistance = 0;
                long targetDistance = (long)(path.config.lineWidth_um * (1-perimeterStartEndOverlapRatio));

                if (path.points.Count > 1)
                {
                    for (int pointIndex = path.points.Count - 1; pointIndex > 0; pointIndex--)
                    {
                        // Calculate distance between 2 points
                        currentDistance = (path.points[pointIndex] - path.points[pointIndex - 1]).Length();

                        // If distance exceeds clip distance:
                        //  - Sets the new last path point
                        if (currentDistance > targetDistance)
                        {
                            long newDistance = currentDistance - targetDistance;
                            if (newDistance > 50) // Don't clip segments less than 50 um. We get too much truncation error.
                            {
                                Point3 dir = (path.points[pointIndex] - path.points[pointIndex - 1]) * newDistance / currentDistance;

                                Point3 clippedEndpoint = path.points[pointIndex - 1] + dir;

                                path.points[pointIndex] = clippedEndpoint;
                            }
                            break;
                        }
                        else if (currentDistance == targetDistance)
                        {
                            // Pops off last point because it is at the limit distance
                            path.points.RemoveAt(path.points.Count - 1);
                            break;
                        }
                        else
                        {
                            // Pops last point and reduces distance remaining to target
                            targetDistance -= currentDistance;
                            path.points.RemoveAt(path.points.Count - 1);
                        }
                    }
                }

                // the path was trimmed
                return true;
            }

            return false;
        }
예제 #6
0
        private static void TrimPerimeterIfNeeded(GCodePath path)
        {
            if (path.config.name == "WALL-OUTER" || path.config.name == "WALL-INNER")
            {
                double currentDistance = 0;
                double targetDistance = (long)(path.config.lineWidth * .90);

                if (path.points.Count > 1)
                {
                    for (int pointIndex = path.points.Count - 1; pointIndex > 0; pointIndex--)
                    {
                        // Calculate distance between 2 points
                        currentDistance = (path.points[pointIndex] - path.points[pointIndex - 1]).Length();

                        // If distance exceeds clip distance:
                        //  - Sets the new last path point
                        if (currentDistance > targetDistance)
                        {
                            DoublePoint dir = new DoublePoint((path.points[pointIndex].X - path.points[pointIndex - 1].X) / currentDistance, (path.points[pointIndex].Y - path.points[pointIndex - 1].Y) / currentDistance);

                            double newDistance = currentDistance - targetDistance;
                            dir.X *= newDistance;
                            dir.Y *= newDistance;

                            IntPoint clippedEndpoint = path.points[pointIndex - 1] + new IntPoint(dir.X, dir.Y);

                            path.points[pointIndex] = clippedEndpoint;
                            break;
                        }
                        else if (currentDistance == targetDistance)
                        {
                            // Pops off last point because it is at the limit distance
                            path.points.RemoveAt(path.points.Count - 1);
                            break;
                        }
                        else
                        {
                            // Pops last point and reduces distance remaining to target
                            targetDistance = targetDistance - currentDistance;
                            path.points.RemoveAt(path.points.Count - 1);
                        }
                    }
                }
            }
        }
예제 #7
0
		private static void TrimPerimeterIfNeeded(GCodePath path)
		{
			if (path.config.gcodeComment == "WALL-OUTER" || path.config.gcodeComment == "WALL-INNER")
			{
				long currentDistance = 0;
				long targetDistance = (long)(path.config.lineWidth_um * .90);

				if (path.points.Count > 1)
				{
					for (int pointIndex = path.points.Count - 1; pointIndex > 0; pointIndex--)
					{
						// Calculate distance between 2 points
						currentDistance = (path.points[pointIndex] - path.points[pointIndex - 1]).Length();

						// If distance exceeds clip distance:
						//  - Sets the new last path point
						if (currentDistance > targetDistance)
						{
							long newDistance = currentDistance - targetDistance;

							Point3 dir = path.points[pointIndex] - path.points[pointIndex - 1] * newDistance / currentDistance;

							Point3 clippedEndpoint = path.points[pointIndex - 1] + dir;

							path.points[pointIndex] = clippedEndpoint;
							break;
						}
						else if (currentDistance == targetDistance)
						{
							// Pops off last point because it is at the limit distance
							path.points.RemoveAt(path.points.Count - 1);
							break;
						}
						else
						{
							// Pops last point and reduces distance remaining to target
							targetDistance = targetDistance - currentDistance;
							path.points.RemoveAt(path.points.Count - 1);
						}
					}
				}
			}
		}
예제 #8
0
		private bool RemoveDoubleDrawPerimeterLines(GCodePath path, double speed)
		{
			return false;
			if (path.config.lineWidth_um > 0
				&& path.points.Count > 2 // If the count is not greater than 2 there is no way it can ovelap itself.
				&& gcodeExport.GetPosition() == path.points[path.points.Count - 1])
			{
				List<List<Point3>> pathsWithOverlapsRemoved = GetPathsWithOverlapsRemoved(path.points, path.config.lineWidth_um / 2);
				if (pathsWithOverlapsRemoved.Count > 0)
				{
					for (int polygonIndex = 0; polygonIndex < pathsWithOverlapsRemoved.Count; polygonIndex++)
					{
						int startIndex = 0;
						List<Point3> polygon = pathsWithOverlapsRemoved[polygonIndex];
						if (polygonIndex > 0)
						{
							gcodeExport.WriteMove(polygon[0], travelConfig.speed, 0);
							startIndex = 1; // We skip the first point in the next extrusion, because we just moved to it.
						}

						for (int pointIndex = startIndex; pointIndex < polygon.Count; pointIndex++)
						{
							gcodeExport.WriteMove(polygon[pointIndex], speed, path.config.lineWidth_um);
						}
					}
				}
			}
		}