package com.vitco.low.triangulate.util;
import com.vitco.low.triangulate.Grid2TriPolyFast;
import com.vitco.low.triangulate.Grid2TriPolySlow;
import com.vividsolutions.jts.geom.Coordinate;
import org.jaitools.imageutils.ImageUtils;
import org.junit.Test;
import javax.imageio.ImageIO;
import javax.media.jai.TiledImage;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Random;
/**
* Test for the Grid2PolyHelper class
*/
public class Grid2PolyHelperTest {
// batch run conversion and triangulation and check for any errors
// in the output (no validation of output is done)
@Test
public void massTest() throws IOException {
for (int i = 1; i < 20000; i++) {
Random rand = new Random(i);
// create image
int sizex = rand.nextInt(200)+5;
int sizey = rand.nextInt(200)+5;
boolean[][] data = new boolean[sizex][sizey];
// fill with random data
int count = rand.nextInt(sizex * sizey * 2);
for (int j = 0; j < count; j++) {
int x = rand.nextInt(sizex);
int y = rand.nextInt(sizey);
data[x][y] = true;
}
short[][][] polys = Grid2PolyHelper.convert(data);
Grid2TriPolyFast.triangulate(polys);
System.out.println("Test " + i);
}
}
// manual test for the new algorithm "voxel -> polygon"
// uses input image and creates output image with created polygon
@Test
public void testNew() throws IOException {
BufferedImage imgIn = ImageIO.read(new File("C:\\Users\\flux\\Dropbox\\java\\VoxelShop\\Test Files\\grid2poly\\file1.png"));
boolean[][] data = new boolean[imgIn.getWidth()][imgIn.getHeight()];
for (int x = 0; x < imgIn.getWidth(); x++) {
for (int y = 0; y < imgIn.getHeight(); y++) {
//System.out.println(img.getRGB(x,y));
data[x][y] = imgIn.getRGB(x,y) != -1;
}
}
// create polygons
short[][][] polys = Grid2PolyHelper.convert(data);
// print data
int zoom = 40;
BufferedImage img = new BufferedImage(zoom*imgIn.getWidth() + zoom, zoom*imgIn.getHeight() + zoom, BufferedImage.TYPE_INT_RGB);
Graphics2D gr = (Graphics2D) img.getGraphics();
gr.setColor(Color.WHITE);
AffineTransform at = new AffineTransform();
at.translate(zoom/2, zoom/2);
gr.setTransform(at);
gr.fillRect(-zoom/2, -zoom/2, img.getWidth(), img.getHeight());
gr.setFont(gr.getFont().deriveFont(Font.BOLD,15f));
gr.drawImage(imgIn,0,0,img.getWidth()-zoom,img.getHeight()-zoom, null);
gr.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
gr.setRenderingHint(
RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
gr.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
for (short[][] poly : polys) {
// draw holes outline
for (int n = 1; n < poly.length; n++) {
for (int i = 0, len = poly[n].length - 2; i < len; i+=2) {
gr.setColor(Color.BLUE);
gr.drawLine(poly[n][i] * zoom, poly[n][i + 1] * zoom, poly[n][i + 2] * zoom, poly[n][i + 3] * zoom);
}
}
// draw poly outline
for (int i = 0; i < poly[0].length - 2; i+=2) {
// draw point to image
gr.setColor(Color.RED);
gr.drawLine(poly[0][i] * zoom, poly[0][i+1] * zoom, poly[0][i+2] * zoom, poly[0][i+3] * zoom);
}
}
for (short[][] poly : polys) {
// draw holes text
for (int n = 1; n < poly.length; n++) {
for (int i = 0, len = poly[n].length - 2; i < len; i+=2) {
gr.setColor(Color.BLUE);
// draw number
gr.drawString(String.valueOf(i/2+1), poly[n][i] * zoom - 10, poly[n][i+1] * zoom + 5);
}
}
// draw poly text
for (int i = 0; i < poly[0].length - 2; i+=2) {
// draw point to image
gr.setColor(Color.RED);
// draw number
gr.drawString(String.valueOf(i/2+1), poly[0][i] * zoom + 5, poly[0][i+1] * zoom + 5);
}
}
gr.dispose();
ImageIO.write(img, "png", new File("C:\\Users\\flux\\Dropbox\\java\\VoxelShop\\Test Files\\grid2poly\\file1_out.png"));
}
// manual test for the old algorithm "voxel -> polygon"
// uses input image and creates output image with created polygon
@Test
public void testOriginal() throws IOException {
BufferedImage imgIn = ImageIO.read(new File("test.png"));
boolean[][] data = new boolean[imgIn.getWidth()][imgIn.getHeight()];
for (int x = 0; x < imgIn.getWidth(); x++) {
for (int y = 0; y < imgIn.getHeight(); y++) {
//System.out.println(img.getRGB(x,y));
data[x][y] = imgIn.getRGB(x,y) != -1;
}
}
// test original algorithm
TiledImage src = ImageUtils.createConstantImage(imgIn.getWidth(), imgIn.getHeight(), 0);
// fill with data
for (int x = 0; x < imgIn.getWidth(); x++) {
for (int y = 0; y < imgIn.getHeight(); y++) {
src.setSample(x, y, 0, data[x][y] ? 1 : 0);
}
}
// create polygons
Collection<com.vividsolutions.jts.geom.Polygon> polys = Grid2TriPolySlow.doVectorize(src);
// print data
int zoom = 40;
BufferedImage img = new BufferedImage(zoom*imgIn.getWidth() + zoom, zoom*imgIn.getHeight() + zoom, BufferedImage.TYPE_INT_RGB);
Graphics2D gr = (Graphics2D) img.getGraphics();
gr.setColor(Color.WHITE);
AffineTransform at = new AffineTransform();
at.translate(zoom/2, zoom/2);
gr.setTransform(at);
gr.fillRect(-zoom/2, -zoom/2, img.getWidth(), img.getHeight());
gr.setFont(gr.getFont().deriveFont(Font.BOLD,15f));
gr.drawImage(imgIn,0,0,img.getWidth()-zoom,img.getHeight()-zoom, null);
gr.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
gr.setRenderingHint(
RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
gr.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
Coordinate[] coordinates;
for (com.vividsolutions.jts.geom.Polygon poly : polys) {
// draw holes outline
for (int n = 0, size = poly.getNumInteriorRing(); n < size; n++) {
coordinates = poly.getInteriorRingN(n).getCoordinates();
for (int i = 0; i < coordinates.length - 1; i++) {
gr.setColor(Color.BLUE);
gr.drawLine((int) (coordinates[i].x * zoom), (int) (coordinates[i].y * zoom), (int) (coordinates[i+1].x * zoom), (int) (coordinates[i+1].y * zoom));
}
}
// draw poly outline
coordinates = poly.getExteriorRing().getCoordinates();
for (int i = 0; i < coordinates.length - 1; i++) {
// draw point to image
gr.setColor(Color.RED);
gr.drawLine((int) (coordinates[i].x * zoom), (int) (coordinates[i].y * zoom), (int) (coordinates[i + 1].x * zoom), (int) (coordinates[i + 1].y * zoom));
}
}
for (com.vividsolutions.jts.geom.Polygon poly : polys) {
// draw holes text
for (int n = 0, size = poly.getNumInteriorRing(); n < size; n++) {
coordinates = poly.getInteriorRingN(n).getCoordinates();
for (int i = 0; i < coordinates.length - 1; i++) {
gr.setColor(Color.BLUE);
// draw number
gr.drawString(String.valueOf(i+1), (int) (coordinates[i].x * zoom) - 10, (int) (coordinates[i].y * zoom) + 5);
}
}
// draw poly text
coordinates = poly.getExteriorRing().getCoordinates();
for (int i = 0; i < coordinates.length - 1; i++) {
// draw point to image
gr.setColor(Color.RED);
// draw number
gr.drawString(String.valueOf(i+1), (int) (coordinates[i].x * zoom) + 5, (int) (coordinates[i].y * zoom) + 5);
}
}
gr.dispose();
ImageIO.write(img, "png", new File("out.png"));
}
// test finding potential t-junction problem spots (in 3D)
@Test
public void testFindProblemSpots() throws IOException {
BufferedImage imgIn = ImageIO.read(new File("C:\\Users\\flux\\Dropbox\\java\\VoxelShop\\Test Files\\grid2poly\\file1.png"));
boolean[][] data = new boolean[imgIn.getWidth()][imgIn.getHeight()];
for (int x = 0; x < imgIn.getWidth(); x++) {
for (int y = 0; y < imgIn.getHeight(); y++) {
//System.out.println(img.getRGB(x,y));
data[x][y] = imgIn.getRGB(x,y) != -1;
}
}
// create polygons
short[][][] polys = Grid2PolyHelper.convert(data);
// print data
int zoom = 40;
BufferedImage img = new BufferedImage(zoom*imgIn.getWidth() + zoom, zoom*imgIn.getHeight() + zoom, BufferedImage.TYPE_INT_RGB);
Graphics2D gr = (Graphics2D) img.getGraphics();
gr.setColor(Color.WHITE);
AffineTransform at = new AffineTransform();
at.translate(zoom/2, zoom/2);
gr.setTransform(at);
gr.fillRect(-zoom/2, -zoom/2, img.getWidth(), img.getHeight());
gr.setFont(gr.getFont().deriveFont(Font.BOLD,15f));
gr.drawImage(imgIn,0,0,img.getWidth()-zoom,img.getHeight()-zoom, null);
gr.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
gr.setRenderingHint(
RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
gr.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
for (short[][] poly : polys) {
// draw holes outline
for (int n = 1; n < poly.length; n++) {
for (int i = 0, len = poly[n].length - 2; i < len; i+=2) {
gr.setColor(Color.BLUE);
gr.drawLine(poly[n][i] * zoom, poly[n][i+1] * zoom, poly[n][i+2] * zoom, poly[n][i+3] * zoom);
}
}
// draw poly outline
for (int i = 0; i < poly[0].length - 2; i+=2) {
// draw point to image
gr.setColor(Color.RED);
gr.drawLine(poly[0][i] * zoom, poly[0][i+1] * zoom, poly[0][i+2] * zoom, poly[0][i+3] * zoom);
}
}
for (short[][] poly : polys) {
// draw holes text
for (int n = 1; n < poly.length; n++) {
for (int i = 0, len = poly[n].length - 2; i < len; i+=2) {
gr.setColor(Color.BLUE);
// draw number
gr.drawString(String.valueOf(i/2+1), poly[n][i] * zoom - 10, poly[n][i+1] * zoom + 5);
}
}
// draw poly text
for (int i = 0; i < poly[0].length - 2; i+=2) {
// draw point to image
gr.setColor(Color.RED);
// draw number
gr.drawString(String.valueOf(i/2+1), poly[0][i] * zoom + 5, poly[0][i+1] * zoom + 5);
}
}
// print potential problem spots
for (short[][] poly : polys) {
// poly and outlines
for (short[] outline : poly) {
for (int i = 0, len = outline.length - 2; i < len; i += 2) {
if (outline[i + 2] == outline[i]) {
// x are equal
int step = outline[i + 3] > outline[i + 1] ? 1 : -1;
for (int y = outline[i + 1] + step; y != outline[i + 3]; y += step) {
int x = outline[i] + (step == 1 ? -1 : 0);
gr.setColor(Color.ORANGE);
gr.setStroke(new BasicStroke(5f));
gr.drawLine(outline[i] * zoom, y * zoom, outline[i] * zoom - step * 10, y * zoom);
gr.setColor(Color.BLACK);
gr.setStroke(new BasicStroke(1f));
gr.drawRect((x) * zoom, (y-1) * zoom, zoom, 2*zoom);
}
} else {
// y are equal
int step = outline[i + 2] > outline[i] ? 1 : -1;
for (int x = outline[i] + step; x != outline[i + 2]; x += step) {
int y = outline[i + 1] + (step == -1 ? -1 : 0);
gr.setColor(Color.ORANGE);
gr.setStroke(new BasicStroke(5f));
gr.drawLine(x * zoom, outline[i + 1] * zoom, x * zoom, outline[i + 1] * zoom + step * 10);
gr.setColor(Color.BLACK);
gr.setStroke(new BasicStroke(1f));
gr.drawRect((x - 1) * zoom, (y) * zoom, 2 * zoom, zoom);
}
}
}
}
}
gr.dispose();
ImageIO.write(img, "png", new File("C:\\Users\\flux\\Dropbox\\java\\VoxelShop\\Test Files\\grid2poly\\file1_out.png"));
}
}