/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.willwinder.universalgcodesender.gcode.processors; import com.willwinder.universalgcodesender.gcode.GcodeState; import com.willwinder.universalgcodesender.gcode.util.GcodeParserException; import com.willwinder.universalgcodesender.gcode.util.Plane; import static com.willwinder.universalgcodesender.gcode.util.Plane.*; import com.willwinder.universalgcodesender.i18n.Localization; import java.util.Collection; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.vecmath.Point3d; import org.junit.After; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; /** * * @author wwinder */ public class ArcExpanderTest { public ArcExpanderTest() { } @Before public void setUp() { } @After public void tearDown() { } @Test public void arcExpandadState() throws Exception { System.out.println("arcExpandBadState"); GcodeState state = new GcodeState(); ArcExpander instance = new ArcExpander(true, 1); boolean threwException = false; try { List<String> result = instance.processCommand("G02 X5 Y0 R12", state); } catch (GcodeParserException e) { threwException = true; assertEquals(Localization.getString("parser.processor.arc.start-error"), e.getMessage()); } assertTrue(threwException); } @Test public void arcExpandBadCommand() throws Exception { System.out.println("arcExpandBadCommand"); GcodeState state = new GcodeState(); state.currentPoint = new Point3d(0,0,0); state.plane = XY; ArcExpander instance = new ArcExpander(true, 1); boolean threwException = false; try { List<String> result = instance.processCommand("G17 G02 X5 Y0 R12", state); } catch (GcodeParserException e) { threwException = true; assertEquals(Localization.getString("parser.processor.arc.multiple-commands"), e.getMessage()); } assertTrue(threwException); } @Test public void arcExpandIgnoreNonArc() throws Exception { System.out.println("arcExpandIgnoreNonArc"); GcodeState state = new GcodeState(); state.currentPoint = new Point3d(0,0,0); state.plane = XY; ArcExpander instance = new ArcExpander(true, 1); boolean threwException = false; String command = "G17 G0 X12"; List<String> result = instance.processCommand(command, state); assertEquals(1, result.size()); assertEquals(command, result.get(0)); } @Test public void expandArcG17() throws Exception { System.out.println("expandArcG17"); GcodeState state = new GcodeState(); state.currentPoint = new Point3d(-1,0,0); state.plane = XY; ///////////////////////////////////////////////////////// // Using a unit circle, so I can verify a^2 + b^2 = 1. // ///////////////////////////////////////////////////////// for (double segmentLength = 0.1; segmentLength < 1; segmentLength+=0.1) { ArcExpander instance = new ArcExpander(true, segmentLength); // Half circle clockwise, X-1 -> X1, Y0 -> Y1 -> Y0 String command = "G2 Y0 X1 R1"; List<String> result = instance.processCommand(command, state); assertEquals((int)Math.ceil(Math.PI / segmentLength), result.size()); verifyLines(new Point3d(0,0,0), result, 1., new Point3d(-1, 0, 0), new Point3d(1,1,0), state.plane); // Half circle counter-clockwise, X-1 -> X1, Y0 -> Y-1 -> Y0 command = "G3 Y0 X1 R1"; result = instance.processCommand(command, state); assertEquals((int)Math.ceil(Math.PI / segmentLength), result.size()); verifyLines(new Point3d(0,0,0), result, 1., new Point3d(-1, -1, 0), new Point3d(1,0,0), state.plane); } } @Test public void expandArcG18() throws Exception { System.out.println("expandArcG18"); GcodeState state = new GcodeState(); state.currentPoint = new Point3d(0,0,-1); state.plane = ZX; ///////////////////////////////////////////////////////// // Using a unit circle, so I can verify a^2 + b^2 = 1. // ///////////////////////////////////////////////////////// for (double segmentLength = 0.1; segmentLength < 1; segmentLength+=0.1) { ArcExpander instance = new ArcExpander(true, segmentLength); // Half circle clockwise, Z-1 -> Z1, X0 -> X1 -> X0 String command = "G2 Z1 X0 R1"; List<String> result = instance.processCommand(command, state); assertEquals((int)Math.ceil(Math.PI / segmentLength), result.size()); verifyLines(new Point3d(0,0,0), result, 1., new Point3d(0, 0, -1), new Point3d(1,0,1), state.plane); // Half circle clockwise, Z-1 -> Z1, X0 -> X-1 -> X0 command = "G3 Z1 X0 R1"; result = instance.processCommand(command, state); assertEquals((int)Math.ceil(Math.PI / segmentLength), result.size()); verifyLines(new Point3d(0,0,0), result, 1., new Point3d(-1, 0, -1), new Point3d(0,0,1), state.plane); } } @Test public void expandArcG19() throws Exception { System.out.println("expandArcG19"); GcodeState state = new GcodeState(); state.currentPoint = new Point3d(0,-1,0); state.plane = YZ; ///////////////////////////////////////////////////////// // Using a unit circle, so I can verify a^2 + b^2 = 1. // ///////////////////////////////////////////////////////// for (double segmentLength = 0.1; segmentLength < 1; segmentLength+=0.1) { ArcExpander instance = new ArcExpander(true, segmentLength); // Half circle clockwise, Y-1 -> Y1, X0 -> X1 -> X0 String command = "G2 Y1 X0 R1"; List<String> result = instance.processCommand(command, state); assertEquals((int)Math.ceil(Math.PI / segmentLength), result.size()); verifyLines(new Point3d(0,0,0), result, 1., new Point3d(0, -1., 0), new Point3d(0,1,1), state.plane); // Half circle clockwise, Y-1 -> Y1, X0 -> X-1 -> X0 command = "G3 Y1 X0 R1"; result = instance.processCommand(command, state); assertEquals((int)Math.ceil(Math.PI / segmentLength), result.size()); verifyLines(new Point3d(0,0,0), result, 1., new Point3d(0, -1, -1), new Point3d(0,1,0), state.plane); } } /** * Verify that the points around given center point have a known radius and * fall within known boundaries. */ static void verifyLines(Point3d center, Collection<String> lines, double radius, Point3d min, Point3d max, Plane p) { for (String line : lines) { verifyLine(center, line, radius, min, max, p); } } static Pattern LINE_COORDS = Pattern.compile("G1" + "X([\\-\\+]?[0-9]+(?:\\.[0-9]+)?)" + "Y([\\-\\+]?[0-9]+(?:\\.[0-9]+)?)" + "Z([\\-\\+]?[0-9]+(?:\\.[0-9]+)?)"); //+ "(F\\d+)?"); static void verifyLine(Point3d center, String line, double radius, Point3d min, Point3d max, Plane p) { Matcher m = LINE_COORDS.matcher(line); if (m.find()) { double x = Double.parseDouble(m.group(1)) - center.x; double y = Double.parseDouble(m.group(2)) - center.y; double z = Double.parseDouble(m.group(3)) - center.z; assertTrue("X is in bounds", x <= max.x && x >= min.x); assertTrue("Y is in bounds", y <= max.y && y >= min.y); assertTrue("Z is in bounds", z <= max.z && z >= min.z); double r; switch (p) { case XY: r = Math.sqrt(x*x + y*y); break; case YZ: r = Math.sqrt(z*z + y*y); break; case ZX: r = Math.sqrt(z*z + x*x); break; default: r = -1; } assertEquals(radius, r, 0.0001); } else { fail("This should have matched."); } } }