ruby_wordcram 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.mvn/extensions.xml +8 -0
  4. data/.mvn/wrapper/maven-wrapper.properties +1 -0
  5. data/Rakefile +28 -5
  6. data/docs/_posts/2017-03-07-getting_started.md +3 -2
  7. data/docs/_posts/2017-03-07-under_the_hood.md +33 -0
  8. data/lib/WordCram.jar +0 -0
  9. data/lib/jsoup-1.10.2.jar +0 -0
  10. data/lib/ruby_wordcram/version.rb +1 -1
  11. data/lib/ruby_wordcram.rb +1 -2
  12. data/pom.rb +53 -0
  13. data/pom.xml +87 -0
  14. data/ruby_wordcram.gemspec +1 -2
  15. data/src/cue/lang/Counter.java +141 -0
  16. data/src/cue/lang/IterableText.java +10 -0
  17. data/src/cue/lang/NGramIterator.java +151 -0
  18. data/src/cue/lang/SentenceIterator.java +86 -0
  19. data/src/cue/lang/WordIterator.java +60 -0
  20. data/src/cue/lang/stop/StopWords.java +114 -0
  21. data/src/cue/lang/stop/arabic +351 -0
  22. data/src/cue/lang/stop/armenian +45 -0
  23. data/src/cue/lang/stop/catalan +219 -0
  24. data/src/cue/lang/stop/croatian +2024 -0
  25. data/src/cue/lang/stop/czech +256 -0
  26. data/src/cue/lang/stop/danish +94 -0
  27. data/src/cue/lang/stop/dutch +107 -0
  28. data/src/cue/lang/stop/english +183 -0
  29. data/src/cue/lang/stop/esperanto +180 -0
  30. data/src/cue/lang/stop/farsi +966 -0
  31. data/src/cue/lang/stop/finnish +235 -0
  32. data/src/cue/lang/stop/french +543 -0
  33. data/src/cue/lang/stop/german +231 -0
  34. data/src/cue/lang/stop/greek +637 -0
  35. data/src/cue/lang/stop/hebrew +220 -0
  36. data/src/cue/lang/stop/hindi +97 -0
  37. data/src/cue/lang/stop/hungarian +202 -0
  38. data/src/cue/lang/stop/italian +279 -0
  39. data/src/cue/lang/stop/latin +1 -0
  40. data/src/cue/lang/stop/norwegian +176 -0
  41. data/src/cue/lang/stop/polish +138 -0
  42. data/src/cue/lang/stop/portuguese +204 -0
  43. data/src/cue/lang/stop/romanian +284 -0
  44. data/src/cue/lang/stop/russian +652 -0
  45. data/src/cue/lang/stop/slovak +110 -0
  46. data/src/cue/lang/stop/slovenian +448 -0
  47. data/src/cue/lang/stop/spanish +308 -0
  48. data/src/cue/lang/stop/swedish +114 -0
  49. data/src/cue/lang/stop/turkish +117 -0
  50. data/src/cue/lang/unicode/BlockUtil.java +103 -0
  51. data/src/cue/lang/unicode/Normalizer.java +55 -0
  52. data/src/cue/lang/unicode/Normalizer6.java +32 -0
  53. data/src/license.txt +201 -0
  54. data/src/wordcram/Anglers.java +137 -0
  55. data/src/wordcram/BBTree.java +133 -0
  56. data/src/wordcram/BBTreeBuilder.java +61 -0
  57. data/src/wordcram/Colorers.java +52 -0
  58. data/src/wordcram/EngineWord.java +73 -0
  59. data/src/wordcram/Fonters.java +17 -0
  60. data/src/wordcram/HsbWordColorer.java +28 -0
  61. data/src/wordcram/ImageShaper.java +91 -0
  62. data/src/wordcram/Observer.java +9 -0
  63. data/src/wordcram/PlacerHeatMap.java +134 -0
  64. data/src/wordcram/Placers.java +74 -0
  65. data/src/wordcram/PlottingWordNudger.java +38 -0
  66. data/src/wordcram/PlottingWordPlacer.java +36 -0
  67. data/src/wordcram/ProcessingWordRenderer.java +42 -0
  68. data/src/wordcram/RandomWordNudger.java +44 -0
  69. data/src/wordcram/RenderOptions.java +10 -0
  70. data/src/wordcram/ShapeBasedPlacer.java +66 -0
  71. data/src/wordcram/Sizers.java +54 -0
  72. data/src/wordcram/SketchCallbackObserver.java +70 -0
  73. data/src/wordcram/SpiralWordNudger.java +31 -0
  74. data/src/wordcram/SvgWordRenderer.java +110 -0
  75. data/src/wordcram/SwirlWordPlacer.java +25 -0
  76. data/src/wordcram/UpperLeftWordPlacer.java +27 -0
  77. data/src/wordcram/WaveWordPlacer.java +25 -0
  78. data/src/wordcram/Word.java +357 -0
  79. data/src/wordcram/WordAngler.java +20 -0
  80. data/src/wordcram/WordArray.java +18 -0
  81. data/src/wordcram/WordBag.java +31 -0
  82. data/src/wordcram/WordColorer.java +25 -0
  83. data/src/wordcram/WordCounter.java +96 -0
  84. data/src/wordcram/WordCram.java +920 -0
  85. data/src/wordcram/WordCramEngine.java +196 -0
  86. data/src/wordcram/WordFonter.java +24 -0
  87. data/src/wordcram/WordNudger.java +44 -0
  88. data/src/wordcram/WordPlacer.java +44 -0
  89. data/src/wordcram/WordRenderer.java +10 -0
  90. data/src/wordcram/WordShaper.java +78 -0
  91. data/src/wordcram/WordSizer.java +46 -0
  92. data/src/wordcram/WordSkipReason.java +42 -0
  93. data/src/wordcram/WordSorterAndScaler.java +31 -0
  94. data/src/wordcram/WordSource.java +5 -0
  95. data/src/wordcram/text/Html.java +15 -0
  96. data/src/wordcram/text/Html2Text.java +17 -0
  97. data/src/wordcram/text/Text.java +15 -0
  98. data/src/wordcram/text/TextFile.java +23 -0
  99. data/src/wordcram/text/TextSource.java +5 -0
  100. data/src/wordcram/text/WebPage.java +23 -0
  101. metadata +94 -5
  102. data/lib/cue.language.jar +0 -0
  103. data/lib/jsoup-1.7.2.jar +0 -0
  104. 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
+ }