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,134 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import java.awt.Shape; // awt: word->shape->rect
|
4
|
+
import java.awt.geom.Rectangle2D; // awt: intersects(box), x-y-w-h, bounds
|
5
|
+
import java.util.ArrayList;
|
6
|
+
import java.util.HashMap;
|
7
|
+
|
8
|
+
import processing.core.PApplet;
|
9
|
+
import processing.core.PFont;
|
10
|
+
import processing.core.PVector;
|
11
|
+
|
12
|
+
public class PlacerHeatMap {
|
13
|
+
|
14
|
+
private final Word[] words;
|
15
|
+
private final WordFonter fonter;
|
16
|
+
private final WordSizer sizer;
|
17
|
+
private final WordAngler angler;
|
18
|
+
private final WordPlacer placer;
|
19
|
+
private final WordNudger nudger;
|
20
|
+
private final WordShaper shaper;
|
21
|
+
|
22
|
+
PlacerHeatMap(Word[] words, WordFonter fonter, WordSizer sizer, WordAngler angler, WordPlacer placer, WordNudger nudger, WordShaper shaper) {
|
23
|
+
|
24
|
+
this.fonter = fonter;
|
25
|
+
this.sizer = sizer;
|
26
|
+
this.angler = angler;
|
27
|
+
this.placer = placer;
|
28
|
+
this.nudger = nudger;
|
29
|
+
this.shaper = shaper;
|
30
|
+
this.words = words;
|
31
|
+
}
|
32
|
+
|
33
|
+
class RectStack {
|
34
|
+
ArrayList<Rectangle2D> rects = new ArrayList<>();
|
35
|
+
|
36
|
+
void add(int x, int y, int w, int h) {
|
37
|
+
rects.add(new Rectangle2D.Float(x, y, w, h));
|
38
|
+
}
|
39
|
+
|
40
|
+
int howManyIntersect(int x, int y, int w, int h) {
|
41
|
+
int sum = 0;
|
42
|
+
|
43
|
+
sum = rects.stream().filter((r) -> (r.intersects(x, y, w, h))).map((_item) -> 1).reduce(sum, Integer::sum);
|
44
|
+
|
45
|
+
return sum;
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
class RectGrid {
|
50
|
+
RectStack stack;
|
51
|
+
HashMap<Rectangle2D, Integer> levels = new HashMap<>();
|
52
|
+
|
53
|
+
RectGrid(RectStack stack) {
|
54
|
+
this.stack = stack;
|
55
|
+
}
|
56
|
+
|
57
|
+
void measure(int x, int y, int w, int h) {
|
58
|
+
Rectangle2D plot = new Rectangle2D.Float(x, y, w, h);
|
59
|
+
int level = stack.howManyIntersect(x, y, w, h);
|
60
|
+
levels.put(plot, level);
|
61
|
+
}
|
62
|
+
|
63
|
+
int maxLevel() {
|
64
|
+
int maxLevel = 0;
|
65
|
+
for (Integer level : levels.values()) {
|
66
|
+
if (level > maxLevel) {
|
67
|
+
maxLevel = level;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
return maxLevel;
|
71
|
+
}
|
72
|
+
|
73
|
+
void draw(PApplet sketch) {
|
74
|
+
int rowHeight = 10;
|
75
|
+
int colWidth = 10;
|
76
|
+
int rows = (int)(sketch.height / (float)rowHeight);
|
77
|
+
int cols = (int)(sketch.width / (float)colWidth);
|
78
|
+
|
79
|
+
for (int i = 0; i < rows; i++) {
|
80
|
+
int y = i * rowHeight;
|
81
|
+
for (int j = 0; j < cols; j++) {
|
82
|
+
int x = j * colWidth;
|
83
|
+
|
84
|
+
measure(x, y, colWidth, rowHeight);
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
sketch.colorMode(PApplet.HSB);
|
89
|
+
|
90
|
+
int max = maxLevel();
|
91
|
+
levels.keySet().forEach((rect) -> {
|
92
|
+
Integer level = levels.get(rect);
|
93
|
+
|
94
|
+
int c = sketch.color(0);
|
95
|
+
if (level > 0) {
|
96
|
+
float scaled = (float)level / 8;
|
97
|
+
int hue = (int)PApplet.map(scaled, 0, 1, 85, 0); // 85 = pure green
|
98
|
+
c = sketch.color(hue, 255, 255);
|
99
|
+
}
|
100
|
+
|
101
|
+
sketch.fill(c);
|
102
|
+
sketch.rect((float)rect.getX(), (float)rect.getY(), (float)rect.getWidth(), (float)rect.getHeight());
|
103
|
+
});
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
public void draw(PApplet sketch) {
|
108
|
+
RectStack rectStack = new RectStack();
|
109
|
+
|
110
|
+
for (int i = 0; i < words.length; i++) {
|
111
|
+
Word word = words[i];
|
112
|
+
PFont wordFont = word.getFont(fonter);
|
113
|
+
float wordSize = word.getSize(sizer, i, words.length);
|
114
|
+
float wordAngle = word.getAngle(angler);
|
115
|
+
|
116
|
+
Shape shape = shaper.getShapeFor(word.word, wordFont, wordSize, wordAngle);
|
117
|
+
Rectangle2D rect = shape.getBounds2D();
|
118
|
+
//return r.getHeight() < minShapeSize || r.getWidth() < minShapeSize;
|
119
|
+
|
120
|
+
int wordImageWidth = (int)rect.getWidth();
|
121
|
+
int wordImageHeight = (int)rect.getHeight();
|
122
|
+
|
123
|
+
PVector desiredLocation = word.getTargetPlace(placer, i, words.length,
|
124
|
+
wordImageWidth, wordImageHeight, sketch.width, sketch.height);
|
125
|
+
|
126
|
+
//sketch.rect(desiredLocation.x, desiredLocation.y, wordImageWidth, wordImageHeight);
|
127
|
+
rectStack.add((int)desiredLocation.x, (int)desiredLocation.y,
|
128
|
+
wordImageWidth, wordImageHeight);
|
129
|
+
}
|
130
|
+
|
131
|
+
RectGrid grid = new RectGrid(rectStack);
|
132
|
+
grid.draw(sketch);
|
133
|
+
}
|
134
|
+
}
|
@@ -0,0 +1,74 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import java.util.Random;
|
4
|
+
|
5
|
+
import processing.core.PApplet;
|
6
|
+
import processing.core.PVector;
|
7
|
+
|
8
|
+
public class Placers {
|
9
|
+
|
10
|
+
public static WordPlacer horizLine() {
|
11
|
+
final Random r = new Random();
|
12
|
+
|
13
|
+
return (Word word, int wordIndex, int wordsCount, int wordImageWidth, int wordImageHeight, int fieldWidth, int fieldHeight) -> {
|
14
|
+
int centerHorizLine = (int) ((fieldHeight - wordImageHeight) * 0.5);
|
15
|
+
int centerVertLine = (int) ((fieldWidth - wordImageWidth) * 0.5);
|
16
|
+
|
17
|
+
float xOff = (float) r.nextGaussian() * ((fieldWidth - wordImageWidth) * 0.2f);
|
18
|
+
float yOff = (float) r.nextGaussian() * 50;
|
19
|
+
|
20
|
+
return new PVector(centerVertLine + xOff, centerHorizLine + yOff);
|
21
|
+
/*
|
22
|
+
int adjFieldWidth = fieldWidth - wordImageWidth;
|
23
|
+
int adjFieldHeight = fieldHeight - wordImageHeight;
|
24
|
+
|
25
|
+
float xOff = (float) r.nextGaussian();// * 0.2f;
|
26
|
+
float yOff = (float) r.nextGaussian();// * 0.5f;
|
27
|
+
yOff = (float)Math.pow(yOff, 3) * 1.5f;
|
28
|
+
|
29
|
+
return new PVector(PApplet.map(xOff, -2, 2, 0, adjFieldWidth),
|
30
|
+
PApplet.map(yOff, -2, 2, 0, adjFieldHeight));
|
31
|
+
*/ };
|
32
|
+
}
|
33
|
+
|
34
|
+
public static WordPlacer centerClump() {
|
35
|
+
final Random r = new Random();
|
36
|
+
final float stdev = 0.4f;
|
37
|
+
|
38
|
+
return new WordPlacer() {
|
39
|
+
|
40
|
+
@Override
|
41
|
+
public PVector place(Word word, int wordIndex, int wordsCount,
|
42
|
+
int wordImageWidth, int wordImageHeight, int fieldWidth, int fieldHeight) {
|
43
|
+
return new PVector(getOneUnder(fieldWidth - wordImageWidth),
|
44
|
+
getOneUnder(fieldHeight - wordImageHeight));
|
45
|
+
}
|
46
|
+
|
47
|
+
private int getOneUnder(float upperLimit) {
|
48
|
+
return PApplet.round(PApplet.map((float) r.nextGaussian()
|
49
|
+
* stdev, -2, 2, 0, upperLimit));
|
50
|
+
}
|
51
|
+
};
|
52
|
+
}
|
53
|
+
|
54
|
+
public static WordPlacer horizBandAnchoredLeft() {
|
55
|
+
final Random r = new Random();
|
56
|
+
return (Word word, int wordIndex, int wordsCount, int wordImageWidth, int wordImageHeight, int fieldWidth, int fieldHeight) -> {
|
57
|
+
float x = (1 - word.weight) * fieldWidth * r.nextFloat(); // big=left, small=right
|
58
|
+
float y = ((float) fieldHeight) * 0.5f;
|
59
|
+
return new PVector(x, y);
|
60
|
+
};
|
61
|
+
}
|
62
|
+
|
63
|
+
public static WordPlacer swirl() {
|
64
|
+
return new SwirlWordPlacer();
|
65
|
+
}
|
66
|
+
|
67
|
+
public static WordPlacer upperLeft() {
|
68
|
+
return new UpperLeftWordPlacer();
|
69
|
+
}
|
70
|
+
|
71
|
+
public static WordPlacer wave() {
|
72
|
+
return new WaveWordPlacer();
|
73
|
+
}
|
74
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import processing.core.PApplet;
|
4
|
+
import processing.core.PVector;
|
5
|
+
|
6
|
+
/**
|
7
|
+
* If you're using a custom WordNudger, and having difficulty seeing
|
8
|
+
* how well it works, try wrapping it in a PlottingWordNudger. As your
|
9
|
+
* WordCram is drawn, it'll render tiny dots at each location it
|
10
|
+
* nudges your words to, so you can see how well it's working.
|
11
|
+
*/
|
12
|
+
public class PlottingWordNudger implements WordNudger {
|
13
|
+
|
14
|
+
private final PApplet parent;
|
15
|
+
private final WordNudger wrappedNudger;
|
16
|
+
|
17
|
+
public PlottingWordNudger(PApplet _parent, WordNudger _wrappedNudger) {
|
18
|
+
parent = _parent;
|
19
|
+
wrappedNudger = _wrappedNudger;
|
20
|
+
}
|
21
|
+
|
22
|
+
@Override
|
23
|
+
public PVector nudgeFor(Word word, int attempt) {
|
24
|
+
PVector v = wrappedNudger.nudgeFor(word, attempt);
|
25
|
+
parent.pushStyle();
|
26
|
+
parent.noStroke();
|
27
|
+
|
28
|
+
float alpha = attempt/700f;
|
29
|
+
//alpha = (float) Math.pow(alpha, 3);
|
30
|
+
parent.fill(40, 255, 255); //, alpha * 255);
|
31
|
+
|
32
|
+
PVector wordLoc = PVector.add(v, word.getTargetPlace());
|
33
|
+
parent.ellipse(wordLoc.x, wordLoc.y, 3, 3);
|
34
|
+
parent.popStyle();
|
35
|
+
return v;
|
36
|
+
}
|
37
|
+
|
38
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import processing.core.PApplet;
|
4
|
+
import processing.core.PVector;
|
5
|
+
|
6
|
+
/**
|
7
|
+
* If you're using a custom WordPlacer, and having difficulty seeing
|
8
|
+
* how well it works, try wrapping it in a PlottingWordPlacer. As your
|
9
|
+
* WordCram is drawn, it'll render tiny dots at each word's target
|
10
|
+
* location, so you can sort-of see how far off they are when they're
|
11
|
+
* finally rendered.
|
12
|
+
*/
|
13
|
+
public class PlottingWordPlacer implements WordPlacer {
|
14
|
+
|
15
|
+
private final PApplet parent;
|
16
|
+
private final WordPlacer wrappedPlacer;
|
17
|
+
|
18
|
+
public PlottingWordPlacer(PApplet _parent, WordPlacer _wrappedPlacer) {
|
19
|
+
parent = _parent;
|
20
|
+
wrappedPlacer = _wrappedPlacer;
|
21
|
+
}
|
22
|
+
|
23
|
+
@Override
|
24
|
+
public PVector place(Word word, int wordIndex, int wordsCount, int wordImageWidth, int wordImageHeight, int fieldWidth, int fieldHeight) {
|
25
|
+
PVector v = wrappedPlacer.place(word, wordIndex, wordsCount, wordImageWidth, wordImageHeight, fieldWidth, fieldHeight);
|
26
|
+
parent.pushStyle();
|
27
|
+
parent.noFill();
|
28
|
+
|
29
|
+
parent.stroke(15, 255, 255, 200);
|
30
|
+
|
31
|
+
parent.ellipse(v.x, v.y, 10, 10);
|
32
|
+
parent.popStyle();
|
33
|
+
return v;
|
34
|
+
}
|
35
|
+
|
36
|
+
}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import java.awt.Color; // awt: for fill color
|
4
|
+
import java.awt.Graphics2D; // awt: draws the word to the screen
|
5
|
+
import java.awt.RenderingHints; // awt: for constants while rendering a word
|
6
|
+
import java.awt.geom.GeneralPath; // awt: Shape -> Path, fill(path)
|
7
|
+
|
8
|
+
import processing.core.PGraphics;
|
9
|
+
import processing.awt.PGraphicsJava2D;
|
10
|
+
|
11
|
+
class ProcessingWordRenderer implements WordRenderer {
|
12
|
+
PGraphics destination;
|
13
|
+
|
14
|
+
ProcessingWordRenderer(PGraphics destination) {
|
15
|
+
this.destination = destination;
|
16
|
+
}
|
17
|
+
|
18
|
+
@Override
|
19
|
+
public int getWidth() {
|
20
|
+
return destination.width;
|
21
|
+
}
|
22
|
+
|
23
|
+
@Override
|
24
|
+
public int getHeight() {
|
25
|
+
return destination.height;
|
26
|
+
}
|
27
|
+
|
28
|
+
@Override
|
29
|
+
public void drawWord(EngineWord word, Color color) {
|
30
|
+
GeneralPath path2d = new GeneralPath(word.getShape());
|
31
|
+
|
32
|
+
// Graphics2D g2 = (Graphics2D)destination.image.getGraphics();
|
33
|
+
Graphics2D g2 = ((PGraphicsJava2D)destination).g2;
|
34
|
+
|
35
|
+
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
36
|
+
g2.setPaint(color);
|
37
|
+
g2.fill(path2d);
|
38
|
+
}
|
39
|
+
|
40
|
+
@Override
|
41
|
+
public void finish() {}
|
42
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import java.util.Random;
|
4
|
+
|
5
|
+
import processing.core.PVector;
|
6
|
+
|
7
|
+
/**
|
8
|
+
* A RandomWordNudger, where each attempt's PVector has X & Y coords
|
9
|
+
* distributed randomly around the desired point, multiplied by a standard deviation,
|
10
|
+
* and multiplied by the attempt number (so it gets farther, as it gets more
|
11
|
+
* desperate).
|
12
|
+
*
|
13
|
+
* @author Dan Bernier
|
14
|
+
*/
|
15
|
+
public class RandomWordNudger implements WordNudger {
|
16
|
+
|
17
|
+
private final Random r = new Random();
|
18
|
+
private float stdDev;
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Create a RandomWordNudger with a standard deviation of 0.6.
|
22
|
+
*/
|
23
|
+
public RandomWordNudger() {
|
24
|
+
this(0.6f);
|
25
|
+
}
|
26
|
+
|
27
|
+
/**
|
28
|
+
* Create a RandomWordNudger with your own standard deviation.
|
29
|
+
* @param stdDev
|
30
|
+
*/
|
31
|
+
public RandomWordNudger(float stdDev) {
|
32
|
+
this.stdDev = stdDev;
|
33
|
+
}
|
34
|
+
|
35
|
+
@Override
|
36
|
+
public PVector nudgeFor(Word w, int attempt) {
|
37
|
+
return new PVector(next(attempt), next(attempt));
|
38
|
+
}
|
39
|
+
|
40
|
+
private float next(int attempt) {
|
41
|
+
return (float)r.nextGaussian() * attempt * stdDev;
|
42
|
+
}
|
43
|
+
|
44
|
+
}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
package wordcram;
|
2
|
+
|
3
|
+
import java.awt.Shape; // awt: passed as arg, turned into Area
|
4
|
+
import java.awt.geom.Area; // awt: from Shape, getBounds2D(), contains(box)
|
5
|
+
import java.awt.geom.Rectangle2D; // awt: from Area, getMinX() and Y(), getMaxX() and Y()
|
6
|
+
import java.util.Random;
|
7
|
+
import processing.core.PVector;
|
8
|
+
|
9
|
+
public class ShapeBasedPlacer implements WordPlacer, WordNudger {
|
10
|
+
|
11
|
+
Area area;
|
12
|
+
float minX;
|
13
|
+
float minY;
|
14
|
+
float maxX;
|
15
|
+
float maxY;
|
16
|
+
Random random;
|
17
|
+
|
18
|
+
public ShapeBasedPlacer(Shape shape) {
|
19
|
+
this.area = new Area(shape);
|
20
|
+
random = new Random();
|
21
|
+
Rectangle2D areaBounds = area.getBounds2D();
|
22
|
+
this.minX = (float) areaBounds.getMinX();
|
23
|
+
this.minY = (float) areaBounds.getMinY();
|
24
|
+
this.maxX = (float) areaBounds.getMaxX();
|
25
|
+
this.maxY = (float) areaBounds.getMaxY();
|
26
|
+
}
|
27
|
+
|
28
|
+
@Override
|
29
|
+
public PVector place(Word w, int rank, int count, int ww, int wh, int fw,
|
30
|
+
int fh) {
|
31
|
+
|
32
|
+
for (int i = 0; i < 1000; i++) {
|
33
|
+
float newX = randomBetween(minX, maxX);
|
34
|
+
float newY = randomBetween(minY, maxY);
|
35
|
+
if (area.contains(newX, newY, ww, wh)) {
|
36
|
+
return new PVector(newX, newY);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
return new PVector(-1, -1);
|
41
|
+
}
|
42
|
+
|
43
|
+
@Override
|
44
|
+
public PVector nudgeFor(Word word, int attempt) {
|
45
|
+
PVector target = word.getTargetPlace();
|
46
|
+
float wx = target.x;
|
47
|
+
float wy = target.y;
|
48
|
+
float ww = word.getRenderedWidth();
|
49
|
+
float wh = word.getRenderedHeight();
|
50
|
+
|
51
|
+
for (int i = 0; i < 1000; i++) {
|
52
|
+
float newX = randomBetween(minX, maxX);
|
53
|
+
float newY = randomBetween(minY, maxY);
|
54
|
+
|
55
|
+
if (area.contains(newX, newY, ww, wh)) {
|
56
|
+
return new PVector(newX - wx, newY - wy);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
return new PVector(-1, -1);
|
61
|
+
}
|
62
|
+
|
63
|
+
float randomBetween(float a, float b) {
|
64
|
+
return a + random.nextFloat() * (b - a);
|
65
|
+
}
|
66
|
+
}
|