ruby_wordcram 1.0.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.mvn/extensions.xml +8 -0
- data/.mvn/wrapper/maven-wrapper.properties +1 -0
- data/Rakefile +28 -5
- data/docs/_posts/2017-03-07-getting_started.md +3 -2
- data/docs/_posts/2017-03-07-under_the_hood.md +33 -0
- data/lib/WordCram.jar +0 -0
- data/lib/jsoup-1.10.2.jar +0 -0
- data/lib/ruby_wordcram/version.rb +1 -1
- data/lib/ruby_wordcram.rb +1 -2
- data/pom.rb +53 -0
- data/pom.xml +87 -0
- data/ruby_wordcram.gemspec +1 -2
- data/src/cue/lang/Counter.java +141 -0
- data/src/cue/lang/IterableText.java +10 -0
- data/src/cue/lang/NGramIterator.java +151 -0
- data/src/cue/lang/SentenceIterator.java +86 -0
- data/src/cue/lang/WordIterator.java +60 -0
- data/src/cue/lang/stop/StopWords.java +114 -0
- data/src/cue/lang/stop/arabic +351 -0
- data/src/cue/lang/stop/armenian +45 -0
- data/src/cue/lang/stop/catalan +219 -0
- data/src/cue/lang/stop/croatian +2024 -0
- data/src/cue/lang/stop/czech +256 -0
- data/src/cue/lang/stop/danish +94 -0
- data/src/cue/lang/stop/dutch +107 -0
- data/src/cue/lang/stop/english +183 -0
- data/src/cue/lang/stop/esperanto +180 -0
- data/src/cue/lang/stop/farsi +966 -0
- data/src/cue/lang/stop/finnish +235 -0
- data/src/cue/lang/stop/french +543 -0
- data/src/cue/lang/stop/german +231 -0
- data/src/cue/lang/stop/greek +637 -0
- data/src/cue/lang/stop/hebrew +220 -0
- data/src/cue/lang/stop/hindi +97 -0
- data/src/cue/lang/stop/hungarian +202 -0
- data/src/cue/lang/stop/italian +279 -0
- data/src/cue/lang/stop/latin +1 -0
- data/src/cue/lang/stop/norwegian +176 -0
- data/src/cue/lang/stop/polish +138 -0
- data/src/cue/lang/stop/portuguese +204 -0
- data/src/cue/lang/stop/romanian +284 -0
- data/src/cue/lang/stop/russian +652 -0
- data/src/cue/lang/stop/slovak +110 -0
- data/src/cue/lang/stop/slovenian +448 -0
- data/src/cue/lang/stop/spanish +308 -0
- data/src/cue/lang/stop/swedish +114 -0
- data/src/cue/lang/stop/turkish +117 -0
- data/src/cue/lang/unicode/BlockUtil.java +103 -0
- data/src/cue/lang/unicode/Normalizer.java +55 -0
- data/src/cue/lang/unicode/Normalizer6.java +32 -0
- data/src/license.txt +201 -0
- data/src/wordcram/Anglers.java +137 -0
- data/src/wordcram/BBTree.java +133 -0
- data/src/wordcram/BBTreeBuilder.java +61 -0
- data/src/wordcram/Colorers.java +52 -0
- data/src/wordcram/EngineWord.java +73 -0
- data/src/wordcram/Fonters.java +17 -0
- data/src/wordcram/HsbWordColorer.java +28 -0
- data/src/wordcram/ImageShaper.java +91 -0
- data/src/wordcram/Observer.java +9 -0
- data/src/wordcram/PlacerHeatMap.java +134 -0
- data/src/wordcram/Placers.java +74 -0
- data/src/wordcram/PlottingWordNudger.java +38 -0
- data/src/wordcram/PlottingWordPlacer.java +36 -0
- data/src/wordcram/ProcessingWordRenderer.java +42 -0
- data/src/wordcram/RandomWordNudger.java +44 -0
- data/src/wordcram/RenderOptions.java +10 -0
- data/src/wordcram/ShapeBasedPlacer.java +66 -0
- data/src/wordcram/Sizers.java +54 -0
- data/src/wordcram/SketchCallbackObserver.java +70 -0
- data/src/wordcram/SpiralWordNudger.java +31 -0
- data/src/wordcram/SvgWordRenderer.java +110 -0
- data/src/wordcram/SwirlWordPlacer.java +25 -0
- data/src/wordcram/UpperLeftWordPlacer.java +27 -0
- data/src/wordcram/WaveWordPlacer.java +25 -0
- data/src/wordcram/Word.java +357 -0
- data/src/wordcram/WordAngler.java +20 -0
- data/src/wordcram/WordArray.java +18 -0
- data/src/wordcram/WordBag.java +31 -0
- data/src/wordcram/WordColorer.java +25 -0
- data/src/wordcram/WordCounter.java +96 -0
- data/src/wordcram/WordCram.java +920 -0
- data/src/wordcram/WordCramEngine.java +196 -0
- data/src/wordcram/WordFonter.java +24 -0
- data/src/wordcram/WordNudger.java +44 -0
- data/src/wordcram/WordPlacer.java +44 -0
- data/src/wordcram/WordRenderer.java +10 -0
- data/src/wordcram/WordShaper.java +78 -0
- data/src/wordcram/WordSizer.java +46 -0
- data/src/wordcram/WordSkipReason.java +42 -0
- data/src/wordcram/WordSorterAndScaler.java +31 -0
- data/src/wordcram/WordSource.java +5 -0
- data/src/wordcram/text/Html.java +15 -0
- data/src/wordcram/text/Html2Text.java +17 -0
- data/src/wordcram/text/Text.java +15 -0
- data/src/wordcram/text/TextFile.java +23 -0
- data/src/wordcram/text/TextSource.java +5 -0
- data/src/wordcram/text/WebPage.java +23 -0
- metadata +94 -5
- data/lib/cue.language.jar +0 -0
- data/lib/jsoup-1.7.2.jar +0 -0
- data/vendors/Rakefile +0 -51
@@ -0,0 +1,133 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import java.util.ArrayList;
|
4
|
+
|
5
|
+
import processing.core.PGraphics;
|
6
|
+
|
7
|
+
public class BBTree {
|
8
|
+
|
9
|
+
private final int left;
|
10
|
+
private final int top;
|
11
|
+
private final int right;
|
12
|
+
private final int bottom;
|
13
|
+
private BBTree[] kids;
|
14
|
+
|
15
|
+
private BBTree parent;
|
16
|
+
private int rootX;
|
17
|
+
private int rootY;
|
18
|
+
|
19
|
+
private int swelling = 0;
|
20
|
+
|
21
|
+
BBTree(int left, int top, int right, int bottom) {
|
22
|
+
this.left = left;
|
23
|
+
this.top = top;
|
24
|
+
this.right = right;
|
25
|
+
this.bottom = bottom;
|
26
|
+
}
|
27
|
+
|
28
|
+
void addKids(BBTree... _kids) {
|
29
|
+
ArrayList<BBTree> kidList = new ArrayList<>();
|
30
|
+
for (BBTree kid : _kids) {
|
31
|
+
if (kid != null) {
|
32
|
+
kidList.add(kid);
|
33
|
+
kid.parent = this;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
kids = kidList.toArray(new BBTree[0]);
|
38
|
+
}
|
39
|
+
|
40
|
+
public void setLocation(int left, int top) {
|
41
|
+
rootX = left;
|
42
|
+
rootY = top;
|
43
|
+
}
|
44
|
+
|
45
|
+
private BBTree getRoot() {
|
46
|
+
return parent == null ? this : parent.getRoot();
|
47
|
+
}
|
48
|
+
|
49
|
+
public boolean overlaps(BBTree otherTree) {
|
50
|
+
if (rectCollide(this, otherTree)) {
|
51
|
+
if (this.isLeaf() && otherTree.isLeaf()) {
|
52
|
+
return true;
|
53
|
+
}
|
54
|
+
else if (this.isLeaf()) { // Then otherTree isn't a leaf.
|
55
|
+
for (BBTree otherKid : otherTree.kids) {
|
56
|
+
if (this.overlaps(otherKid)) {
|
57
|
+
return true;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
else {
|
62
|
+
for (BBTree myKid : this.kids) {
|
63
|
+
if (otherTree.overlaps(myKid)) {
|
64
|
+
return true;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
return false;
|
70
|
+
}
|
71
|
+
|
72
|
+
private boolean rectCollide(BBTree aTree, BBTree bTree) {
|
73
|
+
int[] a = aTree.getPoints();
|
74
|
+
int[] b = bTree.getPoints();
|
75
|
+
|
76
|
+
return a[3] > b[1] && a[1] < b[3] && a[2] > b[0] && a[0] < b[2];
|
77
|
+
}
|
78
|
+
|
79
|
+
private int[] getPoints() {
|
80
|
+
BBTree root = getRoot();
|
81
|
+
return new int[] {
|
82
|
+
root.rootX - swelling + left,
|
83
|
+
root.rootY - swelling + top,
|
84
|
+
root.rootX + swelling + right,
|
85
|
+
root.rootY + swelling + bottom
|
86
|
+
};
|
87
|
+
}
|
88
|
+
|
89
|
+
boolean containsPoint(float x, float y) {
|
90
|
+
BBTree root = getRoot();
|
91
|
+
return root.rootX + this.left < x &&
|
92
|
+
root.rootX + this.right > x &&
|
93
|
+
root.rootY + this.top < y &&
|
94
|
+
root.rootY + this.bottom > y;
|
95
|
+
}
|
96
|
+
|
97
|
+
boolean isLeaf() {
|
98
|
+
return kids == null;
|
99
|
+
}
|
100
|
+
|
101
|
+
void swell(int extra) {
|
102
|
+
swelling += extra;
|
103
|
+
if (!isLeaf()) {
|
104
|
+
for (BBTree kid : kids) {
|
105
|
+
kid.swell(extra);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
public void draw(PGraphics g) {
|
111
|
+
g.pushStyle();
|
112
|
+
g.noFill();
|
113
|
+
|
114
|
+
g.stroke(30, 255, 255, 50);
|
115
|
+
drawLeaves(g);
|
116
|
+
|
117
|
+
g.popStyle();
|
118
|
+
}
|
119
|
+
|
120
|
+
private void drawLeaves(PGraphics g) {
|
121
|
+
if (this.isLeaf()) {
|
122
|
+
drawBounds(g, getPoints());
|
123
|
+
} else {
|
124
|
+
for (BBTree kid : kids) {
|
125
|
+
kid.drawLeaves(g);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
private void drawBounds(PGraphics g, int[] rect) {
|
131
|
+
g.rect(rect[0], rect[1], rect[2], rect[3]);
|
132
|
+
}
|
133
|
+
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import java.awt.Shape; // awt: getBounds2D(), contains(box), intersects(box)
|
4
|
+
import java.awt.geom.Rectangle2D; // awt: from shape bounding box, getX() and Y(), width() and height()
|
5
|
+
|
6
|
+
public class BBTreeBuilder {
|
7
|
+
public BBTree makeTree(Shape shape, int swelling) {
|
8
|
+
Rectangle2D bounds = shape.getBounds2D();
|
9
|
+
int minBoxSize = 1;
|
10
|
+
int x = (int) bounds.getX();
|
11
|
+
int y = (int) bounds.getY();
|
12
|
+
int right = x + (int) bounds.getWidth();
|
13
|
+
int bottom = y + (int) bounds.getHeight();
|
14
|
+
|
15
|
+
BBTree tree = makeTree(shape, minBoxSize, x, y, right, bottom);
|
16
|
+
tree.swell(swelling);
|
17
|
+
return tree;
|
18
|
+
}
|
19
|
+
|
20
|
+
private BBTree makeTree(Shape shape, int minBoxSize, int x, int y,
|
21
|
+
int right, int bottom) {
|
22
|
+
|
23
|
+
int width = right - x;
|
24
|
+
int height = bottom - y;
|
25
|
+
|
26
|
+
if (shape.contains(x, y, width, height)) {
|
27
|
+
return new BBTree(x, y, right, bottom);
|
28
|
+
}
|
29
|
+
else if (shape.intersects(x, y, width, height)) {
|
30
|
+
BBTree tree = new BBTree(x, y, right, bottom);
|
31
|
+
|
32
|
+
boolean tooSmallToContinue = width <= minBoxSize;
|
33
|
+
if (!tooSmallToContinue) {
|
34
|
+
int centerX = avg(x, right);
|
35
|
+
int centerY = avg(y, bottom);
|
36
|
+
|
37
|
+
// upper left
|
38
|
+
BBTree t0 = makeTree(shape, minBoxSize, x, y, centerX, centerY);
|
39
|
+
// upper right
|
40
|
+
BBTree t1 = makeTree(shape, minBoxSize, centerX, y, right, centerY);
|
41
|
+
// lower left
|
42
|
+
BBTree t2 = makeTree(shape, minBoxSize, x, centerY, centerX, bottom);
|
43
|
+
// lower right
|
44
|
+
BBTree t3 = makeTree(shape, minBoxSize, centerX, centerY, right, bottom);
|
45
|
+
|
46
|
+
tree.addKids(t0, t1, t2, t3);
|
47
|
+
}
|
48
|
+
|
49
|
+
return tree;
|
50
|
+
}
|
51
|
+
else { // neither contains nor intersects
|
52
|
+
return null;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
private int avg(int a, int b) {
|
57
|
+
// reminder: x >> 1 == x / 2
|
58
|
+
// avg = (a+b)/2 = (a/2)+(b/2) = (a>>1)+(b>>1)
|
59
|
+
return (a + b) >> 1;
|
60
|
+
}
|
61
|
+
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import java.util.Random;
|
4
|
+
|
5
|
+
import processing.core.PApplet;
|
6
|
+
|
7
|
+
public class Colorers {
|
8
|
+
|
9
|
+
public static WordColorer twoHuesRandomSats(final PApplet host) {
|
10
|
+
|
11
|
+
final float[] hues = new float[] { host.random(256), host.random(256) };
|
12
|
+
|
13
|
+
return new HsbWordColorer(host) {
|
14
|
+
@Override
|
15
|
+
public int getColorFor(Word w) {
|
16
|
+
|
17
|
+
float hue = hues[(int)host.random(hues.length)];
|
18
|
+
float sat = host.random(256);
|
19
|
+
float val = host.random(100, 256);
|
20
|
+
|
21
|
+
return host.color(hue, sat, val);
|
22
|
+
}
|
23
|
+
};
|
24
|
+
}
|
25
|
+
|
26
|
+
public static WordColorer twoHuesRandomSatsOnWhite(final PApplet host) {
|
27
|
+
|
28
|
+
final float[] hues = new float[] { host.random(256), host.random(256) };
|
29
|
+
|
30
|
+
return new HsbWordColorer(host) {
|
31
|
+
@Override
|
32
|
+
public int getColorFor(Word w) {
|
33
|
+
|
34
|
+
float hue = hues[(int)host.random(hues.length)];
|
35
|
+
float sat = host.random(256);
|
36
|
+
float val = host.random(156);
|
37
|
+
|
38
|
+
return host.color(hue, sat, val);
|
39
|
+
}
|
40
|
+
};
|
41
|
+
}
|
42
|
+
|
43
|
+
public static WordColorer pickFrom(final int... colors) {
|
44
|
+
final Random r = new Random();
|
45
|
+
return (Word w) -> colors[r.nextInt(colors.length)];
|
46
|
+
}
|
47
|
+
|
48
|
+
// TODO add an overload that takes 1 int (greyscale), 2 ints (greyscale/alpha), etc
|
49
|
+
public static WordColorer alwaysUse(final int color) {
|
50
|
+
return (Word w) -> color;
|
51
|
+
}
|
52
|
+
}
|
@@ -0,0 +1,73 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import java.awt.Shape; // awt: holds it; from the Word
|
4
|
+
import java.awt.geom.AffineTransform; // awt: for translating shapes
|
5
|
+
|
6
|
+
import processing.core.PVector;
|
7
|
+
|
8
|
+
class EngineWord {
|
9
|
+
Word word;
|
10
|
+
int rank;
|
11
|
+
|
12
|
+
private Shape shape;
|
13
|
+
private final BBTreeBuilder bbTreeBuilder;
|
14
|
+
private BBTree bbTree;
|
15
|
+
|
16
|
+
private PVector desiredLocation;
|
17
|
+
private PVector currentLocation;
|
18
|
+
|
19
|
+
EngineWord(Word word, int rank, int wordCount, BBTreeBuilder bbTreeBuilder) {
|
20
|
+
this.word = word;
|
21
|
+
this.rank = rank;
|
22
|
+
this.bbTreeBuilder = bbTreeBuilder;
|
23
|
+
word.setEngineWord(this);
|
24
|
+
}
|
25
|
+
|
26
|
+
void setShape(Shape shape, int swelling) {
|
27
|
+
this.shape = shape;
|
28
|
+
this.bbTree = bbTreeBuilder.makeTree(shape, swelling);
|
29
|
+
}
|
30
|
+
|
31
|
+
Shape getShape() {
|
32
|
+
return shape;
|
33
|
+
}
|
34
|
+
|
35
|
+
boolean overlaps(EngineWord other) {
|
36
|
+
return bbTree.overlaps(other.bbTree);
|
37
|
+
}
|
38
|
+
|
39
|
+
|
40
|
+
boolean containsPoint(float x, float y) {
|
41
|
+
return bbTree.containsPoint(x, y);
|
42
|
+
}
|
43
|
+
|
44
|
+
void setDesiredLocation(WordPlacer placer, int count, int wordImageWidth, int wordImageHeight, int fieldWidth, int fieldHeight) {
|
45
|
+
desiredLocation = word.getTargetPlace(placer, rank, count, wordImageWidth, wordImageHeight, fieldWidth, fieldHeight);
|
46
|
+
currentLocation = desiredLocation.copy();
|
47
|
+
}
|
48
|
+
|
49
|
+
void nudge(PVector nudge) {
|
50
|
+
currentLocation = PVector.add(desiredLocation, nudge);
|
51
|
+
bbTree.setLocation((int)currentLocation.x, (int)currentLocation.y);
|
52
|
+
}
|
53
|
+
|
54
|
+
void finalizeLocation() {
|
55
|
+
AffineTransform transform = AffineTransform.getTranslateInstance(
|
56
|
+
currentLocation.x, currentLocation.y);
|
57
|
+
shape = transform.createTransformedShape(shape);
|
58
|
+
bbTree.setLocation((int)currentLocation.x, (int)currentLocation.y);
|
59
|
+
word.setRenderedPlace(currentLocation);
|
60
|
+
}
|
61
|
+
|
62
|
+
PVector getCurrentLocation() {
|
63
|
+
return currentLocation.copy();
|
64
|
+
}
|
65
|
+
|
66
|
+
boolean wasPlaced() {
|
67
|
+
return word.wasPlaced();
|
68
|
+
}
|
69
|
+
|
70
|
+
boolean wasSkipped() {
|
71
|
+
return word.wasSkipped();
|
72
|
+
}
|
73
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import java.util.Random;
|
4
|
+
|
5
|
+
import processing.core.PFont;
|
6
|
+
|
7
|
+
public class Fonters {
|
8
|
+
|
9
|
+
public static WordFonter alwaysUse(final PFont pfont) {
|
10
|
+
return (Word word) -> pfont;
|
11
|
+
}
|
12
|
+
|
13
|
+
public static WordFonter pickFrom(final PFont... fonts) {
|
14
|
+
final Random r = new Random();
|
15
|
+
return (Word w) -> fonts[r.nextInt(fonts.length)];
|
16
|
+
}
|
17
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import processing.core.PApplet;
|
4
|
+
import processing.core.PConstants;
|
5
|
+
|
6
|
+
abstract class HsbWordColorer implements WordColorer {
|
7
|
+
private PApplet host;
|
8
|
+
private int range;
|
9
|
+
|
10
|
+
HsbWordColorer(PApplet host) {
|
11
|
+
this(host, 255);
|
12
|
+
}
|
13
|
+
HsbWordColorer(PApplet host, int range) {
|
14
|
+
this.host = host;
|
15
|
+
this.range = range;
|
16
|
+
}
|
17
|
+
|
18
|
+
@Override
|
19
|
+
public int colorFor(Word word) {
|
20
|
+
host.pushStyle();
|
21
|
+
host.colorMode(PConstants.HSB, range);
|
22
|
+
int color = getColorFor(word);
|
23
|
+
host.popStyle();
|
24
|
+
return color;
|
25
|
+
}
|
26
|
+
|
27
|
+
abstract int getColorFor(Word word);
|
28
|
+
}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import java.awt.Shape;
|
4
|
+
import java.awt.Rectangle;
|
5
|
+
import java.awt.geom.Area;
|
6
|
+
import processing.core.PImage;
|
7
|
+
import java.util.ArrayList;
|
8
|
+
|
9
|
+
public class ImageShaper {
|
10
|
+
|
11
|
+
public Shape shape(PImage image, int color) {
|
12
|
+
RectTree tree = new RectTree(0, 0, image.width, image.height);
|
13
|
+
return tree.toShape(image, color);
|
14
|
+
}
|
15
|
+
|
16
|
+
// TODO combine this somehow with BBTree(Builder). It's the same idea.
|
17
|
+
class RectTree {
|
18
|
+
ArrayList<RectTree> kids = null;
|
19
|
+
|
20
|
+
int left; int top; int right; int bottom;
|
21
|
+
int width; int height;
|
22
|
+
RectTree(int l, int t, int r, int b) {
|
23
|
+
left = l;
|
24
|
+
top = t;
|
25
|
+
right = r;
|
26
|
+
bottom = b;
|
27
|
+
|
28
|
+
width = right - left;
|
29
|
+
height = bottom - top; // Yep: upside-down.
|
30
|
+
|
31
|
+
split();
|
32
|
+
}
|
33
|
+
|
34
|
+
private void split() {
|
35
|
+
|
36
|
+
/*
|
37
|
+
Saying width < 2 OR height < 2 means we miss a few odd pixels.
|
38
|
+
Saying width < 2 AND height < 2 means we get them, but it goes a bit slower.
|
39
|
+
For now, we'll go with faster.
|
40
|
+
*/
|
41
|
+
if (width < 2 || height < 2) return;
|
42
|
+
|
43
|
+
int centerX = avg(left, right);
|
44
|
+
int centerY = avg(top, bottom);
|
45
|
+
kids = new ArrayList<>();
|
46
|
+
kids.add(new RectTree(left, top, centerX, centerY));
|
47
|
+
kids.add(new RectTree(centerX, top, right, centerY));
|
48
|
+
kids.add(new RectTree(left, centerY, centerX, bottom));
|
49
|
+
kids.add(new RectTree(centerX, centerY, right, bottom));
|
50
|
+
}
|
51
|
+
|
52
|
+
private int avg(int a, int b) {
|
53
|
+
// reminder: x >> 1 == x / 2
|
54
|
+
// avg = (a+b)/2 = (a/2)+(b/2) = (a>>1)+(b>>1)
|
55
|
+
return (a + b) >> 1;
|
56
|
+
}
|
57
|
+
|
58
|
+
Shape toShape(PImage img, int color) {
|
59
|
+
Area area = new Area();
|
60
|
+
if (isAllCovered(img, color)) {
|
61
|
+
area.add(new Area(new Rectangle(left, top, width, height)));
|
62
|
+
}
|
63
|
+
else if (kids != null) {
|
64
|
+
kids.forEach((kid) -> {
|
65
|
+
area.add(new Area(kid.toShape(img, color)));
|
66
|
+
});
|
67
|
+
}
|
68
|
+
return area;
|
69
|
+
}
|
70
|
+
|
71
|
+
private Boolean isAllCoveredMemo;
|
72
|
+
private boolean isAllCovered(PImage img, int color) {
|
73
|
+
if (isAllCoveredMemo == null) {
|
74
|
+
if (kids == null) {
|
75
|
+
isAllCoveredMemo = (img.get(left, top) == color);
|
76
|
+
}
|
77
|
+
else {
|
78
|
+
// isAllCoveredMemo = kids.all?(&:isAllCovered);
|
79
|
+
isAllCoveredMemo = true;
|
80
|
+
for (RectTree kid : kids) {
|
81
|
+
if (!kid.isAllCovered(img, color)) {
|
82
|
+
isAllCoveredMemo = false;
|
83
|
+
break;
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
return isAllCoveredMemo;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
}
|