Skip to content

Commit 7b83ffd

Browse files
committed
improved CMYK calculations
1 parent d89b977 commit 7b83ffd

File tree

12 files changed

+327
-175
lines changed

12 files changed

+327
-175
lines changed

WeavingRadonJava/app.layout

+10-20
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,29 @@
11
<?xml version="1.0" ?>
22
<app-layout>
3-
<layout main-frame="true" location="487,73" size="1208,922" state="0">
3+
<layout main-frame="true" location="647,49" size="821,904" state="0">
44
<westToolbar>
55
</westToolbar>
66
<eastToolbar>
77
</eastToolbar>
88
<southToolbar>
99
</southToolbar>
10-
<split orientation="1" divider-proportion="0.7118786573410034">
11-
<left>
1210
<tabbed>
1311
<selectedTab persistentID="8e50154c-a149-4e95-9db5-4611d24cc0cc">
1412
</selectedTab>
1513
<tab persistentID="8e50154c-a149-4e95-9db5-4611d24cc0cc">
1614
<properties></properties>
1715
</tab>
18-
<tab persistentID="e675ab55-fea9-49a5-a04d-51daa9cd31e6">
19-
<properties></properties>
20-
</tab>
21-
</tabbed>
22-
</left>
23-
<right>
24-
<tabbed>
25-
<selectedTab persistentID="f2308391-8388-4f90-89f0-61caca03eb18">
26-
</selectedTab>
27-
<tab persistentID="f2308391-8388-4f90-89f0-61caca03eb18">
28-
<properties></properties>
29-
</tab>
30-
<tab persistentID="eb1ea92b-fc66-4c54-a5a9-3e4f8203bd5d">
31-
<properties></properties>
32-
</tab>
3316
</tabbed>
34-
</right>
35-
</split>
3617
</layout>
3718
<undocked>
19+
<simple persistentID="eb1ea92b-fc66-4c54-a5a9-3e4f8203bd5d" class-name="com.marginallyclever.weavingradon.ui.DockingPanel">
20+
<properties></properties>
21+
</simple>
22+
<simple persistentID="e675ab55-fea9-49a5-a04d-51daa9cd31e6" class-name="com.marginallyclever.weavingradon.ui.DockingPanel">
23+
<properties></properties>
24+
</simple>
25+
<simple persistentID="f2308391-8388-4f90-89f0-61caca03eb18" class-name="com.marginallyclever.weavingradon.ui.DockingPanel">
26+
<properties></properties>
27+
</simple>
3828
</undocked>
3929
</app-layout>

WeavingRadonJava/pom.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
55
<modelVersion>4.0.0</modelVersion>
66

7-
<groupId>org.example</groupId>
8-
<artifactId>WeavingRadonJava</artifactId>
9-
<version>1.0-SNAPSHOT</version>
7+
<groupId>com.marginallyclever</groupId>
8+
<artifactId>WeavingRadon</artifactId>
9+
<version>1.0</version>
1010

1111
<properties>
1212
<maven.compiler.source>22</maven.compiler.source>

WeavingRadonJava/src/main/java/com/marginallyclever/weavingradon/WeavingApp.java

+9-23
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,6 @@ public class WeavingApp {
3737
private final RadonPanel radonPanel;
3838

3939
private final RadonThreader myThreader;
40-
/*
41-
private final MonochromaticThreader radonThreaderC = new MonochromaticThreader(new Color( 0,255,255, ALPHA));
42-
private final MonochromaticThreader radonThreaderM = new MonochromaticThreader(new Color(255, 0,255, ALPHA));
43-
private final MonochromaticThreader radonThreaderY = new MonochromaticThreader(new Color(255,255, 0, ALPHA));
44-
private final MonochromaticThreader radonThreaderK = new MonochromaticThreader(new Color( 0, 0, 0, ALPHA));
45-
private final MonochromaticThreader radonThreaderW = new MonochromaticThreader(new Color(255,255,255, ALPHA));*/
4640

4741
private final OneLineOnImage singleLine;
4842
private final RadonPanel singleRadon;
@@ -60,24 +54,17 @@ public WeavingApp() {
6054
frame.setSize(DIAMETER, DIAMETER + TITLEBAR_HEIGHT + DOCKING_TAB_HEIGHT + TOOLBAR_HEIGHT);
6155
//frame.setLocationByPlatform(true);
6256
frame.setLocationRelativeTo(null);
63-
57+
/*/
6458
myThreader = new MonochromaticThreader(new Color(255,255,255, ALPHA));
65-
/*
59+
/*/
6660
MulticolorThreader mct = new MulticolorThreader();
67-
mct.addColor(new Color( 0,255,255, ALPHA));
68-
mct.addColor(new Color(255, 0,255, ALPHA));
69-
mct.addColor(new Color(255,255, 0, ALPHA));
70-
mct.addColor(new Color( 0, 0, 0, ALPHA));
71-
mct.addColor(new Color(255,255,255, ALPHA));
61+
mct.addThreader(new MonochromaticThreader(new Color( 0,255,255, ALPHA)));
62+
mct.addThreader(new MonochromaticThreader(new Color(255, 0,255, ALPHA)));
63+
mct.addThreader(new MonochromaticThreader(new Color(255,255, 0, ALPHA)));
64+
mct.addThreader(new MonochromaticThreader(new Color( 0, 0, 0, ALPHA)));
65+
mct.addThreader(new MonochromaticThreader(new Color(255,255,255, ALPHA)));
7266
myThreader = mct;
73-
*/
74-
/*
75-
mct.addThreader(radonThreaderC);
76-
mct.addThreader(radonThreaderM);
77-
mct.addThreader(radonThreaderY);
78-
mct.addThreader(radonThreaderK);
79-
mct.addThreader(radonThreaderW);
80-
*/
67+
//*/
8168
// create panels
8269
loomPanel = new LoomPanel();
8370
radonPanel = new RadonPanel(loomPanel);
@@ -184,8 +171,7 @@ public void openFile(ActionEvent actionEvent) {
184171
System.out.println("Open file: "+path);
185172
try {
186173
BufferedImage square = makeSquare(ImageIO.read(new File(path)));
187-
// build the nails and threads
188-
loom.reset();
174+
loom.createNailsAndThreads();
189175
// build a radon transform for every thread, based on the color filter for that threader.
190176
myThreader.setLoomAndImage(loom,square);
191177
myThreader.maskRadonTransformByAllThreads();

WeavingRadonJava/src/main/java/com/marginallyclever/weavingradon/core/Loom.java

+20-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,17 @@ public class Loom {
2525
public Loom(int radius,int numNails) {
2626
this.radius = radius;
2727
this.numNails = numNails;
28-
reset();
28+
createNailsAndThreads();
2929
}
3030

31-
public void reset() {
31+
public Loom(Loom other) {
32+
this.radius = other.radius;
33+
this.numNails = other.numNails;
34+
createNailsAndThreads();
35+
}
36+
37+
// Effectively reset the loom.
38+
public void createNailsAndThreads() {
3239
createNails();
3340
createThreads();
3441
}
@@ -146,4 +153,15 @@ public int getNumNails() {
146153
public int getRadius() {
147154
return radius;
148155
}
156+
157+
public int getNailIndex(Vector2d point) {
158+
Vector2d d = new Vector2d();
159+
for(Vector2d n : nails) {
160+
d.sub(n,point);
161+
if(d.lengthSquared() < 1) {
162+
return nails.indexOf(n);
163+
}
164+
}
165+
return -1;
166+
}
149167
}

WeavingRadonJava/src/main/java/com/marginallyclever/weavingradon/core/MonochromaticThreader.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,20 @@ public void setImage(BufferedImage referenceImage) {
2222

2323
/**
2424
* get the next best thread, add it to the loom, and subtract it from the current radon image.
25+
*
26+
* @return
2527
*/
2628
@Override
27-
public void addNextBestThread() {
28-
if (loom.allThreads.isEmpty()) return;
29+
public boolean addNextBestThread() {
30+
if (loom.allThreads.isEmpty()) return false;
2931
ThetaR tr = getBestThetaR();
30-
//System.out.println("best thetaR: " + tr);
32+
System.out.println("best thetaR: " + tr.intensity);
33+
if(tr.intensity==0) return false;
3134
LoomThread bestThread = loom.findThreadClosestToThetaR(tr);
3235
//System.out.println("best thread: " + bestThread);
3336
loom.selectThread(bestThread);
3437
radonTransform.subtractThread(bestThread);
38+
return true;
3539
}
3640

3741
public Color getColor() {
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,76 @@
11
package com.marginallyclever.weavingradon.core;
22

33
import java.awt.*;
4+
import java.awt.image.BufferedImage;
45
import java.util.ArrayList;
56
import java.util.List;
67

78
/**
89
* A GroupRadonThreader is a RadonThreader that can handle multiple colors.
910
*/
1011
public class MulticolorThreader extends RadonThreader {
11-
private final List<Color> colors = new ArrayList<>();
12+
private final List<MonochromaticThreader> colors = new ArrayList<>();
1213

13-
public void addColor(Color c) {
14-
colors.add(c);
14+
private static class ThreaderChoice {
15+
public MonochromaticThreader threader;
16+
public ThetaR bestThetaR;
17+
}
18+
19+
@Override
20+
public void setLoomAndImage(Loom loom, BufferedImage image) {
21+
for(MonochromaticThreader threader : colors) {
22+
threader.setLoomAndImage(loom, image);
23+
}
24+
setLoom(loom);
25+
}
26+
27+
@Override
28+
public void maskRadonTransformByAllThreads() {
29+
for(MonochromaticThreader threader : colors) {
30+
threader.maskRadonTransformByAllThreads();
31+
}
1532
}
1633

1734
/**
1835
* get the next best thread, add it to the loom, and subtract it from the current radon image.
36+
*
37+
* @return
1938
*/
2039
@Override
21-
public void addNextBestThread() {
22-
if (loom.allThreads.isEmpty()) return;
23-
ThetaR tr = getBestThetaR();
24-
LoomThread bestThread = loom.findThreadClosestToThetaR(tr);
25-
Color c = radonTransform.getColor(bestThread.thetaR.theta, bestThread.thetaR.r);
26-
bestThread.col = getNearestColor(c);
27-
loom.selectThread(bestThread);
28-
radonTransform.subtractThread(bestThread);
40+
public boolean addNextBestThread() {
41+
if (loom.allThreads.isEmpty()) return false;
42+
ThreaderChoice choice = getBestThreaderChoice();
43+
System.out.println("best thetaR: " + choice.bestThetaR.intensity);// choice.threader.getColor() + " @ "+choice.bestThetaR);
44+
if(choice.bestThetaR.intensity==0) return false;
45+
LoomThread bestThread = loom.findThreadClosestToThetaR(choice.bestThetaR);
46+
47+
choice.threader.getRadonTransform().subtractThread(bestThread);
48+
49+
LoomThread selection = new LoomThread(bestThread);
50+
selection.col = choice.threader.getColor();
51+
loom.selectThread(selection);
52+
return true;
2953
}
3054

31-
private Color getNearestColor(Color c) {
32-
Color nearest = null;
33-
double nearestDistanceSquared = Double.MAX_VALUE;
34-
for(Color color : colors) {
35-
double distanceSquared = /*Math.sqrt*/(
36-
Math.pow(color.getRed() - c.getRed(), 2) +
37-
Math.pow(color.getGreen() - c.getGreen(), 2) +
38-
Math.pow(color.getBlue() - c.getBlue(), 2)
39-
);
40-
if (distanceSquared < nearestDistanceSquared) {
41-
nearest = color;
42-
nearestDistanceSquared = distanceSquared;
55+
/**
56+
* Finds the best thread in the best color to add to the loom.
57+
*/
58+
public ThreaderChoice getBestThreaderChoice() {
59+
ThreaderChoice bestFound = new ThreaderChoice();
60+
61+
double intensity = 0;
62+
for(MonochromaticThreader threader : colors) {
63+
var tr = threader.getBestThetaR();
64+
if(intensity < tr.intensity) {
65+
bestFound.threader = threader;
66+
bestFound.bestThetaR = tr;
67+
intensity = tr.intensity;
4368
}
4469
}
45-
return nearest;
70+
return bestFound;
71+
}
72+
73+
public void addThreader(MonochromaticThreader radonThreader) {
74+
colors.add(radonThreader);
4675
}
4776
}

WeavingRadonJava/src/main/java/com/marginallyclever/weavingradon/core/RadonThreader.java

+13-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ public abstract class RadonThreader {
1212
protected int radius;
1313
protected RadonTransform radonTransform;
1414

15+
public void setLoomAndImage(Loom loom, BufferedImage image) {
16+
setLoom(loom);
17+
setImage(image);
18+
}
19+
1520
public void setLoom(Loom loom) {
1621
this.loom = loom;
1722
}
@@ -23,9 +28,15 @@ public void setImage(BufferedImage referenceImage) {
2328

2429
/**
2530
* get the next best thread, add it to the loom, and subtract it from the current radon image.
31+
*
32+
* @return false if there are no more threads to add.
2633
*/
27-
abstract public void addNextBestThread();
34+
abstract public boolean addNextBestThread();
2835

36+
/**
37+
* Mask the current radon image with the current threads.
38+
* This is achieved by generating a mask of all possible threads and then masking the radon image with it.
39+
*/
2940
public void maskRadonTransformByAllThreads() {
3041
System.out.println("filterRadonByThreads multicolor");
3142
var filter = new BufferedImage(radonTransform.getWidth(), radonTransform.getHeight(), BufferedImage.TYPE_INT_ARGB);
@@ -51,7 +62,7 @@ public ThetaR getBestThetaR() {
5162
// Find the pixel with the maximum intensity in the current radon transform
5263
for(int r=-radius;r<radius;++r) {
5364
for(int theta = 0; theta<180; ++theta) {
54-
int intensity = radonTransform.getIntensity(theta, r);
65+
double intensity = radonTransform.getIntensity(theta, r);
5566
if (intensity > bestFound.intensity) {
5667
bestFound.set(theta,r,intensity);
5768
}
@@ -63,9 +74,4 @@ public ThetaR getBestThetaR() {
6374
public RadonTransform getRadonTransform() {
6475
return radonTransform;
6576
}
66-
67-
public void setLoomAndImage(Loom loom, BufferedImage image) {
68-
setLoom(loom);
69-
setImage(image);
70-
}
7177
}

0 commit comments

Comments
 (0)