Compare commits

..

No commits in common. "master" and "2015-09-13-18-54" have entirely different histories.

14 changed files with 498 additions and 1247 deletions

View File

@ -316,10 +316,6 @@ class DisplayMachine extends Machine
{
drawExtractedPixelCentres();
}
if (displayingGridSpots)
{
drawGridIntersections();
}
if (displayingDensityPreview)
{
drawExtractedPixelDensities();
@ -536,13 +532,10 @@ class DisplayMachine extends Machine
beginShape();
inShape = true;
}
// PVector nativeCoords = asNativeCoords(inSteps(p));
// println(j + "! Adding point " + nativeCoords);
p = scaleToScreen(p);
stroke(strokeColour);
vertex(p.x, p.y);
// ellipse(p.x, p.y, 2, 2);
//ellipse(p.x, p.y, 3, 3);
}
else
{
@ -667,18 +660,10 @@ class DisplayMachine extends Machine
*/
public void drawRows()
{
float rowThickness = inMM(getGridSize()) * getScaling();
rowThickness = (rowThickness < 1.0) ? 1.0 : rowThickness;
strokeWeight(rowThickness);
stroke(150, 200, 255, 50);
strokeCap(SQUARE);
drawRow(getMouseVector(), true, true);
noStroke();
}
PVector mVect = getMouseVector();
public void drawRow(PVector mouse, boolean left, boolean right) {
// scale it to find out the coordinates on the machine that the mouse is pointing at.
PVector mVect = scaleToDisplayMachine(mouse);
mVect = scaleToDisplayMachine(mVect);
// convert it to the native coordinates system
mVect = convertToNative(mVect);
// snap it to the grid
@ -689,15 +674,17 @@ class DisplayMachine extends Machine
// and finally, because scaleToScreen also allows for the machine position (offset), subtract it.
mVect.sub(getOffset());
float rowThickness = inMM(getGridSize()) * getScaling();
rowThickness = (rowThickness < 1.0) ? 1.0 : rowThickness;
strokeWeight(rowThickness);
stroke(150, 200, 255, 50);
strokeCap(SQUARE);
float dia = mVect.x*2;
if (left) {
arc(getOutline().getLeft(), getOutline().getTop(), dia, dia, 0, 1.57079633);
}
arc(getOutline().getLeft(), getOutline().getTop(), dia, dia, 0, 1.57079633);
dia = mVect.y*2;
if (right) {
arc(getOutline().getRight(), getOutline().getTop(), dia, dia, 1.57079633, 3.14159266);
}
arc(getOutline().getRight(), getOutline().getTop(), dia, dia, 1.57079633, 3.14159266);
}
@ -715,28 +702,6 @@ class DisplayMachine extends Machine
}
}
void drawGridIntersections()
{
// println("oh");
}
int pixel_maxDensity(float penSize, float rowSizeInMM)
{
float numberOfSegments = rowSizeInMM / penSize;
int maxDens = 1;
if (numberOfSegments >= 2.0) {
maxDens = int(numberOfSegments);
}
if (maxDens <= 1) {
maxDens = 1;
}
return maxDens;
}
void drawExtractedPixelDensities()
{
@ -745,37 +710,16 @@ class DisplayMachine extends Machine
pixelSize = pixelSize * getPixelScalingOverGridSize();
float rowSizeInMM = inMM(getGridSize()) * getPixelScalingOverGridSize();
int posterizeLevels = 255;
if (previewPixelDensityRange) {
posterizeLevels = pixel_maxDensity(currentPenWidth, rowSizeInMM);
}
else {
posterizeLevels = densityPreviewPosterize;
}
if (getExtractedPixels() != null)
{
for (PVector cartesianPos : getExtractedPixels())
{
if ((cartesianPos.z <= pixelExtractBrightThreshold) &&
(cartesianPos.z >= pixelExtractDarkThreshold))
if ((cartesianPos.z <= pixelExtractBrightThreshold) && (cartesianPos.z >= pixelExtractDarkThreshold))
{
// scale em, danno.
PVector scaledPos = scaleToScreen(cartesianPos);
noStroke();
if ((scaledPos.x <= 0) || (scaledPos.x > windowWidth) ||
(scaledPos.y <= 0) || (scaledPos.y > windowHeight)) {
continue;
}
// Posterize the density value
int reduced = int(map(cartesianPos.z, 1, 255, 1, posterizeLevels)+0.5);
int brightness = int(map(reduced, 1, posterizeLevels, 1, 255));
fill(brightness);
fill(cartesianPos.z);
switch (getDensityPreviewStyle())
{
case DENSITY_PREVIEW_ROUND:
@ -783,20 +727,20 @@ class DisplayMachine extends Machine
break;
case DENSITY_PREVIEW_ROUND_SIZE:
fill(0);
previewRoundPixel(scaledPos, map(brightness, 1, posterizeLevels, pixelSize, 1));
previewRoundPixel(scaledPos, map(cartesianPos.z, 1, 255, pixelSize, 1));
break;
case DENSITY_PREVIEW_DIAMOND:
previewDiamondPixel(scaledPos, pixelSize, pixelSize, brightness);
previewDiamondPixel(scaledPos, pixelSize, pixelSize, cartesianPos.z);
break;
case DENSITY_PREVIEW_NATIVE:
previewNativePixel(scaledPos, pixelSize, brightness);
previewNativePixel(scaledPos, pixelSize, cartesianPos.z);
break;
case DENSITY_PREVIEW_NATIVE_SIZE:
previewNativePixel(scaledPos, map(brightness, 1, posterizeLevels, pixelSize, 1), 50);
previewNativePixel(scaledPos, map(cartesianPos.z, 1, 255, pixelSize, 1), 50);
break;
case DENSITY_PREVIEW_NATIVE_ARC:
previewRoundPixel(scaledPos, pixelSize*0.8);
previewNativeArcPixel(scaledPos, pixelSize, brightness);
previewNativeArcPixel(scaledPos, pixelSize, cartesianPos.z);
break;
default:
previewRoundPixel(scaledPos, pixelSize);
@ -861,30 +805,25 @@ class DisplayMachine extends Machine
// plot out the vertexes
noFill();
stroke(0,0,0, 255-brightness);
try {
float i1Angle1 = atan2(int1.get(0).y-getOutline().getTop(), int1.get(0).x-getOutline().getLeft());
float i1Angle2 = atan2(int1.get(1).y-getOutline().getTop(), int1.get(1).x-getOutline().getLeft());
arc(getOutline().getLeft(), getOutline().getTop(), (distFromPointA-half)*2, (distFromPointA-half)*2, i1Angle1, i1Angle2);
float i1Angle1 = atan2(int1.get(0).y-getOutline().getTop(), int1.get(0).x-getOutline().getLeft());
float i1Angle2 = atan2(int1.get(1).y-getOutline().getTop(), int1.get(1).x-getOutline().getLeft());
arc(getOutline().getLeft(), getOutline().getTop(), (distFromPointA-half)*2, (distFromPointA-half)*2, i1Angle1, i1Angle2);
i1Angle1 = atan2(int2.get(0).y-getOutline().getTop(), int2.get(0).x-getOutline().getLeft());
i1Angle2 = atan2(int2.get(1).y-getOutline().getTop(), int2.get(1).x-getOutline().getLeft());
arc(getOutline().getLeft(), getOutline().getTop(), (distFromPointA+half)*2, (distFromPointA+half)*2, i1Angle1, i1Angle2);
i1Angle1 = atan2(int2.get(0).y-getOutline().getTop(), int2.get(0).x-getOutline().getLeft());
i1Angle2 = atan2(int2.get(1).y-getOutline().getTop(), int2.get(1).x-getOutline().getLeft());
arc(getOutline().getLeft(), getOutline().getTop(), (distFromPointA+half)*2, (distFromPointA+half)*2, i1Angle1, i1Angle2);
i1Angle1 = atan2( int1.get(0).y-getOutline().getTop(), int1.get(0).x-getOutline().getRight());
i1Angle2 = atan2( int2.get(0).y-getOutline().getTop(), int2.get(0).x-getOutline().getRight());
arc(getOutline().getRight(), getOutline().getTop(), (distFromPointB-half)*2, (distFromPointB-half)*2, i1Angle2, i1Angle1);
i1Angle1 = atan2( int1.get(0).y-getOutline().getTop(), int1.get(0).x-getOutline().getRight());
i1Angle2 = atan2( int2.get(0).y-getOutline().getTop(), int2.get(0).x-getOutline().getRight());
arc(getOutline().getRight(), getOutline().getTop(), (distFromPointB-half)*2, (distFromPointB-half)*2, i1Angle2, i1Angle1);
i1Angle1 = atan2( int1.get(1).y-getOutline().getTop(), int1.get(1).x-getOutline().getRight());
i1Angle2 = atan2( int2.get(1).y-getOutline().getTop(), int2.get(1).x-getOutline().getRight());
arc(getOutline().getRight(), getOutline().getTop(), (distFromPointB+half)*2, (distFromPointB+half)*2, i1Angle2, i1Angle1);
}
catch (IndexOutOfBoundsException ioobe) {
println(ioobe);
}
finally {
endShape();
}
i1Angle1 = atan2( int1.get(1).y-getOutline().getTop(), int1.get(1).x-getOutline().getRight());
i1Angle2 = atan2( int2.get(1).y-getOutline().getTop(), int2.get(1).x-getOutline().getRight());
arc(getOutline().getRight(), getOutline().getTop(), (distFromPointB+half)*2, (distFromPointB+half)*2, i1Angle2, i1Angle1);
endShape();
}

View File

@ -1,439 +0,0 @@
/**
Polargraph controller
Copyright Sandy Noble 2018.
This file is part of Polargraph Controller.
Polargraph Controller is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Polargraph Controller 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Polargraph Controller. If not, see <http://www.gnu.org/licenses/>.
Requires the excellent ControlP5 GUI library available from http://www.sojamo.de/libraries/controlP5/.
Requires the excellent Geomerative library available from http://www.ricardmarxer.com/geomerative/.
This is an application for controlling a polargraph machine, communicating using ASCII command language over a serial link.
sandy.noble@gmail.com
http://www.polargraph.co.uk/
https://github.com/euphy/polargraphcontroller
*/
void loadImageWithFileChooser()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run() {
JFileChooser fc = new JFileChooser();
if (lastImageDirectory != null) fc.setCurrentDirectory(lastImageDirectory);
fc.setFileFilter(new ImageFileFilter());
fc.setDialogTitle("Choose an image file...");
int returned = fc.showOpenDialog(frame);
lastImageDirectory = fc.getCurrentDirectory();
if (returned == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
// see if it's an image
PImage img = loadImage(file.getPath());
if (img != null)
{
img = null;
getDisplayMachine().loadNewImageFromFilename(file.getPath());
if (getDisplayMachine().pixelsCanBeExtracted() && isBoxSpecified())
{
getDisplayMachine().extractPixelsFromArea(getBoxVector1(), getBoxVectorSize(), getGridSize(), sampleArea);
}
}
}
}
});
}
class ImageFileFilter extends javax.swing.filechooser.FileFilter
{
public boolean accept(File file) {
String filename = file.getName();
filename.toLowerCase();
if (file.isDirectory() || filename.endsWith(".png") || filename.endsWith(".jpg") || filename.endsWith(".jpeg"))
return true;
else
return false;
}
public String getDescription() {
return "Image files (PNG or JPG)";
}
}
void loadVectorWithFileChooser()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run() {
JFileChooser fc = new JFileChooser();
if (lastImageDirectory != null)
{
fc.setCurrentDirectory(lastImageDirectory);
}
fc.setFileFilter(new VectorFileFilter());
fc.setDialogTitle("Choose a vector file...");
int returned = fc.showOpenDialog(frame);
lastImageDirectory = fc.getCurrentDirectory();
if (returned == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
if (file.exists())
{
RShape shape = loadShapeFromFile(file.getPath());
if (shape != null)
{
setVectorFilename(file.getPath());
setVectorShape(shape);
}
else
{
println("File not found (" + file.getPath() + ")");
}
}
}
}
}
);
}
class VectorFileFilter extends javax.swing.filechooser.FileFilter
{
public boolean accept(File file) {
String filename = file.getName();
filename.toLowerCase();
if (file.isDirectory() || filename.endsWith(".svg") || isGCodeExtension(filename))
return true;
else
return false;
}
public String getDescription() {
return "Vector graphic files (SVG, GCode)";
}
}
void loadNewPropertiesFilenameWithFileChooser()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JFileChooser fc = new JFileChooser();
if (lastPropertiesDirectory != null) fc.setCurrentDirectory(lastPropertiesDirectory);
fc.setFileFilter(new PropertiesFileFilter());
fc.setDialogTitle("Choose a config file...");
int returned = fc.showOpenDialog(frame);
lastPropertiesDirectory = fc.getCurrentDirectory();
if (returned == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
if (file.exists())
{
println("New properties file exists.");
newPropertiesFilename = file.toString();
println("new propertiesFilename: "+ newPropertiesFilename);
propertiesFilename = newPropertiesFilename;
// clear old properties.
props = null;
loadFromPropertiesFile();
// set values of number spinners etc
updateNumberboxValues();
}
}
}
});
}
class PropertiesFileFilter extends javax.swing.filechooser.FileFilter
{
public boolean accept(File file) {
String filename = file.getName();
filename.toLowerCase();
if (file.isDirectory() || filename.endsWith(".properties.txt"))
return true;
else
return false;
}
public String getDescription() {
return "Properties files (*.properties.txt)";
}
}
void saveNewPropertiesFileWithFileChooser()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JFileChooser fc = new JFileChooser();
if (lastPropertiesDirectory != null) fc.setCurrentDirectory(lastPropertiesDirectory);
fc.setFileFilter(new PropertiesFileFilter());
fc.setDialogTitle("Enter a config file name...");
int returned = fc.showSaveDialog(frame);
if (returned == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
newPropertiesFilename = file.toString();
newPropertiesFilename.toLowerCase();
if (!newPropertiesFilename.endsWith(".properties.txt"))
newPropertiesFilename+=".properties.txt";
println("new propertiesFilename: "+ newPropertiesFilename);
propertiesFilename = newPropertiesFilename;
savePropertiesFile();
// clear old properties.
props = null;
loadFromPropertiesFile();
}
}
});
}
RShape loadShapeFromFile(String filename) {
RShape sh = null;
if (filename.toLowerCase().endsWith(".svg")) {
sh = RG.loadShape(filename);
}
else if (isGCodeExtension(filename)) {
sh = loadShapeFromGCodeFile(filename);
}
return sh;
}
boolean isGCodeExtension(String filename) {
return (filename.toLowerCase().endsWith(".gcode") || filename.toLowerCase().endsWith(".g") || filename.toLowerCase().endsWith(".ngc") || filename.toLowerCase().endsWith(".txt"));
}
int countLines(String filename) throws IOException {
InputStream is = new BufferedInputStream(new FileInputStream(filename));
try {
byte[] c = new byte[1024];
int count = 0;
int readChars = 0;
boolean empty = true;
while ((readChars = is.read(c)) != -1) {
empty = false;
for (int i = 0; i < readChars; ++i) {
if (c[i] == '\n') {
++count;
}
}
}
return (count == 0 && !empty) ? 1 : count+1;
} finally {
is.close();
}
}
RShape loadShapeFromGCodeFile(String filename) {
noLoop();
RShape parent = null;
BufferedReader reader = null;
long totalPoints = 0;
long time = millis();
long countLines = 0;
try {
countLines = countLines(filename);
println("" + countLines + " lines found.");
if (countLines < 1) {
throw new IOException("No lines found in GCode file.");
}
reader = createReader(filename);
parent = new RShape();
String line;
boolean drawLine = false;
int gCodeZAxisChanges = 0;
long lineNo = 0;
float lastPercent = 0.0f;
boolean reportStatus = true;
while ((line = reader.readLine ()) != null) {
lineNo++;
// println("Line: " + line);
if (reportStatus) {
float percent = ((float)lineNo / (float)countLines) * 100.0;
println("----" + percent + "% of the way through.");
lastPercent = percent;
}
if (line.toUpperCase().startsWith("G")) {
if (reportStatus) {
println(new StringBuilder().append(lineNo).append(" of ").append(countLines).append(": ").append(line).append(". Points: ").append(totalPoints).toString());
long free = Runtime.getRuntime().freeMemory();
long maximum = Runtime.getRuntime().maxMemory();
println(new StringBuilder().append("Free: ").append(free).append(", max: ").append(maximum).toString());
}
Map<String, Float> ins = null;
try {
ins = unpackGCodeInstruction(line);
}
catch (Exception e) {
println(e.toString());
continue;
}
// println("Ins: " + ins);
Integer code = Math.round(ins.get("G"));
Float z = ins.get("Z");
if (z != null) {
gCodeZAxisChanges++;
if (gCodeZAxisChanges == 2) {
println("Assume second z axis change is to drop the pen to start drawing " + z);
gcodeZAxisDrawingHeight = z;
drawLine = true;
}
else if (gCodeZAxisChanges > 2) {
drawLine = isGCodeZAxisForDrawing(z);
}
else {
println("Assume first z axis change is to RAISE the pen " + z);
drawLine = false;
}
}
else { // if there is no Z axis, assume it's always on
// drawLine = true; // this isn't always safe!
}
Float x = ins.get("X");
Float y = ins.get("Y");
if (x != null && y == null) {
// move x axis only, use y of last
RPoint[][] points = parent.getPointsInPaths();
RPoint rp = points[points.length-1][points[points.length-1].length-1];
y = rp.y;
}
else if (x == null && y != null) {
// move y axis only, use x of last
RPoint[][] points = parent.getPointsInPaths();
RPoint rp = points[points.length-1][points[points.length-1].length-1];
x = rp.x;
}
if (x != null && y != null) {
// move both x and y axis
if (drawLine) {
parent.addLineTo(x, y);
}
else {
parent.addMoveTo(x, y);
}
}
}
else {
}
if ((millis() - time) > 500) {
time = millis();
reportStatus = true;
}
else {
reportStatus = false;
}
if (lineNo == (countLines-1)) {
reportStatus = true;
}
}
}
catch (IOException e) {
println("IOExecption reading lines from the gcode file " + filename);
e.printStackTrace();
}
finally {
try {
reader.close();
}
catch (IOException e) {
println("IOException closing the gcode file " + filename);
e.printStackTrace();
}
}
RPoint[][] points = parent.getPointsInPaths();
totalPoints = 0;
if (points != null) {
for (int i = 0; i<points.length; i++) {
if (points[i] != null) {
for (int j = 0; j<points[i].length; j++) {
totalPoints++;
}
}
}
}
String conclusionMessage = "Imported " + totalPoints + " points from " + countLines + " lines of code in the file.";
println(conclusionMessage);
javax.swing.JOptionPane.showMessageDialog(null, conclusionMessage);
loop();
return parent;
}
Boolean isGCodeZAxisForDrawing(float z) {
return gcodeZAxisDrawingHeight.compareTo(z) == 0;
}
Map<String, Float> unpackGCodeInstruction(String line) throws Exception {
Map<String, Float> instruction = new HashMap<String, Float>(4);
try {
String[] splitted = line.trim().split(" ");
for (int i = 0; i < splitted.length; i++) {
// remove ; character
splitted[i] = splitted[i].replace(";", "");
String axis = splitted[i].substring(0, 1);
String sanitisedValue = splitted[i].substring(1);
sanitisedValue = sanitisedValue.replace(",", ".");
Float value = Float.parseFloat(sanitisedValue);
if ("X".equalsIgnoreCase(axis) || "Y".equalsIgnoreCase(axis) || "Z".equalsIgnoreCase(axis) || "G".equalsIgnoreCase(axis)) {
instruction.put(axis.toUpperCase(), value);
}
}
// println("instruction: " + instruction);
if (instruction.isEmpty()) {
throw new Exception("Empty instruction");
}
}
catch (NumberFormatException nfe) {
println("Number format exception: " + nfe.getMessage());
}
catch (Exception e) {
println("e: " + e);
throw new Exception("Exception while reading the lines from a gcode file: " + line + ", " + e.getMessage());
}
return instruction;
}

View File

@ -39,7 +39,7 @@ class Machine
protected Rectangle imageFrame = new Rectangle(1500,1500,1000,1000);
protected Rectangle pictureFrame = new Rectangle(1600,1600,800,800);
protected Float stepsPerRev = 200.0;
protected Float stepsPerRev = 800.0;
protected Float mmPerRev = 95.0;
protected Float mmPerStep = null;
@ -186,15 +186,9 @@ class Machine
return mmInt;
}
public float inMMFloat(float steps)
{
double mm = steps / getStepsPerMM();
return (float) mm;
}
public PVector inMM (PVector steps)
{
PVector mm = new PVector(inMMFloat(steps.x), inMMFloat(steps.y));
PVector mm = new PVector(inMM(steps.x), inMM(steps.y));
return mm;
}
@ -292,16 +286,6 @@ class Machine
}
}
boolean isMasked(PVector pos, float scalingFactor)
{
switch (invertMaskMode) {
case MASK_IS_UNUSED: return false;
case MASKED_COLOURS_ARE_HIDDEN: return isChromaKey(pos, scalingFactor);
case MASKED_COLOURS_ARE_SHOWN: return !isChromaKey(pos, scalingFactor);
default: return false;
}
}
boolean isChromaKey(PVector pos, float scalingFactor)
{
if (getImageFrame().surrounds(pos))
@ -338,8 +322,8 @@ class Machine
public PVector asCartesianCoords(PVector pgCoords)
{
float calcX = (pow(getWidth(), 2.0) - pow(pgCoords.y, 2.0) + pow(pgCoords.x, 2.0)) / (getWidth()*2.0);
float calcY = sqrt(pow(pgCoords.x,2.0)-pow(calcX,2.0));
float calcX = int((pow(getWidth(), 2) - pow(pgCoords.y, 2) + pow(pgCoords.x, 2)) / (getWidth()*2));
float calcY = int(sqrt(pow(pgCoords.x,2)-pow(calcX,2)));
PVector vect = new PVector(calcX, calcY);
return vect;
}
@ -380,7 +364,7 @@ class Machine
public void loadDefinitionFromProperties(Properties props)
{
// get these first because they are important to convert the rest of them
setStepsPerRev(getFloatProperty("machine.motors.stepsPerRev", 200.0));
setStepsPerRev(getFloatProperty("machine.motors.stepsPerRev", 800.0));
setMMPerRev(getFloatProperty("machine.motors.mmPerRev", 95.0));
// now stepsPerMM and mmPerStep should have been calculated. It's safe to get the rest.
@ -399,12 +383,12 @@ class Machine
String pos = getStringProperty("controller.page.position.x", "CENTRE");
float px = 0.0;
println("machine size: " + getSize().x + ", " + inSteps(pageSize.x));
if (pos.equalsIgnoreCase("CENTRE")) {
if (pos.equalsIgnoreCase("CENTRE"))
{
px = inMM((getSize().x - pageSize.x) / 2.0);
}
else {
else
px = getFloatProperty("controller.page.position.x", (int) getDisplayMachine().getPageCentrePosition(pageSize.x));
}
float py = getFloatProperty("controller.page.position.y", 120);
@ -636,7 +620,7 @@ class Machine
PVector cartesianCoord = asCartesianCoords(nativeCoord);
if (selectedArea.surrounds(cartesianCoord))
{
if (isMasked(cartesianCoord, scalingFactor))
if (isChromaKey(cartesianCoord, scalingFactor))
{
nativeCoord.z = MASKED_PIXEL_BRIGHTNESS; // magic number
nativeCoords.add(nativeCoord);

View File

@ -24,7 +24,7 @@
sandy.noble@gmail.com
http://www.polargraph.co.uk/
https://github.com/euphy/polargraphcontroller
http://code.google.com/p/polargraph/
*/
class Panel
{
@ -120,11 +120,9 @@ class Panel
public void draw()
{
if (debugPanels) {
stroke(outlineColour);
strokeWeight(2);
rect(getOutline().getLeft(), getOutline().getTop(), getOutline().getWidth(), getOutline().getHeight());
}
//stroke(outlineColour);
//strokeWeight(2);
//rect(getOutline().getLeft(), getOutline().getTop(), getOutline().getWidth(), getOutline().getHeight());
drawControls();
}
@ -133,6 +131,7 @@ class Panel
{
for (Controller c : this.getControls())
{
// println("Control: " + c.getName());
PVector pos = getControlPositions().get(c.getName());
float x = pos.x+getOutline().getLeft();
float y = pos.y+getOutline().getTop();
@ -165,13 +164,6 @@ class Panel
locked = true;
}
// if there's no vector loaded, then hide vector controls
if (getControlsToLockIfVectorNotLoaded().contains(c.getName()) && vectorFilename == null)
{
locked = true;
}
if (c.getName().equals(MODE_LOAD_VECTOR_FILE))
{
if (getVectorShape() != null)
@ -208,28 +200,34 @@ class Panel
}
}
void setSizeByHeight(float h)
void setHeight(float h)
{
// println("Setting size for " + this.getName());
if (this.isResizable())
{
if (h <= getMinimumHeight())
this.getOutline().setHeight(getMinimumHeight());
else
this.getOutline().setHeight(h);
setControlPositions(buildControlPositionsForPanel(this));
float left = 0.0;
String controlName = "";
for (String key : getControlPositions().keySet())
{
PVector pos = getControlPositions().get(key);
if (pos.x > left)
if (pos.x >= left)
{
left = pos.x;
controlName = key;
}
}
Map<String, PVector> map = getControlSizes();
// PVector size = getControlSizes().get(controlName);
// println("size: " + size);
float right = left + DEFAULT_CONTROL_SIZE.x;
this.getOutline().setWidth(right);
}
}

View File

@ -2,7 +2,7 @@ polargraphcontroller
====================
Polargraph controller
Copyright Sandy Noble 2018.
Copyright Sandy Noble 2015.
- Requires the excellent ControlP5 GUI library available from https://github.com/sojamo/controlp5.
- Requires the excellent Geomerative library available from http://www.ricardmarxer.com/geomerative/.
@ -13,7 +13,5 @@ This is a desktop application for controlling a polargraph machine, communicatin
The [latest releases bundle] (https://github.com/euphy/polargraphcontroller/releases/latest) contains
copies of all the libraries that I use, as well as all the source, and compiled versions of the code where sensible.
How to [run it from source](https://github.com/euphy/polargraph/wiki/Running-the-controller-from-source-code).
sandy.noble@gmail.com
http://www.polargraph.co.uk/

View File

@ -29,43 +29,35 @@ ControlFrameSimple addSerialPortControlFrame(String theName, int theWidth, int t
catch(Exception e) {
}
ScrollableList sl = p.cp5().addScrollableList("dropdown_serialPort")
// set up controls
RadioButton r = p.cp5().addRadioButton("radio_serialPort")
.setPosition(10, 10)
.setSize(150, 450)
.setBarHeight(20)
.setItemHeight(16)
.plugTo(this, "dropdown_serialPort");
.setSize(15, 15)
.setSpacingRow(5)
.plugTo(this, "radio_serialPort");
sl.addItem("No serial connection", -1);
r.addItem("No serial connection", -1);
String[] ports = Serial.list();
for (int i = 0; i < ports.length; i++) {
println("Adding " + ports[i]);
sl.addItem(ports[i], i);
r.addItem(ports[i], i);
}
int portNo = getSerialPortNumber();
println("portNo: " + portNo);
if (portNo < 0 || portNo >= ports.length)
portNo = -1;
if (portNo >= 0 && portNo < ports.length)
r.activate(ports[portNo]);
else
r.activate("No serial connection");
// set the value of the actual control
sl.setValue(portNo);
sl.setOpen(true);
return p;
}
void dropdown_serialPort(int newSerialPort)
void radio_serialPort(int newSerialPort)
{
println("In dropdown_serialPort, newSerialPort: " + newSerialPort);
// No serial in list is slot 0 in code because of list index
// So shift port index by one
newSerialPort -= 1;
println("In radio_serialPort");
if (newSerialPort == -2)
{
}

View File

@ -164,16 +164,11 @@ void button_mode_liveConfirmDraw()
PVector position = new PVector(getDisplayMachine().inMM(getDisplayMachine().getImageFrame().getPosition().x),
getDisplayMachine().inMM(getDisplayMachine().getImageFrame().getPosition().y));
int oldPolygonizer = polygonizer;
polygonizer = RG.ADAPTATIVE;
setupPolygonizer();
sendVectorShapes(captureShape, scaling, position, PATH_SORT_CENTRE_FIRST);
button_mode_penUp();
// save shape as SVG
trace_saveShape(captureShape);
polygonizer = oldPolygonizer;
setupPolygonizer();
}
}
void toggle_mode_showWebcamRawVideo(boolean flag)
@ -323,7 +318,6 @@ void button_mode_loadImage()
getDisplayMachine().setImageFilename(null);
}
}
void button_mode_loadVectorFile()
{
if (getVectorShape() == null)
@ -337,7 +331,6 @@ void button_mode_loadVectorFile()
vectorFilename = null;
}
}
void numberbox_mode_pixelBrightThreshold(float value)
{
pixelExtractBrightThreshold = (int) value;
@ -533,14 +526,12 @@ void numberbox_mode_changeMachineWidth(float value)
clearBoxVectors();
float steps = getDisplayMachine().inSteps((int) value);
getDisplayMachine().getSize().x = steps;
getDisplayMachine().maxLength = null;
}
void numberbox_mode_changeMachineHeight(float value)
{
clearBoxVectors();
float steps = getDisplayMachine().inSteps((int) value);
getDisplayMachine().getSize().y = steps;
getDisplayMachine().maxLength = null;
}
void numberbox_mode_changeMMPerRev(float value)
{
@ -617,7 +608,7 @@ void button_mode_sendPenWidth()
NumberFormat nf = NumberFormat.getNumberInstance(Locale.UK);
DecimalFormat df = (DecimalFormat)nf;
df.applyPattern("###.##");
addToRealtimeCommandQueue(CMD_SETPENWIDTH+df.format(currentPenWidth)+",END");
addToRealtimeCommandQueue(CMD_CHANGEPENWIDTH+df.format(currentPenWidth)+",END");
}
void numberbox_mode_changePenTestStartWidth(float value)
@ -734,46 +725,4 @@ void numberbox_mode_previewCordOffsetValue(int value)
previewQueue(true);
}
void dropdown_mode_cycleDensityPreviewStyle(int index)
{
println("In dropdown_mode_cycleDensityPreviewStyle");
densityPreviewStyle = index;
println("Style: " + densityPreviewStyle);
}
void numberbox_mode_changeDensityPreviewPosterize(int value) {
if (value < 1) value = 1;
else if (value > 255) value = 255;
densityPreviewPosterize = value;
}
void minitoggle_mode_previewPixelDensityRange(boolean flag) {
previewPixelDensityRange = flag;
println("previewPixelDensityRange: " + previewPixelDensityRange);
}
void numberbox_mode_changePolygonizerLength(float value) {
polygonizerLength = value;
setupPolygonizer();
}
void numberbox_mode_changePolygonizerAdaptativeAngle(float value) {
println("numberbox_mode_changePolygonizerAdaptativeAngle");
polygonizerAdaptativeAngle = value;
setupPolygonizer();
}
void dropdown_mode_changePolygonizer(int value)
{
polygonizer = value;
setupPolygonizer();
}
void dropdown_mode_changeMaskInvert(int value)
{
invertMaskMode = value;
rebuildPixels();
}

View File

@ -38,7 +38,7 @@ String DRAW_PIXELS_WINDOW_NAME = "drawPixelsWindow";
String DRAW_WRITING_WINDOW_NAME = "drawWritingWindow";
void button_mode_serialPortDialog() {
ControlFrameSimple cf = addSerialPortControlFrame("Serial Port", 200, 500, 20, 240, color( 100 ) );
ControlFrameSimple cf = addSerialPortControlFrame("Serial Port", 200, 200, 20, 240, color( 100 ) );
}
void button_mode_machineStoreDialog() {

View File

@ -83,14 +83,6 @@ Set<String> getControlsToLockIfImageNotLoaded() {
return this.controlsToLockIfImageNotLoaded;
}
Set<String> getControlsToLockIfVectorNotLoaded() {
if (this.controlsToLockIfVectorNotLoaded == null)
{
this.controlsToLockIfVectorNotLoaded = buildControlsToLockIfVectorNotLoaded();
}
return this.controlsToLockIfVectorNotLoaded;
}
void hideAllControls() {
for (String key : allControls.keySet())
{
@ -103,9 +95,9 @@ Map<String, Panel> buildPanels() {
Map<String, Panel> panels = new HashMap<String, Panel>();
float panelHeight = frame.getHeight() - getMainPanelPosition().y - (DEFAULT_CONTROL_SIZE.y*3);
Rectangle panelOutlineInput = new Rectangle(getMainPanelPosition(),
Rectangle panelOutline = new Rectangle(getMainPanelPosition(),
new PVector((DEFAULT_CONTROL_SIZE.x+CONTROL_SPACING.x)*2, panelHeight));
Panel inputPanel = new Panel(PANEL_NAME_INPUT, panelOutlineInput);
Panel inputPanel = new Panel(PANEL_NAME_INPUT, panelOutline);
inputPanel.setResizable(true);
inputPanel.setOutlineColour(color(200, 200, 200));
// get controls
@ -115,9 +107,7 @@ Map<String, Panel> buildPanels() {
inputPanel.setControlSizes(buildControlSizesForPanel(inputPanel));
panels.put(PANEL_NAME_INPUT, inputPanel);
Rectangle panelOutlineRoving = new Rectangle(getMainPanelPosition(),
new PVector((DEFAULT_CONTROL_SIZE.x+CONTROL_SPACING.x)*2, panelHeight));
Panel rovingPanel = new Panel(PANEL_NAME_ROVING, panelOutlineRoving);
Panel rovingPanel = new Panel(PANEL_NAME_ROVING, panelOutline);
rovingPanel.setOutlineColour(color(100,200,200));
// get controls
rovingPanel.setResizable(true);
@ -127,9 +117,7 @@ Map<String, Panel> buildPanels() {
rovingPanel.setControlSizes(buildControlSizesForPanel(rovingPanel));
panels.put(PANEL_NAME_ROVING, rovingPanel);
Rectangle panelOutlineTrace = new Rectangle(getMainPanelPosition(),
new PVector((DEFAULT_CONTROL_SIZE.x+CONTROL_SPACING.x)*2, panelHeight));
Panel tracePanel = new Panel(PANEL_NAME_TRACE, panelOutlineTrace);
Panel tracePanel = new Panel(PANEL_NAME_TRACE, panelOutline);
tracePanel.setOutlineColour(color(200,255,200));
// get controls
tracePanel.setResizable(true);
@ -139,9 +127,7 @@ Map<String, Panel> buildPanels() {
tracePanel.setControlSizes(buildControlSizesForPanel(tracePanel));
panels.put(PANEL_NAME_TRACE, tracePanel);
Rectangle panelOutlineDetails = new Rectangle(getMainPanelPosition(),
new PVector((DEFAULT_CONTROL_SIZE.x+CONTROL_SPACING.x)*2, panelHeight));
Panel detailsPanel = new Panel(PANEL_NAME_DETAILS, panelOutlineDetails);
Panel detailsPanel = new Panel(PANEL_NAME_DETAILS, panelOutline);
detailsPanel.setOutlineColour(color(200, 200, 255));
// get controls
detailsPanel.setResizable(true);
@ -151,9 +137,7 @@ Map<String, Panel> buildPanels() {
detailsPanel.setControlSizes(buildControlSizesForPanel(detailsPanel));
panels.put(PANEL_NAME_DETAILS, detailsPanel);
Rectangle panelOutlineQueue = new Rectangle(getMainPanelPosition(),
new PVector((DEFAULT_CONTROL_SIZE.x+CONTROL_SPACING.x)*2, panelHeight));
Panel queuePanel = new Panel(PANEL_NAME_QUEUE, panelOutlineQueue);
Panel queuePanel = new Panel(PANEL_NAME_QUEUE, panelOutline);
queuePanel.setOutlineColour(color(200, 200, 50));
// get controls
queuePanel.setResizable(true);
@ -163,10 +147,10 @@ Map<String, Panel> buildPanels() {
queuePanel.setControlSizes(buildControlSizesForPanel(queuePanel));
panels.put(PANEL_NAME_QUEUE, queuePanel);
Rectangle panelOutlineGeneral = new Rectangle(
panelOutline = new Rectangle(
new PVector(getMainPanelPosition().x, getMainPanelPosition().y-((DEFAULT_CONTROL_SIZE.y+CONTROL_SPACING.y)*2)),
new PVector((DEFAULT_CONTROL_SIZE.x+CONTROL_SPACING.x)*2, (DEFAULT_CONTROL_SIZE.y+CONTROL_SPACING.y)*2));
Panel generalPanel = new Panel(PANEL_NAME_GENERAL, panelOutlineGeneral);
Panel generalPanel = new Panel(PANEL_NAME_GENERAL, panelOutline);
generalPanel.setResizable(false);
generalPanel.setOutlineColour(color(200, 50, 200));
// get controls
@ -176,8 +160,6 @@ Map<String, Panel> buildPanels() {
generalPanel.setControlSizes(buildControlSizesForPanel(generalPanel));
panels.put(PANEL_NAME_GENERAL, generalPanel);
return panels;
}
@ -191,18 +173,6 @@ void updateNumberboxValues()
initialiseNumberboxValues(getAllControls());
}
void initConsoleWindow() {
consoleArea = cp5.addTextarea("txt")
.setPosition(300, 100)
.setSize(400, 600)
.setFont(createFont("", 12))
.setLineHeight(14)
.setColor(color(255))
.setColorBackground(color(0, 200))
.setColorForeground(color(255, 100))
.setVisible(false);
}
Set<String> buildControlsToLockIfBoxNotSpecified()
{
Set<String> result = new HashSet<String>();
@ -235,42 +205,12 @@ Set<String> buildControlsToLockIfImageNotLoaded()
result.add(MODE_CHANGE_SAMPLE_AREA);
result.add(MODE_SELECT_PICTUREFRAME);
result.add(MODE_CHANGE_PIXEL_SCALING);
result.add(MODE_CHOOSE_CHROMA_KEY_COLOUR);
return result;
}
Set<String> buildControlsToLockIfVectorNotLoaded()
{
Set<String> result = new HashSet<String>();
result.add(MODE_CHANGE_MIN_VECTOR_LINE_LENGTH);
result.add(MODE_RESIZE_VECTOR);
result.add(MODE_MOVE_VECTOR);
result.add(MODE_CHANGE_POLYGONIZER_LENGTH);
result.add(MODE_CHANGE_POLYGONIZER);
return result;
}
CallbackListener toFront = new CallbackListener() {
public void controlEvent(CallbackEvent theEvent) {
theEvent.getController().bringToFront();
((ScrollableList)theEvent.getController()).open();
}
};
CallbackListener close = new CallbackListener() {
public void controlEvent(CallbackEvent theEvent) {
((ScrollableList)theEvent.getController()).close();
}
};
Map<String, Controller> buildAllControls()
{
initConsoleWindow();
Map<String, Controller> map = new HashMap<String, Controller>();
for (String controlName : getControlNames())
@ -280,8 +220,6 @@ Map<String, Controller> buildAllControls()
Button b = cp5.addButton(controlName, 0, 100, 100, 100, 100);
b.setLabel(getControlLabels().get(controlName));
b.hide();
controlP5.Label l = b.getCaptionLabel();
l.align(ControlP5.LEFT, CENTER);
map.put(controlName, b);
// println("Added button " + controlName);
}
@ -291,8 +229,8 @@ Map<String, Controller> buildAllControls()
t.setLabel(getControlLabels().get(controlName));
t.hide();
controlP5.Label l = t.getCaptionLabel();
l.align(ControlP5.LEFT, CENTER);
l.getStyle().setPaddingLeft(4);
l.getStyle().marginTop = -17; //move upwards (relative to button size)
l.getStyle().marginLeft = 4; //move to the right
map.put(controlName, t);
// println("Added toggle " + controlName);
}
@ -302,8 +240,8 @@ Map<String, Controller> buildAllControls()
t.setLabel(getControlLabels().get(controlName));
t.hide();
controlP5.Label l = t.getCaptionLabel();
l.align(ControlP5.LEFT, CENTER);
l.getStyle().setPaddingLeft(4);
l.getStyle().marginTop = -17; //move upwards (relative to button size)
l.getStyle().marginLeft = 4; //move to the right
map.put(controlName, t);
// println("Added minitoggle " + controlName);
}
@ -314,53 +252,17 @@ Map<String, Controller> buildAllControls()
n.hide();
n.setDecimalPrecision(0);
controlP5.Label l = n.getCaptionLabel();
l.align(ControlP5.LEFT, CENTER);
l.getStyle().setPaddingLeft(35);
l.getStyle().marginTop = -17; //move upwards (relative to button size)
l.getStyle().marginLeft = 40; //move to the right
// change the control direction to left/right
n.setDirection(Controller.VERTICAL);
map.put(controlName, n);
// println("Added numberbox " + controlName);
}
else if (controlName.startsWith("dropdown_"))
{
ScrollableList sl = cp5.addScrollableList(controlName, 100, 100, 100, 100);
sl.setBarHeight(20);
sl.setItemHeight(20);
sl.setLabel(getControlLabels().get(controlName));
sl.setType(ScrollableList.DROPDOWN);
sl.onEnter(toFront);
sl.onLeave(close);
sl.setHeight(100);
sl.hide();
controlP5.Label l = sl.getCaptionLabel();
map.put(controlName, sl);
println("Added dropdown " + controlName);
}
}
initialiseButtonValues(map);
initialiseToggleValues(map);
initialiseNumberboxValues(map);
initialiseDropdownContents(map);
initialiseDropdownValues(map);
return map;
}
Map<String, Controller> initialiseButtonValues(Map<String, Controller> map)
{
for (String key : map.keySet())
{
if (key.startsWith("button_"))
{
Button n = (Button) map.get(key);
if (MODE_CHANGE_POLYGONIZER.equals(key)) {
n.setValue(polygonizer);
n.setLabel(this.controlLabels.get(MODE_CHANGE_POLYGONIZER) + ": " + polygonizer);
}
}
}
return map;
}
@ -528,7 +430,7 @@ Map<String, Controller> initialiseNumberboxValues(Map<String, Controller> map)
n.setDecimalPrecision(2);
n.setValue(pixelScalingOverGridSize);
n.setMin(0.1);
// n.setMax(4.0);
n.setMax(4.0);
n.setMultiplier(0.01);
}
else if (MODE_CHANGE_MIN_VECTOR_LINE_LENGTH.equals(key))
@ -587,31 +489,10 @@ Map<String, Controller> initialiseNumberboxValues(Map<String, Controller> map)
}
else if (MODE_ADJUST_PREVIEW_CORD_OFFSET.equals(key))
{
n.setDecimalPrecision(2);
n.setValue(0.0);
n.setDecimalPrecision(0);
n.setValue(0);
n.setMultiplier(0.5);
}
else if (MODE_CHANGE_DENSITY_PREVIEW_POSTERIZE.equals(key))
{
n.setValue(densityPreviewPosterize);
n.setMin(1);
n.setMax(255);
n.setDecimalPrecision(1);
n.setMultiplier(0.1);
}
else if (MODE_CHANGE_POLYGONIZER_LENGTH.equals(key)) {
n.setValue(polygonizerLength);
n.setMin(1.0);
n.setDecimalPrecision(1);
n.setMultiplier(0.1);
}
else if (MODE_CHANGE_POLYGONIZER_ADAPTATIVE_ANGLE.equals(key)) {
n.setValue(polygonizerAdaptativeAngle);
n.setMin(0.0);
n.setMax(1.57079632679);
n.setDecimalPrecision(2);
n.setMultiplier(0.01);
}
}
}
return map;
@ -662,73 +543,11 @@ Map<String, Controller> initialiseToggleValues(Map<String, Controller> map)
Toggle t = (Toggle) map.get(key);
t.setValue((rotateWebcamImage) ? 1 : 0);
}
else if (MODE_PREVIEW_PIXEL_DENSITY_RANGE.equals(key))
{
Toggle t = (Toggle) map.get(key);
t.setValue((previewPixelDensityRange) ? 1 : 0);
}
}
return map;
}
Map<String, Controller> initialiseDropdownContents(Map<String, Controller> map)
{
println("Init dropdown contents");
for (String key : map.keySet())
{
if (MODE_CYCLE_DENSITY_PREVIEW_STYLE.equals(key))
{
println("Adding " + key);
ScrollableList sl = (ScrollableList) map.get(key);
sl.setItems(densityPreviewStyles);
}
if (MODE_CHANGE_POLYGONIZER.equals(key))
{
println("Adding " + key);
ScrollableList sl = (ScrollableList) map.get(key);
sl.setItems(polygonizerStyles);
}
if (MODE_CHANGE_INVERT_MASK.equals(key))
{
println("Adding " + key);
ScrollableList sl = (ScrollableList) map.get(key);
sl.setItems(invertMaskModes);
}
}
return map;
}
Map<String, Controller> initialiseDropdownValues(Map<String, Controller> map)
{
println("Init dropdown values");
for (String key : map.keySet())
{
if (MODE_CYCLE_DENSITY_PREVIEW_STYLE.equals(key))
{
println("Adding " + key);
ScrollableList sl = (ScrollableList) map.get(key);
sl.setValue(densityPreviewStyle);
sl.close();
}
else if (MODE_CHANGE_POLYGONIZER.equals(key))
{
println("Adding " + key);
ScrollableList sl = (ScrollableList) map.get(key);
sl.setValue(polygonizer);
sl.close();
}
else if (MODE_CHANGE_INVERT_MASK.equals(key))
{
println("Adding " + key);
ScrollableList sl = (ScrollableList) map.get(key);
sl.setValue(polygonizer);
sl.close();
}
}
return map;
}
String getControlLabel(String butName)
{
if (controlLabels.containsKey(butName))
@ -745,7 +564,6 @@ Map<String, PVector> buildControlPositionsForPanel(Panel panel)
int row = 0;
for (Controller controller : panel.getControls())
{
if (controller.getName().startsWith("minitoggle_"))
{
PVector p = new PVector(col*(DEFAULT_CONTROL_SIZE.x+CONTROL_SPACING.x), row*(DEFAULT_CONTROL_SIZE.y+CONTROL_SPACING.y));
@ -757,18 +575,6 @@ Map<String, PVector> buildControlPositionsForPanel(Panel panel)
col++;
}
}
else if (controller.getName().startsWith("dropdown_"))
{
PVector p = new PVector(col*(DEFAULT_CONTROL_SIZE.x+CONTROL_SPACING.x), row*(DEFAULT_CONTROL_SIZE.y+CONTROL_SPACING.y));
println(controller);
map.put(controller.getName(), p);
row++;
if (p.y + (DEFAULT_CONTROL_SIZE.y*2) >= panel.getOutline().getHeight())
{
row = 0;
col++;
}
}
else
{
PVector p = new PVector(col*(DEFAULT_CONTROL_SIZE.x+CONTROL_SPACING.x), row*(DEFAULT_CONTROL_SIZE.y+CONTROL_SPACING.y));
@ -798,11 +604,6 @@ Map<String, PVector> buildControlSizesForPanel(Panel panel)
PVector s = new PVector(DEFAULT_CONTROL_SIZE.y, DEFAULT_CONTROL_SIZE.y);
map.put(controller.getName(), s);
}
else if (controller.getName().startsWith("dropdown_"))
{
PVector s = new PVector(DEFAULT_CONTROL_SIZE.x, DEFAULT_CONTROL_SIZE.y * 4);
map.put(controller.getName(), s);
}
else
{
PVector s = new PVector(DEFAULT_CONTROL_SIZE.x, DEFAULT_CONTROL_SIZE.y);
@ -863,7 +664,6 @@ List<String> getControlNamesForInputPanel()
controlNames.add(MODE_CHANGE_GRID_SIZE);
controlNames.add(MODE_CHANGE_SAMPLE_AREA);
controlNames.add(MODE_CHOOSE_CHROMA_KEY_COLOUR);
controlNames.add(MODE_CHANGE_INVERT_MASK);
controlNames.add(MODE_CHANGE_PIXEL_SCALING);
controlNames.add(MODE_RENDER_PIXEL_DIALOG);
@ -875,23 +675,17 @@ List<String> getControlNamesForInputPanel()
controlNames.add(MODE_LOAD_VECTOR_FILE);
controlNames.add(MODE_RESIZE_VECTOR);
controlNames.add(MODE_MOVE_VECTOR);
controlNames.add(MODE_ADJUST_PREVIEW_CORD_OFFSET);
controlNames.add(MODE_RENDER_VECTORS);
controlNames.add(MODE_CHANGE_MIN_VECTOR_LINE_LENGTH);
controlNames.add(MODE_CHANGE_POLYGONIZER);
controlNames.add(MODE_CHANGE_POLYGONIZER_LENGTH);
// controlNames.add(MODE_CHANGE_POLYGONIZER_ADAPTATIVE_ANGLE);
//controlNames.add(MODE_VECTOR_PATH_LENGTH_HIGHPASS_CUTOFF);
controlNames.add(MODE_RENDER_VECTORS);
controlNames.add(MODE_ADJUST_PREVIEW_CORD_OFFSET);
controlNames.add(MODE_SHOW_IMAGE);
controlNames.add(MODE_SHOW_VECTOR);
controlNames.add(MODE_SHOW_QUEUE_PREVIEW);
controlNames.add(MODE_SHOW_GUIDES);
controlNames.add(MODE_SHOW_DENSITY_PREVIEW);
controlNames.add(MODE_PREVIEW_PIXEL_DENSITY_RANGE);
controlNames.add(MODE_CHANGE_DENSITY_PREVIEW_POSTERIZE);
controlNames.add(MODE_CYCLE_DENSITY_PREVIEW_STYLE);
controlNames.add(MODE_SHOW_GUIDES);
return controlNames;
@ -1119,7 +913,6 @@ Map<String, String> buildControlLabels()
result.put(MODE_MOVE_VECTOR, "Move vector");
result.put(MODE_RENDER_PIXEL_DIALOG, "Render pixels...");
result.put(MODE_CHOOSE_CHROMA_KEY_COLOUR, "Choose mask colour");
result.put(MODE_CHANGE_INVERT_MASK, "Mask mode");
result.put(MODE_CHANGE_PIXEL_SCALING, "Pixel scaling");
result.put(MODE_PEN_LIFT_UP, "Pen lift");
@ -1160,14 +953,6 @@ Map<String, String> buildControlLabels()
result.put(MODE_SEND_BUTTON_DEACTIVATE, "Deactivate button");
result.put(MODE_ADJUST_PREVIEW_CORD_OFFSET, "Cord offset");
result.put(MODE_CYCLE_DENSITY_PREVIEW_STYLE, "Density preview style");
result.put(MODE_CHANGE_DENSITY_PREVIEW_POSTERIZE, "Pixel posterize");
result.put(MODE_PREVIEW_PIXEL_DENSITY_RANGE, "Show density range");
result.put(MODE_CHANGE_POLYGONIZER, "Polygonizer style");
result.put(MODE_CHANGE_POLYGONIZER_LENGTH, "Polygonizer length");
result.put(MODE_CHANGE_POLYGONIZER_ADAPTATIVE_ANGLE, "Polygonizer angle");
return result;
@ -1275,7 +1060,6 @@ Set<String> buildControlNames()
result.add(MODE_CHANGE_MIN_VECTOR_LINE_LENGTH);
result.add(MODE_CHOOSE_CHROMA_KEY_COLOUR);
result.add(MODE_CHANGE_INVERT_MASK);
result.add(MODE_CHANGE_PIXEL_SCALING);
result.add(MODE_PEN_LIFT_UP);
result.add(MODE_PEN_LIFT_DOWN);
@ -1314,14 +1098,6 @@ Set<String> buildControlNames()
result.add(MODE_SEND_BUTTON_DEACTIVATE);
result.add(MODE_ADJUST_PREVIEW_CORD_OFFSET);
result.add(MODE_CYCLE_DENSITY_PREVIEW_STYLE);
result.add(MODE_CHANGE_DENSITY_PREVIEW_POSTERIZE);
result.add(MODE_PREVIEW_PIXEL_DENSITY_RANGE);
result.add(MODE_CHANGE_POLYGONIZER_LENGTH);
result.add(MODE_CHANGE_POLYGONIZER);
result.add(MODE_CHANGE_POLYGONIZER_ADAPTATIVE_ANGLE);
return result;
}

View File

@ -27,9 +27,9 @@
https://github.com/euphy/polargraphcontroller
*/
static final String CMD_CHANGELENGTH = "C01,";
static final String CMD_SETPENWIDTH = "C02,";
//static final String CMD_CHANGEMOTORSPEED = "C03,";
//static final String CMD_CHANGEMOTORACCEL = "C04,";
static final String CMD_CHANGEPENWIDTH = "C02,";
static final String CMD_CHANGEMOTORSPEED = "C03,";
static final String CMD_CHANGEMOTORACCEL = "C04,";
static final String CMD_DRAWPIXEL = "C05,";
static final String CMD_DRAWSCRIBBLEPIXEL = "C06,";
static final String CMD_DRAWRECT = "C07,";
@ -120,7 +120,9 @@ void sendRequestMachineSize()
void sendMachineSpec()
{
// ask for input to get the new machine size
String command = CMD_CHANGEMACHINESIZE+getDisplayMachine().inMM(getDisplayMachine().getWidth())+","+getDisplayMachine().inMM(getDisplayMachine().getHeight())+",END";
String command = CMD_CHANGEMACHINENAME+newMachineName+",END";
addToCommandQueue(command);
command = CMD_CHANGEMACHINESIZE+getDisplayMachine().inMM(getDisplayMachine().getWidth())+","+getDisplayMachine().inMM(getDisplayMachine().getHeight())+",END";
addToCommandQueue(command);
command = CMD_CHANGEMACHINEMMPERREV+int(getDisplayMachine().getMMPerRev())+",END";
addToCommandQueue(command);
@ -197,13 +199,13 @@ void sendTestPenWidth()
StringBuilder sb = new StringBuilder();
sb.append(testPenWidthCommand)
.append(int(gridSize))
.append(",")
.append(df.format(testPenWidthStartSize))
.append(",")
.append(df.format(testPenWidthEndSize))
.append(",")
.append(df.format(testPenWidthIncrementSize))
.append(",END");
.append(",")
.append(df.format(testPenWidthStartSize))
.append(",")
.append(df.format(testPenWidthEndSize))
.append(",")
.append(df.format(testPenWidthIncrementSize))
.append(",END");
addToCommandQueue(sb.toString());
}
@ -682,6 +684,7 @@ void sendVectorShapes(RShape vec, float scaling, PVector position, int pathSorti
if (pointPaths[i] != null)
{
boolean firstPointFound = false;
if (pointPaths[i].length > pathLengthHighPassCutoff)
{
List<PVector> filteredPoints = filterPoints(pointPaths[i], VECTOR_FILTER_LOW_PASS, minimumVectorLineLength, scaling, position);
@ -698,7 +701,7 @@ void sendVectorShapes(RShape vec, float scaling, PVector position, int pathSorti
if (liftToGetToNewPoint)
addToCommandQueue(CMD_PENUP+"END");
// move to this point and put the pen down
command = CMD_CHANGELENGTHDIRECT+Math.round(p.x)+","+Math.round(p.y)+","+getMaxSegmentLength()+",END";
command = CMD_CHANGELENGTHDIRECT+(int)p.x+","+(int)p.y+","+getMaxSegmentLength()+",END";
addToCommandQueue(command);
if (liftToGetToNewPoint)
addToCommandQueue(CMD_PENDOWN+"END");
@ -709,7 +712,7 @@ void sendVectorShapes(RShape vec, float scaling, PVector position, int pathSorti
for (int j=1; j<filteredPoints.size(); j++)
{
p = filteredPoints.get(j);
command = CMD_CHANGELENGTHDIRECT+Math.round(p.x)+","+Math.round(p.y)+","+getMaxSegmentLength()+",END";
command = CMD_CHANGELENGTHDIRECT+(int)p.x+","+(int)p.y+","+getMaxSegmentLength()+",END";
addToCommandQueue(command);
}
lastPoint = new PVector(p.x, p.y);
@ -887,7 +890,6 @@ List<PVector> filterPointsLowPass(RPoint[] points, long filterParam, float scali
// scale and convert all the points first
List<PVector> scaled = new ArrayList<PVector>(points.length);
println("a filterPointsLowPass: Scaled length: " + points.length);
for (int j = 0; j<points.length; j++)
{
RPoint firstPoint = points[j];
@ -902,8 +904,7 @@ List<PVector> filterPointsLowPass(RPoint[] points, long filterParam, float scali
}
}
println("b filterPointsLowPass: Scaled length: " + scaled.size());
if (scaled.size() > 1.0)
if (scaled.size() > 1)
{
PVector p = scaled.get(0);
result.add(p);
@ -912,18 +913,17 @@ List<PVector> filterPointsLowPass(RPoint[] points, long filterParam, float scali
{
p = scaled.get(j);
// and even then, only bother drawing if it's a move of over "x" steps
int diffx = abs(int(p.x) - int(result.get(result.size()-1).x));
int diffy = abs(int(p.y) - int(result.get(result.size()-1).y));
int diffx = int(p.x) - int(result.get(result.size()-1).x);
int diffy = int(p.y) - int(result.get(result.size()-1).y);
if (diffx > filterParam || diffy > filterParam)
if (abs(diffx) > filterParam || abs(diffy) > filterParam)
{
println(j + ". Adding point " + p + " because diffx (" + diffx + ") or diffy (" + diffy + ") is > " + filterParam + ", last: " + result.get(result.size()-1));
//println("Adding point " + p + ", last: " + result.get(result.size()-1));
result.add(p);
}
}
}
println("c filterPointsLowPass: Scaled length: " + result.size());
if (result.size() < 2)
result.clear();
@ -968,3 +968,5 @@ void sendDrawRandomSprite(String spriteFilename)
{
addToCommandQueue(CMD_DRAW_RANDOM_SPRITE+","+spriteFilename+",100,500,END");
}

View File

@ -1,42 +1,42 @@
/**
Polargraph controller
Copyright Sandy Noble 2018.
Polargraph controller
Copyright Sandy Noble 2015.
This file is part of Polargraph Controller.
This file is part of Polargraph Controller.
Polargraph Controller is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Polargraph Controller is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Polargraph Controller 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 General Public License for more details.
Polargraph Controller 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Polargraph Controller. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with Polargraph Controller. If not, see <http://www.gnu.org/licenses/>.
Requires the excellent ControlP5 GUI library available from http://www.sojamo.de/libraries/controlP5/.
Requires the excellent Geomerative library available from http://www.ricardmarxer.com/geomerative/.
Requires the excellent ControlP5 GUI library available from http://www.sojamo.de/libraries/controlP5/.
Requires the excellent Geomerative library available from http://www.ricardmarxer.com/geomerative/.
This is an application for controlling a polargraph machine, communicating using ASCII command language over a serial link.
sandy.noble@gmail.com
http://www.polargraph.co.uk
https://github.com/euphy/polargraphcontroller
*/
This is an application for controlling a polargraph machine, communicating using ASCII command language over a serial link.
sandy.noble@gmail.com
http://www.polargraph.co.uk/
https://github.com/euphy/polargraphcontroller
*/
//import processing.video.*;
import diewald_CV_kit.libraryinfo.*;
import diewald_CV_kit.utility.*;
import diewald_CV_kit.blobdetection.*;
import geomerative.*;
//import org.apache.batik.svggen.font.table.*;
//import org.apache.batik.svggen.font.*;
import java.util.zip.CRC32;
// for OSX
import java.text.*;
import java.util.*;
@ -54,13 +54,15 @@ import java.awt.BorderLayout;
import java.lang.reflect.Method;
int majorVersionNo = 2;
int minorVersionNo = 6;
int buildNo = 0;
int minorVersionNo = 0;
int buildNo = 3;
String programTitle = "Polargraph Controller v" + majorVersionNo + "." + minorVersionNo + " build " + buildNo;
ControlP5 cp5;
Map<String, ControlP5> cp5s = new HashMap<String, ControlP5>();
boolean drawbotReady = false;
boolean drawbotConnected = false;
@ -146,8 +148,6 @@ List<String> machineMessageLog = new ArrayList<String>();
List<PreviewVector> previewCommandList = new ArrayList<PreviewVector>();
long lastCommandQueueHash = 0L;
File lastImageDirectory = null;
File lastPropertiesDirectory = null;
String lastCommand = "";
String lastDrawingCommand = "";
@ -187,7 +187,7 @@ float testPenWidthStartSize = 0.5;
float testPenWidthEndSize = 2.0;
float testPenWidthIncrementSize = 0.5;
int machineStepMultiplier = 8;
int machineStepMultiplier = 1;
int maxSegmentLength = 2;
@ -249,7 +249,6 @@ static final String MODE_CHANGE_SAMPLE_AREA = "numberbox_mode_changeSampleArea";
static final String MODE_CHANGE_GRID_SIZE = "numberbox_mode_changeGridSize";
static final String MODE_SHOW_DENSITY_PREVIEW = "minitoggle_mode_showDensityPreview";
static final String MODE_SHOW_IMAGE = "minitoggle_mode_showImage";
static final String MODE_SHOW_QUEUE_PREVIEW = "minitoggle_mode_showQueuePreview";
static final String MODE_SHOW_VECTOR = "minitoggle_mode_showVector";
@ -338,26 +337,6 @@ static final String MODE_SEND_BUTTON_DEACTIVATE = "button_mode_sendButtonDeactiv
static final String MODE_ADJUST_PREVIEW_CORD_OFFSET = "numberbox_mode_previewCordOffsetValue";
static final String MODE_CYCLE_DENSITY_PREVIEW_STYLE = "dropdown_mode_cycleDensityPreviewStyle";
static final String MODE_CHANGE_DENSITY_PREVIEW_POSTERIZE = "numberbox_mode_changeDensityPreviewPosterize";
static final String MODE_PREVIEW_PIXEL_DENSITY_RANGE = "minitoggle_mode_previewPixelDensityRange";
static final String MODE_CHANGE_POLYGONIZER = "dropdown_mode_changePolygonizer";
static final String MODE_CHANGE_POLYGONIZER_LENGTH = "numberbox_mode_changePolygonizerLength";
static final String MODE_CHANGE_POLYGONIZER_ADAPTATIVE_ANGLE = "numberbox_mode_changePolygonizerAdaptativeAngle";
static final String MODE_CHANGE_INVERT_MASK = "dropdown_mode_changeMaskInvert";
List<String> polygonizerStyles = Arrays.asList("ADAPTATIVE", "UNIFORMLENGTH");
List<String> invertMaskModes = Arrays.asList("Mask off", "Mask hides", "Mask shows");
static final int MASK_MODES_COUNT = 3;
static final int MASK_IS_UNUSED = 0;
static final int MASKED_COLOURS_ARE_HIDDEN = 1;
static final int MASKED_COLOURS_ARE_SHOWN = 2;
PVector statusTextPosition = new PVector(300.0, 12.0);
@ -384,7 +363,6 @@ boolean pixelTimerRunning = false;
boolean displayingSelectedCentres = false;
boolean displayingRowGridlines = false;
boolean displayingInfoTextOnInputPage = false;
boolean displayingGridSpots = true;
boolean displayingImage = true;
boolean displayingVector = true;
@ -393,10 +371,6 @@ boolean displayingDensityPreview = false;
boolean displayingGuides = true;
List<String> densityPreviewStyles = Arrays.asList("Round", "Diamond", "Native Simple", "Native Arc", "Round size", "Native size");
static final int DENSITY_PREVIEW_STYLE_COUNT = 6;
static final int DENSITY_PREVIEW_ROUND = 0;
static final int DENSITY_PREVIEW_DIAMOND = 1;
static final int DENSITY_PREVIEW_NATIVE = 2;
@ -406,8 +380,6 @@ static final int DENSITY_PREVIEW_NATIVE_SIZE = 5;
static final int DEFAULT_DENSITY_PREVIEW_STYLE = DENSITY_PREVIEW_NATIVE;
int densityPreviewStyle = DEFAULT_DENSITY_PREVIEW_STYLE;
int densityPreviewPosterize = 255;
boolean previewPixelDensityRange = true;
static final byte COORD_MODE_NATIVE_STEPS = 0;
static final byte COORD_MODE_NATIVE_MM = 1;
@ -422,7 +394,6 @@ static final char BITMAP_BACKGROUND_COLOUR = 0x0F;
PVector homePointCartesian = null;
public color chromaKeyColour = color(0,255,0);
public int invertMaskMode = MASK_IS_UNUSED;
// used in the preview page
public color pageColour = color(220);
@ -434,7 +405,6 @@ public color densityPreviewColour = color(0);
public Integer previewCordOffset = 0;
public boolean debugPanels = false;
public boolean showingSummaryOverlay = true;
public boolean showingDialogBox = false;
@ -444,9 +414,6 @@ public Integer windowHeight = 400;
public static Integer serialPortNumber = -1;
public Textarea consoleArea = null;
public Println console = null;
public PrintStream savedOut = null;
Properties props = null;
public static String propertiesFilename = "default.properties.txt";
@ -504,13 +471,15 @@ RShape vectorShape = null;
String vectorFilename = null;
float vectorScaling = 100;
PVector vectorPosition = new PVector(0.0,0.0);
int minimumVectorLineLength = 2;
int minimumVectorLineLength = 0;
public static final int VECTOR_FILTER_LOW_PASS = 0;
public Set<String> controlsToLockIfVectorNotLoaded = null;
String storeFilename = "comm.txt";
boolean overwriteExistingStoreFile = true;
//private static Logger logger;
public static Console console;
public boolean useWindowedConsole = false;
static boolean drawingTraceShape = true;
static boolean retraceShape = true;
@ -544,19 +513,10 @@ String shapeSavePath = "../../savedcaptures/";
String shapeSavePrefix = "shape-";
String shapeSaveExtension = ".svg";
static Float gcodeZAxisDrawingHeight = 1.0; //-0.125000;
String filePath = null;
static PApplet parentPapplet = null;
boolean rescaleDisplayMachine = true;
// Polygonization. It's a geomerative thing.
int polygonizer = 0;
float polygonizerLength = 0.0;
float polygonizerAdaptativeAngle = 0.0F;
void setup()
{
println("Running polargraph controller");
@ -564,6 +524,10 @@ void setup()
initLogging();
parentPapplet = this;
initImages();
RG.init(this);
RG.setPolygonizer(RG.ADAPTATIVE);
try
{
@ -573,12 +537,12 @@ void setup()
{
e.printStackTrace();
}
RG.init(this);
loadFromPropertiesFile();
size(200, 200);
size(windowWidth, windowHeight);
// size(400, 400, JAVA2D );
// surface.setResizable(true);
// surface.setSize(windowWidth, windowHeight);
size(windowWidth, windowHeight, JAVA2D);
this.cp5 = new ControlP5(this);
initTabs();
@ -586,6 +550,7 @@ void setup()
println("Serial ports available on your machine:");
println(serialPorts);
// println("getSerialPortNumber()"+getSerialPortNumber());
if (getSerialPortNumber() >= 0)
{
println("About to connect to serial port in slot " + getSerialPortNumber());
@ -628,42 +593,13 @@ void setup()
addEventListeners();
frameRate(8);
noLoop();
}
void fitDisplayMachineToWindow() {
Rectangle gr = panels.get(PANEL_NAME_GENERAL).getOutline();
println(gr);
Rectangle ir = panels.get(PANEL_NAME_INPUT).getOutline();
println(ir);
float targetHeight = ir.getBottom() - gr.getTop() - CONTROL_SPACING.y;
println("Target height is " + targetHeight + " pixels");
float machineHeight = getDisplayMachine().getOutline().getHeight();
println(machineHeight);
machineScaling = (targetHeight / machineHeight);
println(machineScaling);
if (machineScaling < 0) {
machineScaling = 1.0;
}
getDisplayMachine().getOffset().x = ((gr.getRight() > ir.getRight()) ? gr.getRight() : ir.getRight()) + CONTROL_SPACING.x;
getDisplayMachine().getOffset().y = gr.getTop();
}
void addEventListeners()
{
frame.addComponentListener(new ComponentAdapter()
{
public void componentResized(ComponentEvent event)
{
windowResized();
if (event.getSource()==frame)
{
windowResized();
@ -685,72 +621,64 @@ void addEventListeners()
void preLoadCommandQueue()
{
addToCommandQueue(CMD_SETPENWIDTH+currentPenWidth+",END");
addToCommandQueue(CMD_CHANGEPENWIDTH+currentPenWidth+",END");
addToCommandQueue(CMD_SETMOTORSPEED+currentMachineMaxSpeed+",END");
addToCommandQueue(CMD_SETMOTORACCEL+currentMachineAccel+",END");
}
void windowResized()
{
noLoop();
windowWidth = frame.getWidth();
windowHeight = frame.getHeight();
println("New window size: " + windowWidth + " x " + windowHeight);
if (frame.getExtendedState() == Frame.MAXIMIZED_BOTH) {
println("Max");
frame.setExtendedState(0);
frame.setSize(windowWidth, windowHeight);
}
for (String key : getPanels().keySet())
{
Panel p = getPanels().get(key);
p.setSizeByHeight(windowHeight - p.getOutline().getTop() - (DEFAULT_CONTROL_SIZE.y*2));
if (debugPanels) {
println("Resize " + key + " to be " + p.getOutline().getWidth() + "px across, " + p.getOutline().getHeight() + "px tall");
}
p.setHeight(frame.getHeight() - p.getOutline().getTop() - (DEFAULT_CONTROL_SIZE.y*2));
}
// Required to tell CP5 to be able to use the new sized window
// How does this work?
cp5.setGraphics(this,0,0);
loop();
}
void draw()
{
if (getCurrentTab() == TAB_NAME_INPUT) {
if (getCurrentTab() == TAB_NAME_INPUT)
{
drawImagePage();
}
else if (getCurrentTab() == TAB_NAME_QUEUE) {
else if (getCurrentTab() == TAB_NAME_QUEUE)
{
drawCommandQueuePage();
}
else if (getCurrentTab() == TAB_NAME_DETAILS) {
else if (getCurrentTab() == TAB_NAME_DETAILS)
{
drawDetailsPage();
}
else if (getCurrentTab() == TAB_NAME_ROVING) {
else if (getCurrentTab() == TAB_NAME_ROVING)
{
drawRovingPage();
}
else if (getCurrentTab() == TAB_NAME_TRACE) {
else if (getCurrentTab() == TAB_NAME_TRACE)
{
drawTracePage();
}
else {
else
{
drawDetailsPage();
}
if (isShowingSummaryOverlay()) {
if (isShowingSummaryOverlay())
{
drawSummaryOverlay();
}
if (isShowingDialogBox()) {
if (isShowingDialogBox())
{
drawDialogBox();
}
if (drawbotReady) {
if (drawbotReady)
{
dispatchCommandQueue();
}
}
String getCurrentTab()
@ -819,7 +747,6 @@ Panel getPanel(String panelName)
void drawImagePage()
{
noLoop();
strokeWeight(1);
background(getBackgroundColour());
noFill();
@ -827,10 +754,6 @@ void drawImagePage()
strokeWeight(3);
stroke(150);
noFill();
if (rescaleDisplayMachine) {
fitDisplayMachineToWindow();
rescaleDisplayMachine = false;
}
getDisplayMachine().draw();
drawMoveImageOutline();
stroke(255, 0, 0);
@ -844,21 +767,13 @@ void drawImagePage()
showGroupBox();
showCurrentMachinePosition();
try {
if (displayingQueuePreview)
previewQueue();
}
catch (ConcurrentModificationException cme)
{
// not doing anything with this exception - I don't mind if it's wrong on the screen for a second or two.
println("Caught the pesky ConcurrentModificationException: " + cme.getMessage());
}
if (displayingQueuePreview)
previewQueue();
if (displayingInfoTextOnInputPage)
showText(250,45);
drawStatusText((int)statusTextPosition.x, (int)statusTextPosition.y);
showCommandQueue((int) getDisplayMachine().getOutline().getRight()+6, 20);
}
void drawMachineOutline()
@ -1029,9 +944,7 @@ void drawMoveImageOutline()
PVector offsetMouseVector = PVector.sub(getDisplayMachine().scaleToDisplayMachine(getMouseVector()), centroid);
if (pointPaths != null)
{
int increment = round((pointPaths.length/10.0)+0.5);
println(increment);
for (int i = 0; i<pointPaths.length; i+=increment)
for (int i = 0; i<pointPaths.length; i++)
{
if (pointPaths[i] != null)
{
@ -1102,6 +1015,176 @@ void showGroupBox()
}
void loadImageWithFileChooser()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run() {
JFileChooser fc = new JFileChooser();
fc.setFileFilter(new ImageFileFilter());
fc.setDialogTitle("Choose an image file...");
int returned = fc.showOpenDialog(frame);
if (returned == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
// see if it's an image
PImage img = loadImage(file.getPath());
if (img != null)
{
img = null;
getDisplayMachine().loadNewImageFromFilename(file.getPath());
if (getDisplayMachine().pixelsCanBeExtracted() && isBoxSpecified())
{
getDisplayMachine().extractPixelsFromArea(getBoxVector1(), getBoxVectorSize(), getGridSize(), sampleArea);
}
}
}
}
});
}
class ImageFileFilter extends javax.swing.filechooser.FileFilter
{
public boolean accept(File file) {
String filename = file.getName();
filename.toLowerCase();
if (file.isDirectory() || filename.endsWith(".png") || filename.endsWith(".jpg") || filename.endsWith(".jpeg"))
return true;
else
return false;
}
public String getDescription() {
return "Image files (PNG or JPG)";
}
}
void loadVectorWithFileChooser()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run() {
JFileChooser fc = new JFileChooser();
fc.setFileFilter(new VectorFileFilter());
fc.setDialogTitle("Choose a vector file...");
int returned = fc.showOpenDialog(frame);
if (returned == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
if (file.exists())
{
RShape shape = RG.loadShape(file.getPath());
if (shape != null)
{
setVectorFilename(file.getPath());
setVectorShape(shape);
}
else
{
println("File not found (" + file.getPath() + ")");
}
}
}
}
});
}
class VectorFileFilter extends javax.swing.filechooser.FileFilter
{
public boolean accept(File file) {
String filename = file.getName();
filename.toLowerCase();
if (file.isDirectory() || filename.endsWith(".svg"))
return true;
else
return false;
}
public String getDescription() {
return "Vector graphic files (SVG)";
}
}
void loadNewPropertiesFilenameWithFileChooser()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JFileChooser fc = new JFileChooser();
fc.setFileFilter(new PropertiesFileFilter());
fc.setDialogTitle("Choose a config file...");
int returned = fc.showOpenDialog(frame);
if (returned == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
if (file.exists())
{
println("New properties file exists.");
newPropertiesFilename = file.toString();
println("new propertiesFilename: "+ newPropertiesFilename);
propertiesFilename = newPropertiesFilename;
// clear old properties.
props = null;
loadFromPropertiesFile();
// set values of number spinners etc
updateNumberboxValues();
}
}
}
});
}
class PropertiesFileFilter extends javax.swing.filechooser.FileFilter
{
public boolean accept(File file) {
String filename = file.getName();
filename.toLowerCase();
if (file.isDirectory() || filename.endsWith(".properties.txt"))
return true;
else
return false;
}
public String getDescription() {
return "Properties files (*.properties.txt)";
}
}
void saveNewPropertiesFileWithFileChooser()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JFileChooser fc = new JFileChooser();
fc.setFileFilter(new PropertiesFileFilter());
fc.setDialogTitle("Enter a config file name...");
int returned = fc.showSaveDialog(frame);
if (returned == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
newPropertiesFilename = file.toString();
newPropertiesFilename.toLowerCase();
if (!newPropertiesFilename.endsWith(".properties.txt"))
newPropertiesFilename+=".properties.txt";
println("new propertiesFilename: "+ newPropertiesFilename);
propertiesFilename = newPropertiesFilename;
savePropertiesFile();
// clear old properties.
props = null;
loadFromPropertiesFile();
}
}
});
}
void setPictureFrameDimensionsToBox()
@ -1257,10 +1340,10 @@ boolean mouseOverPanel()
for (Panel panel : getPanelsForTab(currentTab))
{
if (panel.getOutline().surrounds(getMouseVector())) {
// println("Outline: " + panel.getOutline().toString());
// println("OVER PANEL!" + panel.getName());
println("Outline: " + panel.getOutline().toString());
println("OVER PANEL!" + panel.getName());
result = true;
break;
break;
}
}
return result;
@ -1280,7 +1363,7 @@ boolean mouseOverQueue()
void changeMachineScaling(int delta)
{
boolean scalingChanged = true;
machineScaling += (delta * (machineScaling * 0.1));
machineScaling += (delta * 0.1);
if (machineScaling < MIN_SCALING)
{
machineScaling = MIN_SCALING;
@ -1328,6 +1411,10 @@ void keyPressed()
getDisplayMachine().getOffset().x = getDisplayMachine().getOffset().x - 10;
else if (checkKey(KeyEvent.VK_ESCAPE))
key = 0;
// if (checkKey(CONTROL) && checkKey(KeyEvent.VK_G))
// println("CTRL+G");
else if (checkKey(CONTROL) && checkKey(KeyEvent.VK_G))
{
Toggle t = (Toggle) getAllControls().get(MODE_SHOW_GUIDES);
@ -1345,7 +1432,12 @@ void keyPressed()
}
else if (checkKey(CONTROL) && checkKey(KeyEvent.VK_C))
{
toggleShowConsole();
if (isUseWindowedConsole())
setUseWindowedConsole(false);
else
setUseWindowedConsole(true);
initLogging();
}
else if (checkKey(CONTROL) && checkKey(KeyEvent.VK_S))
{
@ -1356,6 +1448,60 @@ void keyPressed()
{
displayingInfoTextOnInputPage = (displayingInfoTextOnInputPage) ? false : true;
}
// else if (key == '+')
// {
// currentMachineMaxSpeed = currentMachineMaxSpeed+MACHINE_MAXSPEED_INCREMENT;
// currentMachineMaxSpeed = Math.round(currentMachineMaxSpeed*100.0)/100.0;
// NumberFormat nf = NumberFormat.getNumberInstance(Locale.UK);
// DecimalFormat df = (DecimalFormat)nf;
// df.applyPattern("###.##");
// addToRealtimeCommandQueue(CMD_SETMOTORSPEED+df.format(currentMachineMaxSpeed)+",END");
// }
// else if (key == '-')
// {
// currentMachineMaxSpeed = currentMachineMaxSpeed+(0.0 - MACHINE_MAXSPEED_INCREMENT);
// currentMachineMaxSpeed = Math.round(currentMachineMaxSpeed*100.0)/100.0;
// NumberFormat nf = NumberFormat.getNumberInstance(Locale.UK);
// DecimalFormat df = (DecimalFormat)nf;
// df.applyPattern("###.##");
// addToRealtimeCommandQueue(CMD_SETMOTORSPEED+df.format(currentMachineMaxSpeed)+",END");
// }
// else if (key == '*')
// {
// currentMachineAccel = currentMachineAccel+MACHINE_ACCEL_INCREMENT;
// currentMachineAccel = Math.round(currentMachineAccel*100.0)/100.0;
// NumberFormat nf = NumberFormat.getNumberInstance(Locale.UK);
// DecimalFormat df = (DecimalFormat)nf;
// df.applyPattern("###.##");
// addToRealtimeCommandQueue(CMD_SETMOTORACCEL+df.format(currentMachineAccel)+",END");
// }
// else if (key == '/')
// {
// currentMachineAccel = currentMachineAccel+(0.0 - MACHINE_ACCEL_INCREMENT);
// currentMachineAccel = Math.round(currentMachineAccel*100.0)/100.0;
// NumberFormat nf = NumberFormat.getNumberInstance(Locale.UK);
// DecimalFormat df = (DecimalFormat)nf;
// df.applyPattern("###.##");
// addToRealtimeCommandQueue(CMD_SETMOTORACCEL+df.format(currentMachineAccel)+",END");
// }
// else if (key == ']')
// {
// currentPenWidth = currentPenWidth+penIncrement;
// currentPenWidth = Math.round(currentPenWidth*100.0)/100.0;
// NumberFormat nf = NumberFormat.getNumberInstance(Locale.UK);
// DecimalFormat df = (DecimalFormat)nf;
// df.applyPattern("###.##");
// addToRealtimeCommandQueue(CMD_CHANGEPENWIDTH+df.format(currentPenWidth)+",END");
// }
// else if (key == '[')
// {
// currentPenWidth = currentPenWidth-penIncrement;
// currentPenWidth = Math.round(currentPenWidth*100.0)/100.0;
// NumberFormat nf = NumberFormat.getNumberInstance(Locale.UK);
// DecimalFormat df = (DecimalFormat)nf;
// df.applyPattern("###.##");
// addToRealtimeCommandQueue(CMD_CHANGEPENWIDTH+df.format(currentPenWidth)+",END");
// }
else if (key == '#' )
{
addToRealtimeCommandQueue(CMD_PENUP+"END");
@ -1373,10 +1519,18 @@ void keyPressed()
{
this.maxSegmentLength++;
}
// else if (key == ',')
// {
// if (this.minimumVectorLineLength > 0)
// this.minimumVectorLineLength--;
// }
// else if (key == '.')
// {
// this.minimumVectorLineLength++;
// }
}
void mouseDragged()
{
loop();
if (mouseOverControls().isEmpty())
{
if (mouseButton == CENTER)
@ -1394,16 +1548,12 @@ void mouseDragged()
}
}
}
void mouseMoved()
{
loop();
}
void mouseClicked()
{
if (mouseOverPanel())
{ // changing mode
// panelClicked();
}
else
{
@ -1420,7 +1570,7 @@ void mouseClicked()
if (getDisplayMachine().pixelsCanBeExtracted() && isBoxSpecified())
getDisplayMachine().extractPixelsFromArea(getBoxVector1(), getBoxVectorSize(), getGridSize(), sampleArea);
}
else if (currentMode.equals(MODE_MOVE_VECTOR) && vectorShape != null)
else if (currentMode.equals(MODE_MOVE_VECTOR))
{
// offset mouse vector so it grabs the centre of the shape
PVector centroid = new PVector(getVectorShape().width/2, getVectorShape().height/2);
@ -1451,7 +1601,6 @@ void machineDragged()
lastMachineDragPosition = new PVector(currentPos.x, currentPos.y);
PVector currentPosition = getDisplayMachine().getOutline().getPosition();
getDisplayMachine().getOffset().add(change);
cursor(MOVE);
}
}
@ -1554,36 +1703,13 @@ void leftButtonMachineClick()
void mouseWheel(int delta)
{
noLoop();
if (mouseOverMachine()) {
// get the mouse position on the machine, before changing the machine scaling
PVector pos = getDisplayMachine().scaleToDisplayMachine(getMouseVector());
changeMachineScaling(delta);
// now work out what the machine position needs to be to line the pos up with mousevector again
PVector scaledPos = getDisplayMachine().scaleToDisplayMachine(getMouseVector());
PVector change = PVector.sub(scaledPos, pos);
// and adjust for the new scaling factor
change.mult(machineScaling);
// finally update the machine offset (position)
getDisplayMachine().getOffset().add(change);
}
loop();
changeMachineScaling(delta);
}
void setChromaKey(PVector p)
{
color col = getDisplayMachine().getPixelAtScreenCoords(p);
chromaKeyColour = col;
rebuildPixels();
}
void rebuildPixels()
{
if (getDisplayMachine().pixelsCanBeExtracted() && isBoxSpecified())
{
getDisplayMachine().extractPixelsFromArea(getBoxVector1(), getBoxVectorSize(), getGridSize(), sampleArea);
@ -1604,26 +1730,6 @@ boolean isPreviewable(String command)
}
}
boolean toggleShowConsole() {
if (console == null) {
savedOut = System.out;
console = cp5.addConsole(consoleArea);
consoleArea.setVisible(true);
console.play();
}
else {
console.pause();
consoleArea.setVisible(false);
cp5.remove(console);
console = null;
System.setOut(savedOut);
}
// println("Ow");
return console == null;
}
/**
This will comb the command queue and attempt to draw a picture of what it contains.
Coordinates here are in pixels.
@ -1639,8 +1745,6 @@ void previewQueue(boolean forceRebuild)
{
println("regenerating preview queue.");
previewCommandList.clear();
for (String command : commandQueue)
{
if (command.startsWith(CMD_CHANGELENGTHDIRECT) || command.startsWith(CMD_CHANGELENGTH) || command.startsWith(CMD_DRAWPIXEL))
@ -1701,7 +1805,6 @@ void previewQueue(boolean forceRebuild)
ellipse(p.x, p.y, 5,5);
noFill();
}
// ellipse(p.x, p.y, 5,5); // Circle at each node
}
@ -2249,7 +2352,7 @@ public PVector getHomePoint()
public DisplayMachine getDisplayMachine()
{
if (displayMachine == null)
displayMachine = new DisplayMachine(new Machine(5000, 5000, 200.0, 95.0), machinePosition, machineScaling);
displayMachine = new DisplayMachine(new Machine(5000, 5000, 800.0, 95.0), machinePosition, machineScaling);
displayMachine.setOffset(machinePosition);
displayMachine.setScale(machineScaling);
@ -2403,34 +2506,10 @@ void readMachineMessage(String msg)
void readMachinePosition(String sync)
{
String[] splitted = split(sync, ",");
int aPosIndex = 0;
int bPosIndex = 0;
if (splitted.length == 4)
{
aPosIndex = 1;
bPosIndex = 2;
}
else if (splitted.length == 5)
{
aPosIndex = 2;
bPosIndex = 3;
}
if (aPosIndex != 0)
{
String currentAPos = splitted[aPosIndex];
String currentBPos = splitted[bPosIndex];
Float a = Float.valueOf(currentAPos).floatValue();
Float b = Float.valueOf(currentBPos).floatValue();
currentMachinePos.x = a;
currentMachinePos.y = b;
currentMachinePos = getDisplayMachine().inMM(getDisplayMachine().asCartesianCoords(currentMachinePos));
}
else if (splitted.length == 5)
{
String currentAPos = splitted[2];
String currentBPos = splitted[3];
String currentAPos = splitted[1];
String currentBPos = splitted[2];
Float a = Float.valueOf(currentAPos).floatValue();
Float b = Float.valueOf(currentBPos).floatValue();
currentMachinePos.x = a;
@ -2689,9 +2768,9 @@ void loadFromPropertiesFile()
this.currentPenWidth = getFloatProperty("machine.pen.size", 0.8);
// motor settings
this.currentMachineMaxSpeed = getFloatProperty("machine.motors.maxSpeed", 2000.0);
this.currentMachineAccel = getFloatProperty("machine.motors.accel", 2000.0);
this.machineStepMultiplier = getIntProperty("machine.step.multiplier", 8);
this.currentMachineMaxSpeed = getFloatProperty("machine.motors.maxSpeed", 600.0);
this.currentMachineAccel = getFloatProperty("machine.motors.accel", 400.0);
this.machineStepMultiplier = getIntProperty("machine.step.multiplier", 1);
// serial port
this.serialPortNumber = getIntProperty("controller.machine.serialport", 0);
@ -2731,31 +2810,25 @@ void loadFromPropertiesFile()
this.homePointCartesian = new PVector(getDisplayMachine().inSteps(homePointX), getDisplayMachine().inSteps(homePointY));
// println("home point loaded: " + homePointCartesian + ", " + getHomePoint());
// Geomerative stuff
println("RG.ADAPTATIVE is " + RG.ADAPTATIVE);
println("RG.UNIFORMLENGTH is " + RG.UNIFORMLENGTH);
println("RG.UNIFORMSTEP is " + RG.UNIFORMSTEP);
polygonizer = getIntProperty("controller.geomerative.polygonizer", RG.ADAPTATIVE);
polygonizerLength = getFloatProperty("controller.geomerative.polygonizerLength", 1.0);
setupPolygonizer();
setVectorFilename(getStringProperty("controller.vector.filename", null));
if (getVectorFilename() != null)
{
RShape shape = null;
// test if file exists
File f = new File(getVectorFilename());
if (f.isFile()) {
try
{
shape = RG.loadShape(getVectorFilename());
}
else {
println("Tried to load vector file (" + getVectorFilename() + ") but I couldn't find it.");
catch (Exception e)
{
shape = null;
}
if (shape != null) {
if (shape != null)
{
setVectorShape(shape);
}
else {
else
{
println("File not found (" + getVectorFilename() + ")");
}
}
@ -2765,6 +2838,7 @@ void loadFromPropertiesFile()
this.minimumVectorLineLength = getIntProperty("controller.vector.minLineLength", 0);
println("Finished loading configuration from properties file.");
}
@ -2801,8 +2875,8 @@ void savePropertiesFile()
props.setProperty("controller.density.preview.style", new Integer(getDensityPreviewStyle()).toString());
// initial screen size
props.setProperty("controller.window.width", new Integer((windowWidth < 100) ? 100 : windowWidth-16).toString());
props.setProperty("controller.window.height", new Integer((windowWidth < 100) ? 100 : windowHeight-38).toString());
props.setProperty("controller.window.width", new Integer((windowWidth < 50) ? 50 : windowWidth-16).toString());
props.setProperty("controller.window.height", new Integer((windowWidth < 50) ? 50 : windowHeight-38).toString());
props.setProperty("controller.testPenWidth.startSize", df.format(testPenWidthStartSize));
props.setProperty("controller.testPenWidth.endSize", df.format(testPenWidthEndSize));
@ -2837,9 +2911,6 @@ void savePropertiesFile()
props.setProperty("controller.vector.position.y", df.format(getVectorPosition().y));
props.setProperty("controller.vector.minLineLength", new Integer(this.minimumVectorLineLength).toString());
props.setProperty("controller.geomerative.polygonizer", new Integer(polygonizer).toString());
props.setProperty("controller.geomerative.polygonizerLength", df.format(polygonizerLength));
FileOutputStream propertiesOutput = null;
@ -2992,16 +3063,14 @@ Integer getBaudRate()
return baudRate;
}
void setupPolygonizer() {
RG.setPolygonizer(polygonizer); // http://www.polargraph.co.uk/forum/polargraphs-group2/troubleshooting-forum5/svg-differences-between-polargraphcontroller-2-1-1-2-3-0-thread523.0
switch(polygonizer) {
// case 0:
// RG.setPolygonizerAngle(polygonizerAdaptativeAngle);
// break;
case 1:
RG.setPolygonizerLength(polygonizerLength);
break;
}
boolean isUseWindowedConsole()
{
return this.useWindowedConsole;
}
void setUseWindowedConsole(boolean use)
{
this.useWindowedConsole = use;
}
void initLogging()

View File

@ -1,7 +0,0 @@
/**
Tools for dealing with a full command queue.
Optimise queue.
*/

View File

@ -83,35 +83,25 @@ List<String> buildTabNames()
void initTabs()
{
int tabWidth = (int)DEFAULT_CONTROL_SIZE.x;
int tabHeight = (int)DEFAULT_CONTROL_SIZE.y;
cp5.getTab(TAB_NAME_INPUT).setLabel(TAB_LABEL_INPUT);
cp5.getTab(TAB_NAME_INPUT).activateEvent(true);
cp5.getTab(TAB_NAME_INPUT).setId(1);
Tab.padding = 13; // that's a weird thing to do
cp5.getTab(TAB_NAME_DETAILS).setLabel(TAB_LABEL_DETAILS);
cp5.getTab(TAB_NAME_DETAILS).activateEvent(true);
cp5.getTab(TAB_NAME_DETAILS).setId(2);
Tab input = cp5.getTab(TAB_NAME_INPUT);
input.setLabel(TAB_LABEL_INPUT);
input.activateEvent(true);
input.setId(1);
cp5.getTab(TAB_NAME_ROVING).setLabel(TAB_LABEL_ROVING);
cp5.getTab(TAB_NAME_ROVING).activateEvent(true);
cp5.getTab(TAB_NAME_ROVING).setId(3);
Tab details = cp5.getTab(TAB_NAME_DETAILS);
details.setLabel(TAB_LABEL_DETAILS);
details.activateEvent(true);
details.setId(2);
cp5.getTab(TAB_NAME_TRACE).setLabel(TAB_LABEL_TRACE);
cp5.getTab(TAB_NAME_TRACE).activateEvent(true);
cp5.getTab(TAB_NAME_TRACE).setId(4);
Tab roving = cp5.getTab(TAB_NAME_ROVING);
roving.setLabel(TAB_LABEL_ROVING);
roving.activateEvent(true);
roving.setId(3);
Tab trace = cp5.getTab(TAB_NAME_TRACE);
trace.setLabel(TAB_LABEL_TRACE);
trace.activateEvent(true);
trace.setId(4);
Tab queue = cp5.getTab(TAB_NAME_QUEUE);
queue.setLabel(TAB_LABEL_QUEUE);
queue.activateEvent(true);
queue.setId(5);
cp5.getTab(TAB_NAME_QUEUE).setLabel(TAB_LABEL_QUEUE);
cp5.getTab(TAB_NAME_QUEUE).activateEvent(true);
cp5.getTab(TAB_NAME_QUEUE).setId(5);
}
public Set<String> buildPanelNames()