private IEnumerable <HPGLLine> OffsetLine(double offset, HPGLLine line) { var newlines = new List <HPGLLine> { line }; var co = new ClipperOffset(); var solution = new List <List <IntPoint> >(); var solution2 = new List <List <IntPoint> >(); solution.Add(line.Commands.Select(x => new IntPoint(_scale * x.PointFrom.X0, _scale * x.PointFrom.Y0)).ToList()); co.AddPaths(solution, JoinType.jtRound, EndType.etClosedPolygon); co.Execute(ref solution2, offset); var existingline = line; foreach (var polygon in solution2) { var newcmds = new List <HPGLCommand>(); HPGLCommand last = null; foreach (var pt in polygon) { var from = new Point3D { X = pt.X / _scale, Y = pt.Y / _scale }; var hpgl = new HPGLCommand { PointFrom = from, CommandType = HPGLCommand.HPGLCommandType.PenDown }; newcmds.Add(hpgl); if (last != null) { last.PointTo = from; } last = hpgl; } last.PointTo = newcmds.First().PointFrom; if (existingline == null) { // add new line existingline = new HPGLLine { PreCommands = new List <HPGLCommand> { new HPGLCommand { CommandType = HPGLCommand.HPGLCommandType.PenUp } }, PostCommands = new List <HPGLCommand>(), ParentLine = line.ParentLine }; newlines.Add(existingline); } existingline.Commands = newcmds; existingline.PreCommands.Last(l => l.IsPenCommand).PointTo = newcmds.First().PointFrom; existingline = null; } return(newlines); }
private IEnumerable <HPGLCommand> SplitLineImpl(IEnumerable <HPGLCommand> line) { if (line.Count() < 3) { return(line); } var newline = new List <HPGLCommand>(); HPGLCommand prev = null; double minLineLenght = LoadOptions.SmoothMinLineLenght.HasValue ? (double)LoadOptions.SmoothMinLineLenght.Value : double.MaxValue; double maxerror = LoadOptions.SmoothMaxError.HasValue ? (double)LoadOptions.SmoothMaxError.Value : 1.0 / 40.0; minLineLenght /= (double)LoadOptions.ScaleX; maxerror /= (double)LoadOptions.ScaleX; foreach (var pt in line) { double x = (pt.PointTo.X0) - (pt.PointFrom.X0); double y = (pt.PointTo.Y0) - (pt.PointFrom.Y0); double c = Math.Sqrt(x * x + y * y); if (minLineLenght <= c) { double alpha = pt.DiffLineAngleWithNext ?? (prev?.DiffLineAngleWithNext ?? 0.0); double beta = prev != null ? (prev.DiffLineAngleWithNext ?? 0.0) : alpha; double swapscale = 1.0; if ((alpha >= 0.0 && beta >= 0.0) || (alpha <= 0.0 && beta <= 0.0)) { } else { beta = -beta; swapscale = 0.5; } if ((alpha >= 0.0 && beta >= 0.0) || (alpha <= 0.0 && beta <= 0.0)) { double gamma = Math.PI - alpha - beta; double b = Math.Sin(beta) / Math.Sin(gamma) * c; //double a = Math.Sin(alpha) / Math.Sin(gamma) * c; double hc = b * Math.Sin(alpha) * swapscale; double dc = Math.Sqrt(b * b - hc * hc); double hc4 = hc / 4.0; if (Math.Abs(hc4) > maxerror && Math.Abs(hc4) < c && Math.Abs(dc) < c) { newline.Add(GetNewCommand(pt, dc, hc4)); } } } prev = pt; newline.Add(pt); } return(newline); }
/// <summary> /// Create a new point based on a existing line (x,y are based on the line vector) /// </summary> private HPGLCommand GetNewCommand(HPGLCommand pt, double x, double y) { double diffalpha = Math.Atan2(y, x); double linealpha = diffalpha + (pt.LineAngle ?? 0); double dx = x * Math.Cos(linealpha); double dy = x * Math.Sin(linealpha); return(new HPGLCommand { CommandType = pt.CommandType, PointTo = new Point3D { X = pt.PointFrom.X + dx, Y = pt.PointFrom.Y + dy } }); }
public static void CalculateAngles(IEnumerable <HPGLCommand> list, Point3D firstfrom) { HPGLCommand last = null; if (firstfrom != null) { last = new HPGLCommand { PointTo = firstfrom, CommandType = HPGLCommand.HPGLCommandType.PenDown } } ; foreach (var cmd in list) { cmd.ResetCalculated(); if (cmd.IsPointToValid) { if (last != null) { cmd.PointFrom = last.PointTo; cmd.LineAngle = Math.Atan2((cmd.PointTo.Y0) - (cmd.PointFrom.Y0), (cmd.PointTo.X0) - (cmd.PointFrom.X0)); cmd.DiffLineAngleWithNext = null; if (last.LineAngle.HasValue && cmd.IsPenDownCommand) { last.DiffLineAngleWithNext = last.LineAngle - cmd.LineAngle; if (last.DiffLineAngleWithNext > Math.PI) { last.DiffLineAngleWithNext -= Math.PI * 2.0; } if (last.DiffLineAngleWithNext < -Math.PI) { last.DiffLineAngleWithNext += (Math.PI * 2.0); } } } last = cmd; } } } }
public bool LoadFile(CNC.Controls.GCode job, string filename) { bool ok = true; this.job = job; if (filename.EndsWith("Edge_Cuts.plt") || filename.EndsWith("Paste.plt")) { isCut = !filename.EndsWith("Paste.plt"); } else { isCut = (GrblMode)GrblSettings.GetDouble(GrblSetting.Mode) != GrblMode.Laser; } settings.EnableToolSelection = true; settings.Profile = "HPGL" + (isCut ? "" : "Laser"); if (new JobParametersDialog(settings) { Owner = Application.Current.MainWindow }.ShowDialog() != true) { return(false); } FileInfo file = new FileInfo(filename); StreamReader sr = file.OpenText(); using (new UIUtils.WaitCursor()) { string s = sr.ReadLine(); while (s != null) { foreach (string cmd in s.Split(';')) { try { switch (cmd.Substring(0, 2)) { case "PM": if ((inPolygon = dbl.Parse(cmd.Substring(2)) == 0d)) { pm0.Clear(); HPGLCommand hpgl = new HPGLCommand(); hpgl.Command = commands.Last().Command; hpgl.Pos.X = commands.Last().Pos.X; hpgl.Pos.Y = commands.Last().Pos.Y; pm0.Add(hpgl); } else if (pm0.Count > 0) { Polygon polygon; toVectors(pm0); if ((polygon = Polygon.findPolygon(vectors, tolerance)) != null) { polygons.Add(polygon); } } break; case "PT": scaleFix = 0.025d; break; case "PA": { var args = cmd.Substring(2).Split(','); if (args.Length > 1) { HPGLCommand hpgl = new HPGLCommand(); hpgl.Command = cmd.Substring(0, 2); hpgl.Pos.X = dbl.Parse(args[0]) * scaleFix; hpgl.Pos.Y = dbl.Parse(args[1]) * scaleFix; offset.X = Math.Min(offset.X, hpgl.Pos.X); offset.Y = Math.Min(offset.Y, hpgl.Pos.Y); if (inPolygon) { pm0.Add(hpgl); } else { commands.Add(hpgl); } } } break; case "AA": { var args = cmd.Substring(2).Split(','); if (args.Length > 2) { HPGLCommand hpgl = new HPGLCommand(); hpgl.Command = cmd.Substring(0, 2); hpgl.Pos.X = dbl.Parse(args[0]) * scaleFix; hpgl.Pos.Y = dbl.Parse(args[1]) * scaleFix; hpgl.R = dbl.Parse(args[2]) * scaleFix; offset.X = Math.Min(offset.X, hpgl.Pos.X); offset.Y = Math.Min(offset.Y, hpgl.Pos.Y); if (inPolygon) { pm0.Add(hpgl); } else { commands.Add(hpgl); } } } break; case "PD": case "PU": { HPGLCommand hpgl = new HPGLCommand(); hpgl.Command = cmd.Substring(0, 2); if (inPolygon) { pm0.Add(hpgl); } else { isDown = hpgl.Command == "PD"; commands.Add(hpgl); } } break; default: { HPGLCommand hpgl = new HPGLCommand(); hpgl.Command = cmd.Substring(0, 2); commands.Add(hpgl); } break; } } catch { } } s = sr.ReadLine(); } sr.Close(); for (int i = 0; i < commands.Count; i++) { var cmd = commands[i]; try { switch (cmd.Command) { case "IN": pos.X = cmd.Pos.X = 0d; pos.Y = cmd.Pos.Y = 0d; isDown = cmd.isDown = false; break; case "PU": if (isDown) { cmd.Pos.X = pos.X; cmd.Pos.Y = pos.Y; isDown = false; } break; case "PD": if (!isDown) { cmd.Pos.X = pos.X; cmd.Pos.Y = pos.Y; isDown = true; } break; case "PA": cmd.Pos.X -= offset.X; cmd.Pos.Y -= offset.Y; if ((cmd.isDown = isDown)) { var v = new Vector(); v.IsArc = false; v.Start = pos; v.End.X = cmd.Pos.X; v.End.Y = cmd.Pos.Y; vectors.Add(v); } break; case "AA": { cmd.Pos.X = cmd.Pos.X - offset.X; cmd.Pos.Y = cmd.Pos.Y - offset.X; if ((cmd.isDown = isDown)) { var v = new Vector(); v.IsArc = true; v.Start = pos; v.End.X = cmd.Pos.X + (cmd.Pos.X - pos.X); v.End.Y = cmd.Pos.Y + (cmd.Pos.Y - pos.Y); vectors.Add(v); } } break; } pos.X = cmd.Pos.X; pos.Y = cmd.Pos.Y; } catch { } } { Polygon polygon; while ((polygon = Polygon.findPolygon(vectors, tolerance)) != null) { polygons.Add(polygon); } } job.AddBlock(filename, CNC.Core.Action.New); job.AddBlock("(Translated by HPGL to GCode converter)"); job.AddBlock(string.Format("(Tool diameter: {0} mm)", settings.ToolDiameter.ToInvariantString())); job.AddBlock("G90G91.1G17G21G50"); if (settings.ScaleX != 1d || settings.ScaleY != 1d) { job.AddBlock(string.Format("G51X{0}Y{1}", settings.ScaleX.ToInvariantString(), settings.ScaleY.ToInvariantString())); } job.AddBlock("G0Z" + settings.ZRapids.ToInvariantString()); job.AddBlock("X0Y0"); if (isCut) { job.AddBlock(string.Format("M3S{0}", settings.RPM.ToInvariantString())); job.AddBlock("G4P2"); } else { job.AddBlock("M122P1"); // Enable laser job.AddBlock("M123P800"); // PPI job.AddBlock("M124P1500"); // Pulse width job.AddBlock("M125Q1P2"); // Enable tube coolant job.AddBlock("M4S90"); job.AddBlock("M7"); job.AddBlock("M8"); } foreach (var polygon in polygons) { if (settings.ToolDiameter != 0d) { polygon.Offset((isCut ? -settings.ToolDiameter : settings.ToolDiameter) / 2d); } cutPolygon(polygon); } job.AddBlock("G0X0Y0Z" + settings.ZHome.ToInvariantString()); job.AddBlock("M30", CNC.Core.Action.End); } return(ok); }
private bool Command(HPGLCommand cmd) { bool isPenUp = true; if (cmd.IsPenCommand) { switch (cmd.CommandType) { case HPGLCommand.HPGLCommandType.PenDown: isPenUp = false; break; case HPGLCommand.HPGLCommandType.PenUp: isPenUp = true; break; } Point3D pt = Adjust(cmd.PointTo); if (isPenUp != _lastIsPenUp) { if (isPenUp) { LoadPenUp(); } else { LoadPenDown(Adjust(cmd.PointFrom)); } _lastIsPenUp = isPenUp; } string hpglCmd; Command r; if (isPenUp) { r = new G00Command(); hpglCmd = "PU"; } else { r = new G01Command(); AddCamBamPoint(pt); hpglCmd = "PD"; } r.AddVariable('X', pt.X0, false); r.AddVariable('Y', pt.Y0, false); if (_needSpeed) { _needSpeed = false; r.AddVariable('F', LoadOptions.MoveSpeed ?? 0); } Commands.AddCommand(r); r.ImportInfo = $"{hpglCmd}{(int)(pt.X0 * 40.0)},{(int)(pt.Y0 * 40.0)}"; } else { var r = new GxxCommand(); r.SetCode($";HPGL={cmd.CommandString}"); r.ImportInfo = cmd.CommandString; Commands.AddCommand(r); } return(true); }