Commit 97d5bd26 authored by Daniel Schramm's avatar Daniel Schramm
Browse files

HausdorffDistancePrioritized javadoc added

parent 3499640a
Loading
Loading
Loading
Loading
+143 −6
Original line number Diff line number Diff line
@@ -20,6 +20,22 @@ import java.util.concurrent.Executors;
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 computer 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
 */
@@ -31,23 +47,86 @@ public class HausdorffDistancePrioritized extends HumanFaceVisitor {
    
    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;
@@ -57,30 +136,86 @@ public class HausdorffDistancePrioritized extends HumanFaceVisitor {
        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();
    }
@@ -93,25 +228,27 @@ public class HausdorffDistancePrioritized extends HumanFaceVisitor {
        final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        
        final PrioritySphere priorityVisitor = new PrioritySphere(featurePoint.getPosition(), 1 /*TODO TEMPORARY - sphere radius needs to be computed dynamically*/);
        for (final MeshFacet comparedFacet: facets) {
        for (final MeshFacet comparedFacet: facets) {  // For each mesh facet of the visited human face
            if (inParallel() && distanceVisitor.isThreadSafe()) {
                executor.execute(() -> comparedFacet.accept(distanceVisitor));
                executor.execute(() -> comparedFacet.accept(distanceVisitor)); // Fork and continue
            } else {
                comparedFacet.accept(distanceVisitor);
                comparedFacet.accept(distanceVisitor); // Process immediately
            }
            if (inParallel() && priorityVisitor.isThreadSafe()) {
                executor.execute(() -> comparedFacet.accept(priorityVisitor));
                executor.execute(() -> comparedFacet.accept(priorityVisitor)); // Fork and continue
            } else {
                comparedFacet.accept(priorityVisitor);
                comparedFacet.accept(priorityVisitor); // Proces immediately
            }
            // Visitors store results into their internal structure
        }
        
        if (inParallel()) {
            executor.shutdown();
            while (!executor.isTerminated()){}
            while (!executor.isTerminated()){} // Wait until all computations are finished
        }
        
        synchronized(this) {
            // Retrieve results from the visitor's internal structure
            priorities.putAll(priorityVisitor.getPriorities());
        }
    }