From fcbf4ce5422b82fb0e2d9f8112df6fb8f63ac40a Mon Sep 17 00:00:00 2001 From: Radek Oslejsek <oslejsek@fi.muni.cz> Date: Sat, 20 Feb 2021 08:16:13 +0100 Subject: [PATCH] Implementation of Point2MeshTriVisitorTest --- .../mesh/visitors/Point2MeshTriVisitor.java | 40 +-- .../mesh/visitors/Point2MeshVisitor.java | 43 +-- .../visitors/Point2MeshTriVisitorTest.java | 320 ++++++++++++++++++ .../mesh/visitors/Point2MeshVisitorTest.java | 6 - 4 files changed, 352 insertions(+), 57 deletions(-) create mode 100644 MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitorTest.java diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitor.java index 01f5191d..7c8ed4fa 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitor.java +++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitor.java @@ -16,12 +16,12 @@ import javax.vecmath.Vector3d; * * Because there can be multiple triangles with the same minimal distance, the visitor * returns a list of mesh facets and a list of indices corresponding - * to the facets. Returned lists have the same size and i-th mesh point index - * corresponds to the i-th mesh facet. - - * - * This visitor is instantiated on a single mesh facet or multiple facets. - * Then, when applied to other facets, it computes Huasdorff distance to these facets. + * to the facets. + * + * Returned lists have the same size. + * {@code n = getIndices().get(i)} returns the index of the closest triangle on the i-th facet. + * Then iterate into the n-th triangle of facet {@code getClosestFacets().get(i)} to get + * the triangle instance. * * @author Matej Lukes * @author Radek Oslejsek @@ -51,39 +51,17 @@ public class Point2MeshTriVisitor extends Point2MeshVisitor { @Override public void visitMeshFacet(MeshFacet facet) { - Vector3d helperVector = new Vector3d(); - Vector3d vertexPosition = getMyPoint().getPosition(); + Vector3d my = getMyPoint().getPosition(); int i = 0; - for (MeshTriangle tri: facet) { - Vector3d projection = getProjectionToTrianglePlane(vertexPosition, tri); - + Vector3d projection = getProjectionToTrianglePlane(my, tri); if (!isPointInTriangle(projection, tri)) { projection = getProjectionToClosestEdge(projection, tri); } - - helperVector.sub(vertexPosition, projection); - double dist = helperVector.length(); - double currentDist = getDistance(); - - if (dist > currentDist) { - i++; - continue; - } - if (dist < currentDist) { // new closest point - setDistance(dist); - getModifClosestFacets().clear(); - getModifIndices().clear(); - getModifClosestFacets().add(facet); - getModifIndices().add(i++); - } else { // the same distance - getModifClosestFacets().add(facet); - getModifIndices().add(i++); - } + checkAndUpdateDistance(projection, facet, i); } } - /** * returns perpendicular projection from vertex to plane of triangle * diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitor.java index be06e205..0a043a42 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitor.java +++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitor.java @@ -60,26 +60,7 @@ public class Point2MeshVisitor implements MeshVisitor { public void visitMeshFacet(MeshFacet facet) { List<MeshPoint> vertices = facet.getVertices(); for (int i = 0; i < vertices.size(); i++) { - MeshPoint otherPoint = vertices.get(i); - - Vector3d aux = new Vector3d(otherPoint.getPosition()); - aux.sub(myPoint.getPosition()); - sign = relativeDist ? (int) Math.signum(aux.dot(myPoint.getNormal())): 1; - double dist = aux.length(); - - if (dist > distance) { - continue; - } - if (dist < distance) { // new closest point - distance = dist; - closestFacets.clear(); - indices.clear(); - closestFacets.add(facet); - indices.add(i); - } else { // the same distance - closestFacets.add(facet); - indices.add(i); - } + checkAndUpdateDistance(vertices.get(i).getPosition(), facet, i); } } @@ -147,4 +128,26 @@ public class Point2MeshVisitor implements MeshVisitor { protected List<MeshFacet> getModifClosestFacets() { return closestFacets; } + + protected void checkAndUpdateDistance(Vector3d other, MeshFacet facet, int index) { + Vector3d aux = new Vector3d(other); + aux.sub(myPoint.getPosition()); + sign = relativeDist ? (int) Math.signum(aux.dot(myPoint.getNormal())): 1; + double dist = aux.length(); + + if (dist > distance) { + return; + } + + if (dist < distance) { // new closest point + distance = dist; + closestFacets.clear(); + indices.clear(); + closestFacets.add(facet); + indices.add(index); + } else { // the same distance + closestFacets.add(facet); + indices.add(index); + } + } } diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitorTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitorTest.java new file mode 100644 index 00000000..9fbaae3b --- /dev/null +++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshTriVisitorTest.java @@ -0,0 +1,320 @@ +package cz.fidentis.analyst.mesh.visitors; + +import cz.fidentis.analyst.mesh.core.CornerTableRow; +import cz.fidentis.analyst.mesh.core.MeshFacet; +import cz.fidentis.analyst.mesh.core.MeshFacetImpl; +import cz.fidentis.analyst.mesh.core.MeshPoint; +import cz.fidentis.analyst.mesh.core.MeshPointImpl; +import cz.fidentis.analyst.mesh.core.MeshTriangle; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import javax.vecmath.Vector3d; +import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import org.junit.jupiter.api.Test; + +/** + * + * @author oslejsek + */ +public class Point2MeshTriVisitorTest { + private MeshFacet getTrivialFacet(double offset, double size) { + MeshFacet facet = new MeshFacetImpl(); + facet.addVertex(new MeshPointImpl(new Vector3d(0, 0, offset), new Vector3d(0, 0, 1), new Vector3d())); + facet.addVertex(new MeshPointImpl(new Vector3d(size, 0, offset), new Vector3d(0, 0, 1), new Vector3d())); + facet.addVertex(new MeshPointImpl(new Vector3d(0, size, offset), new Vector3d(0, 0, 1), new Vector3d())); + + facet.getCornerTable().addRow(new CornerTableRow(0, -1)); + facet.getCornerTable().addRow(new CornerTableRow(1, -1)); + facet.getCornerTable().addRow(new CornerTableRow(2, -1)); + + return facet; + } + + @Test + public void absoluteDistTest() { + MeshFacet facet = getTrivialFacet(1.5, 1); + MeshPoint point = new MeshPointImpl(new Vector3d(0,0,0), new Vector3d(0,0,-1), new Vector3d()); + + Point2MeshVisitor vis = new Point2MeshTriVisitor(point, false); + facet.accept(vis); + assertEquals(1.5, vis.getDistance()); + + List<Integer> closestPoints = vis.getIndices(); + List<MeshFacet> closestMeshes = vis.getClosestFacets(); + assertNotNull(closestPoints); + assertNotNull(closestMeshes); + assertEquals(1, closestPoints.size()); + assertEquals(1, closestMeshes.size()); + assertEquals(facet, closestMeshes.get(0)); + assertEquals(0, closestPoints.get(0)); + } + + @Test + public void relativeDistTest() { + MeshFacet facet = getTrivialFacet(1.5, 1); + MeshPoint point = new MeshPointImpl(new Vector3d(0,0,0), new Vector3d(0,0,-1), new Vector3d()); + + Point2MeshVisitor vis = new Point2MeshTriVisitor(point, true); + facet.accept(vis); + assertEquals(-1.5, vis.getDistance()); + + List<Integer> closestPoints = vis.getIndices(); + List<MeshFacet> closestMeshes = vis.getClosestFacets(); + assertNotNull(closestPoints); + assertNotNull(closestMeshes); + assertEquals(1, closestPoints.size()); + assertEquals(1, closestMeshes.size()); + assertEquals(facet, closestMeshes.get(0)); + assertEquals(0, closestPoints.get(0)); + } + + @Test + public void exactMatchTest() { + MeshFacet facet = getTrivialFacet(1.5, 1); + MeshPoint point = new MeshPointImpl(new Vector3d(0, 0, 1.5), new Vector3d(0, 0, 1), new Vector3d()); + + System.out.println(facet.getVertices()); + + Point2MeshVisitor vis = new Point2MeshTriVisitor(point, false); + facet.accept(vis); + assertEquals(0, vis.getDistance()); + + System.out.println(facet.getVertices()); + + List<Integer> closestPoints = vis.getIndices(); + List<MeshFacet> closestMeshes = vis.getClosestFacets(); + assertNotNull(closestPoints); + assertNotNull(closestMeshes); + assertEquals(1, closestPoints.size()); + assertEquals(1, closestMeshes.size()); + assertEquals(facet, closestMeshes.get(0)); + assertEquals(0, closestPoints.get(0)); + } + + @Test + public void getProjectionToTrianglePlaneTest() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class<?>[] argClasses = new Class[2]; + argClasses[0] = Vector3d.class; + argClasses[1] = MeshTriangle.class; + Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToTrianglePlane", argClasses); + method.setAccessible(true); + Object[] args = new Object[2]; + + args[0] = new Vector3d(0, 0.5, 1); + MeshTriangle triangle = new MeshTriangle( + new MeshPointImpl(new Vector3d(1, 0, 0), null, null), + new MeshPointImpl(new Vector3d(1, 2, 0), null, null), + new MeshPointImpl(new Vector3d(2, 0, 0), null, null) + ); + args[1] = triangle; + + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); + + Assertions.assertEquals(0d, result.x); + Assertions.assertEquals(0.5d, result.y); + Assertions.assertEquals(0d, result.z); + } + + @Test + public void getProjectionToTrianglePlaneBelowPLaneTest() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class<?>[] argClasses = new Class[2]; + argClasses[0] = Vector3d.class; + argClasses[1] = MeshTriangle.class; + Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToTrianglePlane", argClasses); + method.setAccessible(true); + Object[] args = new Object[2]; + + args[0] = new Vector3d(0, 0.5, 1); + MeshTriangle triangle = new MeshTriangle( + new MeshPointImpl(new Vector3d(1, 0, 0), null, null), + new MeshPointImpl(new Vector3d(1, 2, 0), null, null), + new MeshPointImpl(new Vector3d(2, 0, 0), null, null) + ); + args[1] = triangle; + + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); + + Assertions.assertEquals(0d, result.x); + Assertions.assertEquals(0.5d, result.y); + Assertions.assertEquals(0d, result.z); + } + + @Test + public void isPointInTriangleInsideTriangleTest() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class<?>[] argClasses = new Class[2]; + argClasses[0] = Vector3d.class; + argClasses[1] = MeshTriangle.class; + Method method = Point2MeshTriVisitor.class.getDeclaredMethod("isPointInTriangle", argClasses); + method.setAccessible(true); + Object[] args = new Object[2]; + + args[0] = new Vector3d(1.2, 0.2, 0); + MeshTriangle triangle = new MeshTriangle( + new MeshPointImpl(new Vector3d(1, 0, 0), null, null), + new MeshPointImpl(new Vector3d(1, 2, 0), null, null), + new MeshPointImpl(new Vector3d(2, 0, 0), null, null) + ); + args[1] = triangle; + + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + boolean result = (boolean) method.invoke(hausdorffDistance, args); + + Assertions.assertTrue(result); + } + + @Test + public void isPointInTriangleOutsideTriangleTest() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class<?>[] argClasses = new Class[2]; + argClasses[0] = Vector3d.class; + argClasses[1] = MeshTriangle.class; + Method method = Point2MeshTriVisitor.class.getDeclaredMethod("isPointInTriangle", argClasses); + method.setAccessible(true); + Object[] args = new Object[2]; + + args[0] = new Vector3d(0, 0.5, 0); + MeshTriangle triangle = new MeshTriangle( + new MeshPointImpl(new Vector3d(1, 0, 0), null, null), + new MeshPointImpl(new Vector3d(1, 2, 0), null, null), + new MeshPointImpl(new Vector3d(2, 0, 0), null, null) + ); + args[1] = triangle; + + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + boolean result = (boolean) method.invoke(hausdorffDistance, args); + + Assertions.assertFalse(result); + } + + @Test + public void getProjectionToClosestEdgeTest() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class<?>[] argClasses = new Class[2]; + argClasses[0] = Vector3d.class; + argClasses[1] = MeshTriangle.class; + Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToClosestEdge", argClasses); + method.setAccessible(true); + Object[] args = new Object[2]; + + args[0] = new Vector3d(0, 0.5, 0); + MeshTriangle triangle = new MeshTriangle( + new MeshPointImpl(new Vector3d(1, 0, 0), null, null), + new MeshPointImpl(new Vector3d(1, 2, 0), null, null), + new MeshPointImpl(new Vector3d(2, 0, 0), null, null) + ); + args[1] = triangle; + + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); + + Assertions.assertEquals(1d, result.x); + Assertions.assertEquals(0.5d, result.y); + Assertions.assertEquals(0d, result.z); + } + + @Test + public void getProjectionToClosestEdgeNormalProjectionOutsideEdgeTestTest() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class<?>[] argClasses = new Class[2]; + argClasses[0] = Vector3d.class; + argClasses[1] = MeshTriangle.class; + Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToClosestEdge", argClasses); + method.setAccessible(true); + Object[] args = new Object[2]; + + args[0] = new Vector3d(0, -0.5, 0); + MeshTriangle triangle = new MeshTriangle( + new MeshPointImpl(new Vector3d(1, 0, 0), null, null), + new MeshPointImpl(new Vector3d(1, 2, 0), null, null), + new MeshPointImpl(new Vector3d(2, 0, 0), null, null) + ); + args[1] = triangle; + + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); + + Assertions.assertEquals(1d, result.x); + Assertions.assertEquals(0d, result.y); + Assertions.assertEquals(0d, result.z); + } + + @Test + public void getProjectionToEdgeTest() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class<?>[] argClasses = new Class[3]; + argClasses[0] = Vector3d.class; + argClasses[1] = Vector3d.class; + argClasses[2] = Vector3d.class; + Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToEdge", argClasses); + method.setAccessible(true); + Object[] args = new Object[3]; + + args[0] = new Vector3d(0, 0.5, 0); + args[1] = new Vector3d(1, 2, 0); + args[2] = new Vector3d(1, 0, 0); + + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); + + Assertions.assertEquals(1d, result.x); + Assertions.assertEquals(0.5d, result.y); + Assertions.assertEquals(0d, result.z); + } + + @Test + public void getProjectionToEdgeNormalProjectionOutsideEdgeTest() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class<?>[] argClasses = new Class[3]; + argClasses[0] = Vector3d.class; + argClasses[1] = Vector3d.class; + argClasses[2] = Vector3d.class; + Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToEdge", argClasses); + method.setAccessible(true); + Object[] args = new Object[3]; + + args[0] = new Vector3d(0, -0.5, 0); + args[1] = new Vector3d(1, 2, 0); + args[2] = new Vector3d(1, 0, 0); + + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); + + Assertions.assertEquals(1d, result.x); + Assertions.assertEquals(0d, result.y); + Assertions.assertEquals(0d, result.z); + } + + @Test + public void getProjectionToEdgeNormalProjectionOutsideEdge2Test() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class<?>[] argClasses = new Class[3]; + argClasses[0] = Vector3d.class; + argClasses[1] = Vector3d.class; + argClasses[2] = Vector3d.class; + Method method = Point2MeshTriVisitor.class.getDeclaredMethod("getProjectionToEdge", argClasses); + method.setAccessible(true); + Object[] args = new Object[3]; + + args[0] = new Vector3d(0, 2.5, 0); + args[1] = new Vector3d(1, 2, 0); + args[2] = new Vector3d(1, 0, 0); + + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); + + Assertions.assertEquals(1d, result.x); + Assertions.assertEquals(2d, result.y); + Assertions.assertEquals(0d, result.z); + } + +} diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitorTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitorTest.java index 5e34764a..1a53154a 100644 --- a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitorTest.java +++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/visitors/Point2MeshVisitorTest.java @@ -11,10 +11,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import org.junit.jupiter.api.Test; -/** - * - * @author oslejsek - */ public class Point2MeshVisitorTest { private MeshFacet getTrivialFacet(double offset, double size) { MeshFacet facet = new MeshFacetImpl(); @@ -78,8 +74,6 @@ public class Point2MeshVisitorTest { facet.accept(vis); assertEquals(0, vis.getDistance()); - System.out.println(facet.getVertices()); - List<Integer> closestPoints = vis.getIndices(); List<MeshFacet> closestMeshes = vis.getClosestFacets(); assertNotNull(closestPoints); -- GitLab