From 5e0da9579c32b6035138d22515df62cbc44fc952 Mon Sep 17 00:00:00 2001
From: Thomas Oster <thomas.oster@rwth-aachen.de>
Date: Tue, 18 Sep 2012 14:08:10 +0200
Subject: [PATCH] LaserPropertys are now Device dependent - Deleted useless
 UnitTests (were interactive anyway) - LAOS driver uses now floats instead of
 ints (untested)

---
 ...FloatPowerSpeedFocusFrequencyProperty.java | 228 ++++++++++++++++++
 src/com/t_oster/liblasercut/LaserCutter.java  |  15 +-
 .../t_oster/liblasercut/LaserProperty.java    |   7 +-
 .../PowerSpeedFocusFrequencyProperty.java     |  23 +-
 .../liblasercut/PowerSpeedFocusProperty.java  |  22 +-
 .../liblasercut/drivers/EpilogCutter.java     |  67 ++---
 .../liblasercut/drivers/LaosCutter.java       |  69 ++++--
 .../liblasercut/drivers/Lasersaur.java        |  20 +-
 .../liblasercut/examples/PhotoPrint.java      |   6 +-
 .../liblasercut/drivers/EpilogCutterTest.java | 127 ----------
 .../liblasercut/drivers/FocusStrokesTest.java |  48 ----
 .../liblasercut/drivers/LaosCutterTest.java   |  46 ----
 .../liblasercut/drivers/MaterialTest.java     | 120 ---------
 .../liblasercut/drivers/StartPointTest.java   |  85 -------
 14 files changed, 346 insertions(+), 537 deletions(-)
 create mode 100644 src/com/t_oster/liblasercut/FloatPowerSpeedFocusFrequencyProperty.java
 delete mode 100644 test/com/t_oster/liblasercut/drivers/EpilogCutterTest.java
 delete mode 100644 test/com/t_oster/liblasercut/drivers/FocusStrokesTest.java
 delete mode 100644 test/com/t_oster/liblasercut/drivers/LaosCutterTest.java
 delete mode 100644 test/com/t_oster/liblasercut/drivers/MaterialTest.java
 delete mode 100644 test/com/t_oster/liblasercut/drivers/StartPointTest.java

diff --git a/src/com/t_oster/liblasercut/FloatPowerSpeedFocusFrequencyProperty.java b/src/com/t_oster/liblasercut/FloatPowerSpeedFocusFrequencyProperty.java
new file mode 100644
index 0000000..794a3b4
--- /dev/null
+++ b/src/com/t_oster/liblasercut/FloatPowerSpeedFocusFrequencyProperty.java
@@ -0,0 +1,228 @@
+/**
+ * This file is part of VisiCut.
+ * Copyright (C) 2011 Thomas Oster <thomas.oster@rwth-aachen.de>
+ * RWTH Aachen University - 52062 Aachen, Germany
+ * 
+ *     VisiCut is free software: you can redistribute it and/or modify
+ *     it under the terms of the GNU Lesser General Public License as published by
+ *     the Free Software Foundation, either version 3 of the License, or
+ *     (at your option) any later version.
+ * 
+ *    VisiCut is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU Lesser General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU Lesser General Public License
+ *     along with VisiCut.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+package com.t_oster.liblasercut;
+
+/**
+ * The LaserProperty holds all the parameters for parts of the LaserJob.
+ * The Frequency value is ignored for Engraving operations
+ * 
+ * @author oster
+ */
+public class FloatPowerSpeedFocusFrequencyProperty implements LaserProperty
+{
+
+  private float power = 20;
+  private float speed = 100;
+  private float focus = 0;
+  private float frequency = 500;
+
+  public FloatPowerSpeedFocusFrequencyProperty()
+  {
+  }
+
+  /**
+   * Sets the Laserpower. Valid values are from 0 to 100.
+   * In 3d-Raster mode, the intensity is scaled to this power setting
+   * @param power 
+   */
+  public void setPower(float power)
+  {
+    power = power < 0 ? 0 : power;
+    power = power > 100 ? 100 : power;
+    this.power = power;
+  }
+
+  public float getPower()
+  {
+    return power;
+  }
+
+  /**
+   * Sets the speed for the Laser. Valid values is from 0 to 100
+   * @param speed 
+   */
+  public void setSpeed(float speed)
+  {
+    speed = speed < 0 ? 0 : speed;
+    speed = speed > 100 ? 100 : speed;
+    this.speed = speed;
+  }
+
+  public float getSpeed()
+  {
+    return speed;
+  }
+
+  /**
+   * Sets the Focus aka moves the Z axis. Values are given in mm.
+   * Positive values move the Z axis down aka makes the distance between
+   * laser and object bigger.
+   * The possible range depends on the LaserCutter, so wrong setting
+   * may result in IllegalJobExceptions
+   * @param focus the relative Distance from object to Laser in mm
+   */
+  public void setFocus(float focus)
+  {
+    this.focus = focus;
+  }
+
+  /**
+   * Returns the relative (to the distance at starting the job) distance
+   * between laser and object in mm/10s
+   */
+  public float getFocus()
+  {
+    return this.focus;
+  }
+  
+  public void setFrequency(float f)
+  {
+    this.frequency = f;
+  }
+  
+  public float getFrequency()
+  {
+    return this.frequency;
+  }
+
+  @Override
+  public FloatPowerSpeedFocusFrequencyProperty clone()
+  {
+    FloatPowerSpeedFocusFrequencyProperty p = new FloatPowerSpeedFocusFrequencyProperty();
+    p.focus = focus;
+    p.frequency = frequency;
+    p.power = power;
+    p.speed = speed;
+    return p;
+  }
+
+  private static String[] propertyNames = new String[]{"power", "speed", "focus", "frequency"};
+  
+  @Override
+  public String[] getPropertyNames()
+  {
+    return propertyNames;
+  }
+
+  @Override
+  public Object getProperty(String name)
+  {
+    if ("power".equals(name))
+    {
+      return (Float) this.getPower();
+    }
+    else if ("speed".equals(name))
+    {
+      return (Float) this.getSpeed();
+    }
+    else if ("focus".equals(name))
+    {
+      return (Float) this.getFocus();
+    }
+    else if ("frequency".equals(name))
+    {
+      return (Float) this.getFrequency();
+    }
+    else
+    {
+      throw new IllegalArgumentException("Unknown setting '"+name+"'");
+    }
+  }
+
+  @Override
+  public void setProperty(String name, Object value)
+  {
+    if ("power".equals(name))
+    {
+      this.setPower((Integer) value);
+    }
+    else if ("speed".equals(name))
+    {
+      this.setSpeed((Integer) value);
+    }
+    else if ("focus".equals(name))
+    {
+      this.setFocus((Float) value);
+    }
+    else if ("frequency".equals(name))
+    {
+      this.setFrequency((Float) value);
+    }
+    else
+    {
+      throw new IllegalArgumentException("Unknown setting '"+name+"'");
+    }
+  }
+
+  @Override
+  public Object getMinimumValue(String name)
+  {
+  if ("power".equals(name))
+    {
+      return (Float) 0f;
+    }
+    else if ("speed".equals(name))
+    {
+      return (Float) 0f;
+    }
+    else if ("focus".equals(name))
+    {
+      return null;
+    }
+    else if ("frequency".equals(name))
+    {
+      return null;
+    }
+    else
+    {
+      throw new IllegalArgumentException("Unknown setting '"+name+"'");
+    }  
+  }
+
+  @Override
+  public Object getMaximumValue(String name)
+  {
+    if ("power".equals(name))
+    {
+      return (Float) 100f;
+    }
+    else if ("speed".equals(name))
+    {
+      return (Float) 100f;
+    }
+    else if ("focus".equals(name))
+    {
+      return null;
+    }
+    else if ("frequency".equals(name))
+    {
+      return null;
+    }
+    else
+    {
+      throw new IllegalArgumentException("Unknown setting '"+name+"'");
+    }
+  }
+
+  @Override
+  public Object[] getPossibleValues(String name)
+  {
+    return null;
+  }
+}
diff --git a/src/com/t_oster/liblasercut/LaserCutter.java b/src/com/t_oster/liblasercut/LaserCutter.java
index 3462a45..8aec004 100644
--- a/src/com/t_oster/liblasercut/LaserCutter.java
+++ b/src/com/t_oster/liblasercut/LaserCutter.java
@@ -178,11 +178,20 @@ public abstract class LaserCutter implements Cloneable
    */
   public abstract int estimateJobDuration(LaserJob job);
   
-  public abstract LaserProperty getLaserPropertyForVectorPart();
+  public LaserProperty getLaserPropertyForVectorPart()
+  {
+    return new PowerSpeedFocusFrequencyProperty();
+  }
   
-  public abstract LaserProperty getLaserPropertyForRasterPart();
+  public LaserProperty getLaserPropertyForRasterPart()
+  {
+    return new PowerSpeedFocusProperty();
+  }
   
-  public abstract LaserProperty getLaserPropertyForRaster3dPart();
+  public LaserProperty getLaserPropertyForRaster3dPart()
+  {
+    return new PowerSpeedFocusProperty();
+  }
   
   public abstract String getModelName();
   
diff --git a/src/com/t_oster/liblasercut/LaserProperty.java b/src/com/t_oster/liblasercut/LaserProperty.java
index 9e66248..7970967 100644
--- a/src/com/t_oster/liblasercut/LaserProperty.java
+++ b/src/com/t_oster/liblasercut/LaserProperty.java
@@ -26,12 +26,8 @@ import java.util.List;
  * 
  * @author oster
  */
-public abstract class LaserProperty implements Cloneable
+public interface LaserProperty extends Cloneable
 {
-  
-  public LaserProperty()
-  {
-  }
 
   /**
    * Returns the names of possible propertys,
@@ -63,6 +59,5 @@ public abstract class LaserProperty implements Cloneable
   
   public abstract Object[] getPossibleValues(String name);
   
-  @Override
   public abstract LaserProperty clone();
 }
diff --git a/src/com/t_oster/liblasercut/PowerSpeedFocusFrequencyProperty.java b/src/com/t_oster/liblasercut/PowerSpeedFocusFrequencyProperty.java
index 0c379b6..5e66170 100644
--- a/src/com/t_oster/liblasercut/PowerSpeedFocusFrequencyProperty.java
+++ b/src/com/t_oster/liblasercut/PowerSpeedFocusFrequencyProperty.java
@@ -33,22 +33,6 @@ public class PowerSpeedFocusFrequencyProperty extends PowerSpeedFocusProperty
   {
   }
 
-  public PowerSpeedFocusFrequencyProperty(int power, int speed)
-  {
-      this(power, speed, 0, 5000);
-  }
-  
-  public PowerSpeedFocusFrequencyProperty(int power, int speed, float focus)
-  {
-    this(power, speed, focus, 5000);
-  }
-
-  public PowerSpeedFocusFrequencyProperty(int power, int speed, float focus, int frequency)
-  {
-    super(power, speed, focus);
-    this.frequency = frequency;
-  }
-
   public void setFrequency(int frequency)
   {
     frequency = frequency < 100 ? 100 : frequency;
@@ -137,6 +121,11 @@ public class PowerSpeedFocusFrequencyProperty extends PowerSpeedFocusProperty
   @Override
   public PowerSpeedFocusFrequencyProperty clone()
   {
-    return new PowerSpeedFocusFrequencyProperty(this.getPower(), this.getSpeed(), this.getFocus(), frequency);
+    PowerSpeedFocusFrequencyProperty p = new PowerSpeedFocusFrequencyProperty();
+    p.frequency = this.frequency;
+    p.setPower(getPower());
+    p.setSpeed(getSpeed());
+    p.setFocus(getFocus());
+    return p;
   }
 }
diff --git a/src/com/t_oster/liblasercut/PowerSpeedFocusProperty.java b/src/com/t_oster/liblasercut/PowerSpeedFocusProperty.java
index 8d6c281..2493e31 100644
--- a/src/com/t_oster/liblasercut/PowerSpeedFocusProperty.java
+++ b/src/com/t_oster/liblasercut/PowerSpeedFocusProperty.java
@@ -18,15 +18,13 @@
  **/
 package com.t_oster.liblasercut;
 
-import java.util.List;
-
 /**
  * The LaserProperty holds all the parameters for parts of the LaserJob.
  * The Frequency value is ignored for Engraving operations
  * 
  * @author oster
  */
-public class PowerSpeedFocusProperty extends LaserProperty
+public class PowerSpeedFocusProperty implements LaserProperty
 {
 
   private int power = 20;
@@ -37,18 +35,6 @@ public class PowerSpeedFocusProperty extends LaserProperty
   {
   }
 
-  public PowerSpeedFocusProperty(int power, int speed)
-  {
-      this(power, speed, 0);
-  }
-  
-  public PowerSpeedFocusProperty(int power, int speed, float focus)
-  {
-    this.power = power;
-    this.speed = speed;
-    this.focus = focus;
-  }
-
   /**
    * Sets the Laserpower. Valid values are from 0 to 100.
    * In 3d-Raster mode, the intensity is scaled to this power setting
@@ -107,7 +93,11 @@ public class PowerSpeedFocusProperty extends LaserProperty
   @Override
   public PowerSpeedFocusProperty clone()
   {
-    return new PowerSpeedFocusProperty(power, speed, focus);
+    PowerSpeedFocusProperty p = new PowerSpeedFocusProperty();
+    p.power = power;
+    p.speed = speed;
+    p.focus = focus;
+    return p;
   }
 
   private static String[] propertyNames = new String[]{"power", "speed", "focus"};
diff --git a/src/com/t_oster/liblasercut/drivers/EpilogCutter.java b/src/com/t_oster/liblasercut/drivers/EpilogCutter.java
index 8a4a763..15adc27 100644
--- a/src/com/t_oster/liblasercut/drivers/EpilogCutter.java
+++ b/src/com/t_oster/liblasercut/drivers/EpilogCutter.java
@@ -395,12 +395,12 @@ abstract class EpilogCutter extends LaserCutter
   {
     ByteArrayOutputStream result = new ByteArrayOutputStream();
     PrintStream out = new PrintStream(result, true, "US-ASCII");
-    PowerSpeedFoc curprop = new LaserProperty();
+    PowerSpeedFocusProperty curprop = null;
     if (rp != null && rp.getRasterCount() > 0)
     {
       if (rp.getRasterCount() > 0)
       {
-        curprop = rp.getLaserProperty(0);
+        curprop = (PowerSpeedFocusProperty) rp.getLaserProperty(0);
       }
       /* Raster Orientation: Printed in current direction */
       out.printf("\033*r0F");
@@ -429,7 +429,7 @@ abstract class EpilogCutter extends LaserCutter
 
       for (int i = 0; rp != null && i < rp.getRasterCount(); i++)
       {
-        LaserProperty newprop = rp.getLaserProperty(i);
+        PowerSpeedFocusProperty newprop = (PowerSpeedFocusProperty) rp.getLaserProperty(i);
         if (newprop.getPower() != curprop.getPower())
         {
           /* Raster power */
@@ -510,14 +510,14 @@ abstract class EpilogCutter extends LaserCutter
   private byte[] generateRasterPCL(LaserJob job, RasterPart rp) throws UnsupportedEncodingException, IOException
   {
 
-    LaserProperty curprop = null;
+    PowerSpeedFocusProperty curprop = null;
     if (rp != null && rp.getRasterCount() > 0)
     {
-      curprop = rp.getLaserProperty(0);
+      curprop = (PowerSpeedFocusProperty) rp.getLaserProperty(0);
     }
-    if (curprop == null)
+    else
     {
-      curprop = new LaserProperty();
+      curprop = new PowerSpeedFocusProperty();
     }
     ByteArrayOutputStream result = new ByteArrayOutputStream();
     PrintStream out = new PrintStream(result, true, "US-ASCII");
@@ -549,7 +549,7 @@ abstract class EpilogCutter extends LaserCutter
     for (int i = 0; rp != null && i < rp.getRasterCount(); i++)
     {
       //TODO: Test if new Settings are applied
-      LaserProperty newprop = rp.getLaserProperty(i);
+      PowerSpeedFocusProperty newprop = (PowerSpeedFocusProperty) rp.getLaserProperty(i);
       if (newprop.getPower() != curprop.getPower())
       {
         /* Raster power */
@@ -645,6 +645,10 @@ abstract class EpilogCutter extends LaserCutter
 
     if (vp != null)
     {
+      Integer currentPower = null;
+      Integer currentSpeed = null;
+      Integer currentFrequency = null;
+      Float currentFocus = null;
       int sx = job.getStartX();
       int sy = job.getStartY();
       VectorCommand.CmdType lastType = null;
@@ -656,24 +660,29 @@ abstract class EpilogCutter extends LaserCutter
         }
         switch (cmd.getType())
         {
-          case SETFOCUS:
-          {
-            out.printf("WF%d;", mm2focus(cmd.getFocus()));
-            break;
-          }
-          case SETFREQUENCY:
-          {
-            out.printf("XR%04d;", cmd.getFrequency());
-            break;
-          }
-          case SETPOWER:
-          {
-            out.printf("YP%03d;", cmd.getPower());
-            break;
-          }
-          case SETSPEED:
+          case SETPROPERTY:
           {
-            out.printf("ZS%03d;", cmd.getSpeed());
+            PowerSpeedFocusFrequencyProperty p = (PowerSpeedFocusFrequencyProperty) cmd.getProperty();
+            if (currentFocus == null || !currentFocus.equals(p.getFocus()))
+            {
+              out.printf("WF%d;", mm2focus(p.getFocus()));
+              currentFocus = p.getFocus();
+            }
+            if (currentFrequency == null || !currentFrequency.equals(p.getFrequency()))
+            {
+              out.printf("XR%04d;", p.getFrequency());
+              currentFrequency = p.getFrequency();
+            }
+            if (currentPower == null || !currentPower.equals(p.getPower()))
+            {
+              out.printf("YP%03d;", p.getPower());
+              currentPower = p.getPower();
+            }
+            if (currentSpeed == null || !currentSpeed.equals(p.getSpeed()))
+            {
+              out.printf("ZS%03d;", p.getSpeed());
+              currentSpeed = p.getSpeed();
+            }
             break;
           }
           case MOVETO:
@@ -861,7 +870,7 @@ abstract class EpilogCutter extends LaserCutter
         Point sp = rp.getRasterStart(i);
         result += Math.max((double) (p.x - sp.x) / VECTOR_MOVESPEED_X,
           (double) (p.y - sp.y) / VECTOR_MOVESPEED_Y);
-        double linespeed = ((double) RASTER_LINESPEED * rp.getLaserProperty(i).getSpeed()) / 100;
+        double linespeed = ((double) RASTER_LINESPEED * ((PowerSpeedFocusProperty) rp.getLaserProperty(i)).getSpeed()) / 100;
         BlackWhiteRaster bwr = rp.getImages()[i];
         for (int y = 0; y < bwr.getHeight(); y++)
         {//Find any black point
@@ -896,7 +905,7 @@ abstract class EpilogCutter extends LaserCutter
         Point sp = rp.getRasterStart(i);
         result += Math.max((double) (p.x - sp.x) / VECTOR_MOVESPEED_X,
           (double) (p.y - sp.y) / VECTOR_MOVESPEED_Y);
-        double linespeed = ((double) RASTER3D_LINESPEED * rp.getLaserProperty(i).getSpeed()) / 100;
+        double linespeed = ((double) RASTER3D_LINESPEED * ((PowerSpeedFocusProperty) rp.getLaserProperty(i)).getSpeed()) / 100;
         GreyscaleRaster gsr = rp.getImages()[i];
         for (int y = 0; y < gsr.getHeight(); y++)
         {//Check if
@@ -927,9 +936,9 @@ abstract class EpilogCutter extends LaserCutter
       {
         switch (cmd.getType())
         {
-          case SETSPEED:
+          case SETPROPERTY:
           {
-            speed = VECTOR_LINESPEED * cmd.getSpeed() / 100;
+            speed = VECTOR_LINESPEED * ((PowerSpeedFocusFrequencyProperty) cmd.getProperty()).getSpeed() / 100;
             break;
           }
           case MOVETO:
diff --git a/src/com/t_oster/liblasercut/drivers/LaosCutter.java b/src/com/t_oster/liblasercut/drivers/LaosCutter.java
index 0dc1965..e98b5b8 100644
--- a/src/com/t_oster/liblasercut/drivers/LaosCutter.java
+++ b/src/com/t_oster/liblasercut/drivers/LaosCutter.java
@@ -19,6 +19,7 @@
 package com.t_oster.liblasercut.drivers;
 
 import com.t_oster.liblasercut.BlackWhiteRaster;
+import com.t_oster.liblasercut.FloatPowerSpeedFocusFrequencyProperty;
 import com.t_oster.liblasercut.IllegalJobException;
 import com.t_oster.liblasercut.LaserCutter;
 import com.t_oster.liblasercut.LaserJob;
@@ -66,6 +67,24 @@ public class LaosCutter extends LaserCutter
   
   private boolean unidir = false;
   
+  @Override
+  public FloatPowerSpeedFocusFrequencyProperty getLaserPropertyForVectorPart()
+  {
+    return new FloatPowerSpeedFocusFrequencyProperty();
+  }
+  
+  @Override
+  public FloatPowerSpeedFocusFrequencyProperty getLaserPropertyForRasterPart()
+  {
+    return new FloatPowerSpeedFocusFrequencyProperty();
+  }
+  
+  @Override
+  public FloatPowerSpeedFocusFrequencyProperty getLaserPropertyForRaster3dPart()
+  {
+    return new FloatPowerSpeedFocusFrequencyProperty();
+  }
+  
   public void setEngraveUnidirectional(boolean uni)
   {
     this.unidir = uni;
@@ -258,9 +277,9 @@ public class LaosCutter extends LaserCutter
     this.mmPerStep = mmPerStep;
   }
 
-  private int px2steps(double px, double dpi)
+  private float px2steps(double px, double dpi)
   {
-    return (int) (Util.px2mm(px, dpi) / this.mmPerStep);
+    return (float) (Util.px2mm(px, dpi) / this.mmPerStep);
   }
 
   private byte[] generateVectorGCode(VectorPart vp, int resolution) throws UnsupportedEncodingException
@@ -285,18 +304,19 @@ public class LaosCutter extends LaserCutter
         case LINETO:
           line(out, cmd.getX(), cmd.getY(), power, speed, frequency, resolution);
           break;
-        case SETPOWER:
-          power = cmd.getPower();
-          break;
-        case SETFOCUS:
-          out.printf(Locale.US, "2 %d\n", (int) Util.mm2px(cmd.getFocus(), resolution));
-          break;
-        case SETSPEED:
-          speed = cmd.getSpeed();
-          break;
-        case SETFREQUENCY:
-          frequency = cmd.getFrequency();
+        case SETPROPERTY:
+        {
+          FloatPowerSpeedFocusFrequencyProperty p = (FloatPowerSpeedFocusFrequencyProperty) cmd.getProperty();
+          currentPower = p.getPower();
+          currentSpeed = p.getSpeed();
+          currentFrequency = p.getFrequency();
+          if (currentFocus != p.getFocus())
+          {
+            out.printf(Locale.US, "2 %f\n", (float) Util.mm2px(p.getFocus(), resolution));
+            currentFocus = p.getFocus();
+          }
           break;
+        }
       }
     }
     return result.toByteArray();
@@ -306,28 +326,29 @@ public class LaosCutter extends LaserCutter
   {
     out.printf("0 %d %d\n", px2steps(isFlipXaxis() ? Util.mm2px(bedWidth, resolution) - x : x, resolution), px2steps(isFlipYaxis() ? Util.mm2px(bedHeight, resolution) - y : y, resolution));
   }
-  private int currentPower = -1;
-  private int currentSpeed = -1;
-  private int currentFrequency = -1;
+  private float currentPower = -1;
+  private float currentSpeed = -1;
+  private float currentFocus = 0;
+  private float currentFrequency = -1;
 
-  private void line(PrintStream out, int x, int y, int power, int speed, int frequency, int resolution)
+  private void line(PrintStream out, int x, int y, float power, float speed, float frequency, int resolution)
   {
     if (currentPower != power)
     {
-      out.printf("7 101 %d\n", power * 100);
+      out.printf("7 101 %f\n", power * 100);
       currentPower = power;
     }
     if (currentSpeed != speed)
     {
-      out.printf("7 100 %d\n", speed * 100);
+      out.printf("7 100 %f\n", speed * 100);
       currentSpeed = speed;
     }
     if (currentFrequency != frequency)
     {
-      out.printf("7 102 %d\n", frequency);
+      out.printf("7 102 %f\n", frequency);
       currentFrequency = frequency;
     }
-    out.printf("1 %d %d\n", px2steps(isFlipXaxis() ? Util.mm2px(bedWidth, resolution) - x : x, resolution), px2steps(isFlipYaxis() ? Util.mm2px(bedHeight, resolution) - y : y, resolution));
+    out.printf("1 %f %f\n", px2steps(isFlipXaxis() ? Util.mm2px(bedWidth, resolution) - x : x, resolution), px2steps(isFlipYaxis() ? Util.mm2px(bedHeight, resolution) - y : y, resolution));
   }
 
   private byte[] generatePseudoRaster3dGCode(Raster3dPart rp, int resolution) throws UnsupportedEncodingException
@@ -338,7 +359,7 @@ public class LaosCutter extends LaserCutter
     for (int raster = 0; raster < rp.getRasterCount(); raster++)
     {
       Point rasterStart = rp.getRasterStart(raster);
-      LaserProperty prop = rp.getLaserProperty(raster);
+      FloatPowerSpeedFocusFrequencyProperty prop = (FloatPowerSpeedFocusFrequencyProperty) rp.getLaserProperty(raster);
       //Set focus
       out.printf(Locale.US, "2 %d\n", (int) Util.mm2px(prop.getFocus(), resolution));
       for (int line = 0; line < rp.getRasterHeight(raster); line++)
@@ -425,7 +446,7 @@ public class LaosCutter extends LaserCutter
     for (int raster = 0; raster < rp.getRasterCount(); raster++)
     {
       Point rasterStart = rp.getRasterStart(raster);
-      LaserProperty prop = rp.getLaserProperty(raster);
+      FloatPowerSpeedFocusFrequencyProperty prop = (FloatPowerSpeedFocusFrequencyProperty) rp.getLaserProperty(raster);
       //Set focus
       out.printf(Locale.US, "2 %d\n", (int) Util.mm2px(prop.getFocus(), resolution));
       for (int line = 0; line < rp.getRasterHeight(raster); line++)
@@ -579,7 +600,7 @@ public class LaosCutter extends LaserCutter
     for (int raster = 0; raster < rp.getRasterCount(); raster++)
     {
       Point rasterStart = rp.getRasterStart(raster);
-      LaserProperty prop = rp.getLaserProperty(raster);
+      FloatPowerSpeedFocusFrequencyProperty prop = (FloatPowerSpeedFocusFrequencyProperty) rp.getLaserProperty(raster);
       //Set focus
       out.printf(Locale.US, "2 %d\n", (int) Util.mm2px(prop.getFocus(), resolution));
       for (int line = 0; line < rp.getRasterHeight(raster); line++)
diff --git a/src/com/t_oster/liblasercut/drivers/Lasersaur.java b/src/com/t_oster/liblasercut/drivers/Lasersaur.java
index 1ceb673..85550db 100644
--- a/src/com/t_oster/liblasercut/drivers/Lasersaur.java
+++ b/src/com/t_oster/liblasercut/drivers/Lasersaur.java
@@ -162,18 +162,10 @@ public class Lasersaur extends LaserCutter {
           y = cmd.getY();
           line(out, x, y, resolution);
           break;
-        case SETPOWER:
-          setPower(out, cmd.getPower());
-          break;
-        case SETFOCUS:
-          float focus = cmd.getFocus();
-          break;
-        case SETSPEED:
-          int speed = cmd.getSpeed();
-          setSpeed(out, speed);
-          break;
-        case SETFREQUENCY:
-          int frequency = cmd.getFrequency();
+        case SETPROPERTY:
+          PowerSpeedFocusFrequencyProperty p = (PowerSpeedFocusFrequencyProperty) cmd.getProperty();
+          setPower(out, p.getPower());
+          setSpeed(out, p.getSpeed());
           break;
       }
     }
@@ -211,7 +203,7 @@ public class Lasersaur extends LaserCutter {
     boolean dirRight = true;
     for (int raster = 0; raster < rp.getRasterCount(); raster++) {
       Point rasterStart = rp.getRasterStart(raster);
-      LaserProperty prop = rp.getLaserProperty(raster);
+      PowerSpeedFocusProperty prop = (PowerSpeedFocusProperty) rp.getLaserProperty(raster);
       setSpeed(out, prop.getSpeed());
       for (int line = 0; line < rp.getRasterHeight(raster); line++) {
         Point lineStart = rasterStart.clone();
@@ -279,7 +271,7 @@ public class Lasersaur extends LaserCutter {
     boolean dirRight = true;
     for (int raster = 0; raster < rp.getRasterCount(); raster++) {
       Point rasterStart = rp.getRasterStart(raster);
-      LaserProperty prop = rp.getLaserProperty(raster);
+      PowerSpeedFocusProperty prop = (PowerSpeedFocusProperty) rp.getLaserProperty(raster);
       setSpeed(out, prop.getSpeed());
       setPower(out, prop.getPower());
       for (int line = 0; line < rp.getRasterHeight(raster); line++) {
diff --git a/src/com/t_oster/liblasercut/examples/PhotoPrint.java b/src/com/t_oster/liblasercut/examples/PhotoPrint.java
index 6d37b29..e743ea8 100644
--- a/src/com/t_oster/liblasercut/examples/PhotoPrint.java
+++ b/src/com/t_oster/liblasercut/examples/PhotoPrint.java
@@ -23,6 +23,8 @@ import com.t_oster.liblasercut.BlackWhiteRaster.DitherAlgorithm;
 import com.t_oster.liblasercut.IllegalJobException;
 import com.t_oster.liblasercut.LaserJob;
 import com.t_oster.liblasercut.LaserProperty;
+import com.t_oster.liblasercut.PowerSpeedFocusFrequencyProperty;
+import com.t_oster.liblasercut.PowerSpeedFocusProperty;
 import com.t_oster.liblasercut.RasterPart;
 import com.t_oster.liblasercut.VectorPart;
 import com.t_oster.liblasercut.drivers.EpilogZing;
@@ -175,11 +177,11 @@ public class PhotoPrint {
             //}
             //JOptionPane.showMessageDialog(null, material);
             //TODO: repair Material Selection
-            RasterPart rp = new RasterPart(new LaserProperty());
+            RasterPart rp = new RasterPart(new PowerSpeedFocusProperty());
             rp.addImage(new BlackWhiteRaster(new BufferedImageAdapter(outImg), BlackWhiteRaster.DitherAlgorithm.AVERAGE), new Point(0, 0));
             VectorPart vp = null;
             if (cbCut.isSelected()) {
-                vp = new VectorPart(new LaserProperty());
+                vp = new VectorPart(new PowerSpeedFocusFrequencyProperty());
                 vp.moveto(0, 0);
                 vp.lineto(outImg.getWidth(), 0);
                 vp.lineto(outImg.getWidth(), outImg.getHeight());
diff --git a/test/com/t_oster/liblasercut/drivers/EpilogCutterTest.java b/test/com/t_oster/liblasercut/drivers/EpilogCutterTest.java
deleted file mode 100644
index d51f3db..0000000
--- a/test/com/t_oster/liblasercut/drivers/EpilogCutterTest.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/**
- * This file is part of VisiCut.
- * 
- *     VisiCut is free software: you can redistribute it and/or modify
- *     it under the terms of the Lesser GNU General Public License as published by
- *     the Free Software Foundation, either version 3 of the License, or
- *     (at your option) any later version.
- * 
- *    VisiCut is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     Lesser GNU General Public License for more details.
- * 
- *     You should have received a copy of the GNU General Public License
- *     along with VisiCut.  If not, see <http://www.gnu.org/licenses/>.
- **/
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package com.t_oster.liblasercut.drivers;
-
-import java.awt.Font;
-import com.t_oster.liblasercut.utils.BufferedImageAdapter;
-import java.awt.Graphics;
-import java.awt.image.BufferedImage;
-import com.t_oster.liblasercut.platform.Point;
-import com.t_oster.liblasercut.*;
-import java.awt.Color;
-import java.util.LinkedList;
-import java.util.List;
-import org.junit.Test;
-import static org.junit.Assert.*;
-
-/**
- *
- * @author thommy
- */
-public class EpilogCutterTest
-{
-
-  @Test
-  public void testEncode()
-  {
-    EpilogCutter instance = new EpilogZing(null);
-    List<Byte> in = new LinkedList<Byte>();
-    for (int k = 0; k < 100; k++)
-    {
-      in.add((byte) 7);
-    }
-    for (int k = 0; k < 50; k++)
-    {
-      in.add((byte) k);
-    }
-    in = instance.encode(in);
-    assertEquals((byte) -99, (byte) in.get(0));
-    assertEquals((byte) 7, (byte) in.get(1));
-    assertEquals((byte) 49, (byte) in.get(2));
-    for (int k = 0; k < 50; k++)
-    {
-      assertEquals((byte) k, (byte) in.get(3 + k));
-    }
-    assertEquals((byte) -128, (byte) 0x80);
-  }
-
-  private BufferedImage getTestImage()
-    {
-      BufferedImage testbild = new BufferedImage(300,300, BufferedImage.TYPE_INT_RGB);
-    Graphics g = testbild.getGraphics();
-    g.setColor(Color.WHITE);
-    g.fillRect(0, 0, 300, 300);
-    g.setColor(Color.BLACK);
-    g.drawRect(0, 0, 299, 299);
-    g.setFont(new Font("sansserif", Font.BOLD, 12));
-    g.drawString("The quick brown fox jumps", 0, 20);
-    g.drawString("over the lazy dog.", 0, 40);
-    g.fillRect(0, 150, 75, 75);
-    g.setColor(Color.WHITE);
-    g.fillRect(75, 150, 75, 75);
-    g.setColor(Color.DARK_GRAY);
-    g.fillRect(150, 150, 75, 75);
-    g.setColor(Color.LIGHT_GRAY);
-    g.fillRect(3*75, 150, 75, 75);
-    for (int x=0;x<300;x++){
-        g.setColor(new Color(255*x/300,255*x/300,255*x/300));
-        g.drawLine(x, 200, x, 300);
-    }
-    return testbild;
-  }
-
-  /**
-   * This method sends a job which contains all three parts (raster,raster3d,vector)
-   * and also tests focus change on every part
-   */
-  @Test
-  public void testFullJob() throws IllegalJobException, Exception
-  {
-    EpilogCutter.SIMULATE_COMMUNICATION = false;
-    System.out.println("sendJob");
-
-    EpilogCutter instance = new EpilogZing("137.226.56.228");
-    System.out.println("Creating VP");
-    VectorPart vp = new VectorPart(new LaserProperty(50, 100, 5000));
-    vp.moveto(0, 0);
-    vp.lineto(100, 0);
-    vp.lineto(100, 100);
-    vp.lineto(0, 100);
-    vp.lineto(0, 0);
-    vp.moveto(200, 0);
-    vp.setFocus(300);
-    vp.lineto(300, 0);
-    vp.lineto(300, 100);
-    vp.lineto(200, 100);
-    vp.lineto(200, 0);
-    System.out.println("Creating RP");
-    RasterPart rp = new RasterPart(new LaserProperty(80, 100));
-    rp.addImage(new BlackWhiteRaster(new BufferedImageAdapter(getTestImage()), BlackWhiteRaster.DitherAlgorithm.FLOYD_STEINBERG), new Point(0, 200));
-    System.out.println("Creating R3dP");
-    Raster3dPart r3p = new Raster3dPart(new LaserProperty(80, 100));
-    r3p.addImage(new BufferedImageAdapter(getTestImage()), new Point(0, 600));
-    System.out.println("Creating Job");
-    LaserJob job = new LaserJob("allparts", "123", "bla", 500, r3p, vp, rp);
-    System.out.println("Sending Job");
-    instance.sendJob(job);
-    System.out.println("Done.");
-  }
-}
diff --git a/test/com/t_oster/liblasercut/drivers/FocusStrokesTest.java b/test/com/t_oster/liblasercut/drivers/FocusStrokesTest.java
deleted file mode 100644
index d9a785d..0000000
--- a/test/com/t_oster/liblasercut/drivers/FocusStrokesTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * This file is part of VisiCut.
- * 
- *     VisiCut is free software: you can redistribute it and/or modify
- *     it under the terms of the Lesser GNU General Public License as published by
- *     the Free Software Foundation, either version 3 of the License, or
- *     (at your option) any later version.
- * 
- *    VisiCut is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     Lesser GNU General Public License for more details.
- * 
- *     You should have received a copy of the GNU General Public License
- *     along with VisiCut.  If not, see <http://www.gnu.org/licenses/>.
- **/
-package com.t_oster.liblasercut.drivers;
-
-import com.t_oster.liblasercut.*;
-import com.t_oster.liblasercut.platform.Point;
-import org.junit.Test;
-
-/**
- * This test is a cutting job which detects the line behavior
- * at different focus distances
- * @author oster
- */
-public class FocusStrokesTest
-{
-
-  @Test
-  public void focuslines() throws IllegalJobException, Exception
-  {
-    RasterPart rp = new RasterPart(new LaserProperty(20,10,5000,10));
-    BlackWhiteRaster bwr = new BlackWhiteRaster(10000,50);
-    for (int y=0;y<50;y++)
-    {
-      for (int x=0;x<10000;x++)
-      {
-        bwr.setBlack(x, y, true);
-      }
-    }
-    rp.addImage(bwr, new Point(0,0));
-    LaserJob job = new LaserJob("focus", "bla", "bla", 500, null, null, rp);
-    EpilogCutter instance = new EpilogZing("137.226.56.228");
-    instance.sendJob(job);
-  }
-}
diff --git a/test/com/t_oster/liblasercut/drivers/LaosCutterTest.java b/test/com/t_oster/liblasercut/drivers/LaosCutterTest.java
deleted file mode 100644
index 4e661f7..0000000
--- a/test/com/t_oster/liblasercut/drivers/LaosCutterTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.t_oster.liblasercut.drivers;
-
-import com.t_oster.liblasercut.IllegalJobException;
-import com.t_oster.liblasercut.LaserJob;
-import com.t_oster.liblasercut.LaserProperty;
-import com.t_oster.liblasercut.VectorPart;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import static org.junit.Assert.*;
-
-/**
- *
- * @author Thomas Oster <thomas.oster@rwth-aachen.de>
- */
-public class LaosCutterTest
-{
-  
-  public LaosCutterTest()
-  {
-  }
-
-  @BeforeClass
-  public static void setUpClass() throws Exception
-  {
-  }
-
-  @AfterClass
-  public static void tearDownClass() throws Exception
-  {
-  }
-
-  @Test
-  public void testSomeMethod() throws IllegalJobException, Exception
-  {
-    LaosCutter lc = new LaosCutter();
-    lc.setUseTftp(true);
-    lc.setHostname("192.168.2.111");
-    lc.setPort(2000);
-    VectorPart vp = new VectorPart(new LaserProperty());
-    vp.moveto(100,100);
-    vp.lineto(200, 100);
-    LaserJob job = new LaserJob("bla", "bla", "bla", 500, null, vp, null);
-    lc.sendJob(job);
-  }
-}
diff --git a/test/com/t_oster/liblasercut/drivers/MaterialTest.java b/test/com/t_oster/liblasercut/drivers/MaterialTest.java
deleted file mode 100644
index d6edd32..0000000
--- a/test/com/t_oster/liblasercut/drivers/MaterialTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * This file is part of VisiCut.
- * 
- *     VisiCut is free software: you can redistribute it and/or modify
- *     it under the terms of the Lesser GNU General Public License as published by
- *     the Free Software Foundation, either version 3 of the License, or
- *     (at your option) any later version.
- * 
- *    VisiCut is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     Lesser GNU General Public License for more details.
- * 
- *     You should have received a copy of the GNU General Public License
- *     along with VisiCut.  If not, see <http://www.gnu.org/licenses/>.
- **/
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package com.t_oster.liblasercut.drivers;
-
-import com.t_oster.liblasercut.*;
-import javax.swing.JOptionPane;
-import org.junit.Test;
-
-/**
- *
- * @author oster
- */
-public class MaterialTest
-{
-
-  @Test
-  public void rects2() throws IllegalJobException, Exception
-  {
-    VectorPart vp = new VectorPart(new LaserProperty(10, 100, 5000));
-    int x = 0;
-    for (int speed = 40; speed >= 10; speed -= 10)
-    {
-      vp.setSpeed(speed);
-      for (int power = 10; power <= 100; power += 5)
-      {
-        vp.moveto(300 * x, 15 * power);
-        vp.setPower(power);
-        vp.lineto(300 * x + 200, 15 * power);
-        vp.lineto(300 * x + 200, 15 * power + 50);
-        vp.lineto(300 * x, 15 * power + 50);
-        vp.lineto(300 * x, 15 * power);
-      }
-      x++;
-    }
-    LaserJob job = new LaserJob("rects40-10", "bla", "bla", 500, null, vp, null);
-    EpilogCutter instance = new EpilogZing("137.226.56.228");
-    //instance.sendJob(job);
-    JOptionPane.showConfirmDialog(null, "Please start the job with the name 'rects100-50' and STOP when cut through");
-    int row = Integer.parseInt(JOptionPane.showInputDialog(null, "Please enter row of the first cut through (1...20)"));
-    int column = Integer.parseInt(JOptionPane.showInputDialog(null, "Please enter column of the first cut through (1...5)"));
-    int cutpower = 5 + row * 5;
-    int cutspeed = 50 - column * 10;
-    vp = new VectorPart(new LaserProperty(cutpower, cutspeed, 5000));
-    x = 0;
-    for (int speed = 40; speed >= 10; speed -= 10)
-    {
-      //vp.setSpeed(speed);
-      vp.moveto(300 * x, 0);
-      vp.lineto(300 * x + 100, 0);
-      vp.lineto(300 * x + 100, 1500);
-      vp.lineto(300 * x, 1500);
-      vp.lineto(300 * x, 0);
-      x++;
-    }
-    job = new LaserJob("cutout", "bla", "bla", 500, null, vp, null);
-    instance.sendJob(job);
-    JOptionPane.showConfirmDialog(null, "please cut out");
-  }
-
-  @Test
-  public void rects() throws IllegalJobException, Exception
-  {
-    VectorPart vp = new VectorPart(new LaserProperty(10, 100, 5000));
-    int x = 0;
-    for (int speed = 100; speed >= 50; speed -= 10)
-    {
-      vp.setSpeed(speed);
-      for (int power = 10; power <= 100; power += 5)
-      {
-        vp.moveto(300 * x, 15 * power);
-        vp.setPower(power);
-        vp.lineto(300 * x + 200, 15 * power);
-        vp.lineto(300 * x + 200, 15 * power + 50);
-        vp.lineto(300 * x, 15 * power + 50);
-        vp.lineto(300 * x, 15 * power);
-      }
-      x++;
-    }
-    LaserJob job = new LaserJob("rects100-50", "bla", "bla", 500, null, vp, null);
-    EpilogCutter instance = new EpilogZing("137.226.56.228");
-    instance.sendJob(job);
-    JOptionPane.showConfirmDialog(null, "Please start the job with the name 'rects100-50' and STOP when cut through");
-    int row = Integer.parseInt(JOptionPane.showInputDialog(null, "Please enter row of the first cut through (1...20)"));
-    int column = Integer.parseInt(JOptionPane.showInputDialog(null, "Please enter column of the first cut through (1...5)"));
-    int cutpower = 5 + row * 5;
-    int cutspeed = 100 - column * 10;
-    vp = new VectorPart(new LaserProperty(cutpower, cutspeed, 5000));
-    x = 0;
-    for (int speed = 100; speed >= 50; speed -= 10)
-    {
-      //vp.setSpeed(speed);
-      vp.moveto(300 * x, 0);
-      vp.lineto(300 * x + 100, 0);
-      vp.lineto(300 * x + 100, 1500);
-      vp.lineto(300 * x, 1500);
-      vp.lineto(300 * x, 0);
-      x++;
-    }
-    job = new LaserJob("cutout", "bla", "bla", 500, null, vp, null);
-    JOptionPane.showConfirmDialog(null, "please cut out");
-  }
-}
diff --git a/test/com/t_oster/liblasercut/drivers/StartPointTest.java b/test/com/t_oster/liblasercut/drivers/StartPointTest.java
deleted file mode 100644
index 1500e88..0000000
--- a/test/com/t_oster/liblasercut/drivers/StartPointTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- * This file is part of VisiCut.
- * 
- *     VisiCut is free software: you can redistribute it and/or modify
- *     it under the terms of the Lesser GNU General Public License as published by
- *     the Free Software Foundation, either version 3 of the License, or
- *     (at your option) any later version.
- * 
- *    VisiCut is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     Lesser GNU General Public License for more details.
- * 
- *     You should have received a copy of the GNU General Public License
- *     along with VisiCut.  If not, see <http://www.gnu.org/licenses/>.
- **/
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package com.t_oster.liblasercut.drivers;
-
-import javax.swing.JOptionPane;
-import com.t_oster.liblasercut.LaserJob;
-import com.t_oster.liblasercut.VectorPart;
-import com.t_oster.liblasercut.LaserProperty;
-import com.t_oster.liblasercut.IllegalJobException;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/**
- *
- * @author oster
- */
-public class StartPointTest {
-
-    public StartPointTest() {
-    }
-
-    @BeforeClass
-    public static void setUpClass() throws Exception {
-    }
-
-    @AfterClass
-    public static void tearDownClass() throws Exception {
-    }
-
-    @Before
-    public void setUp() {
-    }
-
-    @After
-    public void tearDown() {
-    }
-
-    @Test
-  public void testMovingAtTheEnd() throws IllegalJobException, Exception
-  {
-    EpilogCutter.SIMULATE_COMMUNICATION = false;
-    System.out.println("sendJob");
-
-    EpilogCutter instance = new EpilogZing("137.226.56.228");
-    VectorPart vp = new VectorPart(new LaserProperty(50, 100, 5000));
-    vp.moveto(2000, 1000);
-    vp.setFocus(200);
-    vp.setFocus(0);
-    vp.moveto(0, 100);
-    vp.lineto(200, 100);
-    vp.moveto(100, 0);
-    vp.lineto(100,200);
-
-    vp.moveto(2000, 1100);
-    vp.lineto(2200, 1100);
-    vp.moveto(2100, 1000);
-    vp.lineto(2100,1200);
-    LaserJob job = new LaserJob("startPoint", "123", "bla", 500, null, vp, null);
-    instance.sendJob(job);
-    JOptionPane.showMessageDialog(null, "Please start the job 'startPoint' and then position your material");
-  }
-
-}
\ No newline at end of file
-- 
GitLab