protected int figureId; // track GCode figure-id public PathObject Copy() { if (this is ItemDot) { ItemDot n = new ItemDot(this.Start.X, this.Start.Y); n.info = this.info.Copy(); n.pathLength = this.pathLength; n.distance = this.distance; n.start = this.start; n.startAngle = this.startAngle; n.end = this.end; return(n); } else { ItemPath n = new ItemPath(); n.info = this.info.Copy(); if (((ItemPath)this).dashArray.Length > 0) { n.dashArray = new double[((ItemPath)this).dashArray.Length]; ((ItemPath)this).dashArray.CopyTo(n.dashArray, 0); } foreach (GCodeMotion motion in ((ItemPath)this).path) { if (motion is GCodeLine) { n.AddMotion(new GCodeLine((GCodeLine)motion)); } else if (motion is GCodeArc) { n.AddMotion(new GCodeArc((GCodeArc)motion)); } } n.pathLength = this.pathLength; n.distance = this.distance; n.start = this.start; n.startAngle = this.startAngle; n.end = this.end; n.dimension = new Dimensions(this.dimension); return(n); } }
//convert graphic to gcode ################################################################## private static void ProcessPathObject(PathObject pathObject, Graphic.GraphicInformation graphicInfo) { if (logDetailed) { Logger.Trace("ProcessPathObject start"); } figureEnable = graphicInfo.FigureEnable; float origZ = gcode.gcodeZDown; /* Create Dot */ if (pathObject is ItemDot) { ItemDot DotData = (ItemDot)pathObject; if (DotData.UseZ) { double setZ = calculateZFromRange(graphicInfo.DotZMin, graphicInfo.DotZMax, DotData.Z);//-Math.Abs(DotData.Z); // be sure for right sign if (logEnable) { Logger.Trace("---Dot DotData.UseZ: RangeMin:{0:0.00} RangeMax:{1:0.00} DotData.Z:{2:0.00} -> setZ:{3:0.00}", graphicInfo.DotZMin, graphicInfo.DotZMax, DotData.Z, setZ); } setZ = Math.Max(origZ, setZ); // don't go deeper than set Z if (logCoordinates) { Logger.Trace(" PenDownWithZ z:{0:0.00} setZ:{1:0.00} gcodeZDown:{2:0.00}", DotData.Z, setZ, origZ); } gcode.gcodeZDown = (float)setZ; penIsDown = false; } else if (graphicInfo.OptionZFromWidth) { double newZ = calculateZFromRange(graphicInfo.PenWidthMin, graphicInfo.PenWidthMax, DotData.Z); if (logEnable) { Logger.Trace("---Dot OptionZFromWidth: RangeMin:{0:0.00} RangeMax:{1:0.00} DotData.Z:{2:0.00} -> setZ:{3:0.00}", graphicInfo.PenWidthMin, graphicInfo.PenWidthMax, DotData.Z, newZ); } newZ = Math.Max(origZ, newZ); // don't go deeper than set Z gcode.gcodeZDown = (float)newZ; penIsDown = false; } pathObject.FigureId = StartPath(DotData); PenDown(); StopPath(); gcode.gcodeZDown = origZ; } else { if (graphicInfo.OptionZFromWidth) { gcode.gcodeZDown = 0; } ItemPath PathData = (ItemPath)pathObject; if (logDetailed) { Logger.Trace(" {0} cnt:{1}", PathData.Info.List(), PathData.path.Count); } if (PathData.path.Count == 0) { if (logEnable) { Logger.Trace("--ProcessPathObject: Empty path ID:{0}", PathData.Info.id); } return; } pathObject.FigureId = StartPath(PathData); PathDashArray = PathData.dashArray; double newZ = gcode.gcodeZDown; // default for (int index = 1; index < PathData.path.Count; index++) // 0 was already processed in StartPath { GCodeMotion entity = PathData.path[index]; if (graphicInfo.OptionZFromWidth) { newZ = calculateZFromRange(graphicInfo.PenWidthMin, graphicInfo.PenWidthMax, entity.Depth); newZ = Math.Max(origZ, newZ); // don't go deeper than set Z gcode.gcodeZDown = (float)newZ; if (!Properties.Settings.Default.importDepthFromWidthRamp) { penIsDown = false; } if (logEnable) { Logger.Trace("--ProcessPathObject: penWidth:{0:0.00} -> setZ:{1:0.00}", entity.Depth, newZ); } } /* Create Line */ if (entity is GCodeLine) { MoveTo(entity.MoveTo, newZ, entity.Angle, ""); } else if (entity is GCodeArc) { /* Create Arc */ GCodeArc ArcData = (GCodeArc)entity; Arc(ArcData.IsCW, ArcData.MoveTo, ArcData.CenterIJ, newZ, ArcData.AngleStart, ArcData.Angle, ""); // entity.comment); } } StopPath(""); } gcode.gcodeZDown = origZ; if (logDetailed) { Logger.Trace("ProcessPathObject end"); } }
public static void CalculateTangentialAxis() { const uint loggerSelect = (uint)LogEnable.PathModification; double maxAngleChangeDeg = (double)Properties.Settings.Default.importGCTangentialAngle; bool limitRange = Properties.Settings.Default.importGCTangentialRange; double maxAngleRad = maxAngleChangeDeg * Math.PI / 180; // in RAD double angleNow, angleLast, angleOffset, angleApply, angleLastApply; finalPathList = new List <PathObject>(); // figures of one tile ItemPath tempPath = new ItemPath(); Point pStart, pEnd; Logger.Trace("...CalculateTangentialAxis maxAngle:{0}", maxAngleChangeDeg); gcodeMath.resetAngles(); foreach (PathObject graphicItem in completeGraphic) { angleLast = angleApply = angleLastApply = 0; angleOffset = 0; if (!(graphicItem is ItemDot)) { ItemPath item = (ItemPath)graphicItem; if (item.path.Count == 0) { continue; } pStart = item.path[0].MoveTo; /* copy general info */ actualDashArray = new double[0]; if (item.dashArray.Length > 0) { actualDashArray = new double[item.dashArray.Length]; item.dashArray.CopyTo(actualDashArray, 0); } tempPath = new ItemPath(new Point(pStart.X, pStart.Y)); // create new path tempPath.Info.CopyData(graphicItem.Info); // preset global info for GROUP if (actualDashArray.Length > 0) // set dash array { tempPath.dashArray = new double[actualDashArray.Length]; actualDashArray.CopyTo(tempPath.dashArray, 0); } for (int i = 1; i < item.path.Count; i++) // go through path objects { pStart = item.path[i - 1].MoveTo; pEnd = item.path[i].MoveTo; /* Process Line */ if (item.path[i] is GCodeLine) { angleNow = gcodeMath.getAlpha(pStart, pEnd); // angle-i = p[i-1] to p[i] in radiant // if ((loggerTrace & loggerSelect) > 0) Logger.Trace(" TangentialAxis diff:{0:0.00} now:{1:0.00} last:{2:0.00} offfset:{3:0.00} ", diff, angleNow,angleLast, angleOffset); if (i == 1) { angleLast = item.path[0].Angle = angleNow; tempPath.StartAngle = angleNow; angleLastApply = angleApply = angleNow; } if ((logFlags & loggerSelect) > 0) { Logger.Trace(" before angleNow:{0:0.00} angleLast:{1:0.00} angleApply:{2:0.00} offset:{3:0.00}", (angleNow * 180 / Math.PI), (angleLast * 180 / Math.PI), (angleApply * 180 / Math.PI), (angleOffset * 180 / Math.PI)); } double diff = angleNow - angleLast; // + angleOffset; if (diff > Math.PI) { angleOffset -= 2 * Math.PI; } else if (diff < -Math.PI) { angleOffset += 2 * Math.PI; } angleApply = angleNow + angleOffset; if ((logFlags & loggerSelect) > 0) { Logger.Trace(" after angleNow:{0:0.00} angleLast:{1:0.00} angleApply:{2:0.00} offset:{3:0.00}", (angleNow * 180 / Math.PI), (angleLast * 180 / Math.PI), (angleApply * 180 / Math.PI), (angleOffset * 180 / Math.PI)); } item.path[i].Angle = angleApply; // if ((loggerTrace & loggerSelect) > 0) Logger.Trace(" TangentialAxis Line X:{0:0.00} Y:{1:0.00} end X:{2:0.00} Y:{3:0.00} angleNow:{4:0.00} angleApply:{5:0.00} offset:{6:0.00}", pStart.X, pStart.Y, pEnd.X, pEnd.Y, (angleNow * 180 / Math.PI), (angleApply * 180 / Math.PI), (angleOffset* 180 / Math.PI)); /* split path if swivel angle is reached*/ if ((Math.Abs(angleLastApply - angleApply) > maxAngleRad) || fixAngleExceed(ref angleApply, ref angleNow, ref angleOffset)) // change in angle is too large -> insert pen up/turn/down -> seperate path { if (tempPath.path.Count > 1) { finalPathList.Add(tempPath); // save prev path, start new path to force pen up/turn/down } if ((logFlags & loggerSelect) > 0) { Logger.Trace(" Exceed angle max:{0:0.00} actual:{1:0.00}", (maxAngleRad * 180 / Math.PI), (Math.Abs(angleLast - angleNow) * 180 / Math.PI)); } tempPath = new ItemPath(new Point(pStart.X, pStart.Y)); // start new path with clipped start position tempPath.Info.CopyData(graphicItem.Info); // preset global info for GROUP if (actualDashArray.Length > 0) // set dash array { tempPath.dashArray = new double[actualDashArray.Length]; actualDashArray.CopyTo(tempPath.dashArray, 0); } tempPath.Add(pEnd, item.path[i].Depth, angleApply); tempPath.StartAngle = angleApply; } else { tempPath.Add(pEnd, item.path[i].Depth, angleApply); } // add point and angle angleLast = angleApply; //angleNow; angleLastApply = angleApply; } else /* Process Arc implement fixAngleExceed(ref angleApply, ref angleNow, ref angleOffset)?*/ { double offset = +Math.PI / 2; // angle-i = center to p[i] + 90° it is the tangente double aStart = 0; if (!((GCodeArc)item.path[i]).IsCW) { offset = -offset; } // angleStart-i = center to p[i-1] + 90° Point center = new Point(pStart.X + ((GCodeArc)item.path[i]).CenterIJ.X, pStart.Y + ((GCodeArc)item.path[i]).CenterIJ.Y); aStart = gcodeMath.getAngle(pStart, center, offset, 0); // angle of tangente if (i == 1) { angleLast = item.path[0].Angle = aStart; tempPath.StartAngle = aStart; } double diff = aStart - angleLast; // + angleOffset; if (diff > Math.PI) { angleOffset -= 2 * Math.PI; } else if (diff < -Math.PI) { angleOffset += 2 * Math.PI; } angleApply = aStart + angleOffset; // if (loggerTrace) Logger.Trace(" Tang Circle a-start:{0:0.00} a-end:{1:0.00} ", (angle * 180 / Math.PI)); ((GCodeArc)item.path[i]).AngleStart = angleApply; angleNow = gcodeMath.getAngle(pEnd, center, offset, 0); diff = angleNow - angleLast; //+ angleOffset; if (diff > Math.PI) { angleOffset -= 2 * Math.PI; } else if (diff < -Math.PI) { angleOffset += 2 * Math.PI; } angleApply = angleNow + angleOffset; ((GCodeArc)item.path[i]).Angle = angleApply; if ((logFlags & loggerSelect) > 0) { Logger.Trace(" Tangential Circle X:{0:0.00} Y:{1:0.00} end X:{2:0.00} Y:{3:0.00} angleStart:{4:0.00} angleEnd:{5:0.00}", pStart.X, pStart.Y, pEnd.X, pEnd.Y, (aStart * 180 / Math.PI), (angleNow * 180 / Math.PI)); } if (Math.Abs(angleLast - angleNow) > maxAngleRad) // change in angle is too large -> insert pen up/turn/down -> seperate path { if (tempPath.path.Count > 1) { finalPathList.Add(tempPath); // save prev path, start new path to force pen up/turn/down } tempPath = new ItemPath(new Point(pStart.X, pStart.Y)); // start new path with clipped start position tempPath.Info.CopyData(graphicItem.Info); // preset global info for GROUP if (actualDashArray.Length > 0) { tempPath.dashArray = new double[actualDashArray.Length]; actualDashArray.CopyTo(tempPath.dashArray, 0); } } else { tempPath.AddArc((GCodeArc)item.path[i], aStart, angleApply, item.path[i].Depth); } // add point and angle } angleLast = angleNow; } if (tempPath.path.Count > 1) { finalPathList.Add(tempPath); // save prev path } } else /* Process Dot */ { ItemDot dot = new ItemDot(graphicItem.Start.X, graphicItem.Start.Y); dot.Info.CopyData(graphicItem.Info); // preset global info for GROUP finalPathList.Add(dot); if ((logFlags & loggerSelect) > 0) { Logger.Trace(" Clip Dot copied"); } } } completeGraphic.Clear(); foreach (PathObject item in finalPathList) // add tile to full graphic { completeGraphic.Add(item); } }