public void QueueTravel(IntPoint positionToMoveTo) { GCodePath path = GetLatestPathWithConfig(travelConfig); if (forceRetraction) { path.Retract = true; forceRetraction = false; } if (PathFinder != null) { Polygon pathPolygon = new Polygon(); if (PathFinder.CreatePathInsideBoundary(LastPosition, positionToMoveTo, pathPolygon)) { IntPoint lastPathPosition = LastPosition; long lineLength_um = 0; // we can stay inside so move within the boundary for (int positionIndex = 0; positionIndex < pathPolygon.Count; positionIndex++) { path.polygon.Add(new IntPoint(pathPolygon[positionIndex], CurrentZ) { Width = 0 }); lineLength_um += (pathPolygon[positionIndex] - lastPathPosition).Length(); lastPathPosition = pathPolygon[positionIndex]; } // If the internal move is very long (> retractionMinimumDistance_um), do a retraction if (lineLength_um > retractionMinimumDistance_um) { path.Retract = true; } } else { if ((LastPosition - positionToMoveTo).LongerThen(retractionMinimumDistance_um)) { // We are moving relatively far and are going to cross a boundary so do a retraction. path.Retract = true; } } } else { if ((LastPosition - positionToMoveTo).LongerThen(retractionMinimumDistance_um)) { path.Retract = true; } } path.polygon.Add(new IntPoint(positionToMoveTo, CurrentZ) { Width = 0, }); LastPosition = positionToMoveTo; //ValidatePaths(); }
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 overlap 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); } } } } }
public GCodePath(GCodePath copyPath) { this.config = copyPath.config; this.done = copyPath.done; this.extruderIndex = copyPath.extruderIndex; this.Retract = copyPath.Retract; this.points = new Polygon(copyPath.points); }
public GCodePath(GCodePath copyPath) { this.config = copyPath.config; this.Done = copyPath.Done; this.ExtruderIndex = copyPath.ExtruderIndex; this.Retract = copyPath.Retract; this.Polygon = new Polygon(copyPath.Polygon); }
public static GCodePath TrimGCodePathEnd(GCodePath inPath, long targetDistance) { GCodePath path = new GCodePath(inPath); // get a new trimmed polygon path.Polygon = path.Polygon.TrimEnd(targetDistance); return(path); }
public void QueueTravel(IntPoint positionToMoveTo) { GCodePath path = GetLatestPathWithConfig(travelConfig); if (forceRetraction) { path.Retract = true; forceRetraction = false; } else if (outerPerimetersToAvoidCrossing != null) { Polygon pointList = new Polygon(); if (outerPerimetersToAvoidCrossing.CreatePathInsideBoundary(LastPosition, positionToMoveTo, pointList)) { long lineLength_um = 0; // we can stay inside so move within the boundary for (int pointIndex = 0; pointIndex < pointList.Count; pointIndex++) { path.points.Add(new IntPoint(pointList[pointIndex], CurrentZ) { Width = 0 }); if (pointIndex > 0) { lineLength_um += (pointList[pointIndex] - pointList[pointIndex - 1]).Length(); } } // If the internal move is very long (20 mm), do a retraction anyway if (lineLength_um > retractionMinimumDistance_um) { path.Retract = true; } } else { if ((LastPosition - positionToMoveTo).LongerThen(retractionMinimumDistance_um)) { // We are moving relatively far and are going to cross a boundary so do a retraction. path.Retract = true; } } } else if (alwaysRetract) { if ((LastPosition - positionToMoveTo).LongerThen(retractionMinimumDistance_um)) { path.Retract = true; } } path.points.Add(new IntPoint(positionToMoveTo, CurrentZ) { Width = 0, }); LastPosition = positionToMoveTo; }
public void writeTravel(IntPoint positionToMoveTo) { GCodePath path = getLatestPathWithConfig(travelConfig); if (forceRetraction) { if (!(lastPosition - positionToMoveTo).ShorterThen(retractionMinimumDistance)) { path.retract = true; } forceRetraction = false; } else if (avaidCrossingPerimeters != null) { List <IntPoint> pointList = new List <IntPoint>(); if (avaidCrossingPerimeters.CreatePathInsideBoundary(lastPosition, positionToMoveTo, pointList)) { long lineLength = 0; // we can stay inside so move within the boundary for (int pointIndex = 0; pointIndex < pointList.Count; pointIndex++) { path.points.Add(pointList[pointIndex]); if (pointIndex > 0) { lineLength += (pointList[pointIndex] - pointList[pointIndex - 1]).Length(); } } // If the internal move is very long (20 mm), do a retration anyway if (lineLength > (20 * 1000)) { path.retract = true; } } else { if (!(lastPosition - positionToMoveTo).ShorterThen(retractionMinimumDistance)) { // We are moving relatively far and are going to cross a boundary so do a retraction. path.retract = true; } } } else if (alwaysRetract) { if (!(lastPosition - positionToMoveTo).ShorterThen(retractionMinimumDistance)) { path.retract = true; } } path.points.Add(positionToMoveTo); lastPosition = positionToMoveTo; }
private GCodePath GetNewPath(GCodePathConfig config) { GCodePath path = new GCodePath(); paths.Add(path); path.Retract = RetractType.None; path.ExtruderIndex = currentExtruderIndex; path.Done = false; path.Config = config; return(path); }
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); }
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); }
private static void TrimPerimeterIfNeeded(GCodePath path) { if (path.config.gcodeComment == "WALL-OUTER" || path.config.gcodeComment == "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); } } } } }
public static GCodePath TrimPerimeter(GCodePath inPath, double perimeterStartEndOverlapRatio) { GCodePath path = new GCodePath(inPath); 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 (targetDistance > 50) // Don't clip segments less than 50 um. We get too much truncation error. { IntPoint dir = (path.points[pointIndex] - path.points[pointIndex - 1]) * newDistance / currentDistance; IntPoint 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); } } } return(path); }
GCodePath getLatestPathWithConfig(GCodePathConfig config) { if (paths.Count > 0 && paths[paths.Count - 1].config == config && !paths[paths.Count - 1].done) { return(paths[paths.Count - 1]); } paths.Add(new GCodePath()); GCodePath ret = paths[paths.Count - 1]; ret.Retract = false; ret.config = config; ret.extruderIndex = currentExtruderIndex; ret.done = false; return(ret); }
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); } } } } }
public void CorrectLayerTimeConsideringMinimumLayerTime(double minTime, int minimumPrintingSpeed) { IntPoint lastPosition = gcodeExport.GetPosition(); double travelTime = 0.0; double extrudeTime = 0.0; for (int pathIndex = 0; pathIndex < paths.Count; pathIndex++) { GCodePath path = paths[pathIndex]; for (int pointIndex = 0; pointIndex < path.Polygon.Count; pointIndex++) { IntPoint currentPosition = path.Polygon[pointIndex]; double thisTime = (lastPosition - currentPosition).LengthMm() / (double)(path.config.speed); if (path.config.lineWidth_um != 0) { extrudeTime += thisTime; } else { travelTime += thisTime; } lastPosition = currentPosition; } } gcodeExport.LayerTime = extrudeTime + travelTime; if (gcodeExport.LayerTime < minTime && extrudeTime > 0.0) { double minExtrudeTime = minTime - travelTime; if (minExtrudeTime < 1) { minExtrudeTime = 1; } gcodeExport.LayerSpeedRatio = GetNewLayerSpeedRatio(minimumPrintingSpeed, extrudeTime, minExtrudeTime); gcodeExport.LayerTime = (extrudeTime / gcodeExport.LayerSpeedRatio) + travelTime; } this.totalPrintTime = gcodeExport.LayerTime; }
public void writeGCode(bool liftHeadIfNeeded, int layerThickness) { GCodePathConfig lastConfig = null; int extruderIndex = gcode.getExtruderIndex(); for (int pathIndex = 0; pathIndex < paths.Count; pathIndex++) { GCodePath path = paths[pathIndex]; if (extruderIndex != path.extruderIndex) { extruderIndex = path.extruderIndex; gcode.switchExtruder(extruderIndex); } else if (path.Retract) { gcode.writeRetraction(); } if (path.config != travelConfig && lastConfig != path.config) { gcode.writeComment("TYPE:{0}".FormatWith(path.config.name)); lastConfig = path.config; } int speed = path.config.speed; if (path.config.lineWidth != 0) { // Only apply the extrudeSpeedFactor to extrusion moves speed = speed * extrudeSpeedFactor / 100; } else { speed = speed * travelSpeedFactor / 100; } if (path.points.Count == 1 && path.config != travelConfig && (gcode.getPositionXY() - path.points[0]).ShorterThen(path.config.lineWidth * 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 * 2)) { nextPosition = paths[i].points[0]; i++; } if (paths[i - 1].config == travelConfig) { i--; } if (i > pathIndex + 2) { nextPosition = gcode.getPositionXY(); for (int x = pathIndex; x < i - 1; x += 2) { long oldLen = (nextPosition - paths[x].points[0]).vSize(); IntPoint newPoint = (paths[x].points[0] + paths[x + 1].points[0]) / 2; long newLen = (gcode.getPositionXY() - newPoint).vSize(); if (newLen > 0) { gcode.writeMove(newPoint, speed, (int)(path.config.lineWidth * oldLen / newLen)); } nextPosition = paths[x + 1].points[0]; } gcode.writeMove(paths[i - 1].points[0], speed, path.config.lineWidth); 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 need to spiralize then raise the head slowly by 1 layer as this path progresses. double totalLength = 0; int z = gcode.getPositionZ(); IntPoint currentPosition = gcode.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 = gcode.getPositionXY(); for (int i = 0; i < path.points.Count; i++) { IntPoint nextPosition = path.points[i]; length += (currentPosition - nextPosition).LengthMm(); currentPosition = nextPosition; gcode.setZ((int)(z + layerThickness * length / totalLength + .5)); gcode.writeMove(path.points[i], speed, path.config.lineWidth); } } else { for (int pointIndex = 0; pointIndex < path.points.Count; pointIndex++) { gcode.writeMove(path.points[pointIndex], speed, path.config.lineWidth); } } } gcode.updateTotalPrintTime(); if (liftHeadIfNeeded && extraTime > 0.0) { gcode.writeComment("Small layer, adding delay of {0}".FormatWith(extraTime)); gcode.writeRetraction(); gcode.setZ(gcode.getPositionZ() + 3000); gcode.writeMove(gcode.getPositionXY(), travelConfig.speed, 0); gcode.writeMove(gcode.getPositionXY() - new IntPoint(-20000, 0), travelConfig.speed, 0); gcode.writeDelay(extraTime); } }
public void forceMinimumLayerTime(double minTime, int minimumPrintingSpeed) { IntPoint lastPosition = gcode.getPositionXY(); double travelTime = 0.0; double extrudeTime = 0.0; for (int n = 0; n < paths.Count; n++) { GCodePath path = paths[n]; for (int pointIndex = 0; pointIndex < path.points.Count; pointIndex++) { IntPoint currentPosition = path.points[pointIndex]; double thisTime = (lastPosition - currentPosition).LengthMm() / (double)(path.config.speed); if (path.config.lineWidth != 0) { extrudeTime += thisTime; } else { travelTime += thisTime; } lastPosition = currentPosition; } } double totalTime = extrudeTime + travelTime; if (totalTime < minTime && extrudeTime > 0.0) { double minExtrudeTime = minTime - travelTime; if (minExtrudeTime < 1) { minExtrudeTime = 1; } double factor = extrudeTime / minExtrudeTime; for (int n = 0; n < paths.Count; n++) { GCodePath path = paths[n]; if (path.config.lineWidth == 0) { continue; } int speed = (int)(path.config.speed * factor); if (speed < minimumPrintingSpeed) { factor = (double)(minimumPrintingSpeed) / (double)(path.config.speed); } } //Only slow down with the minimum time if that will be slower then a factor already set. First layer slowdown also sets the speed factor. if (factor * 100 < getExtrudeSpeedFactor()) { setExtrudeSpeedFactor((int)(factor * 100)); } else { factor = getExtrudeSpeedFactor() / 100.0; } if (minTime - (extrudeTime / factor) - travelTime > 0.1) { //TODO: Use up this extra time (circle around the print?) this.extraTime = minTime - (extrudeTime / factor) - travelTime; } this.totalPrintTime = (extrudeTime / factor) + travelTime; } else { this.totalPrintTime = totalTime; } }
public void WriteGCode(bool liftHeadIfNeeded, int layerThickness) { GCodePathConfig lastConfig = null; int extruderIndex = gcode.GetExtruderIndex(); for (int pathIndex = 0; pathIndex < paths.Count; pathIndex++) { GCodePath path = paths[pathIndex]; if (extruderIndex != path.extruderIndex) { extruderIndex = path.extruderIndex; gcode.SwitchExtruder(extruderIndex); } else if (path.Retract) { gcode.WriteRetraction(); } if (path.config != travelConfig && lastConfig != path.config) { //gcode.WriteComment("TYPE:{0}".FormatWith(path.config.gcodeComment)); lastConfig = path.config; ////后加的//只是边框,不填充。 if ((path.config.gcodeComment == "SKIRT") || (path.config.gcodeComment == "FILL") || (path.config.gcodeComment == "TOP-FILL")) { return; } } double speed = path.config.speed; if (path.config.lineWidth != 0) { // Only apply the extrudeSpeedFactor to extrusion moves speed = speed * extrudeSpeedFactor / 100; } else { speed = speed * travelSpeedFactor / 100; } if (path.points.Count == 1 && path.config != travelConfig && (gcode.GetPositionXY() - path.points[0]).ShorterThen(path.config.lineWidth * 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 * 2)) { nextPosition = paths[i].points[0]; i++; } if (paths[i - 1].config == travelConfig) { i--; } if (i > pathIndex + 2) { nextPosition = gcode.GetPositionXY(); 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 = (gcode.GetPositionXY() - newPoint).Length(); if (newLen > 0) { gcode.WriteMove(newPoint, speed, (int)(path.config.lineWidth * oldLen / newLen)); } nextPosition = paths[x + 1].points[0]; } gcode.WriteMove(paths[i - 1].points[0], speed, path.config.lineWidth); 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 need to spiralize then raise the head slowly by 1 layer as this path progresses. double totalLength = 0; int z = gcode.GetPositionZ(); IntPoint currentPosition = gcode.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 = gcode.GetPositionXY(); for (int i = 0; i < path.points.Count; i++) { IntPoint nextPosition = path.points[i]; length += (currentPosition - nextPosition).LengthMm(); currentPosition = nextPosition; gcode.setZ((int)(z + layerThickness * length / totalLength + .5)); gcode.WriteMove(path.points[i], speed, path.config.lineWidth); } } else { #if false // This is test code to remove double drawn small perimeter lines. if (path.config.lineWidth > 0 && path.points.Count > 2 && // If the count is not greater than 2 there is no way it can ovelap itself. gcode.GetPositionXY() == path.points[path.points.Count - 1]) { Polygons pathsWithOverlapsRemoved = GetPathsWithOverlapsRemoved(path.points, path.config.lineWidth / 2); if (pathsWithOverlapsRemoved.Count > 0) { for (int polygonIndex = 0; polygonIndex < pathsWithOverlapsRemoved.Count; polygonIndex++) { int startIndex = 0; Polygon polygon = pathsWithOverlapsRemoved[polygonIndex]; if (polygonIndex > 0) { gcode.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++) { gcode.WriteMove(polygon[pointIndex], speed, path.config.lineWidth); } } } } else #endif { //TrimPerimeterIfNeeded(path); for (int i = 0; i < path.points.Count; i++) { gcode.WriteMove(path.points[i], speed, path.config.lineWidth); } } } } gcode.UpdateTotalPrintTime(); if (liftHeadIfNeeded && extraTime > 0.0) { gcode.WriteComment("Small layer, adding delay of {0}".FormatWith(extraTime)); gcode.WriteRetraction(); gcode.setZ(gcode.GetPositionZ() + 3000); gcode.WriteMove(gcode.GetPositionXY(), travelConfig.speed, 0); gcode.WriteMove(gcode.GetPositionXY() - new IntPoint(-20000, 0), travelConfig.speed, 0); gcode.WriteDelay(extraTime); } }
public void WriteQueuedGCode(int layerThickness) { 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) { gcodeExport.WriteComment("TYPE:{0}".FormatWith(path.config.gcodeComment)); lastConfig = path.config; } double speed = path.config.speed; if (path.config.lineWidth_um != 0) { // Only apply the extrudeSpeedFactor to extrusion moves speed = speed * extrudeSpeedFactor / 100; } else { speed = speed * travelSpeedFactor / 100; } if (path.points.Count == 1 && path.config != travelConfig && (gcodeExport.GetPositionXY() - path.points[0].XYPoint).ShorterThen(path.config.lineWidth_um * 2)) { //Check for lots of small moves and combine them into one large line Point3 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(); Point3 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]; } gcodeExport.WriteMove(paths[i - 1].points[0], speed, path.config.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].XYPoint; 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].XYPoint; length += (currentPosition - nextPosition).LengthMm(); currentPosition = nextPosition; Point3 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. if (RemoveDoubleDrawPerimeterLines(path, speed)) { return; } else { //TrimPerimeterIfNeeded(path); for (int i = 0; i < path.points.Count; i++) { gcodeExport.WriteMove(path.points[i], speed, path.config.lineWidth_um); } } } } gcodeExport.UpdateTotalPrintTime(); }
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].XYPoint).ShorterThen(path.config.lineWidth_um * 2)) { //Check for lots of small moves and combine them into one large line Point3 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(); Point3 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]; } gcodeExport.WriteMove(paths[i - 1].points[0], speed, path.config.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].XYPoint; 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].XYPoint; length += (currentPosition - nextPosition).LengthMm(); currentPosition = nextPosition; Point3 nextExtrusion = path.points[i]; nextExtrusion.z = (int)(z + layerThickness * length / totalLength + .5); gcodeExport.WriteMove(nextExtrusion, speed, path.config.lineWidth_um); } } else { bool pathIsClosed = true; if (perimeterStartEndOverlapRatio < 1) { pathIsClosed = !TrimPerimeterIfNeeded(path, perimeterStartEndOverlapRatio); } // This is test code to remove double drawn small perimeter lines. List <PathAndWidth> pathsWithOverlapsRemoved; if (RemovePerimetersThatOverlap(path, speed, out pathsWithOverlapsRemoved, pathIsClosed)) { for (int polygonIndex = 0; polygonIndex < pathsWithOverlapsRemoved.Count; polygonIndex++) { PathAndWidth polygon = pathsWithOverlapsRemoved[polygonIndex]; if (polygon.Path.Count == 2) { // make sure the path is ordered with the first point the closest to where we are now Point3 currentPosition = gcodeExport.GetPosition(); // if the second point is closer swap them if ((polygon.Path[1] - currentPosition).LengthSquared() < (polygon.Path[0] - currentPosition).LengthSquared()) { // swap them Point3 temp = polygon.Path[0]; polygon.Path[0] = polygon.Path[1]; polygon.Path[1] = temp; } } // move to the start of this polygon gcodeExport.WriteMove(polygon.Path[0], travelConfig.speed, 0); // write all the data for the polygon for (int pointIndex = 1; pointIndex < polygon.Path.Count; pointIndex++) { gcodeExport.WriteMove(polygon.Path[pointIndex], speed, polygon.ExtrusionWidthUm); } } } else { for (int i = 0; i < path.points.Count; i++) { gcodeExport.WriteMove(path.points[i], speed, path.config.lineWidth_um); } } } } gcodeExport.UpdateTotalPrintTime(); }
public void QueueTravel(IntPoint positionToMoveTo, bool forceUniquePath = false) { GCodePath path = GetLatestPathWithConfig(travelConfig, forceUniquePath || !canAppendTravel); canAppendTravel = !forceUniquePath; if (forceRetraction) { path.Retract = RetractType.Force; forceRetraction = false; } if (PathFinder != null) { Polygon pathPolygon = new Polygon(); if (PathFinder.CreatePathInsideBoundary(LastPosition, positionToMoveTo, pathPolygon, true, gcodeExport.LayerIndex)) { IntPoint lastPathPosition = LastPosition; long lineLength_um = 0; if (pathPolygon.Count > 0) { // we can stay inside so move within the boundary for (int positionIndex = 0; positionIndex < pathPolygon.Count; positionIndex++) { path.Polygon.Add(new IntPoint(pathPolygon[positionIndex], CurrentZ) { Width = 0 }); lineLength_um += (pathPolygon[positionIndex] - lastPathPosition).Length(); lastPathPosition = pathPolygon[positionIndex]; } // If the internal move is very long (> retractionMinimumDistance_um), do a retraction if (lineLength_um > retractionMinimumDistance_um) { path.Retract = RetractType.Requested; } } // else the path is good it just goes directly to the positionToMoveTo } else if ((LastPosition - positionToMoveTo).LongerThen(retractionMinimumDistance_um / 10)) { // can't find a good path and moving more than a very little bit path.Retract = RetractType.Requested; } } // Always check if the distance is greater than the amount need to retract. if ((LastPosition - positionToMoveTo).LongerThen(retractionMinimumDistance_um)) { path.Retract = RetractType.Requested; } path.Polygon.Add(new IntPoint(positionToMoveTo, CurrentZ) { Width = 0, }); LastPosition = positionToMoveTo; //ValidatePaths(); }
bool PathCanAdjustSpeed(GCodePath path) { return(path.Config.LineWidthUM > 0 && path.Config.GCodeComment != "BRIDGE"); }
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(); }
bool PathCanAdjustSpeed(GCodePath path) { return(path.Config.lineWidth_um > 0 && path.Config.gcodeComment != "BRIDGE"); }
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.polygon.Count == 1 && path.config != travelConfig && (gcodeExport.GetPositionXY() - path.polygon[0]).ShorterThen(path.config.lineWidth_um * 2)) { //Check for lots of small moves and combine them into one large line IntPoint nextPosition = path.polygon[0]; int i = pathIndex + 1; while (i < paths.Count && paths[i].polygon.Count == 1 && (nextPosition - paths[i].polygon[0]).ShorterThen(path.config.lineWidth_um * 2)) { nextPosition = paths[i].polygon[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].polygon[0]).Length(); IntPoint newPoint = (paths[x].polygon[0] + paths[x + 1].polygon[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].polygon[0]; } long lineWidth_um = path.config.lineWidth_um; if (paths[i - 1].polygon[0].Width != 0) { lineWidth_um = paths[i - 1].polygon[0].Width; } gcodeExport.WriteMove(paths[i - 1].polygon[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.polygon.Count; pointIndex++) { IntPoint nextPosition = path.polygon[pointIndex]; totalLength += (currentPosition - nextPosition).LengthMm(); currentPosition = nextPosition; } double length = 0.0; currentPosition = gcodeExport.GetPositionXY(); for (int i = 0; i < path.polygon.Count; i++) { IntPoint nextPosition = path.polygon[i]; length += (currentPosition - nextPosition).LengthMm(); currentPosition = nextPosition; IntPoint nextExtrusion = path.polygon[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. if (path.config.gcodeComment == "WALL-OUTER" || path.config.gcodeComment == "WALL-INNER") { //string perimeterString = Newtonsoft.Json.JsonConvert.SerializeObject(path); if (perimeterStartEndOverlapRatio < 1) { path = TrimPerimeter(path, perimeterStartEndOverlapRatio); } } int outputCount = path.polygon.Count; for (int i = 0; i < outputCount; i++) { long lineWidth_um = path.config.lineWidth_um; if (path.polygon[i].Width != 0) { lineWidth_um = path.polygon[i].Width; } gcodeExport.WriteMove(path.polygon[i], speed, lineWidth_um); } } } gcodeExport.UpdateTotalPrintTime(); }