Loading Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java +47 −1 Original line number Diff line number Diff line package cz.fidentis.analyst.face; import com.google.common.eventbus.EventBus; import cz.fidentis.analyst.feature.FeaturePoint; import cz.fidentis.analyst.feature.services.FeaturePointImportExportService; import cz.fidentis.analyst.kdtree.KdTree; import cz.fidentis.analyst.mesh.core.MeshFacet; import cz.fidentis.analyst.mesh.core.MeshModel; Loading @@ -8,6 +10,7 @@ import cz.fidentis.analyst.mesh.events.MeshEvent; import cz.fidentis.analyst.mesh.events.MeshListener; import cz.fidentis.analyst.mesh.io.MeshObjLoader; import cz.fidentis.analyst.symmetry.Plane; import cz.fidentis.analyst.visitors.face.HumanFaceVisitor; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; Loading @@ -18,6 +21,8 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Collections; import java.util.List; import java.util.ArrayList; import java.util.Objects; //import org.nustaq.serialization.FSTConfiguration; Loading Loading @@ -57,6 +62,8 @@ public class HumanFace implements MeshListener, Serializable { private MeshFacet cuttingPlane; private List<FeaturePoint> featurePoints; private final transient EventBus eventBus = new EventBus(); private final String id; Loading Loading @@ -134,7 +141,7 @@ public class HumanFace implements MeshListener, Serializable { /** * * @param plane The new symmetry plane * @param paneFacet The symmetry plane mesh * @param planeFacet The symmetry plane mesh */ public void setSymmetryPlane(Plane plane, MeshFacet planeFacet) { this.symmetryPlane = plane; Loading Loading @@ -169,6 +176,36 @@ public class HumanFace implements MeshListener, Serializable { return cuttingPlane; } /** * * @param points List of feature points */ public void setFeaturePoints(List<FeaturePoint> points) { featurePoints = points; } /** * Reads feature points from a file on the given path. * * @param path Directory where the file is located * @param fileName Name of the file * @throws IOException on I/O failure */ public void loadFeaturePoints(String path, String fileName) throws IOException { featurePoints = FeaturePointImportExportService.importFeaturePoints(path, fileName); } /** * * @return The face's feature points. */ public List<FeaturePoint> getFeaturePoints() { if (featurePoints == null) { return Collections.emptyList(); } return Collections.unmodifiableList(featurePoints); } /** * Returns unique ID of the face. * Loading Loading @@ -268,6 +305,15 @@ public class HumanFace implements MeshListener, Serializable { */ } /** * Visits this face. * * @param visitor Visitor */ public void accept(HumanFaceVisitor visitor) { visitor.visitHumanFace(this); } @Override public int hashCode() { int hash = 7; Loading Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceFactory.java +3 −0 Original line number Diff line number Diff line Loading @@ -227,6 +227,9 @@ public class HumanFaceFactory { HumanFace face = inMemoryFaces.get(oldTime); long newTime = System.currentTimeMillis(); while (inMemoryFaces.containsKey(newTime)) { // wait until we get unique ms newTime = System.currentTimeMillis(); } inMemoryFaces.remove(oldTime); inMemoryFaces.put(newTime, face); usage.put(faceId, newTime); Loading Comparison/src/main/java/cz/fidentis/analyst/visitors/face/HausdorffDistancePrioritized.java 0 → 100644 +242 −0 Original line number Diff line number Diff line package cz.fidentis.analyst.visitors.face; import cz.fidentis.analyst.face.HumanFace; import cz.fidentis.analyst.feature.FeaturePoint; import cz.fidentis.analyst.feature.FeaturePointType; import cz.fidentis.analyst.kdtree.KdTree; import cz.fidentis.analyst.mesh.core.MeshFacet; import cz.fidentis.analyst.mesh.core.MeshModel; import cz.fidentis.analyst.visitors.mesh.HausdorffDistance; import cz.fidentis.analyst.visitors.mesh.HausdorffDistance.Strategy; import cz.fidentis.analyst.visitors.mesh.PrioritySphere; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.vecmath.Point3d; /** * Visitor for prioritized Hausdorff distance. * This visitor is instantiated with a single k-d tree (either given as the input * parameter, or automatically created from the triangular mesh). * When applied to other human faces, it computes prioritized Hausdorff distance from their mesh facets * to the instantiated k-d tree. * <p> * This visitor is thread-safe, i.e., a single instance of the visitor can be used * to inspect multiple human faces simultaneously. * </p> * <p> * The distance is computed either as absolute or relative. Absolute * represents Euclidean distance (all numbers are positive). On the contrary, * relative distance considers orientation of the visited face's facets (determined by its normal vectors) * and produces positive or negative distances depending on whether the primary * mesh is "in front of" or "behind" the given vertex. * </p> * * @author Daniel Schramm */ public class HausdorffDistancePrioritized extends HumanFaceVisitor { private final HausdorffDistance distanceVisitor; private final FeaturePointType featurePointType; private final Map<MeshFacet, List<Double>> priorities = new HashMap<>(); /** * Constructor. * * @param mainFacets Facets to which distance from the visited human face's facets is to be computed. * Must not be {@code null}. * @param featurePoint Feature point according to which the Hausdorff distances will be prioritized * @param strategy Strategy of the computation of distance * @param relativeDistance If {@code 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 {@code true}, then the algorithm runs concurrently utilizing all CPU cores * @throws IllegalArgumentException if some parameter is wrong */ public HausdorffDistancePrioritized(Set<MeshFacet> mainFacets, FeaturePointType featurePoint, Strategy strategy, boolean relativeDistance, boolean parallel) { distanceVisitor = new HausdorffDistance(mainFacets, strategy, relativeDistance, parallel); featurePointType = featurePoint; } /** * Constructor. * * @param mainFacet Primary facet to which distance from the visited human face's facets is to be computed. Must not be {@code null}. * @param featurePoint Feature point according to which the Hausdorff distances will be prioritized * @param strategy Strategy of the computation of distance * @param relativeDistance If {@code 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 {@code true}, then the algorithm runs concurrently utilizing all CPU cores * @throws IllegalArgumentException if some parameter is wrong */ public HausdorffDistancePrioritized(MeshFacet mainFacet, FeaturePointType featurePoint, Strategy strategy, boolean relativeDistance, boolean parallel) { this(new HashSet<>(Collections.singleton(mainFacet)), featurePoint, strategy, relativeDistance, parallel); } /** * Constructor. * * @param mainModel The mesh model with primary facets to which distance from the visited human face's facets is to be computed. * Must not be {@code null} or empty. * @param featurePoint Feature point according to which the Hausdorff distances will be prioritized * @param strategy Strategy of the computation of distance * @param relativeDistance If {@code 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 {@code true}, then the algorithm runs concurrently utilizing all CPU cores * @throws IllegalArgumentException if some parameter is wrong */ public HausdorffDistancePrioritized(MeshModel mainModel, FeaturePointType featurePoint, Strategy strategy, boolean relativeDistance, boolean parallel) { this(new HashSet<>(mainModel.getFacets()), featurePoint, strategy, relativeDistance, parallel); } /** * Constructor. * * @param face Human face to which distance from other human faces is to be computed. Must not be {@code null}. * @param featurePoint Feature point according to which the Hausdorff distances will be prioritized * @param strategy Strategy of the computation of distance * @param relativeDistance If {@code 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 {@code true}, then the algorithm runs concurrently utilizing all CPU cores * @throws IllegalArgumentException if some parameter is wrong */ public HausdorffDistancePrioritized(HumanFace face, FeaturePointType featurePoint, Strategy strategy, boolean relativeDistance, boolean parallel) { this(face.getMeshModel(), featurePoint, strategy, relativeDistance, parallel); } /** * Constructor. * * @param mainKdTree The KD tree to which distance from the visited human face's facets is to be computed. * Must not be {@code null}. * @param featurePoint Feature point according to which the Hausdorff distances will be prioritized * @param strategy Strategy of the computation of distance * @param relativeDistance If {@code 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 {@code true}, then the algorithm runs concurrently utilizing all CPU cores * @throws IllegalArgumentException if some parameter is wrong */ public HausdorffDistancePrioritized(KdTree mainKdTree, FeaturePointType featurePoint, Strategy strategy, boolean relativeDistance, boolean parallel) { distanceVisitor = new HausdorffDistance(mainKdTree, strategy, relativeDistance, parallel); featurePointType = featurePoint; } public FeaturePointType getFeaturePointType() { return featurePointType; } /** * Returns Hausdorff distance of the visited faces' mesh facets to the source mesh facets. * * Keys in the map contain mesh facets that were measured with the * source facets. * For each facet of the visited human face, a list of distances to the source * facets is stored. The order of distances corresponds to the order of vertices * in the measured facet, i.e., the i-th value is the distance of the i-th vertex * of the visited face's facet. * * @return Hausdorff distance for all points of all the visited human faces' facets */ public Map<MeshFacet, List<Double>> getDistances() { return distanceVisitor.getDistances(); } /** * Returns the nearest points of the visited faces' mesh facets to the source mesh facets. * * Keys in the map contain mesh facets that were measured with the * source facets. * For each facet of the visited human face, a list of the nearest points to the source * facets is stored. The order of points corresponds to the order of vertices * in the measured facet, i.e., the i-th point is the nearest point of the i-th vertex * of the visited face's facet. * * @return The nearest points for all points of all the visited human faces' facets */ public Map<MeshFacet, List<Point3d>> getNearestPoints() { return distanceVisitor.getNearestPoints(); } /** * Returns priorities of points of the visited faces' mesh facets. * * Keys in the map contain mesh facets of the visited human faces. * For each facet of the visited human face, a list of priorities is stored. * The order of priorities corresponds to the order of vertices * in the visited facet, i.e., the i-th value is the priority of the i-th vertex * of the visited face's facet. * * @return Priorities of all points of all the visited human faces' facets */ public Map<MeshFacet, List<Double>> getPriorities() { return Collections.unmodifiableMap(priorities); } /** * Returns {@code true} if the distance was computed as relative * (with possibly negative values). * * @return {@code true} if the distance is computed as relative, {@code false} otherwise */ public boolean relativeDistance() { return distanceVisitor.relativeDistance(); } /** * Returns the strategy of the computation of distance. * * @return strategy of the computation of distance */ public Strategy getStrategy() { return distanceVisitor.getStrategy(); } /** * Returns {@code true} if the distance computation is parallel. * * @return {@code true} if the distance computation is parallel */ public boolean inParallel() { return distanceVisitor.inParallel(); } /** * Return the KD tree to which distances are computed. * * @return KD tree to which distances are computed */ public KdTree getMainKdTree() { return distanceVisitor.getMainKdTree(); } @Override public void visitHumanFace(HumanFace humanFace) { humanFace.getMeshModel().compute(distanceVisitor, inParallel()); final FeaturePoint featurePoint = humanFace.getFeaturePoints().get(featurePointType.getType()); final PrioritySphere priorityVisitor = new PrioritySphere(featurePoint.getPosition(), computeSphereRadius(humanFace)); humanFace.getMeshModel().compute(priorityVisitor, inParallel()); synchronized(this) { // Retrieve results from the visitor's internal structure priorities.putAll(priorityVisitor.getPriorities()); } } private double computeSphereRadius(HumanFace humanFace) { // TODO TEMPORARY // Sphere radius needs to be computed dynamically. // The best way to compute the right radius should be thought out in more depth. return 1; // TODO TEMPORARY } } Comparison/src/main/java/cz/fidentis/analyst/visitors/face/HumanFaceVisitor.java 0 → 100644 +42 −0 Original line number Diff line number Diff line package cz.fidentis.analyst.visitors.face; import cz.fidentis.analyst.face.HumanFace; /** * A functor. When instantiated, it can be gradually applied to multiple faces. * It inspects the state of the human face one by one, and (cumulatively) computes results. * <p> * Implement this interface whenever you want to define new algorithm over a human face. * </p> * <p> * If the visitor is thread-safe, then a single instance of the visitor * can visit concurrently (and asynchronously) multiple faces. Otherwise, * the parallel inspection is still possible, but a new instance of the visitor * has to be used for each human face. * </p> * * @author Daniel Schramm */ public abstract class HumanFaceVisitor { /** * Returns {@code true} if the implementation is thread-safe and then * <b>a single visitor instance</b> can be applied to multiple faces simultaneously. * <p> * Thread-safe implementation means that any read or write from/to the visitor's * state is protected by {@code synchronized}. * </p> * * @return {@code true} if the implementation is thread-safe. */ public boolean isThreadSafe() { return true; } /** * The main inspection method to be implemented by specific visitors. * * @param humanFace Face to be visited */ public abstract void visitHumanFace(HumanFace humanFace); } Comparison/src/main/java/cz/fidentis/analyst/visitors/face/package-info.java 0 → 100644 +5 −0 Original line number Diff line number Diff line /** * Visitors used to explore the human face (i.e., implementing the * {@link cz.fidentis.analyst.visitors.face.HumanFaceVisitor}). */ package cz.fidentis.analyst.visitors.face; No newline at end of file Loading
Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java +47 −1 Original line number Diff line number Diff line package cz.fidentis.analyst.face; import com.google.common.eventbus.EventBus; import cz.fidentis.analyst.feature.FeaturePoint; import cz.fidentis.analyst.feature.services.FeaturePointImportExportService; import cz.fidentis.analyst.kdtree.KdTree; import cz.fidentis.analyst.mesh.core.MeshFacet; import cz.fidentis.analyst.mesh.core.MeshModel; Loading @@ -8,6 +10,7 @@ import cz.fidentis.analyst.mesh.events.MeshEvent; import cz.fidentis.analyst.mesh.events.MeshListener; import cz.fidentis.analyst.mesh.io.MeshObjLoader; import cz.fidentis.analyst.symmetry.Plane; import cz.fidentis.analyst.visitors.face.HumanFaceVisitor; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; Loading @@ -18,6 +21,8 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Collections; import java.util.List; import java.util.ArrayList; import java.util.Objects; //import org.nustaq.serialization.FSTConfiguration; Loading Loading @@ -57,6 +62,8 @@ public class HumanFace implements MeshListener, Serializable { private MeshFacet cuttingPlane; private List<FeaturePoint> featurePoints; private final transient EventBus eventBus = new EventBus(); private final String id; Loading Loading @@ -134,7 +141,7 @@ public class HumanFace implements MeshListener, Serializable { /** * * @param plane The new symmetry plane * @param paneFacet The symmetry plane mesh * @param planeFacet The symmetry plane mesh */ public void setSymmetryPlane(Plane plane, MeshFacet planeFacet) { this.symmetryPlane = plane; Loading Loading @@ -169,6 +176,36 @@ public class HumanFace implements MeshListener, Serializable { return cuttingPlane; } /** * * @param points List of feature points */ public void setFeaturePoints(List<FeaturePoint> points) { featurePoints = points; } /** * Reads feature points from a file on the given path. * * @param path Directory where the file is located * @param fileName Name of the file * @throws IOException on I/O failure */ public void loadFeaturePoints(String path, String fileName) throws IOException { featurePoints = FeaturePointImportExportService.importFeaturePoints(path, fileName); } /** * * @return The face's feature points. */ public List<FeaturePoint> getFeaturePoints() { if (featurePoints == null) { return Collections.emptyList(); } return Collections.unmodifiableList(featurePoints); } /** * Returns unique ID of the face. * Loading Loading @@ -268,6 +305,15 @@ public class HumanFace implements MeshListener, Serializable { */ } /** * Visits this face. * * @param visitor Visitor */ public void accept(HumanFaceVisitor visitor) { visitor.visitHumanFace(this); } @Override public int hashCode() { int hash = 7; Loading
Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceFactory.java +3 −0 Original line number Diff line number Diff line Loading @@ -227,6 +227,9 @@ public class HumanFaceFactory { HumanFace face = inMemoryFaces.get(oldTime); long newTime = System.currentTimeMillis(); while (inMemoryFaces.containsKey(newTime)) { // wait until we get unique ms newTime = System.currentTimeMillis(); } inMemoryFaces.remove(oldTime); inMemoryFaces.put(newTime, face); usage.put(faceId, newTime); Loading
Comparison/src/main/java/cz/fidentis/analyst/visitors/face/HausdorffDistancePrioritized.java 0 → 100644 +242 −0 Original line number Diff line number Diff line package cz.fidentis.analyst.visitors.face; import cz.fidentis.analyst.face.HumanFace; import cz.fidentis.analyst.feature.FeaturePoint; import cz.fidentis.analyst.feature.FeaturePointType; import cz.fidentis.analyst.kdtree.KdTree; import cz.fidentis.analyst.mesh.core.MeshFacet; import cz.fidentis.analyst.mesh.core.MeshModel; import cz.fidentis.analyst.visitors.mesh.HausdorffDistance; import cz.fidentis.analyst.visitors.mesh.HausdorffDistance.Strategy; import cz.fidentis.analyst.visitors.mesh.PrioritySphere; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.vecmath.Point3d; /** * Visitor for prioritized Hausdorff distance. * This visitor is instantiated with a single k-d tree (either given as the input * parameter, or automatically created from the triangular mesh). * When applied to other human faces, it computes prioritized Hausdorff distance from their mesh facets * to the instantiated k-d tree. * <p> * This visitor is thread-safe, i.e., a single instance of the visitor can be used * to inspect multiple human faces simultaneously. * </p> * <p> * The distance is computed either as absolute or relative. Absolute * represents Euclidean distance (all numbers are positive). On the contrary, * relative distance considers orientation of the visited face's facets (determined by its normal vectors) * and produces positive or negative distances depending on whether the primary * mesh is "in front of" or "behind" the given vertex. * </p> * * @author Daniel Schramm */ public class HausdorffDistancePrioritized extends HumanFaceVisitor { private final HausdorffDistance distanceVisitor; private final FeaturePointType featurePointType; private final Map<MeshFacet, List<Double>> priorities = new HashMap<>(); /** * Constructor. * * @param mainFacets Facets to which distance from the visited human face's facets is to be computed. * Must not be {@code null}. * @param featurePoint Feature point according to which the Hausdorff distances will be prioritized * @param strategy Strategy of the computation of distance * @param relativeDistance If {@code 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 {@code true}, then the algorithm runs concurrently utilizing all CPU cores * @throws IllegalArgumentException if some parameter is wrong */ public HausdorffDistancePrioritized(Set<MeshFacet> mainFacets, FeaturePointType featurePoint, Strategy strategy, boolean relativeDistance, boolean parallel) { distanceVisitor = new HausdorffDistance(mainFacets, strategy, relativeDistance, parallel); featurePointType = featurePoint; } /** * Constructor. * * @param mainFacet Primary facet to which distance from the visited human face's facets is to be computed. Must not be {@code null}. * @param featurePoint Feature point according to which the Hausdorff distances will be prioritized * @param strategy Strategy of the computation of distance * @param relativeDistance If {@code 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 {@code true}, then the algorithm runs concurrently utilizing all CPU cores * @throws IllegalArgumentException if some parameter is wrong */ public HausdorffDistancePrioritized(MeshFacet mainFacet, FeaturePointType featurePoint, Strategy strategy, boolean relativeDistance, boolean parallel) { this(new HashSet<>(Collections.singleton(mainFacet)), featurePoint, strategy, relativeDistance, parallel); } /** * Constructor. * * @param mainModel The mesh model with primary facets to which distance from the visited human face's facets is to be computed. * Must not be {@code null} or empty. * @param featurePoint Feature point according to which the Hausdorff distances will be prioritized * @param strategy Strategy of the computation of distance * @param relativeDistance If {@code 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 {@code true}, then the algorithm runs concurrently utilizing all CPU cores * @throws IllegalArgumentException if some parameter is wrong */ public HausdorffDistancePrioritized(MeshModel mainModel, FeaturePointType featurePoint, Strategy strategy, boolean relativeDistance, boolean parallel) { this(new HashSet<>(mainModel.getFacets()), featurePoint, strategy, relativeDistance, parallel); } /** * Constructor. * * @param face Human face to which distance from other human faces is to be computed. Must not be {@code null}. * @param featurePoint Feature point according to which the Hausdorff distances will be prioritized * @param strategy Strategy of the computation of distance * @param relativeDistance If {@code 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 {@code true}, then the algorithm runs concurrently utilizing all CPU cores * @throws IllegalArgumentException if some parameter is wrong */ public HausdorffDistancePrioritized(HumanFace face, FeaturePointType featurePoint, Strategy strategy, boolean relativeDistance, boolean parallel) { this(face.getMeshModel(), featurePoint, strategy, relativeDistance, parallel); } /** * Constructor. * * @param mainKdTree The KD tree to which distance from the visited human face's facets is to be computed. * Must not be {@code null}. * @param featurePoint Feature point according to which the Hausdorff distances will be prioritized * @param strategy Strategy of the computation of distance * @param relativeDistance If {@code 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 {@code true}, then the algorithm runs concurrently utilizing all CPU cores * @throws IllegalArgumentException if some parameter is wrong */ public HausdorffDistancePrioritized(KdTree mainKdTree, FeaturePointType featurePoint, Strategy strategy, boolean relativeDistance, boolean parallel) { distanceVisitor = new HausdorffDistance(mainKdTree, strategy, relativeDistance, parallel); featurePointType = featurePoint; } public FeaturePointType getFeaturePointType() { return featurePointType; } /** * Returns Hausdorff distance of the visited faces' mesh facets to the source mesh facets. * * Keys in the map contain mesh facets that were measured with the * source facets. * For each facet of the visited human face, a list of distances to the source * facets is stored. The order of distances corresponds to the order of vertices * in the measured facet, i.e., the i-th value is the distance of the i-th vertex * of the visited face's facet. * * @return Hausdorff distance for all points of all the visited human faces' facets */ public Map<MeshFacet, List<Double>> getDistances() { return distanceVisitor.getDistances(); } /** * Returns the nearest points of the visited faces' mesh facets to the source mesh facets. * * Keys in the map contain mesh facets that were measured with the * source facets. * For each facet of the visited human face, a list of the nearest points to the source * facets is stored. The order of points corresponds to the order of vertices * in the measured facet, i.e., the i-th point is the nearest point of the i-th vertex * of the visited face's facet. * * @return The nearest points for all points of all the visited human faces' facets */ public Map<MeshFacet, List<Point3d>> getNearestPoints() { return distanceVisitor.getNearestPoints(); } /** * Returns priorities of points of the visited faces' mesh facets. * * Keys in the map contain mesh facets of the visited human faces. * For each facet of the visited human face, a list of priorities is stored. * The order of priorities corresponds to the order of vertices * in the visited facet, i.e., the i-th value is the priority of the i-th vertex * of the visited face's facet. * * @return Priorities of all points of all the visited human faces' facets */ public Map<MeshFacet, List<Double>> getPriorities() { return Collections.unmodifiableMap(priorities); } /** * Returns {@code true} if the distance was computed as relative * (with possibly negative values). * * @return {@code true} if the distance is computed as relative, {@code false} otherwise */ public boolean relativeDistance() { return distanceVisitor.relativeDistance(); } /** * Returns the strategy of the computation of distance. * * @return strategy of the computation of distance */ public Strategy getStrategy() { return distanceVisitor.getStrategy(); } /** * Returns {@code true} if the distance computation is parallel. * * @return {@code true} if the distance computation is parallel */ public boolean inParallel() { return distanceVisitor.inParallel(); } /** * Return the KD tree to which distances are computed. * * @return KD tree to which distances are computed */ public KdTree getMainKdTree() { return distanceVisitor.getMainKdTree(); } @Override public void visitHumanFace(HumanFace humanFace) { humanFace.getMeshModel().compute(distanceVisitor, inParallel()); final FeaturePoint featurePoint = humanFace.getFeaturePoints().get(featurePointType.getType()); final PrioritySphere priorityVisitor = new PrioritySphere(featurePoint.getPosition(), computeSphereRadius(humanFace)); humanFace.getMeshModel().compute(priorityVisitor, inParallel()); synchronized(this) { // Retrieve results from the visitor's internal structure priorities.putAll(priorityVisitor.getPriorities()); } } private double computeSphereRadius(HumanFace humanFace) { // TODO TEMPORARY // Sphere radius needs to be computed dynamically. // The best way to compute the right radius should be thought out in more depth. return 1; // TODO TEMPORARY } }
Comparison/src/main/java/cz/fidentis/analyst/visitors/face/HumanFaceVisitor.java 0 → 100644 +42 −0 Original line number Diff line number Diff line package cz.fidentis.analyst.visitors.face; import cz.fidentis.analyst.face.HumanFace; /** * A functor. When instantiated, it can be gradually applied to multiple faces. * It inspects the state of the human face one by one, and (cumulatively) computes results. * <p> * Implement this interface whenever you want to define new algorithm over a human face. * </p> * <p> * If the visitor is thread-safe, then a single instance of the visitor * can visit concurrently (and asynchronously) multiple faces. Otherwise, * the parallel inspection is still possible, but a new instance of the visitor * has to be used for each human face. * </p> * * @author Daniel Schramm */ public abstract class HumanFaceVisitor { /** * Returns {@code true} if the implementation is thread-safe and then * <b>a single visitor instance</b> can be applied to multiple faces simultaneously. * <p> * Thread-safe implementation means that any read or write from/to the visitor's * state is protected by {@code synchronized}. * </p> * * @return {@code true} if the implementation is thread-safe. */ public boolean isThreadSafe() { return true; } /** * The main inspection method to be implemented by specific visitors. * * @param humanFace Face to be visited */ public abstract void visitHumanFace(HumanFace humanFace); }
Comparison/src/main/java/cz/fidentis/analyst/visitors/face/package-info.java 0 → 100644 +5 −0 Original line number Diff line number Diff line /** * Visitors used to explore the human face (i.e., implementing the * {@link cz.fidentis.analyst.visitors.face.HumanFaceVisitor}). */ package cz.fidentis.analyst.visitors.face; No newline at end of file