mirror of
https://github.com/kennycason/kumo
synced 2025-03-26 08:48:49 -04:00
fixed the calculation of the maximum spiral radius and added a test to it
the maximum spiral radius might be bigger or smaller than the image width, e.g. if the image height is bigger than the width.
This commit is contained in:
parent
1ca095b4e7
commit
ee9ad38574
kumo-core/src
@ -161,6 +161,21 @@ public class WordCloud {
|
||||
graphics2.drawImage(backgroundBufferedImage, 0, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* compute the maximum radius for the placing spiral
|
||||
*
|
||||
* @param dimension the size of the backgound
|
||||
* @param start the center of the spiral
|
||||
* @return the maximum usefull radius
|
||||
*/
|
||||
static int computeRadius(Dimension dimension, Point start) {
|
||||
int maxDistanceX = Math.max(start.x, dimension.width - start.x) + 1;
|
||||
int maxDistanceY = Math.max(start.y, dimension.height - start.y) + 1;
|
||||
|
||||
// we use the pythagorean theorem to determinate the maximum radius
|
||||
return (int) Math.ceil(Math.sqrt(maxDistanceX * maxDistanceX + maxDistanceY * maxDistanceY));
|
||||
}
|
||||
|
||||
/**
|
||||
* try to place in center, build out in a spiral trying to place words for N steps
|
||||
* @param word the word being placed
|
||||
@ -169,12 +184,12 @@ public class WordCloud {
|
||||
protected boolean place(final Word word, final Point start) {
|
||||
final Graphics graphics = this.bufferedImage.getGraphics();
|
||||
|
||||
final int maxRadius = dimension.width;
|
||||
final int maxRadius = computeRadius(dimension, start);
|
||||
|
||||
for (int r = 0; r < maxRadius; r += 2) {
|
||||
for (int x = -r; x <= r; x++) {
|
||||
if (start.x + x < 0) { continue; }
|
||||
if (start.x + x >= maxRadius) { continue; }
|
||||
if (start.x + x >= dimension.width) { continue; }
|
||||
|
||||
boolean placed = false;
|
||||
word.getPosition().x = start.x + x;
|
||||
|
115
kumo-core/src/test/java/com/kennycason/kumo/SpiralTest.java
Normal file
115
kumo-core/src/test/java/com/kennycason/kumo/SpiralTest.java
Normal file
@ -0,0 +1,115 @@
|
||||
package com.kennycason.kumo;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import javax.imageio.ImageIO;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joerg1985
|
||||
*/
|
||||
public class SpiralTest {
|
||||
|
||||
@Test
|
||||
public void NewImplementationVsOldImplementation() throws IOException {
|
||||
// draw the spiral as image?
|
||||
// red pixels -> only returned by the old implementation
|
||||
// blue pixels -> only returned by the new implementation
|
||||
// pink pixels -> returned by the old and the new implementation
|
||||
boolean debug = false;
|
||||
|
||||
final int white = 0;
|
||||
final int red = 0xFFFF0000;
|
||||
final int blue = 0xFF0000FF;
|
||||
final int pink = red | blue;
|
||||
|
||||
// we seed to get the same numbers on each run
|
||||
Random random = new Random(42);
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
Dimension dimension = new Dimension(
|
||||
100 + random.nextInt(900),
|
||||
100 + random.nextInt(900)
|
||||
);
|
||||
|
||||
for (int j = 0; j < 20; j++) {
|
||||
Point start = new Point(
|
||||
random.nextInt(dimension.width),
|
||||
random.nextInt(dimension.height)
|
||||
);
|
||||
|
||||
// the old implementation did not repect images higher than wide
|
||||
int originalRadius = dimension.width;
|
||||
int optimizedRadius = WordCloud.computeRadius(dimension, start);
|
||||
|
||||
List<Point> original = spiral(dimension, start, originalRadius);
|
||||
List<Point> optimized = spiral(dimension, start, optimizedRadius);
|
||||
|
||||
BufferedImage img = new BufferedImage(
|
||||
dimension.width, dimension.height, BufferedImage.TYPE_4BYTE_ABGR
|
||||
);
|
||||
|
||||
original.forEach((p) -> img.setRGB(p.x, p.y, red));
|
||||
optimized.forEach((p) -> {
|
||||
if (img.getRGB(p.x, p.y) != 0) {
|
||||
img.setRGB(p.x, p.y, pink);
|
||||
} else {
|
||||
img.setRGB(p.x, p.y, blue);
|
||||
}
|
||||
});
|
||||
|
||||
boolean next = false;
|
||||
|
||||
for (int y = 0; !next && y < dimension.height; y++) {
|
||||
for (int x = 0; !next && x < dimension.width; x++) {
|
||||
int rgb = img.getRGB(x, y);
|
||||
|
||||
if (rgb == red) {
|
||||
ImageIO.write(img, "png", new File("output\\failed_spiral_test.png"));
|
||||
Assert.fail();
|
||||
} else if (debug && rgb != white && rgb != pink) {
|
||||
ImageIO.write(img, "png", new File("output\\debug_spiral_test_" + System.currentTimeMillis() + ".png"));
|
||||
next = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Point> spiral(Dimension dimension, Point start, final int maxRadius) {
|
||||
List<Point> points = new ArrayList<>();
|
||||
|
||||
for (int r = 0; r < maxRadius; r += 2) {
|
||||
for (int x = -r; x <= r; x++) {
|
||||
if (start.x + x < 0) {
|
||||
continue;
|
||||
}
|
||||
if (start.x + x >= dimension.width) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// try positive root
|
||||
final int y1 = (int) Math.sqrt(r * r - x * x);
|
||||
if (start.y + y1 >= 0 && start.y + y1 < dimension.height) {
|
||||
points.add(new Point(start.x + x, start.y + y1));
|
||||
}
|
||||
// try negative root
|
||||
final int y2 = -y1;
|
||||
if (start.y + y2 >= 0 && start.y + y2 < dimension.height) {
|
||||
points.add(new Point(start.x + x, start.y + y2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user