mirror of
https://github.com/euphy/polargraphcontroller
synced 2025-01-10 04:05:15 +01:00
SWEET. Added centre-first path sorting. This shows the first paths to be drawn as darker on the capture preview. For speed it does not show it like that on the live preview.
This commit is contained in:
parent
b1a4daf69f
commit
2b3bfd9c5c
@ -403,19 +403,16 @@ class DisplayMachine extends Machine
|
|||||||
|
|
||||||
if (captureShape != null)
|
if (captureShape != null)
|
||||||
{
|
{
|
||||||
stroke(150);
|
//displayWebcamShapeAtFullSize(webcamShape, false, color(150,150,150));
|
||||||
displayWebcamShapeAtFullSize(webcamShape);
|
displayWebcamShapeAtFullSize(captureShape, true, color(0,0,0));
|
||||||
stroke(255);
|
|
||||||
displayWebcamShapeAtFullSize(captureShape);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stroke(255);
|
displayWebcamShapeAtFullSize(webcamShape, false, color(255,255,255));
|
||||||
displayWebcamShapeAtFullSize(webcamShape);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void displayWebcamShapeAtFullSize(RShape vec)
|
public void displayWebcamShapeAtFullSize(RShape vec, boolean illustrateSequence, Integer colour)
|
||||||
{
|
{
|
||||||
RG.ignoreStyles();
|
RG.ignoreStyles();
|
||||||
// work out scaling to make it full size on the screen
|
// work out scaling to make it full size on the screen
|
||||||
@ -423,28 +420,31 @@ class DisplayMachine extends Machine
|
|||||||
float h = height - getPanel(PANEL_NAME_GENERAL).getOutline().getTop() -10;
|
float h = height - getPanel(PANEL_NAME_GENERAL).getOutline().getTop() -10;
|
||||||
float w = h * aspectRatio;
|
float w = h * aspectRatio;
|
||||||
float scaler = h / vec.getHeight();
|
float scaler = h / vec.getHeight();
|
||||||
PVector position = new PVector(getPanel(PANEL_NAME_WEBCAM).getOutline().getRight()+7, height -10);
|
PVector position = new PVector(getPanel(PANEL_NAME_WEBCAM).getOutline().getRight()+7, getPanel(PANEL_NAME_GENERAL).getOutline().getTop() -10);
|
||||||
|
|
||||||
// int noOfChildren = vec.countChildren();
|
|
||||||
// List<RShape> children = new ArrayList<RShape>(noOfChildren);
|
|
||||||
// for (int i=0; i < noOfChildren; i++)
|
|
||||||
// {
|
|
||||||
// if (vec.children[i].getArea() > pathLengthHighPassCutoff)
|
|
||||||
// children.add(vec.children[i]);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// RShape[] newArray = children.toArray(new RShape[children.size()]);
|
|
||||||
// vec.children = newArray;
|
|
||||||
|
|
||||||
|
noFill();
|
||||||
RPoint[][] pointPaths = vec.getPointsInPaths();
|
RPoint[][] pointPaths = vec.getPointsInPaths();
|
||||||
|
if (illustrateSequence)
|
||||||
|
pointPaths = sortPathsCentreFirst(vec, pathLengthHighPassCutoff);
|
||||||
|
|
||||||
if (pointPaths != null)
|
if (pointPaths != null)
|
||||||
{
|
{
|
||||||
|
float incPerPath = 0.0;
|
||||||
|
if (illustrateSequence)
|
||||||
|
incPerPath = 255.0 / (float) pointPaths.length;
|
||||||
|
|
||||||
for(int i = 0; i<pointPaths.length; i++)
|
for(int i = 0; i<pointPaths.length; i++)
|
||||||
{
|
{
|
||||||
if (pointPaths[i].length >= pathLengthHighPassCutoff)
|
float col = (float)i * incPerPath;
|
||||||
{
|
// if (pointPaths[i].length >= pathLengthHighPassCutoff)
|
||||||
|
// {
|
||||||
if (pointPaths[i] != null)
|
if (pointPaths[i] != null)
|
||||||
{
|
{
|
||||||
|
if (illustrateSequence)
|
||||||
|
stroke((int)col, (int)col, (int)col, 128);
|
||||||
|
else
|
||||||
|
stroke(colour);
|
||||||
|
|
||||||
beginShape();
|
beginShape();
|
||||||
for (int j = 0; j<pointPaths[i].length; j++)
|
for (int j = 0; j<pointPaths[i].length; j++)
|
||||||
{
|
{
|
||||||
@ -454,10 +454,11 @@ class DisplayMachine extends Machine
|
|||||||
vertex(p.x, p.y);
|
vertex(p.x, p.y);
|
||||||
}
|
}
|
||||||
endShape();
|
endShape();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
noFill();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void displayVectorImage()
|
public void displayVectorImage()
|
||||||
|
@ -145,7 +145,8 @@ void button_mode_liveConfirmDraw()
|
|||||||
|
|
||||||
// work out scaling and position
|
// work out scaling and position
|
||||||
float scaling = getDisplayMachine().inMM(getDisplayMachine().getPictureFrame().getWidth()) / captureShape.getWidth();
|
float scaling = getDisplayMachine().inMM(getDisplayMachine().getPictureFrame().getWidth()) / captureShape.getWidth();
|
||||||
PVector position = new PVector(getDisplayMachine().inMM(getDisplayMachine().getPictureFrame().getPosition().x), getDisplayMachine().inMM(getDisplayMachine().getPictureFrame().getPosition().y) + (captureShape.getHeight() * scaling));
|
PVector position = new PVector(getDisplayMachine().inMM(getDisplayMachine().getPictureFrame().getPosition().x),
|
||||||
|
getDisplayMachine().inMM(getDisplayMachine().getPictureFrame().getPosition().y));
|
||||||
|
|
||||||
sendVectorShapes(captureShape, scaling, position);
|
sendVectorShapes(captureShape, scaling, position);
|
||||||
button_mode_penUp();
|
button_mode_penUp();
|
||||||
|
160
drawing.pde
160
drawing.pde
@ -25,7 +25,7 @@
|
|||||||
sandy.noble@gmail.com
|
sandy.noble@gmail.com
|
||||||
http://www.polargraph.co.uk/
|
http://www.polargraph.co.uk/
|
||||||
http://code.google.com/p/polargraph/
|
http://code.google.com/p/polargraph/
|
||||||
*/
|
*/
|
||||||
static final String CMD_CHANGELENGTH = "C01,";
|
static final String CMD_CHANGELENGTH = "C01,";
|
||||||
static final String CMD_CHANGEPENWIDTH = "C02,";
|
static final String CMD_CHANGEPENWIDTH = "C02,";
|
||||||
static final String CMD_CHANGEMOTORSPEED = "C03,";
|
static final String CMD_CHANGEMOTORSPEED = "C03,";
|
||||||
@ -71,7 +71,7 @@ static final String CMD_DRAW_NORWEGIAN = "C43,";
|
|||||||
static final String CMD_DRAW_NORWEGIAN_OUTLINE = "C44,";
|
static final String CMD_DRAW_NORWEGIAN_OUTLINE = "C44,";
|
||||||
static final String CMD_SETPENLIFTRANGE = "C45,";
|
static final String CMD_SETPENLIFTRANGE = "C45,";
|
||||||
|
|
||||||
private PVector mouseVector = new PVector(0,0);
|
private PVector mouseVector = new PVector(0, 0);
|
||||||
|
|
||||||
Comparator xAscending = new Comparator()
|
Comparator xAscending = new Comparator()
|
||||||
{
|
{
|
||||||
@ -128,7 +128,7 @@ public PVector getMouseVector()
|
|||||||
{
|
{
|
||||||
if (mouseVector == null)
|
if (mouseVector == null)
|
||||||
{
|
{
|
||||||
mouseVector = new PVector(0,0);
|
mouseVector = new PVector(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
mouseVector.x = mouseX;
|
mouseVector.x = mouseX;
|
||||||
@ -224,7 +224,7 @@ int scaleDensity(int inDens, int inMax, int outMax)
|
|||||||
{
|
{
|
||||||
float reducedDens = (float(inDens) / float(inMax)) * float(outMax);
|
float reducedDens = (float(inDens) / float(inMax)) * float(outMax);
|
||||||
reducedDens = outMax-reducedDens;
|
reducedDens = outMax-reducedDens;
|
||||||
// println("inDens:"+inDens+", inMax:"+inMax+", outMax:"+outMax+", reduced:"+reducedDens);
|
// println("inDens:"+inDens+", inMax:"+inMax+", outMax:"+outMax+", reduced:"+reducedDens);
|
||||||
|
|
||||||
// round up if bigger than .5
|
// round up if bigger than .5
|
||||||
int result = int(reducedDens);
|
int result = int(reducedDens);
|
||||||
@ -283,26 +283,26 @@ PVector sortPixelsInRowsAlternating(SortedMap<Float, List<PVector>> inRows, int
|
|||||||
// reverse it (descending)
|
// reverse it (descending)
|
||||||
Collections.sort(row, comp);
|
Collections.sort(row, comp);
|
||||||
Collections.reverse(row);
|
Collections.reverse(row);
|
||||||
// if (startPoint == null)
|
// if (startPoint == null)
|
||||||
// {
|
// {
|
||||||
// if (rowIsAlongXAxis)
|
// if (rowIsAlongXAxis)
|
||||||
// startPoint = new PVector(row.get(0).x+(maxPixelSize/2.0), row.get(0).y);
|
// startPoint = new PVector(row.get(0).x+(maxPixelSize/2.0), row.get(0).y);
|
||||||
// else
|
// else
|
||||||
// startPoint = new PVector(row.get(0).x, row.get(0).y-(maxPixelSize/2.0));
|
// startPoint = new PVector(row.get(0).x, row.get(0).y-(maxPixelSize/2.0));
|
||||||
// }
|
// }
|
||||||
reverse = false;
|
reverse = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// sort row ascending
|
// sort row ascending
|
||||||
Collections.sort(row, comp);
|
Collections.sort(row, comp);
|
||||||
// if (startPoint == null)
|
// if (startPoint == null)
|
||||||
// {
|
// {
|
||||||
// if (rowIsAlongXAxis)
|
// if (rowIsAlongXAxis)
|
||||||
// startPoint = new PVector(row.get(0).x-(maxPixelSize/2.0), row.get(0).y);
|
// startPoint = new PVector(row.get(0).x-(maxPixelSize/2.0), row.get(0).y);
|
||||||
// else
|
// else
|
||||||
// startPoint = new PVector(row.get(0).x, row.get(0).y+(maxPixelSize/2.0));
|
// startPoint = new PVector(row.get(0).x, row.get(0).y+(maxPixelSize/2.0));
|
||||||
// }
|
// }
|
||||||
reverse = true;
|
reverse = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -466,7 +466,7 @@ void sendPixels(Set<PVector> pixels, String pixelCommand, int initialDirection,
|
|||||||
// put the pen down if lifting over masked pixels is on
|
// put the pen down if lifting over masked pixels is on
|
||||||
if (liftPenOnMaskedPixels && penLifted)
|
if (liftPenOnMaskedPixels && penLifted)
|
||||||
{
|
{
|
||||||
// println("Pen down.");
|
// println("Pen down.");
|
||||||
String lowerPen = CMD_PENDOWN + "END";
|
String lowerPen = CMD_PENDOWN + "END";
|
||||||
addToCommandQueue(lowerPen);
|
addToCommandQueue(lowerPen);
|
||||||
penLifted = false;
|
penLifted = false;
|
||||||
@ -635,7 +635,6 @@ void sendOutlineOfBox()
|
|||||||
|
|
||||||
command = CMD_CHANGELENGTHDIRECT+(int)tl.x+","+(int)tl.y+","+getMaxSegmentLength()+",END";
|
command = CMD_CHANGELENGTHDIRECT+(int)tl.x+","+(int)tl.y+","+getMaxSegmentLength()+",END";
|
||||||
addToCommandQueue(command);
|
addToCommandQueue(command);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendVectorShapes()
|
void sendVectorShapes()
|
||||||
@ -649,7 +648,9 @@ void sendVectorShapes(RShape vec, float scaling, PVector position)
|
|||||||
RPoint[][] pointPaths = vec.getPointsInPaths();
|
RPoint[][] pointPaths = vec.getPointsInPaths();
|
||||||
|
|
||||||
// sort the paths to optimise the draw sequence
|
// sort the paths to optimise the draw sequence
|
||||||
pointPaths = sortPathLongestFirst(pointPaths, pathLengthHighPassCutoff);
|
// pointPaths = sortPathsLongestFirst(pointPaths, pathLengthHighPassCutoff);
|
||||||
|
// pointPaths = sortPathsGreatestAreaFirst(vec, pathLengthHighPassCutoff);
|
||||||
|
pointPaths = sortPathsCentreFirst(vec, pathLengthHighPassCutoff);
|
||||||
|
|
||||||
String command = "";
|
String command = "";
|
||||||
PVector lastPoint = new PVector();
|
PVector lastPoint = new PVector();
|
||||||
@ -665,7 +666,6 @@ void sendVectorShapes(RShape vec, float scaling, PVector position)
|
|||||||
if (pointPaths[i].length > pathLengthHighPassCutoff)
|
if (pointPaths[i].length > pathLengthHighPassCutoff)
|
||||||
{
|
{
|
||||||
List<PVector> filteredPoints = filterPoints(pointPaths[i], VECTOR_FILTER_LOW_PASS, minimumVectorLineLength, scaling, position);
|
List<PVector> filteredPoints = filterPoints(pointPaths[i], VECTOR_FILTER_LOW_PASS, minimumVectorLineLength, scaling, position);
|
||||||
//println(filteredPoints);
|
|
||||||
if (!filteredPoints.isEmpty())
|
if (!filteredPoints.isEmpty())
|
||||||
{
|
{
|
||||||
// draw the first one with a pen up and down to get to it
|
// draw the first one with a pen up and down to get to it
|
||||||
@ -693,8 +693,7 @@ void sendVectorShapes(RShape vec, float scaling, PVector position)
|
|||||||
command = CMD_CHANGELENGTHDIRECT+(int)p.x+","+(int)p.y+","+getMaxSegmentLength()+",END";
|
command = CMD_CHANGELENGTHDIRECT+(int)p.x+","+(int)p.y+","+getMaxSegmentLength()+",END";
|
||||||
addToCommandQueue(command);
|
addToCommandQueue(command);
|
||||||
}
|
}
|
||||||
lastPoint = new PVector(p.x,p.y);
|
lastPoint = new PVector(p.x, p.y);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -719,13 +718,16 @@ public RPoint[][] sortPathLongestFirst(RPoint[][] pointPaths, int highPassCutoff
|
|||||||
public int compare(RPoint[] o1, RPoint[] o2) {
|
public int compare(RPoint[] o1, RPoint[] o2) {
|
||||||
if (o1.length > o2.length) {
|
if (o1.length > o2.length) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (o1.length < o2.length) {
|
}
|
||||||
|
else if (o1.length < o2.length) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// filter out some short paths
|
// filter out some short paths
|
||||||
pathsList = removeShortPaths(pathsList, highPassCutoff);
|
pathsList = removeShortPaths(pathsList, highPassCutoff);
|
||||||
@ -739,13 +741,110 @@ public RPoint[][] sortPathLongestFirst(RPoint[][] pointPaths, int highPassCutoff
|
|||||||
return pointPaths;
|
return pointPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RPoint[][] sortPathsGreatestAreaFirst(RShape vec, int highPassCutoff)
|
||||||
|
{
|
||||||
|
// put the paths into a list
|
||||||
|
SortedMap<Float, RPoint[]> pathsList = new TreeMap<Float, RPoint[]>();
|
||||||
|
|
||||||
|
int noOfChildren = vec.countChildren();
|
||||||
|
for (int i=0; i < noOfChildren; i++)
|
||||||
|
{
|
||||||
|
float area = vec.children[i].getArea();
|
||||||
|
RPoint[] path = vec.children[i].getPointsInPaths()[0];
|
||||||
|
pathsList.put(area, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
RPoint[][] pointPaths = vec.getPointsInPaths();
|
||||||
|
List<RPoint[]> filtered = new ArrayList<RPoint[]>();
|
||||||
|
|
||||||
|
// and put them into a new array
|
||||||
|
int i = 0;
|
||||||
|
for (Float k : pathsList.keySet())
|
||||||
|
{
|
||||||
|
if (k >= highPassCutoff)
|
||||||
|
{
|
||||||
|
filtered.add(pathsList.get(k));
|
||||||
|
println("Filtered kept path of area " + k);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
println("Filtered discarded path of area " + k);
|
||||||
|
}
|
||||||
|
|
||||||
|
pointPaths = new RPoint[filtered.size()][];
|
||||||
|
for (i = 0; i < filtered.size(); i++)
|
||||||
|
{
|
||||||
|
pointPaths[i] = filtered.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pointPaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RPoint[][] sortPathsCentreFirst(RShape vec, int highPassCutoff)
|
||||||
|
{
|
||||||
|
// put the paths into a list
|
||||||
|
int noOfChildren = vec.countChildren();
|
||||||
|
List<RShape> pathsList = new ArrayList<RShape>(noOfChildren);
|
||||||
|
for (int i=0; i < noOfChildren; i++)
|
||||||
|
pathsList.add(vec.children[i]);
|
||||||
|
List<RShape> orderedPathsList = new ArrayList<RShape>(noOfChildren);
|
||||||
|
|
||||||
|
// make a tiny area in the centre of the shape,
|
||||||
|
// plan to increment the size of the area until it covers vec entirely
|
||||||
|
// (radius of area min = 0, max = distance from shape centre to any corner.)
|
||||||
|
|
||||||
|
float aspectRatio = vec.getHeight() / vec.getWidth();
|
||||||
|
int n = 0;
|
||||||
|
float w = 1.0;
|
||||||
|
float h = w * aspectRatio;
|
||||||
|
|
||||||
|
RPoint topLeft = vec.getTopLeft();
|
||||||
|
RPoint botRight = vec.getBottomRight();
|
||||||
|
|
||||||
|
PVector centre = new PVector(vec.getWidth()/2, vec.getHeight()/2);
|
||||||
|
|
||||||
|
float vecWidth = vec.getWidth();
|
||||||
|
|
||||||
|
while (w <= vecWidth)
|
||||||
|
{
|
||||||
|
w+=6.0;
|
||||||
|
h = w * aspectRatio;
|
||||||
|
|
||||||
|
//println(n++ + ". Rect w " + w + ", h " + h);
|
||||||
|
RShape field = RShape.createRectangle(centre.x-(w/2.0), centre.y-(h/2.0), w, h);
|
||||||
|
// add all the shapes that are entirely inside the circle to orderedPathsList
|
||||||
|
ListIterator<RShape> it = pathsList.listIterator();
|
||||||
|
int shapesAdded = 0;
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
RShape sh = it.next();
|
||||||
|
if (field.contains(sh.getCenter()))
|
||||||
|
{
|
||||||
|
orderedPathsList.add(sh);
|
||||||
|
// remove the shapes from pathsList (so it isn't found again)
|
||||||
|
shapesAdded++;
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// increase the size of the circle and try again
|
||||||
|
}
|
||||||
|
|
||||||
|
RPoint[][] pointPaths = new RPoint[orderedPathsList.size()][];// vec.getPointsInPaths();
|
||||||
|
for (int i = 0; i < orderedPathsList.size(); i++)
|
||||||
|
{
|
||||||
|
pointPaths[i] = orderedPathsList.get(i).getPointsInPaths()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return pointPaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
List<RPoint[]> removeShortPaths(List<RPoint[]> list, int cutoff)
|
List<RPoint[]> removeShortPaths(List<RPoint[]> list, int cutoff)
|
||||||
{
|
{
|
||||||
if (cutoff > 0)
|
if (cutoff > 0)
|
||||||
{
|
{
|
||||||
int numberOfPaths = list.size();
|
int numberOfPaths = list.size();
|
||||||
ListIterator<RPoint[]> it = list.listIterator();
|
ListIterator<RPoint[]> it = list.listIterator();
|
||||||
while (it.hasNext())
|
while (it.hasNext ())
|
||||||
{
|
{
|
||||||
RPoint[] paths = it.next();
|
RPoint[] paths = it.next();
|
||||||
if (paths == null || cutoff >= paths.length)
|
if (paths == null || cutoff >= paths.length)
|
||||||
@ -818,11 +917,11 @@ void sendMachineStoreMode()
|
|||||||
if (!getOverwriteExistingStoreFile())
|
if (!getOverwriteExistingStoreFile())
|
||||||
overwrite = ",A";
|
overwrite = ",A";
|
||||||
|
|
||||||
addToCommandQueue(CMD_MACHINE_MODE_STORE_COMMANDS + getStoreFilename()+overwrite+",END");
|
addToRealtimeCommandQueue(CMD_MACHINE_MODE_STORE_COMMANDS + getStoreFilename()+overwrite+",END");
|
||||||
}
|
}
|
||||||
void sendMachineLiveMode()
|
void sendMachineLiveMode()
|
||||||
{
|
{
|
||||||
addToCommandQueue(CMD_MACHINE_MODE_LIVE+"END");
|
addToRealtimeCommandQueue(CMD_MACHINE_MODE_LIVE+"END");
|
||||||
}
|
}
|
||||||
void sendMachineExecMode()
|
void sendMachineExecMode()
|
||||||
{
|
{
|
||||||
@ -848,4 +947,3 @@ void sendDrawRandomSprite(String spriteFilename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,6 +105,9 @@ public RShape webcam_traceImage(Map<Integer, PImage> seps)
|
|||||||
}
|
}
|
||||||
// rotate image
|
// rotate image
|
||||||
allShapes.rotate(radians(-90));
|
allShapes.rotate(radians(-90));
|
||||||
|
// transform it so that top left is at 0,0.
|
||||||
|
RPoint topLeft = allShapes.getTopLeft();
|
||||||
|
allShapes.translate(-topLeft.x, -topLeft.y);
|
||||||
return allShapes;
|
return allShapes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user