Skip to content

Commit d68b46f

Browse files
committed
fix #790 and vastly increase PrintTurtle performance
1 parent 4db9c9b commit d68b46f

File tree

4 files changed

+94
-60
lines changed

4 files changed

+94
-60
lines changed

src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/turtle/DetectEdges.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public void update() {
3434
BufferedImage img = src.getValue();
3535
var edge = cutoff.getValue();
3636

37+
setComplete(0);
3738
FilterDesaturate desaturates = new FilterDesaturate(new TransformedImage(img));
3839
var img2 = desaturates.filter();
3940

@@ -45,18 +46,27 @@ public void update() {
4546
var img5 = dog.filter();
4647

4748
output.setValue(marchingSquares(img5.getSourceImage(),edge));
49+
setComplete(100);
4850
}
4951

5052
Turtle marchingSquares(BufferedImage img,int edge) {
5153
var turtle = new Turtle();
5254
int height = img.getHeight();
5355
int width = img.getWidth();
5456

57+
int size=width*height;
58+
int i=0;
5559
for(int y=0;y<height-1;++y) {
5660
for(int x=0;x<width-1;++x) {
5761
marchSquare(img,turtle,edge,x, y);
62+
setComplete((int)(i * 100.0/size));
5863
}
5964
}
65+
66+
var x0 = -width/2;
67+
var y0 = -height/2;
68+
turtle.translate(x0,y0);
69+
6070
return turtle;
6171
}
6272

src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/turtle/PrintTurtle.java

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.slf4j.LoggerFactory;
1313

1414
import java.awt.*;
15+
import java.awt.image.BufferedImage;
1516
import java.util.ArrayList;
1617
import java.util.List;
1718
import java.util.concurrent.locks.Lock;
@@ -31,8 +32,7 @@ public class PrintTurtle extends Node implements PrintWithGraphics {
3132
private final InputInt lineThickness = new InputInt("line thickness",1);
3233
private final InputInt layer = new InputInt("layer",5);
3334

34-
private final List<Polyline> polylines = new ArrayList<>();
35-
35+
private BufferedImage image = new BufferedImage(1,1,BufferedImage.TYPE_INT_ARGB);
3636
private final Lock lock = new ReentrantLock();
3737

3838
public PrintTurtle() {
@@ -48,40 +48,38 @@ public PrintTurtle() {
4848
public void update() {
4949
lock.lock();
5050
try {
51-
polylines.clear();
51+
setComplete(0);
5252
Turtle myTurtle = turtle.getValue();
53-
if (myTurtle == null || myTurtle.history.isEmpty()) return;
54-
55-
generatePolylines(myTurtle);
53+
image = TurtleToBufferedImage.generateImage(myTurtle,this);
54+
//generatePolylines(myTurtle);
55+
setComplete(100);
5656
} catch(Exception e) {
5757
logger.error("Failed to update", e);
5858
} finally {
5959
lock.unlock();
6060
}
6161
}
6262

63+
@Override
64+
public int getLayer() {
65+
return layer.getValue();
66+
}
67+
6368
@Override
6469
public void print(Graphics g) {
6570
if(getComplete()<100) return;
6671
Turtle myTurtle = turtle.getValue();
6772
if(myTurtle==null || myTurtle.history.isEmpty()) return;
68-
69-
Graphics2D g2 = (Graphics2D)g.create();
70-
GraphViewPanel.setHints(g2);
71-
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
72-
g2.setStroke(new BasicStroke(lineThickness.getValue()));
73-
74-
lock.lock();
75-
try {
76-
polylines.forEach(p -> p.draw(g2));
77-
} finally {
78-
lock.unlock();
79-
}
80-
81-
g2.dispose();
73+
//drawPolyglines(g);
74+
g.drawImage(image,-image.getWidth()/2,-image.getHeight()/2,null);
8275
}
8376

77+
private final List<Polyline> polylines = new ArrayList<>();
78+
8479
private void generatePolylines(Turtle myTurtle) {
80+
polylines.clear();
81+
if (myTurtle == null || myTurtle.history.isEmpty()) return;
82+
8583
int size = myTurtle.history.size();
8684
int count = 0;
8785

@@ -127,8 +125,19 @@ private void generatePolylines(Turtle myTurtle) {
127125
setComplete(100);
128126
}
129127

130-
@Override
131-
public int getLayer() {
132-
return layer.getValue();
128+
private void drawPolylines(Graphics g) {
129+
Graphics2D g2 = (Graphics2D)g.create();
130+
GraphViewPanel.setHints(g2);
131+
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
132+
g2.setStroke(new BasicStroke(lineThickness.getValue()));
133+
134+
lock.lock();
135+
try {
136+
polylines.forEach(p -> p.draw(g2));
137+
} finally {
138+
lock.unlock();
139+
}
140+
141+
g2.dispose();
133142
}
134143
}

src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/turtle/TurtleToBufferedImage.java

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,42 +25,56 @@ public TurtleToBufferedImage() {
2525

2626
@Override
2727
public void update() {
28-
Turtle myTurtle = turtle.getValue();
29-
if(myTurtle!=null && !myTurtle.history.isEmpty()) {
30-
Rectangle2D r = myTurtle.getBounds();
31-
int h = (int)Math.ceil(r.getHeight());
32-
int w = (int)Math.ceil(r.getWidth());
33-
BufferedImage img = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
34-
Graphics2D g = img.createGraphics();
35-
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
36-
g.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
37-
g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_PURE);
38-
g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,RenderingHints.VALUE_COLOR_RENDER_QUALITY);
39-
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
40-
g.translate(-r.getX(),-r.getY());
28+
Turtle source = turtle.getValue();
29+
output.setValue(generateImage(source,this));
30+
}
4131

42-
TurtleMove previousMove = null;
43-
Color downColor = Color.BLACK;
32+
public static BufferedImage generateImage(Turtle source,Node node) {
33+
if(source==null || source.history.isEmpty()) {
34+
return new BufferedImage(1,1,BufferedImage.TYPE_INT_ARGB);
35+
}
4436

45-
for (TurtleMove m : myTurtle.history) {
46-
if (m == null) throw new NullPointerException();
37+
int size = source.history.size();
4738

48-
switch (m.type) {
49-
case TRAVEL -> previousMove = m;
50-
case DRAW_LINE -> {
51-
if (previousMove != null) {
52-
g.setColor(downColor);
53-
g.drawLine((int) previousMove.x, (int) previousMove.y, (int) m.x, (int) m.y);
54-
}
55-
previousMove = m;
56-
}
57-
case TOOL_CHANGE -> {
58-
downColor = m.getColor();
59-
g.setStroke(new BasicStroke((int) m.getDiameter()));
39+
node.setComplete(0);
40+
Rectangle2D r = source.getBounds();
41+
int h = (int) Math.ceil(r.getHeight());
42+
int w = (int) Math.ceil(r.getWidth());
43+
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
44+
Graphics2D g = img.createGraphics();
45+
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
46+
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
47+
g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
48+
g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
49+
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
50+
g.translate(-r.getX(), -r.getY());
51+
52+
TurtleMove previousMove = null;
53+
Color downColor = Color.BLACK;
54+
55+
int i=0;
56+
for (TurtleMove m : source.history) {
57+
if (m == null) throw new NullPointerException();
58+
59+
switch (m.type) {
60+
case TRAVEL -> previousMove = m;
61+
case DRAW_LINE -> {
62+
if (previousMove != null) {
63+
g.setColor(downColor);
64+
g.drawLine((int) previousMove.x, (int) previousMove.y, (int) m.x, (int) m.y);
6065
}
66+
previousMove = m;
67+
}
68+
case TOOL_CHANGE -> {
69+
downColor = m.getColor();
70+
g.setStroke(new BasicStroke((int) m.getDiameter()));
6171
}
6272
}
63-
output.setValue(img);
73+
node.setComplete((int) (i++ * 100.0 / size));
6474
}
75+
76+
node.setComplete(100);
77+
78+
return img;
6579
}
6680
}

src/main/java/module-info.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,18 @@
2929
requires com.marginallyclever.nodegraphcore;
3030

3131
exports com.marginallyclever.communications;
32-
exports com.marginallyclever.makelangelo.makeart;
33-
exports com.marginallyclever.makelangelo.makeart.imagefilter;
34-
exports com.marginallyclever.makelangelo.makeart.turtletool;
35-
exports com.marginallyclever.makelangelo.paper;
3632
exports com.marginallyclever.makelangelo.donatelloimpl to com.marginallyclever.nodegraphcore;
3733
exports com.marginallyclever.makelangelo.donatelloimpl.nodes to com.marginallyclever.nodegraphcore;
3834
exports com.marginallyclever.makelangelo.donatelloimpl.nodes.turtle.shapes to com.marginallyclever.nodegraphcore;
35+
exports com.marginallyclever.makelangelo.donatelloimpl.ports to com.marginallyclever.nodegraphcore;
36+
exports com.marginallyclever.makelangelo.donatelloimpl.nodes.turtle to com.marginallyclever.nodegraphcore;
37+
exports com.marginallyclever.makelangelo.donatelloimpl.nodes.points to com.marginallyclever.nodegraphcore;
3938
exports com.marginallyclever.convenience.log to ch.qos.logback.core;
39+
exports com.marginallyclever.makelangelo.makeart;
40+
exports com.marginallyclever.makelangelo.makeart.imagefilter;
41+
exports com.marginallyclever.makelangelo.makeart.turtletool;
42+
exports com.marginallyclever.makelangelo.paper;
43+
exports com.marginallyclever.makelangelo.turtle;
4044

4145
opens com.marginallyclever.convenience;
4246
opens com.marginallyclever.makelangelo.turtle;
@@ -47,9 +51,6 @@
4751
opens com.marginallyclever.convenience.helpers;
4852
opens com.marginallyclever.convenience.log to ch.qos.logback.core;
4953
opens com.marginallyclever.makelangelo.preview;
50-
exports com.marginallyclever.makelangelo.donatelloimpl.ports to com.marginallyclever.nodegraphcore;
51-
exports com.marginallyclever.makelangelo.donatelloimpl.nodes.turtle to com.marginallyclever.nodegraphcore;
52-
exports com.marginallyclever.makelangelo.donatelloimpl.nodes.points to com.marginallyclever.nodegraphcore;
5354

5455
// A Java module that wants to implement a service interface from a service interface module must:
5556
// - Require the service interface module in its own module descriptor.

0 commit comments

Comments
 (0)