Loading GeometryData/src/main/java/cz/fidentis/analyst/data/mesh/MeshTriangle.java +1 −1 Original line number Diff line number Diff line Loading @@ -200,7 +200,7 @@ public interface MeshTriangle extends Iterable<MeshPoint>, Serializable { */ Vector4d getCurvatureOfTrianglePlane(Point3d samplePosition, double distanceAccepted, Vector3d base1, Vector3d base2); boolean AABBintersect(double splitPosition, int depth); boolean intersectAABB(double splitPosition, int depth); Point3d getMaxAABB(); Loading GeometryData/src/main/java/cz/fidentis/analyst/data/mesh/impl/MeshTriangleImpl.java +32 −24 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ import java.util.*; /** * Adapter for the corner table representing a single triangle of {@code MeshFacet}. * * @author Ľubomír Jurčišin * @author Natalia Bebjakova * @author Dominik Racek * @author Enkh-Undral EnkhBayar Loading @@ -25,8 +26,8 @@ import java.util.*; public class MeshTriangleImpl implements MeshTriangle { private Point3d AABBmax; private Point3d AABBmin; private Point3d aabbMax; private Point3d aabbMin; private Point3d centroid; @Serial Loading Loading @@ -789,42 +790,49 @@ public class MeshTriangleImpl implements MeshTriangle { } private void calculateBoundingBox() { Point3d A = getVertex1(); Point3d B = getVertex2(); Point3d C = getVertex3(); Point3d pointA = getVertex1(); Point3d pointB = getVertex2(); Point3d pointC = getVertex3(); if (AABBmax == null) { AABBmax = new Point3d( Math.max(Math.max(A.x, B.x), C.x), Math.max(Math.max(A.y, B.y), C.y), Math.max(Math.max(A.z, B.z), C.z)); if (aabbMax == null) { aabbMax = new Point3d( Math.max(Math.max(pointA.x, pointB.x), pointC.x), Math.max(Math.max(pointA.y, pointB.y), pointC.y), Math.max(Math.max(pointA.z, pointB.z), pointC.z)); } if (AABBmin == null) { AABBmin = new Point3d( Math.min(Math.min(A.x, B.x), C.x), Math.min(Math.min(A.y, B.y), C.y), Math.min(Math.min(A.z, B.z), C.z)); if (aabbMin == null) { aabbMin = new Point3d( Math.min(Math.min(pointA.x, pointB.x), pointC.x), Math.min(Math.min(pointA.y, pointB.y), pointC.y), Math.min(Math.min(pointA.z, pointB.z), pointC.z)); } } @Override public Point3d getMaxAABB() { if (AABBmax == null) { if (aabbMax == null) { calculateBoundingBox(); } return AABBmax; return aabbMax; } @Override public Point3d getMinAABB() { if (AABBmin == null) { if (aabbMin == null) { calculateBoundingBox(); } return AABBmin; return aabbMin; } public boolean AABBintersect(double splitPosition, int depth) { /** * Checks if splitting plane at a certain depth of a KdTree intersects triangles axis-aligned bounding box. * * @param splitPosition Coordinate of splitting plane, based on depth either x/y/z axis. * @param depth Depth of splitting plane in KdTree. * @return {@code true} if the splitting plane intersects AABB. {@code false} otherwise. */ public boolean intersectAABB(double splitPosition, int depth) { return switch (depth % 3) { case 0 -> getMinAABB().x < splitPosition && splitPosition < getMaxAABB().x; case 1 -> getMinAABB().y < splitPosition && splitPosition < getMaxAABB().y; Loading @@ -834,13 +842,13 @@ public class MeshTriangleImpl implements MeshTriangle { } private void calculateCentroid() { if (AABBmax == null || AABBmin == null) { if (aabbMax == null || aabbMin == null) { calculateBoundingBox(); } this.centroid = new Point3d( (AABBmax.x + AABBmin.x) / 2, (AABBmax.y + AABBmin.y) / 2, (AABBmax.z + AABBmin.z) / 2); (aabbMax.x + aabbMin.x) / 2, (aabbMax.y + aabbMin.y) / 2, (aabbMax.z + aabbMin.z) / 2); } @Override Loading GeometryEngines/src/main/java/cz/fidentis/analyst/engines/distance/MeshDistanceConfig.java +0 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,6 @@ import cz.fidentis.analyst.engines.distance.impl.*; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; /** * Mesh-to-mesh distance strategies and their configuration. Loading GeometryEngines/src/main/java/cz/fidentis/analyst/engines/distance/impl/MeshDistancePreciseGPU.java +23 −11 Original line number Diff line number Diff line Loading @@ -27,6 +27,12 @@ import java.util.logging.Logger; import static com.jogamp.opencl.CLMemory.Mem.WRITE_ONLY; import static java.lang.Math.pow; /** * Finds closest point on mesh even when the point is not on a triangleFan around the closest vertex. * Utilizes a TriangleKdTree and GPU search of closest point on triangles. * * @author Ľubomír Jurčišin */ public class MeshDistancePreciseGPU extends MeshDistanceVisitorImpl { private final TriangleKdTree kdTree; Loading @@ -43,9 +49,13 @@ public class MeshDistancePreciseGPU extends MeshDistanceVisitorImpl { /** * Constructor. * * @param kdTree TriangleKdTree of primary mesh to which other distances should be calculated. * @param relativeDistance If true, then the visitor calculates the relative distances with respect * to the normal vectors of source facets (normal vectors have to present), * i.e., we can get negative distances. * @param parallel If the tree traversal should be parallelized. * Testing showed that parallel traversal is around 1s slower as the running of the * GPU kernel must be serialized. * @throws IllegalArgumentException if some parameter is wrong */ public MeshDistancePreciseGPU(TriangleKdTree kdTree, boolean relativeDistance, boolean parallel) { Loading Loading @@ -118,8 +128,7 @@ public class MeshDistancePreciseGPU extends MeshDistanceVisitorImpl { depth % 3 == 2 && point.getPosition().z < currentNode.getSplit()) { closeChild = (TriangleKdNode) currentNode.getLesser(); farChild = (TriangleKdNode) currentNode.getGreater(); } else { } else { closeChild = (TriangleKdNode) currentNode.getGreater(); farChild = (TriangleKdNode) currentNode.getLesser(); } Loading @@ -139,14 +148,12 @@ public class MeshDistancePreciseGPU extends MeshDistanceVisitorImpl { prevNode = currentNode; currentNode = currentNode.getParent(); depth--; } else { // else go down to closer child } else { // else go down to closer child prevNode = currentNode; currentNode = closeChild; depth++; } } else if (prevNode == closeChild) { // coming up from close child } else if (prevNode == closeChild) { // coming up from close child // test if distance from point to splitting plane is smaller than the closest distance if (depth % 3 == 0 && pow(point.getPosition().x - currentNode.getSplit(), 2) < closestDistance || depth % 3 == 1 && pow(point.getPosition().y - currentNode.getSplit(), 2) < closestDistance || Loading @@ -155,14 +162,12 @@ public class MeshDistancePreciseGPU extends MeshDistanceVisitorImpl { prevNode = currentNode; currentNode = farChild; depth++; } else { // no need to check other subtree, go up } else { // no need to check other subtree, go up prevNode = currentNode; currentNode = currentNode.getParent(); depth--; } } else { // coming up from far child, go up } else { // coming up from far child, go up prevNode = currentNode; currentNode = currentNode.getParent(); depth--; Loading @@ -172,7 +177,14 @@ public class MeshDistancePreciseGPU extends MeshDistanceVisitorImpl { return closestPoint; } /** * Finds closest point on triangles stored in leaf. * Runs on GPU. * * @param point point to which we are searching for the closest point * @param leaf leaf node of a TriangleKdTree storing triangles * @return closest point to {@code point} located on triangles */ public synchronized Point3d findClosestInLeaf(MeshPoint point, TriangleKdNode leaf) { if (!leaf.isLeaf()) { throw new IllegalArgumentException("Node is not a leaf."); Loading SpacePartitioningData/src/main/java/cz/fidentis/analyst/data/kdtree/TriangleKdNode.java +25 −0 Original line number Diff line number Diff line Loading @@ -4,12 +4,37 @@ import cz.fidentis.analyst.data.mesh.MeshTriangle; import java.util.List; /** * Node of a TriangleKdTree. * * @author Ľubomír Jurčišin */ public interface TriangleKdNode extends KdNode{ /** * Gets parent of this node or {@code null} if it is the root node. * * @return Parent node. */ TriangleKdNode getParent(); /** * Gets triangles stored in this node if it is a leaf node. * * @return List of stored triangles or empty list if not a leaf node. */ List<MeshTriangle> getTriangles(); /** * Gets splitting plane position on axis according to depth. * * @return Splitting plane position on either x/y/z based on depth. */ double getSplit(); /** * Check if current node is leaf. * * @return {@code true} if it is a leaf node. {@code false} otherwise. */ boolean isLeaf(); } Loading
GeometryData/src/main/java/cz/fidentis/analyst/data/mesh/MeshTriangle.java +1 −1 Original line number Diff line number Diff line Loading @@ -200,7 +200,7 @@ public interface MeshTriangle extends Iterable<MeshPoint>, Serializable { */ Vector4d getCurvatureOfTrianglePlane(Point3d samplePosition, double distanceAccepted, Vector3d base1, Vector3d base2); boolean AABBintersect(double splitPosition, int depth); boolean intersectAABB(double splitPosition, int depth); Point3d getMaxAABB(); Loading
GeometryData/src/main/java/cz/fidentis/analyst/data/mesh/impl/MeshTriangleImpl.java +32 −24 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ import java.util.*; /** * Adapter for the corner table representing a single triangle of {@code MeshFacet}. * * @author Ľubomír Jurčišin * @author Natalia Bebjakova * @author Dominik Racek * @author Enkh-Undral EnkhBayar Loading @@ -25,8 +26,8 @@ import java.util.*; public class MeshTriangleImpl implements MeshTriangle { private Point3d AABBmax; private Point3d AABBmin; private Point3d aabbMax; private Point3d aabbMin; private Point3d centroid; @Serial Loading Loading @@ -789,42 +790,49 @@ public class MeshTriangleImpl implements MeshTriangle { } private void calculateBoundingBox() { Point3d A = getVertex1(); Point3d B = getVertex2(); Point3d C = getVertex3(); Point3d pointA = getVertex1(); Point3d pointB = getVertex2(); Point3d pointC = getVertex3(); if (AABBmax == null) { AABBmax = new Point3d( Math.max(Math.max(A.x, B.x), C.x), Math.max(Math.max(A.y, B.y), C.y), Math.max(Math.max(A.z, B.z), C.z)); if (aabbMax == null) { aabbMax = new Point3d( Math.max(Math.max(pointA.x, pointB.x), pointC.x), Math.max(Math.max(pointA.y, pointB.y), pointC.y), Math.max(Math.max(pointA.z, pointB.z), pointC.z)); } if (AABBmin == null) { AABBmin = new Point3d( Math.min(Math.min(A.x, B.x), C.x), Math.min(Math.min(A.y, B.y), C.y), Math.min(Math.min(A.z, B.z), C.z)); if (aabbMin == null) { aabbMin = new Point3d( Math.min(Math.min(pointA.x, pointB.x), pointC.x), Math.min(Math.min(pointA.y, pointB.y), pointC.y), Math.min(Math.min(pointA.z, pointB.z), pointC.z)); } } @Override public Point3d getMaxAABB() { if (AABBmax == null) { if (aabbMax == null) { calculateBoundingBox(); } return AABBmax; return aabbMax; } @Override public Point3d getMinAABB() { if (AABBmin == null) { if (aabbMin == null) { calculateBoundingBox(); } return AABBmin; return aabbMin; } public boolean AABBintersect(double splitPosition, int depth) { /** * Checks if splitting plane at a certain depth of a KdTree intersects triangles axis-aligned bounding box. * * @param splitPosition Coordinate of splitting plane, based on depth either x/y/z axis. * @param depth Depth of splitting plane in KdTree. * @return {@code true} if the splitting plane intersects AABB. {@code false} otherwise. */ public boolean intersectAABB(double splitPosition, int depth) { return switch (depth % 3) { case 0 -> getMinAABB().x < splitPosition && splitPosition < getMaxAABB().x; case 1 -> getMinAABB().y < splitPosition && splitPosition < getMaxAABB().y; Loading @@ -834,13 +842,13 @@ public class MeshTriangleImpl implements MeshTriangle { } private void calculateCentroid() { if (AABBmax == null || AABBmin == null) { if (aabbMax == null || aabbMin == null) { calculateBoundingBox(); } this.centroid = new Point3d( (AABBmax.x + AABBmin.x) / 2, (AABBmax.y + AABBmin.y) / 2, (AABBmax.z + AABBmin.z) / 2); (aabbMax.x + aabbMin.x) / 2, (aabbMax.y + aabbMin.y) / 2, (aabbMax.z + aabbMin.z) / 2); } @Override Loading
GeometryEngines/src/main/java/cz/fidentis/analyst/engines/distance/MeshDistanceConfig.java +0 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,6 @@ import cz.fidentis.analyst.engines.distance.impl.*; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; /** * Mesh-to-mesh distance strategies and their configuration. Loading
GeometryEngines/src/main/java/cz/fidentis/analyst/engines/distance/impl/MeshDistancePreciseGPU.java +23 −11 Original line number Diff line number Diff line Loading @@ -27,6 +27,12 @@ import java.util.logging.Logger; import static com.jogamp.opencl.CLMemory.Mem.WRITE_ONLY; import static java.lang.Math.pow; /** * Finds closest point on mesh even when the point is not on a triangleFan around the closest vertex. * Utilizes a TriangleKdTree and GPU search of closest point on triangles. * * @author Ľubomír Jurčišin */ public class MeshDistancePreciseGPU extends MeshDistanceVisitorImpl { private final TriangleKdTree kdTree; Loading @@ -43,9 +49,13 @@ public class MeshDistancePreciseGPU extends MeshDistanceVisitorImpl { /** * Constructor. * * @param kdTree TriangleKdTree of primary mesh to which other distances should be calculated. * @param relativeDistance If true, then the visitor calculates the relative distances with respect * to the normal vectors of source facets (normal vectors have to present), * i.e., we can get negative distances. * @param parallel If the tree traversal should be parallelized. * Testing showed that parallel traversal is around 1s slower as the running of the * GPU kernel must be serialized. * @throws IllegalArgumentException if some parameter is wrong */ public MeshDistancePreciseGPU(TriangleKdTree kdTree, boolean relativeDistance, boolean parallel) { Loading Loading @@ -118,8 +128,7 @@ public class MeshDistancePreciseGPU extends MeshDistanceVisitorImpl { depth % 3 == 2 && point.getPosition().z < currentNode.getSplit()) { closeChild = (TriangleKdNode) currentNode.getLesser(); farChild = (TriangleKdNode) currentNode.getGreater(); } else { } else { closeChild = (TriangleKdNode) currentNode.getGreater(); farChild = (TriangleKdNode) currentNode.getLesser(); } Loading @@ -139,14 +148,12 @@ public class MeshDistancePreciseGPU extends MeshDistanceVisitorImpl { prevNode = currentNode; currentNode = currentNode.getParent(); depth--; } else { // else go down to closer child } else { // else go down to closer child prevNode = currentNode; currentNode = closeChild; depth++; } } else if (prevNode == closeChild) { // coming up from close child } else if (prevNode == closeChild) { // coming up from close child // test if distance from point to splitting plane is smaller than the closest distance if (depth % 3 == 0 && pow(point.getPosition().x - currentNode.getSplit(), 2) < closestDistance || depth % 3 == 1 && pow(point.getPosition().y - currentNode.getSplit(), 2) < closestDistance || Loading @@ -155,14 +162,12 @@ public class MeshDistancePreciseGPU extends MeshDistanceVisitorImpl { prevNode = currentNode; currentNode = farChild; depth++; } else { // no need to check other subtree, go up } else { // no need to check other subtree, go up prevNode = currentNode; currentNode = currentNode.getParent(); depth--; } } else { // coming up from far child, go up } else { // coming up from far child, go up prevNode = currentNode; currentNode = currentNode.getParent(); depth--; Loading @@ -172,7 +177,14 @@ public class MeshDistancePreciseGPU extends MeshDistanceVisitorImpl { return closestPoint; } /** * Finds closest point on triangles stored in leaf. * Runs on GPU. * * @param point point to which we are searching for the closest point * @param leaf leaf node of a TriangleKdTree storing triangles * @return closest point to {@code point} located on triangles */ public synchronized Point3d findClosestInLeaf(MeshPoint point, TriangleKdNode leaf) { if (!leaf.isLeaf()) { throw new IllegalArgumentException("Node is not a leaf."); Loading
SpacePartitioningData/src/main/java/cz/fidentis/analyst/data/kdtree/TriangleKdNode.java +25 −0 Original line number Diff line number Diff line Loading @@ -4,12 +4,37 @@ import cz.fidentis.analyst.data.mesh.MeshTriangle; import java.util.List; /** * Node of a TriangleKdTree. * * @author Ľubomír Jurčišin */ public interface TriangleKdNode extends KdNode{ /** * Gets parent of this node or {@code null} if it is the root node. * * @return Parent node. */ TriangleKdNode getParent(); /** * Gets triangles stored in this node if it is a leaf node. * * @return List of stored triangles or empty list if not a leaf node. */ List<MeshTriangle> getTriangles(); /** * Gets splitting plane position on axis according to depth. * * @return Splitting plane position on either x/y/z based on depth. */ double getSplit(); /** * Check if current node is leaf. * * @return {@code true} if it is a leaf node. {@code false} otherwise. */ boolean isLeaf(); }