Skip to content
Snippets Groups Projects
Commit 16c6037a authored by Michael Adams's avatar Michael Adams
Browse files

Add support for bi-directional raster cutting

parent 13b1e776
No related branches found
No related tags found
No related merge requests found
......@@ -187,26 +187,37 @@ public abstract class LaserCutter implements Cloneable, Customizable {
* emulate this functionality using gcode.
* @param rp the raster job to convert
* @param resolution resolution to output job at
* @param bidirectional cut in both directions
* @return a VectorPart job of VectorCommands
*/
protected VectorPart convertRasterizableToVectorPart(RasterizableJobPart rp, double resolution)
protected VectorPart convertRasterizableToVectorPart(RasterizableJobPart rp, double resolution, boolean bidirectional)
{
boolean cutDirectionleftToRight = true;
VectorPart result = new VectorPart(rp.getLaserProperty(), resolution);
for (int y = 0; y < rp.getRasterHeight(); y++)
{
if (rp.lineIsBlank(y) == false)
{
rp.setRasteringCutDirection(cutDirectionleftToRight);
Point lineStart = rp.getStartPosition(y);
// fix off-by-one errors when cutting in reverse direction, since
// functions always refer to the bottom left corner of a pixels
// and when cutting in reverse direction, we need to take pixel width
// into account.
int lineCompensation = cutDirectionleftToRight ? 0 : 1;
//move to the first point of the line
result.moveto(lineStart.x + rp.firstNonWhitePixel(y), lineStart.y);
result.moveto(lineStart.x + rp.firstNonWhitePixel(y)+lineCompensation, lineStart.y);
for (int x = rp.firstNonWhitePixel(y); x < rp.lastNonWhitePixel(y);)
for (int x = rp.firstNonWhitePixel(y); cutDirectionleftToRight ? (x < rp.lastNonWhitePixel(y)) : (x > rp.lastNonWhitePixel(y));)
{
result.setProperty(rp.getPowerSpeedFocusPropertyForPixel(x, y));
x = rp.nextColorChange(x, y);
result.lineto(lineStart.x + x, lineStart.y);
result.lineto(lineStart.x + x + lineCompensation, lineStart.y);
}
if (bidirectional) cutDirectionleftToRight = !cutDirectionleftToRight;
}
}
return result;
......
......@@ -28,6 +28,7 @@ abstract public class RasterizableJobPart extends JobPart
{
protected GreyscaleRaster image;
protected Point start = null;
protected boolean cutDirectionleftToRight;
/**
* The initial laser settings to start a rasterization job with.
......@@ -64,12 +65,38 @@ abstract public class RasterizableJobPart extends JobPart
return true;
}
/**
* Set the direction cutting is done in. Left to right by default; when changed
* then "start" of the line is the right-most side, and "end" is the left-most
* side.
* @param cutDirectionleftToRight
* true to cut in a left to right direction,
* false for other directions.
*/
public void setRasteringCutDirection(boolean cutDirectionleftToRight)
{
this.cutDirectionleftToRight = cutDirectionleftToRight;
}
/**
* Finds the x coordinate of the first pixel that needs lasering
* @param y
* @return x coordinate to start lasering from
*/
public int firstNonWhitePixel(int y)
{
return cutDirectionleftToRight
? leftMostNonWhitePixel(y)
: rightMostNonWhitePixel(y);
}
/**
* Finds the x coordinate for the left most pixel, since "start" depends on
* what direction you are cutting in.
* @param y
* @return x coordinate of left most non-white pixel
*/
protected int leftMostNonWhitePixel(int y)
{
for (int x=0; x<getRasterWidth(); x++)
if (image.getGreyScale(x, y) < 255)
......@@ -83,6 +110,19 @@ abstract public class RasterizableJobPart extends JobPart
* @return x coordinate to end lasering at
*/
public int lastNonWhitePixel(int y)
{
return cutDirectionleftToRight
? rightMostNonWhitePixel(y)
: leftMostNonWhitePixel(y);
}
/**
* Finds the x coordinate for the right most pixel, since "end" depends on
* what direction you are cutting in.
* @param y
* @return x coordinate of right most non-white pixel
*/
protected int rightMostNonWhitePixel(int y)
{
for (int x=getRasterWidth()-1; x >= 0; x--)
if (image.getGreyScale(x, y) < 255)
......@@ -98,13 +138,42 @@ abstract public class RasterizableJobPart extends JobPart
* @return x coordinate of the next different color in this row
*/
public int nextColorChange(int x, int y)
{
return cutDirectionleftToRight
? nextColorChangeHeadingRight(x, y)
: nextColorChangeHeadingLeft(x, y);
}
/**
* nextColorChange logic when heading ->
* @param x x coordinate to start scanning from
* @param y y coordinate to start scanning from
* @return x coordinate of the next different color in this row
*/
protected int nextColorChangeHeadingRight(int x, int y)
{
int color = image.getGreyScale(x, y);
for (int i=x; i<getRasterWidth(); i++)
if (image.getGreyScale(i, y) != color)
return i;
// whole line is the same color, so go to end of line
return lastNonWhitePixel(y);
return rightMostNonWhitePixel(y);
}
/**
* nextColorChange logic when heading <-
* @param x x coordinate to start scanning from
* @param y y coordinate to start scanning from
* @return x coordinate of the next different color in this row
*/
protected int nextColorChangeHeadingLeft(int x, int y)
{
int color = image.getGreyScale(x, y);
for (int i=x; i>=0; i--)
if (image.getGreyScale(i, y) != color)
return i;
// whole line is the same color, so go to end of line
return leftMostNonWhitePixel(y);
}
/**
......
......@@ -68,6 +68,7 @@ public class GenericGcodeDriver extends LaserCutter {
protected static final String SETTING_SERIAL_TIMEOUT = "Milliseconds to wait for response";
protected static final String SETTING_BLANK_LASER_DURING_RAPIDS = "Force laser off during G0 moves";
protected static final String SETTING_FILE_EXPORT_PATH = "Path to save exported gcode";
protected static final String SETTING_USE_BIDIRECTIONAL_RASTERING = "Use bidirectional rastering";
protected static Locale FORMAT_LOCALE = Locale.US;
......@@ -322,6 +323,22 @@ public class GenericGcodeDriver extends LaserCutter {
this.blankLaserDuringRapids = blankLaserDuringRapids;
}
/**
* When rastering, whether to always cut from left to right, or to cut in both
* directions? (i.e. use the return stroke to raster as well)
*/
protected boolean useBidirectionalRastering = false;
public boolean getUseBidirectionalRastering()
{
return useBidirectionalRastering;
}
public void setUseBidirectionalRastering(boolean useBidirectionalRastering)
{
this.useBidirectionalRastering = useBidirectionalRastering;
}
@Override
/**
* We do not support Frequency atm, so we return power,speed and focus
......@@ -723,7 +740,7 @@ public class GenericGcodeDriver extends LaserCutter {
{
if (p instanceof Raster3dPart || p instanceof RasterPart)
{
p = convertRasterizableToVectorPart((RasterizableJobPart) p, p.getDPI());
p = convertRasterizableToVectorPart((RasterizableJobPart) p, p.getDPI(), getUseBidirectionalRastering());
}
if (p instanceof VectorPart)
{
......@@ -763,7 +780,7 @@ public void saveJob(java.io.PrintStream fileOutputStream, LaserJob job) throws I
{
if (p instanceof Raster3dPart || p instanceof RasterPart)
{
p = convertRasterizableToVectorPart((RasterizableJobPart) p, p.getDPI());
p = convertRasterizableToVectorPart((RasterizableJobPart) p, p.getDPI(), getUseBidirectionalRastering());
}
if (p instanceof VectorPart)
{
......@@ -851,7 +868,8 @@ public void saveJob(java.io.PrintStream fileOutputStream, LaserJob job) throws I
SETTING_RESOLUTIONS,
SETTING_WAIT_FOR_OK,
SETTING_SERIAL_TIMEOUT,
SETTING_FILE_EXPORT_PATH
SETTING_FILE_EXPORT_PATH,
SETTING_USE_BIDIRECTIONAL_RASTERING
};
@Override
......@@ -905,6 +923,8 @@ public void saveJob(java.io.PrintStream fileOutputStream, LaserJob job) throws I
return this.getBlankLaserDuringRapids();
} else if (SETTING_FILE_EXPORT_PATH.equals(attribute)) {
return this.getExportPath();
} else if (SETTING_USE_BIDIRECTIONAL_RASTERING.equals(attribute)) {
return this.getUseBidirectionalRastering();
}
return null;
......@@ -956,6 +976,8 @@ public void saveJob(java.io.PrintStream fileOutputStream, LaserJob job) throws I
this.setBlankLaserDuringRapids((Boolean) value);
} else if (SETTING_FILE_EXPORT_PATH.equals(attribute)) {
this.setExportPath((String) value);
} else if (SETTING_USE_BIDIRECTIONAL_RASTERING.equals(attribute)) {
this.setUseBidirectionalRastering((Boolean) value);
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment