Loading MeshModel/src/main/java/cz/fidentis/analyst/mesh/HumanFace.java→Comparison/src/main/java/cz/fidentis/analyst/HumanFace.java +1 −1 Original line number Diff line number Diff line package cz.fidentis.analyst.mesh; package cz.fidentis.analyst; import cz.fidentis.analyst.mesh.core.MeshModel; import cz.fidentis.analyst.mesh.io.MeshObjLoader; Loading Comparison/src/main/java/cz/fidentis/analyst/comparison/ClosestVertices.javadeleted 100644 → 0 +0 −39 Original line number Diff line number Diff line package cz.fidentis.analyst.comparison; import cz.fidentis.analyst.mesh.core.MeshPoint; /** * * @author Matej Lukes */ public class ClosestVertices { private MeshPoint firstVertex; private MeshPoint secondVertex; private double distance; /** * Constructor. * * @param firstVertex Firt vertex of the pair * @param secondVertex Second vertex of the pair * @param distance Distance */ public ClosestVertices(MeshPoint firstVertex, MeshPoint secondVertex, double distance) { this.firstVertex = firstVertex; this.secondVertex = secondVertex; this.distance = distance; } public MeshPoint getFirstVertex() { return firstVertex; } public MeshPoint getSecondVertex() { return secondVertex; } public double getDistance() { return distance; } } Comparison/src/main/java/cz/fidentis/analyst/comparison/Comparison.javadeleted 100644 → 0 +0 −95 Original line number Diff line number Diff line package cz.fidentis.analyst.comparison; import cz.fidentis.analyst.mesh.core.MeshFacet; import cz.fidentis.analyst.mesh.io.MeshObjLoader; import java.io.File; import java.io.IOException; import java.util.List; import java.util.concurrent.CompletableFuture; /** * @author Matej Lukes */ public class Comparison { private HausdorffDistance hausdorffDistance; private MeshFacet mainFacet; private MeshFacet comparedFacet; /** * Asynchronously loads main meshModel * * @param path path to meshModel file * @return CompletableFuture */ public CompletableFuture loadMainModel(String path) { return CompletableFuture.runAsync(() -> { try { mainFacet = MeshObjLoader.read(new File(path)).getFacets().get(1); } catch (IOException e) { e.printStackTrace(); } }); } /** * Asynchronously loads compared meshModel * * @param path path to meshModel file * @return CompletableFuture */ public CompletableFuture loadComparedModel(String path) { return CompletableFuture.runAsync(() -> { try { comparedFacet = MeshObjLoader.read(new File(path)).getFacets().get(1); } catch (IOException e) { e.printStackTrace(); } }); } /** * Asynchronously registers compared meshFacet to main meshFacet * * @param method registration method * @return CompletableFuture */ public CompletableFuture register(RegistrationMethod method) { return CompletableFuture.runAsync(() -> comparedFacet = Registration .register(mainFacet, comparedFacet, method)); } /** * Asynchronously compares MeshFacets from vertices to vertices * * @return list containing vertex from first facet, closest vertex to it from second facet, distance */ public CompletableFuture<List<ClosestVertices>> compareHausdorffDistanceToVertices() { hausdorffDistance = new HausdorffDistance(mainFacet, comparedFacet); return CompletableFuture.supplyAsync(() -> hausdorffDistance.calculateHausdorffDistanceToVertices()); } /** * Asynchronously compares MeshFacets from vertices to any point on mesh * * @return list containing vertex from first facet, closest point to it from second facet, distance */ public CompletableFuture<List<ClosestVertices>> compareHausdorffDistanceToMesh() { hausdorffDistance = new HausdorffDistance(mainFacet, comparedFacet); return CompletableFuture.supplyAsync(() -> hausdorffDistance.calculateHausdorffDistanceToMesh()); } /** * returns progress percentage * * @return progress percentage */ public double getComparisonProgress() { if (hausdorffDistance == null) { return -1; } return hausdorffDistance.getProgressPercentage(); } } Comparison/src/main/java/cz/fidentis/analyst/comparison/HausdorffDistance.javadeleted 100644 → 0 +0 −359 Original line number Diff line number Diff line package cz.fidentis.analyst.comparison; import cz.fidentis.analyst.mesh.core.MeshFacet; import cz.fidentis.analyst.mesh.core.MeshPoint; import cz.fidentis.analyst.mesh.core.MeshPointImpl; import cz.fidentis.analyst.mesh.core.MeshTriangle; import cz.fidentis.analyst.mesh.visitors.TriangleListVisitor; import javax.vecmath.Vector3d; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; /** * @author Matej Lukes */ public class HausdorffDistance { private MeshFacet mainFacet; private MeshFacet comparedFacet; private AtomicInteger progress = new AtomicInteger(); private int numberOfVertices; /** * @param mainFacet main MeshFacet * @param comparedFacet compared MeshFacet */ public HausdorffDistance(MeshFacet mainFacet, MeshFacet comparedFacet) { this.mainFacet = mainFacet; this.comparedFacet = comparedFacet; this.numberOfVertices = mainFacet.getNumberOfVertices(); } /** * returns progress percentage * * @return progress */ public double getProgressPercentage() { return ((double) progress.get() / numberOfVertices) * 100; } /** * Finds the nearest vertex on the second facet. * * @param vertex vertex from * @return vertex, nearest vertex from second facet, distance */ private ClosestVertices getNearestVertex(MeshPoint vertex) { Optional<Pair<MeshPoint, Double>> closestVertexAndDistance = comparedFacet.getVertices().parallelStream() .map((meshPoint) -> new Pair<>(meshPoint, getDistanceBetweenPoints(vertex, meshPoint.getPosition()))) .max((Comparator.comparingDouble(Pair::getValue))); return closestVertexAndDistance.map(vector3dDoublePair -> new ClosestVertices(vertex, vector3dDoublePair.getKey(), vector3dDoublePair.getValue())).orElse(null); } /** * returns distance between two points * * @param point1 first point * @param point2 second point * @return distance */ private double getDistanceBetweenPoints(MeshPoint point1, Vector3d point2) { Vector3d helperVector = new Vector3d(); helperVector.sub(point1.getPosition(), point2); return Math.signum(helperVector.dot(point1.getNormal())) * helperVector.length(); } /** * calculates Hausdorff Distance to the nearest vertex from second facet for each vertex in first facet * this implementation uses executor * * @return list containing vertex from first facet, closest vertex to it from second facet, distance */ public List<ClosestVertices> calculateHausdorffDistanceToVertices() { progress.set(0); int numberOfVertices = mainFacet.getNumberOfVertices(); List<Future<ClosestVertices>> closestVerticesFutures = new ArrayList<>(numberOfVertices); ExecutorService executor = Executors.newCachedThreadPool(); for (final MeshPoint vertex : mainFacet.getVertices()) { closestVerticesFutures.add(executor.submit(() -> { ClosestVertices result = getNearestVertex(vertex); progress.addAndGet(1); return result; })); } List<ClosestVertices> closestVertices = new ArrayList<>(numberOfVertices); for (Future<ClosestVertices> future : closestVerticesFutures) { executor.submit(() -> { try { ClosestVertices result = future.get(); synchronized (closestVertices) { closestVertices.add(result); } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } }); } executor.shutdown(); return closestVertices; } /** * calculates Hausdorff Distance to the nearest vertex from second facet for each vertex in first facet * this implementation uses parallel streams * * @return list containing vertex from first facet, closest vertex to it from second facet, distance */ public List<ClosestVertices> calculateHausdorffDistanceToVertices2() { progress.set(0); return mainFacet.getVertices().parallelStream() .map((vertex) -> { ClosestVertices result = getNearestVertex(vertex); progress.addAndGet(1); return result; }) .collect(Collectors.toList()); } /** * calculates Hausdorff Distance to the nearest point on second facet for each vertex * this implementation uses executor * * @return list containing vertex from first facet, closest point to it from second facet, distance */ public List<ClosestVertices> calculateHausdorffDistanceToMesh() { progress.set(0); int numberOfVertices = mainFacet.getNumberOfVertices(); List<Future<ClosestVertices>> closestPointsFutures = new ArrayList<>(numberOfVertices); ExecutorService executor = Executors.newCachedThreadPool(); for (final MeshPoint vertex : mainFacet.getVertices()) { closestPointsFutures.add(executor.submit(() -> { ClosestVertices result = calculateNearestPointOnMesh(vertex, comparedFacet.getCornerTable() .getTriangleIndexesByVertexIndex(comparedFacet.getVertices() .indexOf(getNearestVertex(vertex) .getSecondVertex()))); progress.addAndGet(1); return result; })); } List<ClosestVertices> closestVertices = new ArrayList<>(numberOfVertices); for (Future<ClosestVertices> future : closestPointsFutures) { executor.submit(() -> { try { ClosestVertices result = future.get(); synchronized (closestVertices) { closestVertices.add(result); } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } }); } executor.shutdown(); return closestVertices; } /** * calculates Hausdorff Distance to the nearest point on second facet for each vertex * this implementation uses parallel streams * * @return list containing vertex from first facet, closest point to it from second facet, distance */ public List<ClosestVertices> calculateHausdorffDistanceToMesh2() { progress.set(0); return mainFacet.getVertices().parallelStream() .map((meshPoint) -> { ClosestVertices result = calculateNearestPointOnMesh(meshPoint, comparedFacet.getCornerTable() .getTriangleIndexesByVertexIndex(comparedFacet.getVertices() .indexOf(getNearestVertex(meshPoint) .getSecondVertex()))); progress.addAndGet(1); return result; }).collect(Collectors.toList()); } /** * calculates Hausdorff Distance to the nearest point on second facet for vertex * * @param vertex vertex from first facet * @param indicesOfTrianglesOfVertex indices of triangles that contain the nearest vertex on second mesh * @return vertex from first facet, closest point to it from second facet, distance */ private ClosestVertices calculateNearestPointOnMesh(MeshPoint vertex, List<Integer> indicesOfTrianglesOfVertex) { Vector3d vertexPosition = vertex.getPosition(); List<Pair<Vector3d, Double>> projections = new ArrayList<>(indicesOfTrianglesOfVertex.size()); Vector3d helperVector = new Vector3d(); TriangleListVisitor visitor = new TriangleListVisitor(); comparedFacet.accept(visitor); List<MeshTriangle> trList = visitor.getTriangles(); for (int index : indicesOfTrianglesOfVertex) { List<Vector3d> triangle = new ArrayList<>(); triangle.add(trList.get(index).vertex1.getPosition()); triangle.add(trList.get(index).vertex2.getPosition()); triangle.add(trList.get(index).vertex3.getPosition()); //List<Vector3d> triangle = comparedFacet.asTriangles()..getVerticesOfTriangle(index).stream() // .map(MeshPoint::getPosition) // .collect(Collectors.toList()); Vector3d projection = getProjectionToTrianglePlane(vertexPosition, triangle); if (isPointInTriangle(projection, triangle)) { helperVector.sub(vertexPosition, projection); projections.add(new Pair<>(projection, helperVector.length())); } else { projection = getProjectionToClosestEdge(projection, triangle); helperVector.sub(vertexPosition, projection); projections.add(new Pair<>(projection, helperVector.length())); } } Pair<Vector3d, Double> closestPosition = projections.stream() .min(Comparator.comparingDouble(Pair::getValue)).orElseGet(() -> new Pair<>(null, Double.MAX_VALUE)); return new ClosestVertices(vertex, new MeshPointImpl(closestPosition.getKey(), null, null), closestPosition.getValue()); } /** * returns perpendicular projection from vertex to plane of triangle * * @param vertex vertex from which the projection is created * @param triangle triangle that defines the plane * @return projection to plane of triangle */ private Vector3d getProjectionToTrianglePlane(Vector3d vertex, List<Vector3d> triangle) { Vector3d ab = new Vector3d(); ab.sub(triangle.get(0), triangle.get(1)); Vector3d ac = new Vector3d(); ac.sub(triangle.get(0), triangle.get(2)); Vector3d normal = new Vector3d(); normal.cross(ab, ac); normal.normalize(); Vector3d helperVector = new Vector3d(vertex); helperVector.sub(triangle.get(0)); double distance = helperVector.dot(normal); helperVector.scaleAdd(-distance, normal, helperVector); return helperVector; } /** * checks if a point in plane of triangle lies within the triangle * * @param point checked point * @param triangle triangle * @return true if point is in triangle, false otherwise */ private boolean isPointInTriangle(Vector3d point, List<Vector3d> triangle) { List<Vector3d> pointToVertices = triangle.stream() .map((vertex) -> { Vector3d v = new Vector3d(vertex); v.sub(point); return v; }).collect(Collectors.toList()); double angleSum = 0; for (int i = 0; i < 3; i++) { angleSum += pointToVertices.get(i).angle(pointToVertices.get((i + 1) % 3)); } angleSum -= Math.PI; return -0.01 < angleSum && angleSum < 0.01; } /** * returns projection to to the nearest edge of triangle * * @param point point in plane of triangle * @param triangle triangle * @return perpendicular projection to the nearest edge */ private Vector3d getProjectionToClosestEdge(Vector3d point, List<Vector3d> triangle) { Vector3d[] projections = new Vector3d[3]; for (int i = 0; i < 3; i++) { projections[i] = getProjectionToEdge(point, triangle.get(i), triangle.get((i + 1) % 3)); } double minDistance = Double.MAX_VALUE; Vector3d closestProjection = null; Vector3d helperVector = new Vector3d(); for (Vector3d projection : projections) { helperVector.sub(point, projection); double distance = helperVector.length(); if (distance < minDistance) { minDistance = distance; closestProjection = projection; } } return closestProjection; } /** * returns projection to edge * * @param point point in plane of triangle * @param edgeVertex1 first vertex of edge * @param edgeVertex2 second vertex of edge * @return projection to edge */ private Vector3d getProjectionToEdge(Vector3d point, Vector3d edgeVertex1, Vector3d edgeVertex2) { Vector3d ab = new Vector3d(); ab.sub(edgeVertex1, edgeVertex2); Vector3d ap = new Vector3d(); ap.sub(edgeVertex1, point); double t = ab.dot(ap) / ab.lengthSquared(); return new Vector3d(edgeVertex1.x + t * ab.x, edgeVertex1.y + t * ab.y, edgeVertex1.z + t * ab.z); } /** * Helper class for pairs. * * @param <K> key * @param <V> value * @author Radek Oslejsek */ private final class Pair<K,V> { private final K key; private final V value; /** * Constructor. * @param key key * @param value value */ private Pair(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public V getValue() { return value; } } } Comparison/src/main/java/cz/fidentis/analyst/comparison/Registration.javadeleted 100644 → 0 +0 −27 Original line number Diff line number Diff line package cz.fidentis.analyst.comparison; import cz.fidentis.analyst.mesh.core.MeshFacet; /** * * @author Matej Lukes */ public class Registration { /** * Heler method - TO DO * * @param facet main facet * @param registeredFacet refistered facet * @param method registration method * @return TO DO */ public static MeshFacet register(MeshFacet facet, MeshFacet registeredFacet, RegistrationMethod method) { switch (method) { case NO_REGISTRATION: return registeredFacet; default: return null; } } } Loading
MeshModel/src/main/java/cz/fidentis/analyst/mesh/HumanFace.java→Comparison/src/main/java/cz/fidentis/analyst/HumanFace.java +1 −1 Original line number Diff line number Diff line package cz.fidentis.analyst.mesh; package cz.fidentis.analyst; import cz.fidentis.analyst.mesh.core.MeshModel; import cz.fidentis.analyst.mesh.io.MeshObjLoader; Loading
Comparison/src/main/java/cz/fidentis/analyst/comparison/ClosestVertices.javadeleted 100644 → 0 +0 −39 Original line number Diff line number Diff line package cz.fidentis.analyst.comparison; import cz.fidentis.analyst.mesh.core.MeshPoint; /** * * @author Matej Lukes */ public class ClosestVertices { private MeshPoint firstVertex; private MeshPoint secondVertex; private double distance; /** * Constructor. * * @param firstVertex Firt vertex of the pair * @param secondVertex Second vertex of the pair * @param distance Distance */ public ClosestVertices(MeshPoint firstVertex, MeshPoint secondVertex, double distance) { this.firstVertex = firstVertex; this.secondVertex = secondVertex; this.distance = distance; } public MeshPoint getFirstVertex() { return firstVertex; } public MeshPoint getSecondVertex() { return secondVertex; } public double getDistance() { return distance; } }
Comparison/src/main/java/cz/fidentis/analyst/comparison/Comparison.javadeleted 100644 → 0 +0 −95 Original line number Diff line number Diff line package cz.fidentis.analyst.comparison; import cz.fidentis.analyst.mesh.core.MeshFacet; import cz.fidentis.analyst.mesh.io.MeshObjLoader; import java.io.File; import java.io.IOException; import java.util.List; import java.util.concurrent.CompletableFuture; /** * @author Matej Lukes */ public class Comparison { private HausdorffDistance hausdorffDistance; private MeshFacet mainFacet; private MeshFacet comparedFacet; /** * Asynchronously loads main meshModel * * @param path path to meshModel file * @return CompletableFuture */ public CompletableFuture loadMainModel(String path) { return CompletableFuture.runAsync(() -> { try { mainFacet = MeshObjLoader.read(new File(path)).getFacets().get(1); } catch (IOException e) { e.printStackTrace(); } }); } /** * Asynchronously loads compared meshModel * * @param path path to meshModel file * @return CompletableFuture */ public CompletableFuture loadComparedModel(String path) { return CompletableFuture.runAsync(() -> { try { comparedFacet = MeshObjLoader.read(new File(path)).getFacets().get(1); } catch (IOException e) { e.printStackTrace(); } }); } /** * Asynchronously registers compared meshFacet to main meshFacet * * @param method registration method * @return CompletableFuture */ public CompletableFuture register(RegistrationMethod method) { return CompletableFuture.runAsync(() -> comparedFacet = Registration .register(mainFacet, comparedFacet, method)); } /** * Asynchronously compares MeshFacets from vertices to vertices * * @return list containing vertex from first facet, closest vertex to it from second facet, distance */ public CompletableFuture<List<ClosestVertices>> compareHausdorffDistanceToVertices() { hausdorffDistance = new HausdorffDistance(mainFacet, comparedFacet); return CompletableFuture.supplyAsync(() -> hausdorffDistance.calculateHausdorffDistanceToVertices()); } /** * Asynchronously compares MeshFacets from vertices to any point on mesh * * @return list containing vertex from first facet, closest point to it from second facet, distance */ public CompletableFuture<List<ClosestVertices>> compareHausdorffDistanceToMesh() { hausdorffDistance = new HausdorffDistance(mainFacet, comparedFacet); return CompletableFuture.supplyAsync(() -> hausdorffDistance.calculateHausdorffDistanceToMesh()); } /** * returns progress percentage * * @return progress percentage */ public double getComparisonProgress() { if (hausdorffDistance == null) { return -1; } return hausdorffDistance.getProgressPercentage(); } }
Comparison/src/main/java/cz/fidentis/analyst/comparison/HausdorffDistance.javadeleted 100644 → 0 +0 −359 Original line number Diff line number Diff line package cz.fidentis.analyst.comparison; import cz.fidentis.analyst.mesh.core.MeshFacet; import cz.fidentis.analyst.mesh.core.MeshPoint; import cz.fidentis.analyst.mesh.core.MeshPointImpl; import cz.fidentis.analyst.mesh.core.MeshTriangle; import cz.fidentis.analyst.mesh.visitors.TriangleListVisitor; import javax.vecmath.Vector3d; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; /** * @author Matej Lukes */ public class HausdorffDistance { private MeshFacet mainFacet; private MeshFacet comparedFacet; private AtomicInteger progress = new AtomicInteger(); private int numberOfVertices; /** * @param mainFacet main MeshFacet * @param comparedFacet compared MeshFacet */ public HausdorffDistance(MeshFacet mainFacet, MeshFacet comparedFacet) { this.mainFacet = mainFacet; this.comparedFacet = comparedFacet; this.numberOfVertices = mainFacet.getNumberOfVertices(); } /** * returns progress percentage * * @return progress */ public double getProgressPercentage() { return ((double) progress.get() / numberOfVertices) * 100; } /** * Finds the nearest vertex on the second facet. * * @param vertex vertex from * @return vertex, nearest vertex from second facet, distance */ private ClosestVertices getNearestVertex(MeshPoint vertex) { Optional<Pair<MeshPoint, Double>> closestVertexAndDistance = comparedFacet.getVertices().parallelStream() .map((meshPoint) -> new Pair<>(meshPoint, getDistanceBetweenPoints(vertex, meshPoint.getPosition()))) .max((Comparator.comparingDouble(Pair::getValue))); return closestVertexAndDistance.map(vector3dDoublePair -> new ClosestVertices(vertex, vector3dDoublePair.getKey(), vector3dDoublePair.getValue())).orElse(null); } /** * returns distance between two points * * @param point1 first point * @param point2 second point * @return distance */ private double getDistanceBetweenPoints(MeshPoint point1, Vector3d point2) { Vector3d helperVector = new Vector3d(); helperVector.sub(point1.getPosition(), point2); return Math.signum(helperVector.dot(point1.getNormal())) * helperVector.length(); } /** * calculates Hausdorff Distance to the nearest vertex from second facet for each vertex in first facet * this implementation uses executor * * @return list containing vertex from first facet, closest vertex to it from second facet, distance */ public List<ClosestVertices> calculateHausdorffDistanceToVertices() { progress.set(0); int numberOfVertices = mainFacet.getNumberOfVertices(); List<Future<ClosestVertices>> closestVerticesFutures = new ArrayList<>(numberOfVertices); ExecutorService executor = Executors.newCachedThreadPool(); for (final MeshPoint vertex : mainFacet.getVertices()) { closestVerticesFutures.add(executor.submit(() -> { ClosestVertices result = getNearestVertex(vertex); progress.addAndGet(1); return result; })); } List<ClosestVertices> closestVertices = new ArrayList<>(numberOfVertices); for (Future<ClosestVertices> future : closestVerticesFutures) { executor.submit(() -> { try { ClosestVertices result = future.get(); synchronized (closestVertices) { closestVertices.add(result); } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } }); } executor.shutdown(); return closestVertices; } /** * calculates Hausdorff Distance to the nearest vertex from second facet for each vertex in first facet * this implementation uses parallel streams * * @return list containing vertex from first facet, closest vertex to it from second facet, distance */ public List<ClosestVertices> calculateHausdorffDistanceToVertices2() { progress.set(0); return mainFacet.getVertices().parallelStream() .map((vertex) -> { ClosestVertices result = getNearestVertex(vertex); progress.addAndGet(1); return result; }) .collect(Collectors.toList()); } /** * calculates Hausdorff Distance to the nearest point on second facet for each vertex * this implementation uses executor * * @return list containing vertex from first facet, closest point to it from second facet, distance */ public List<ClosestVertices> calculateHausdorffDistanceToMesh() { progress.set(0); int numberOfVertices = mainFacet.getNumberOfVertices(); List<Future<ClosestVertices>> closestPointsFutures = new ArrayList<>(numberOfVertices); ExecutorService executor = Executors.newCachedThreadPool(); for (final MeshPoint vertex : mainFacet.getVertices()) { closestPointsFutures.add(executor.submit(() -> { ClosestVertices result = calculateNearestPointOnMesh(vertex, comparedFacet.getCornerTable() .getTriangleIndexesByVertexIndex(comparedFacet.getVertices() .indexOf(getNearestVertex(vertex) .getSecondVertex()))); progress.addAndGet(1); return result; })); } List<ClosestVertices> closestVertices = new ArrayList<>(numberOfVertices); for (Future<ClosestVertices> future : closestPointsFutures) { executor.submit(() -> { try { ClosestVertices result = future.get(); synchronized (closestVertices) { closestVertices.add(result); } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } }); } executor.shutdown(); return closestVertices; } /** * calculates Hausdorff Distance to the nearest point on second facet for each vertex * this implementation uses parallel streams * * @return list containing vertex from first facet, closest point to it from second facet, distance */ public List<ClosestVertices> calculateHausdorffDistanceToMesh2() { progress.set(0); return mainFacet.getVertices().parallelStream() .map((meshPoint) -> { ClosestVertices result = calculateNearestPointOnMesh(meshPoint, comparedFacet.getCornerTable() .getTriangleIndexesByVertexIndex(comparedFacet.getVertices() .indexOf(getNearestVertex(meshPoint) .getSecondVertex()))); progress.addAndGet(1); return result; }).collect(Collectors.toList()); } /** * calculates Hausdorff Distance to the nearest point on second facet for vertex * * @param vertex vertex from first facet * @param indicesOfTrianglesOfVertex indices of triangles that contain the nearest vertex on second mesh * @return vertex from first facet, closest point to it from second facet, distance */ private ClosestVertices calculateNearestPointOnMesh(MeshPoint vertex, List<Integer> indicesOfTrianglesOfVertex) { Vector3d vertexPosition = vertex.getPosition(); List<Pair<Vector3d, Double>> projections = new ArrayList<>(indicesOfTrianglesOfVertex.size()); Vector3d helperVector = new Vector3d(); TriangleListVisitor visitor = new TriangleListVisitor(); comparedFacet.accept(visitor); List<MeshTriangle> trList = visitor.getTriangles(); for (int index : indicesOfTrianglesOfVertex) { List<Vector3d> triangle = new ArrayList<>(); triangle.add(trList.get(index).vertex1.getPosition()); triangle.add(trList.get(index).vertex2.getPosition()); triangle.add(trList.get(index).vertex3.getPosition()); //List<Vector3d> triangle = comparedFacet.asTriangles()..getVerticesOfTriangle(index).stream() // .map(MeshPoint::getPosition) // .collect(Collectors.toList()); Vector3d projection = getProjectionToTrianglePlane(vertexPosition, triangle); if (isPointInTriangle(projection, triangle)) { helperVector.sub(vertexPosition, projection); projections.add(new Pair<>(projection, helperVector.length())); } else { projection = getProjectionToClosestEdge(projection, triangle); helperVector.sub(vertexPosition, projection); projections.add(new Pair<>(projection, helperVector.length())); } } Pair<Vector3d, Double> closestPosition = projections.stream() .min(Comparator.comparingDouble(Pair::getValue)).orElseGet(() -> new Pair<>(null, Double.MAX_VALUE)); return new ClosestVertices(vertex, new MeshPointImpl(closestPosition.getKey(), null, null), closestPosition.getValue()); } /** * returns perpendicular projection from vertex to plane of triangle * * @param vertex vertex from which the projection is created * @param triangle triangle that defines the plane * @return projection to plane of triangle */ private Vector3d getProjectionToTrianglePlane(Vector3d vertex, List<Vector3d> triangle) { Vector3d ab = new Vector3d(); ab.sub(triangle.get(0), triangle.get(1)); Vector3d ac = new Vector3d(); ac.sub(triangle.get(0), triangle.get(2)); Vector3d normal = new Vector3d(); normal.cross(ab, ac); normal.normalize(); Vector3d helperVector = new Vector3d(vertex); helperVector.sub(triangle.get(0)); double distance = helperVector.dot(normal); helperVector.scaleAdd(-distance, normal, helperVector); return helperVector; } /** * checks if a point in plane of triangle lies within the triangle * * @param point checked point * @param triangle triangle * @return true if point is in triangle, false otherwise */ private boolean isPointInTriangle(Vector3d point, List<Vector3d> triangle) { List<Vector3d> pointToVertices = triangle.stream() .map((vertex) -> { Vector3d v = new Vector3d(vertex); v.sub(point); return v; }).collect(Collectors.toList()); double angleSum = 0; for (int i = 0; i < 3; i++) { angleSum += pointToVertices.get(i).angle(pointToVertices.get((i + 1) % 3)); } angleSum -= Math.PI; return -0.01 < angleSum && angleSum < 0.01; } /** * returns projection to to the nearest edge of triangle * * @param point point in plane of triangle * @param triangle triangle * @return perpendicular projection to the nearest edge */ private Vector3d getProjectionToClosestEdge(Vector3d point, List<Vector3d> triangle) { Vector3d[] projections = new Vector3d[3]; for (int i = 0; i < 3; i++) { projections[i] = getProjectionToEdge(point, triangle.get(i), triangle.get((i + 1) % 3)); } double minDistance = Double.MAX_VALUE; Vector3d closestProjection = null; Vector3d helperVector = new Vector3d(); for (Vector3d projection : projections) { helperVector.sub(point, projection); double distance = helperVector.length(); if (distance < minDistance) { minDistance = distance; closestProjection = projection; } } return closestProjection; } /** * returns projection to edge * * @param point point in plane of triangle * @param edgeVertex1 first vertex of edge * @param edgeVertex2 second vertex of edge * @return projection to edge */ private Vector3d getProjectionToEdge(Vector3d point, Vector3d edgeVertex1, Vector3d edgeVertex2) { Vector3d ab = new Vector3d(); ab.sub(edgeVertex1, edgeVertex2); Vector3d ap = new Vector3d(); ap.sub(edgeVertex1, point); double t = ab.dot(ap) / ab.lengthSquared(); return new Vector3d(edgeVertex1.x + t * ab.x, edgeVertex1.y + t * ab.y, edgeVertex1.z + t * ab.z); } /** * Helper class for pairs. * * @param <K> key * @param <V> value * @author Radek Oslejsek */ private final class Pair<K,V> { private final K key; private final V value; /** * Constructor. * @param key key * @param value value */ private Pair(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public V getValue() { return value; } } }
Comparison/src/main/java/cz/fidentis/analyst/comparison/Registration.javadeleted 100644 → 0 +0 −27 Original line number Diff line number Diff line package cz.fidentis.analyst.comparison; import cz.fidentis.analyst.mesh.core.MeshFacet; /** * * @author Matej Lukes */ public class Registration { /** * Heler method - TO DO * * @param facet main facet * @param registeredFacet refistered facet * @param method registration method * @return TO DO */ public static MeshFacet register(MeshFacet facet, MeshFacet registeredFacet, RegistrationMethod method) { switch (method) { case NO_REGISTRATION: return registeredFacet; default: return null; } } }