public static void ApplyMatrix(this Polygons polygons, PointMatrix matrix) { for (int i = 0; i < polygons.Count; i++) { for (int j = 0; j < polygons[i].Count; j++) { polygons[i][j] = matrix.apply(polygons[i][j]); } } }
public static bool polygonCollidesWithlineSegment(Polygon poly, 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(poly, transformed_startPoint, transformed_endPoint, transformation_matrix)); }
public static void GenerateLinePaths(Polygons polygonToInfill, Polygons infillLinesToPrint, long lineSpacing_um, long infillExtendIntoPerimeter_um, double rotation, long rotationOffset = 0, int speed = 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_um) - 1) * lineSpacing_um - rotationOffset; int xLineCount = (int)((boundary.max.X - boundary.min.X + (lineSpacing_um - 1)) / lineSpacing_um); Polygons unclippedPattern = new Polygons(); long firstX = boundary.min.X / lineSpacing_um * lineSpacing_um; for (int lineIndex = 0; lineIndex < xLineCount; lineIndex++) { Polygon line = new Polygon(); line.Add(new IntPoint(firstX + lineIndex * lineSpacing_um, boundary.min.Y) { Speed = speed }); line.Add(new IntPoint(firstX + lineIndex * lineSpacing_um, boundary.max.Y) { Speed = speed }); unclippedPattern.Add(line); } PolyTree ret = new PolyTree(); Clipper clipper = new Clipper(); clipper.AddPaths(unclippedPattern, 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); } } }
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); } } }
public static void GenerateLinePaths(Polygons in_outline, ref Polygons result, int extrusionWidth_um, int lineSpacing, int infillExtendIntoPerimeter_um, double rotation, long rotationOffset = 0) { if (in_outline.Count > 0) { Polygons outlines = in_outline.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 lineCount = (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 < lineCount; 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); result.AddRange(newSegments); } } }
bool collisionTest(IntPoint startPoint, IntPoint endPoint) { IntPoint diff = endPoint - startPoint; matrix = new PointMatrix(diff); this.nomalizedStartPoint = matrix.apply(startPoint); this.normalizedEndPoint = matrix.apply(endPoint); for (int bounderyIndex = 0; bounderyIndex < bounderyPolygons.Count; bounderyIndex++) { Polygon boundryPolygon = bounderyPolygons[bounderyIndex]; if (boundryPolygon.Count < 1) { continue; } IntPoint lastPosition = matrix.apply(boundryPolygon[boundryPolygon.Count - 1]); for (int pointIndex = 0; pointIndex < boundryPolygon.Count; pointIndex++) { IntPoint currentPosition = matrix.apply(boundryPolygon[pointIndex]); if ((lastPosition.Y > nomalizedStartPoint.Y && currentPosition.Y < nomalizedStartPoint.Y) || (currentPosition.Y > nomalizedStartPoint.Y && lastPosition.Y < nomalizedStartPoint.Y)) { long x = lastPosition.X + (currentPosition.X - lastPosition.X) * (nomalizedStartPoint.Y - lastPosition.Y) / (currentPosition.Y - lastPosition.Y); if (x > nomalizedStartPoint.X && x < normalizedEndPoint.X) { return(true); } } lastPosition = currentPosition; } } return(false); }
public static void GenerateHexLinePaths(Polygons in_outline, ref 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 plusses 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); } } }
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); }
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; }
public bool CreatePathInsideBoundary(IntPoint startPoint, IntPoint endPoint, List <IntPoint> pathThatIsInside) { if (saveDebugData) { using (StreamWriter sw = File.AppendText("test.txt")) { if (boundry) { string pointsString = bounderyPolygons.WriteToString(); sw.WriteLine(pointsString); } sw.WriteLine(startPoint.ToString() + " " + endPoint.ToString()); } } if ((endPoint - startPoint).ShorterThen(1500)) { // If the movement is very short (not a lot of time to ooze filament) // then don't add any points return(true); } bool addEndpoint = false; //Check if we are inside the comb boundaries if (!PointIsInsideBoundary(startPoint)) { if (!MovePointInsideBoundary(ref startPoint)) { //If we fail to move the point inside the comb boundary we need to retract. return(false); } pathThatIsInside.Add(startPoint); } if (!PointIsInsideBoundary(endPoint)) { if (!MovePointInsideBoundary(ref endPoint)) { //If we fail to move the point inside the comb boundary we need to retract. return(false); } addEndpoint = true; } // Check if we are crossing any bounderies if (!DoesLineCrossBoundery(startPoint, endPoint)) { //We're not crossing any boundaries. So skip the comb generation. if (!addEndpoint && pathThatIsInside.Count == 0) { //Only skip if we didn't move the start and end point. return(true); } } // Calculate the matrix to change points so they are in the direction of the line segment. { IntPoint diff = endPoint - startPoint; lineToSameYMatrix = new PointMatrix(diff); this.rotatedStartPoint = lineToSameYMatrix.apply(startPoint); this.rotatedEndPoint = lineToSameYMatrix.apply(endPoint); } // Calculate the minimum and maximum positions where we cross the comb boundary CalcMinMax(); long nomalizedStartX = rotatedStartPoint.X; List <IntPoint> pointList = new List <IntPoint>(); // Now walk trough the crossings, for every boundary we cross, find the initial cross point and the exit point. // Then add all the points in between to the pointList and continue with the next boundary we will cross, // until there are no more boundaries to cross. // This gives a path from the start to finish curved around the holes that it encounters. while (true) { // if we go up enough we should run into the boundry int abovePolyIndex = GetPolygonIndexAbove(nomalizedStartX); if (abovePolyIndex < 0) { break; } pointList.Add(lineToSameYMatrix.unapply(new IntPoint(minXPosition[abovePolyIndex] - 200, rotatedStartPoint.Y))); if ((indexOfMinX[abovePolyIndex] - indexOfMaxX[abovePolyIndex] + bounderyPolygons[abovePolyIndex].Count) % bounderyPolygons[abovePolyIndex].Count > (indexOfMaxX[abovePolyIndex] - indexOfMinX[abovePolyIndex] + bounderyPolygons[abovePolyIndex].Count) % bounderyPolygons[abovePolyIndex].Count) { for (int i = indexOfMinX[abovePolyIndex]; i != indexOfMaxX[abovePolyIndex]; i = (i < bounderyPolygons[abovePolyIndex].Count - 1) ? (i + 1) : (0)) { pointList.Add(GetBounderyPointWithOffset(abovePolyIndex, i)); } } else { indexOfMinX[abovePolyIndex]--; if (indexOfMinX[abovePolyIndex] == -1) { indexOfMinX[abovePolyIndex] = bounderyPolygons[abovePolyIndex].Count - 1; } indexOfMaxX[abovePolyIndex]--; if (indexOfMaxX[abovePolyIndex] == -1) { indexOfMaxX[abovePolyIndex] = bounderyPolygons[abovePolyIndex].Count - 1; } for (int i = indexOfMinX[abovePolyIndex]; i != indexOfMaxX[abovePolyIndex]; i = (i > 0) ? (i - 1) : (bounderyPolygons[abovePolyIndex].Count - 1)) { pointList.Add(GetBounderyPointWithOffset(abovePolyIndex, i)); } } pointList.Add(lineToSameYMatrix.unapply(new IntPoint(maxXPosition[abovePolyIndex] + 200, rotatedStartPoint.Y))); nomalizedStartX = maxXPosition[abovePolyIndex]; } pointList.Add(endPoint); if (addEndpoint) { pointList.Add(endPoint); } #if false // Optimize the pointList, skip each point we could already reach by connecting directly to the next point. for (int startIndex = 0; startIndex < pointList.Count - 2; startIndex++) { IntPoint startPosition = pointList[startIndex]; // make sure there is at least one point between the start and the end to optomize if (pointList.Count > startIndex + 2) { for (int checkIndex = pointList.Count - 1; checkIndex > startIndex + 1; checkIndex--) { IntPoint checkPosition = pointList[checkIndex]; if (!DoesLineCrossBoundery(startPosition, checkPosition)) { // Remove all the points from startIndex+1 to checkIndex-1, inclusive. for (int i = startIndex + 1; i < checkIndex; i++) { pointList.RemoveAt(startIndex + 1); } // we removed all the points up to start so we are done with the inner loop break; } } } } #endif foreach (IntPoint point in pointList) { pathThatIsInside.Add(point); } return(true); }
public static bool polygonCollidesWithlineSegment(Polygon poly, IntPoint transformed_startPoint, IntPoint transformed_endPoint, PointMatrix transformation_matrix) { IntPoint p0 = transformation_matrix.apply(poly.back()); foreach (IntPoint p1_ in poly) { IntPoint p1 = transformation_matrix.apply(p1_); if ((p0.Y >= transformed_startPoint.Y && p1.Y <= transformed_startPoint.Y) || (p1.Y >= transformed_startPoint.Y && p0.Y <= transformed_startPoint.Y)) { long x; if (p1.Y == p0.Y) { x = p0.X; } else { x = p0.X + (p1.X - p0.X) * (transformed_startPoint.Y - p0.Y) / (p1.Y - p0.Y); } if (x >= transformed_startPoint.X && x <= transformed_endPoint.X) { return(true); } } p0 = p1; } return(false); }
public bool CreatePathInsideBoundary(IntPoint startPoint, IntPoint endPoint, List<IntPoint> pathThatIsInside) { if (saveDebugData) { using (StreamWriter sw = File.AppendText("test.txt")) { if (boundry) { string pointsString = bounderyPolygons.WriteToString(); sw.WriteLine(pointsString); } sw.WriteLine(startPoint.ToString() + " " + endPoint.ToString()); } } if ((endPoint - startPoint).ShorterThen(1500)) { // If the movement is very short (not a lot of time to ooze filament) // then don't add any points return true; } bool addEndpoint = false; //Check if we are inside the comb boundaries if (!PointIsInsideBoundary(startPoint)) { if (!MovePointInsideBoundary(ref startPoint)) { //If we fail to move the point inside the comb boundary we need to retract. return false; } pathThatIsInside.Add(startPoint); } if (!PointIsInsideBoundary(endPoint)) { if (!MovePointInsideBoundary(ref endPoint)) { //If we fail to move the point inside the comb boundary we need to retract. return false; } addEndpoint = true; } // Check if we are crossing any bounderies if (!DoesLineCrossBoundery(startPoint, endPoint)) { //We're not crossing any boundaries. So skip the comb generation. if (!addEndpoint && pathThatIsInside.Count == 0) { //Only skip if we didn't move the start and end point. return true; } } // Calculate the matrix to change points so they are in the direction of the line segment. { IntPoint diff = endPoint - startPoint; lineToSameYMatrix = new PointMatrix(diff); this.rotatedStartPoint = lineToSameYMatrix.apply(startPoint); this.rotatedEndPoint = lineToSameYMatrix.apply(endPoint); } // Calculate the minimum and maximum positions where we cross the comb boundary CalcMinMax(); long nomalizedStartX = rotatedStartPoint.X; List<IntPoint> pointList = new List<IntPoint>(); // Now walk trough the crossings, for every boundary we cross, find the initial cross point and the exit point. // Then add all the points in between to the pointList and continue with the next boundary we will cross, // until there are no more boundaries to cross. // This gives a path from the start to finish curved around the holes that it encounters. while (true) { // if we go up enough we should run into the boundry int abovePolyIndex = GetPolygonIndexAbove(nomalizedStartX); if (abovePolyIndex < 0) { break; } pointList.Add(lineToSameYMatrix.unapply(new IntPoint(minXPosition[abovePolyIndex] - 200, rotatedStartPoint.Y))); if ((indexOfMinX[abovePolyIndex] - indexOfMaxX[abovePolyIndex] + bounderyPolygons[abovePolyIndex].Count) % bounderyPolygons[abovePolyIndex].Count > (indexOfMaxX[abovePolyIndex] - indexOfMinX[abovePolyIndex] + bounderyPolygons[abovePolyIndex].Count) % bounderyPolygons[abovePolyIndex].Count) { for (int i = indexOfMinX[abovePolyIndex]; i != indexOfMaxX[abovePolyIndex]; i = (i < bounderyPolygons[abovePolyIndex].Count - 1) ? (i + 1) : (0)) { pointList.Add(GetBounderyPointWithOffset(abovePolyIndex, i)); } } else { indexOfMinX[abovePolyIndex]--; if (indexOfMinX[abovePolyIndex] == -1) { indexOfMinX[abovePolyIndex] = bounderyPolygons[abovePolyIndex].Count - 1; } indexOfMaxX[abovePolyIndex]--; if (indexOfMaxX[abovePolyIndex] == -1) { indexOfMaxX[abovePolyIndex] = bounderyPolygons[abovePolyIndex].Count - 1; } for (int i = indexOfMinX[abovePolyIndex]; i != indexOfMaxX[abovePolyIndex]; i = (i > 0) ? (i - 1) : (bounderyPolygons[abovePolyIndex].Count - 1)) { pointList.Add(GetBounderyPointWithOffset(abovePolyIndex, i)); } } pointList.Add(lineToSameYMatrix.unapply(new IntPoint(maxXPosition[abovePolyIndex] + 200, rotatedStartPoint.Y))); nomalizedStartX = maxXPosition[abovePolyIndex]; } pointList.Add(endPoint); if (addEndpoint) { pointList.Add(endPoint); } #if false // Optimize the pointList, skip each point we could already reach by connecting directly to the next point. for (int startIndex = 0; startIndex < pointList.Count - 2; startIndex++) { IntPoint startPosition = pointList[startIndex]; // make sure there is at least one point between the start and the end to optomize if (pointList.Count > startIndex + 2) { for (int checkIndex = pointList.Count - 1; checkIndex > startIndex + 1; checkIndex--) { IntPoint checkPosition = pointList[checkIndex]; if (!DoesLineCrossBoundery(startPosition, checkPosition)) { // Remove all the points from startIndex+1 to checkIndex-1, inclusive. for (int i = startIndex + 1; i < checkIndex; i++) { pointList.RemoveAt(startIndex + 1); } // we removed all the points up to start so we are done with the inner loop break; } } } } #endif foreach (IntPoint point in pointList) { pathThatIsInside.Add(point); } return true; }
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); }
public static bool polygonCollidesWithlineSegment(Polygon poly, IntPoint transformed_startPoint, IntPoint transformed_endPoint, PointMatrix transformation_matrix) { IntPoint p0 = transformation_matrix.apply(poly.back()); foreach (IntPoint p1_ in poly) { IntPoint p1 = transformation_matrix.apply(p1_); if ((p0.Y >= transformed_startPoint.Y && p1.Y <= transformed_startPoint.Y) || (p1.Y >= transformed_startPoint.Y && p0.Y <= transformed_startPoint.Y)) { long x; if (p1.Y == p0.Y) { x = p0.X; } else { x = p0.X + (p1.X - p0.X) * (transformed_startPoint.Y - p0.Y) / (p1.Y - p0.Y); } if (x >= transformed_startPoint.X && x <= transformed_endPoint.X) return true; } p0 = p1; } return false; }