package com.vitco.low.hull; import org.junit.Test; /** * Testing that the hull detection is working properly. */ public class HullManagerTest { // todo create "big random" test case // helper - get point for one direction private static short[] get(int val, int direction) { switch (direction) { case 0: return new short[] {(short) val,50,570}; case 1: return new short[] {-10, (short) val,570}; default: return new short[] {-10,50, (short) val}; } } // helper private static short[] get(int x, int y, int z) { return new short[] {(short) x, (short) y, (short) z}; } // helper private static String toString(short[] val) { return val[0] + " " + val[1] + " " + val[2]; } // helper private static void update(HullManager<String> hullManager, short[] val) { hullManager.update(val, toString(val)); } @Test public void testInsideVoxel() throws Exception { HullManager<String> hullManager = new HullManager<String>(); // one block for (short x = 0; x < 10; x++) { for (short y = 0; y < 10; y++) { for (short z = 0; z < 10; z++) { update(hullManager, get(x, y, z)); } } } update(hullManager, get(10, 5, 5)); for (int j = 0; j < 6; j++) { assert hullManager.getHullAdditions(j).size() == (j/2 == 0 ? 100 : 101); assert hullManager.getHullRemovals(j).size() == 0; } for (short x = 10; x < 20; x++) { for (short y = 0; y < 10; y++) { for (short z = 0; z < 10; z++) { update(hullManager, get(x, y, z)); } } } for (int j = 0; j < 6; j++) { int sa = hullManager.getHullAdditions(j).size(); int sr = hullManager.getHullRemovals(j).size(); //System.out.println(sa); //System.out.println(sr); assert sa == (j/2 == 0 ? (j == 0 ? 100 : 0) : 100); assert sr == (j/2 == 0 ? (j == 0 ? 100 : 0) : 1); } } @Test public void testHoleDetection() throws Exception { HullManager<String> hullManager = new HullManager<String>(); // one block for (short x = 0; x < 10; x++) { for (short y = 0; y < 10; y++) { for (short z = 0; z < 10; z++) { update(hullManager, get(x, y, z)); } } } for (int j = 0; j < 6; j++) { assert hullManager.getHullAdditions(j).size() == 100; assert hullManager.getHullRemovals(j).size() == 0; } // remove inner voxel from one side hullManager.clearPosition(get(9,5,5)); for (int j = 0; j < 6; j++) { assert hullManager.getHullAdditions(j).size() == (j == 1 ? 0 : 1); assert hullManager.getHullRemovals(j).size() == (j == 0 ? 1 : 0); } } @Test public void testAccuracy() throws Exception { HullManager<String> hullManager = new HullManager<String>(); for (int i = 0; i < 3; i++) { // test that double adding does not return // the edge "in between" as changed update(hullManager,get(0, i)); update(hullManager,get(1, i)); for (int j = 0; j < 6; j++) { assert hullManager.getHullAdditions(j).size() == (j/2 == i ? 1 : 2); assert hullManager.getHullRemovals(j).size() == 0; } for (int j = 0; j < 6; j++) { assert hullManager.getHullAdditions(j).size() == 0; assert hullManager.getHullRemovals(j).size() == 0; } // test that double removing does not return // the edge "in between" as changed assert hullManager.clearPosition(get(0, i)); assert !hullManager.clearPosition(get(0, i)); assert hullManager.clearPosition(get(1, i)); for (int j = 0; j < 6; j++) { assert hullManager.getHullAdditions(j).size() == 0; assert hullManager.getHullRemovals(j).size() == (j/2 == i ? 1 : 2); } hullManager.clear(); } // test that double adding only reports edges from the voxel (and not the neighbours) for (int i = 0; i < 3; i++) { update(hullManager,get(0, i)); update(hullManager,get(1, i)); update(hullManager,get(2, i)); for (int j = 0; j < 6; j++) { assert hullManager.getHullAdditions(j).size() == (j/2 == i ? 1 : 3); assert hullManager.getHullRemovals(j).size() == 0; } update(hullManager,get(1, i)); for (int j = 0; j < 6; j++) { assert hullManager.getHullAdditions(j).size() == (j/2 == i ? 0 : 1); assert hullManager.getHullRemovals(j).size() == 0; } hullManager.clear(); } for (int i = 0; i < 3; i++) { update(hullManager,get(0, i)); // test that empty removal does not trigger any changes for (int j = 0; j < 6; j++) { assert hullManager.getHullAdditions(j).size() == 1; assert hullManager.getHullRemovals(j).size() == 0; } assert !hullManager.clearPosition(get(1, i)); for (int j = 0; j < 6; j++) { assert hullManager.getHullAdditions(j).size() == 0; assert hullManager.getHullRemovals(j).size() == 0; } hullManager.clear(); } } @Test public void massTest() throws Exception { HullManager<String> hullManager = new HullManager<String>(); long time = System.currentTimeMillis(); // one million (as a block) 100 ^ 3 for (short x = 0; x < 100; x++) { for (short y = 0; y < 100; y++) { for (short z = 0; z < 100; z++) { hullManager.update(new short[]{x,y,z}, x + "," + y + "," + z); } } } for (byte b : new byte[] {0,1,2,3,4,5}) { System.out.println(b + " ==="); hullManager.getHullAdditions(b); hullManager.getHullRemovals(b); } System.out.println("Time for 100^3 block: " + (System.currentTimeMillis() - time) + " ms"); } @Test public void testExteriorDetection() { for (int max = 3; max < 20; max++) { HullManagerExt<String> hullManager = new HullManagerExt<String>(); // create the "flat" outline of a block (corners not set), e.g. // --- // | | // --- for (short x = 0; x < max; x++) { for (short y = 0; y < max; y++) { for (short z = 0; z < max; z++) { boolean valid = (x == 0 || x == max - 1) && (y > 0 && y < max - 1) && (z > 0 && z < max - 1) || (y == 0 || y == max - 1) && (x > 0 && x < max - 1) && (z > 0 && z < max - 1) || (z == 0 || z == max - 1) && (y > 0 && y < max - 1) && (x > 0 && x < max - 1); if (valid) { update(hullManager, get(x, y, z)); } } } } // test exterior detection hullManager.computeExterior(); for (int j = 0; j < 6; j++) { //System.out.println(hullManager.getHull(j).length); //System.out.println(hullManager.getExteriorHull(j).length); assert hullManager.getHull(j).length == max * max - 4 + (max - 2) * (max - 2); assert hullManager.getExteriorHull(j).length == max * max - 4; } } } }