From bca74096bb0b5351d9087487e2eddb8fc9fd7762 Mon Sep 17 00:00:00 2001
From: Radek Oslejsek <oslejsek@fi.muni.cz>
Date: Tue, 16 Mar 2021 18:25:13 +0100
Subject: [PATCH] Added DistanceMeshVisitor

---
 .../kdtree/ClosestNodeMultipleVisitor.java    |   2 +-
 .../kdtree/DistanceKdTreeVisitor.java         |   2 +-
 .../kdtree/DistanceToKdTrianglesApprox.java   |   3 +-
 .../visitors/kdtree/DistanceToKdVertices.java |   3 +-
 .../visitors/mesh/DistanceMeshVisitor.java    | 172 ++++++++++++++++++
 .../analyst/kdtree/KdTreeVisitor.java         |   4 +-
 .../cz/fidentis/analyst/mesh/MeshVisitor.java |  10 +
 7 files changed, 190 insertions(+), 6 deletions(-)
 create mode 100644 Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/DistanceMeshVisitor.java

diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/ClosestNodeMultipleVisitor.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/ClosestNodeMultipleVisitor.java
index 99020c3c..f33514d3 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/ClosestNodeMultipleVisitor.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/ClosestNodeMultipleVisitor.java
@@ -74,7 +74,7 @@ public class ClosestNodeMultipleVisitor extends KdTreeVisitor {
     
     
     @Override
-    public Object clone() {
+    public KdTreeVisitor clone() {
         return new ClosestNodeMultipleVisitor(myPoint, concurrently());
     }
 
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/DistanceKdTreeVisitor.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/DistanceKdTreeVisitor.java
index df361129..f700ef61 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/DistanceKdTreeVisitor.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/DistanceKdTreeVisitor.java
@@ -109,7 +109,7 @@ public abstract class DistanceKdTreeVisitor extends KdTreeVisitor implements Nea
     }
 
     @Override
-    public abstract Object clone();
+    public abstract KdTreeVisitor clone();
     
     
     
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/DistanceToKdTrianglesApprox.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/DistanceToKdTrianglesApprox.java
index 197f2b26..83af0ffd 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/DistanceToKdTrianglesApprox.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/DistanceToKdTrianglesApprox.java
@@ -1,6 +1,7 @@
 package cz.fidentis.analyst.visitors.kdtree;
 
 import cz.fidentis.analyst.kdtree.KdTree;
+import cz.fidentis.analyst.kdtree.KdTreeVisitor;
 import cz.fidentis.analyst.mesh.core.MeshFacet;
 import cz.fidentis.analyst.mesh.core.MeshPoint;
 import cz.fidentis.analyst.mesh.core.MeshPointImpl;
@@ -80,7 +81,7 @@ public class DistanceToKdTrianglesApprox extends DistanceKdTreeVisitor implement
     }
     
     @Override
-    public Object clone() {
+    public KdTreeVisitor clone() {
         return new DistanceToKdTrianglesApprox(this);
     }
     
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/DistanceToKdVertices.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/DistanceToKdVertices.java
index 83473feb..8d237f87 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/DistanceToKdVertices.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/DistanceToKdVertices.java
@@ -2,6 +2,7 @@ package cz.fidentis.analyst.visitors.kdtree;
 
 import cz.fidentis.analyst.kdtree.KdNode;
 import cz.fidentis.analyst.kdtree.KdTree;
+import cz.fidentis.analyst.kdtree.KdTreeVisitor;
 import cz.fidentis.analyst.mesh.core.MeshPoint;
 import cz.fidentis.analyst.mesh.core.MeshPointImpl;
 import java.util.ArrayList;
@@ -65,7 +66,7 @@ public class DistanceToKdVertices extends DistanceKdTreeVisitor implements Neare
     }
 
     @Override
-    public Object clone() {
+    public KdTreeVisitor clone() {
         return new DistanceToKdVertices(this);
     }
 
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/DistanceMeshVisitor.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/DistanceMeshVisitor.java
new file mode 100644
index 00000000..68db884e
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/DistanceMeshVisitor.java
@@ -0,0 +1,172 @@
+package cz.fidentis.analyst.visitors.mesh;
+
+import cz.fidentis.analyst.mesh.MeshVisitor;
+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.visitors.NearestMeshFacets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import javax.vecmath.Vector3d;
+
+/**
+ * A functor. When instantiated, it can be gradually applied to multiple mesh facets.
+ * It inspects the state of triangular meshes one by one, and (cumulatevely) computes results.
+ * <p>
+ * Implement this interface whenever you want to define new algorithm over a {@link MeshFacet}.
+ * </p>
+ * <p>
+ * The visitor can be instatiated either as sequential and concurrent. 
+ * The {@link cz.fidentis.analyst.mesh.MeshVisitor#visit} inspection method
+ * of a sequential visitor is applied immediately. On the contrary, if the
+ * visitor is concurrent and thread-safe, then the method only stores the inpected
+ * mesh for later concurrent inspection. To trigger the mesh inspection,
+ * a {@link java.util.concurrent.ExecutorService} has to be used calling
+ * the {@link cz.fidentis.analyst.mesh.MeshVisitor#call} method asynchronously
+ * and then waiting for the results of all triggered visitors. 
+ * </p>
+ * <p>
+ * All visitors have to be cloneable. A returned clone represents a visitor in 
+ * the initial state, i.e., only the configuration options provided to the constructor 
+ * are cloned while the computation state is set to initial values.
+ * </p>
+ * 
+ * @author Radek Oslejsek
+ */
+public abstract class DistanceMeshVisitor extends MeshVisitor implements NearestMeshFacets {
+    
+    private final boolean relativeDist;
+    
+    /**
+     * A 3D point in space from which the distance is measured.
+     */
+    private final MeshPoint point3d;
+    
+    private int sign = 1;
+    
+    /**
+     * The minimum distance found so far.
+     */
+    private double distance = Double.POSITIVE_INFINITY;
+    
+    /**
+     * Mesh facets lying at the minimal distance
+     */
+    private List<MeshFacet> closestFacets = new ArrayList<>();
+
+    /**
+     * Constructor.
+     * 
+     * @param point A 3D point from which the distance is computed. Must not be {@code null}
+     * @param relativeDistance If {@true}, the visitor calculates the distances with respect 
+     * to the normals of the 3D point (the normal has to be present), 
+     * i.e., we can get negative distance.
+     * @param concurrently If {@code true} and this visitor is thread-safe, then
+     * the visitor is applied concurrently on multiple KD trees.
+     * @throws IllegalArgumentException if some parametr is wrong
+     */
+    public DistanceMeshVisitor(MeshPoint point, boolean relativeDistance, boolean concurrently) {
+        super(concurrently);
+        if (point == null) {
+            throw new IllegalArgumentException("point");
+        }
+        if (point.getNormal() == null && relativeDistance) {
+            throw new IllegalArgumentException("normal required for relative distance");
+        }
+        this.point3d = point;
+        this.relativeDist = relativeDistance;
+    }
+    
+    /**
+     * Constructor.
+     * 
+     * @param point A 3D point from which distance is computed. Must not be {@code null}
+     * @param concurrently If {@code true} and this visitor is thread-safe, then
+     * the visitor is applied concurrently on multiple KD trees.
+     * @throws IllegalArgumentException if some parametr is wrong
+     */
+    public DistanceMeshVisitor(Vector3d point, boolean concurrently) {
+        this (new MeshPointImpl(point, null, null), false, concurrently);
+    }
+    
+    /**
+     * Copy constructor.
+     * 
+     * @param vis source visitor to be coppied
+     * @throws NullPointerException if the input parameter is {@code null}
+     */
+    protected DistanceMeshVisitor(DistanceMeshVisitor vis) {
+        super(vis);
+        this.point3d = vis.point3d;
+        this.relativeDist = vis.relativeDist;
+    }
+    
+    
+    @Override
+    public double getDistance() {
+        return relativeDist ? sign * distance : distance;
+    }
+
+    @Override
+    public boolean relativeDistance() {
+        return relativeDist;
+    }
+
+    @Override
+    public List<MeshFacet> getClosestFacets() {
+        return Collections.unmodifiableList(closestFacets);
+    }
+
+    @Override
+    public abstract MeshVisitor clone();
+    
+    
+    
+    
+    protected MeshPoint getPoint3d() {
+        return point3d;
+    }
+    
+    /**
+     * @return -1 if the distance is migger (no update), 0 the same , 1 smaller
+     */
+    protected synchronized int checkAndUpdateFacets(double dist, int sign, Collection<MeshFacet> facets) {
+        if (dist > distance) {
+            return -1;
+        }
+        
+        if (dist < distance) {
+            distance = dist;
+            this.sign = sign;
+            closestFacets.clear();
+            closestFacets.addAll(facets);
+            return 1;
+        } else { // the same distance
+            closestFacets.addAll(facets);
+            return 0;
+        }
+    }
+    
+    /**
+     * @return -1 if the distance is migger (no update), 0 the same , 1 smaller
+     */
+    protected synchronized int checkAndUpdateFacet(double dist, int sign, MeshFacet facet) {
+        if (dist > distance) {
+            return -1;
+        }
+        
+        if (dist < distance) {
+            distance = dist;
+            this.sign = sign;
+            closestFacets.clear();
+            closestFacets.add(facet);
+            return 1;
+        } else { // the same distance
+            closestFacets.add(facet);
+            return 0;
+        }
+    }
+    
+}
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTreeVisitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTreeVisitor.java
index 12d2308c..26a6ecd8 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTreeVisitor.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTreeVisitor.java
@@ -15,7 +15,7 @@ import java.util.concurrent.Callable;
  * visitor is concurrent and thread-safe, then the method only stores the inpected
  * k-d tree for later concurrent inspection. To trigger the tree inspection,
  * a {@link java.util.concurrent.ExecutorService} has to be used calling
- * the {@link cz.fidentis.analyst.mesh.mesh.MeshVisitor#call} method asynchronously
+ * the {@link cz.fidentis.analyst.kdtree.KdTreeVisitor#call} method asynchronously
  * and then waiting for the results of all triggered visitors. 
  * </p>
  * <p>
@@ -124,5 +124,5 @@ public abstract class KdTreeVisitor implements Callable<KdTreeVisitor>, Cloneabl
      * @return a copy of this visitor
      */
     @Override
-    public abstract Object clone();
+    public abstract KdTreeVisitor clone();
 }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/MeshVisitor.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/MeshVisitor.java
index 11ac8a47..88c6a15e 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/MeshVisitor.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/MeshVisitor.java
@@ -52,6 +52,16 @@ public abstract class MeshVisitor implements Callable<MeshVisitor>, Cloneable {
         this.concurrently = concurrently;
     }
     
+    /**
+     * Copy constructor.
+     * 
+     * @param vis source visitor to be coppied
+     * @throws NullPointerException if the input parameter is {@code null}
+     */
+    protected MeshVisitor(MeshVisitor vis) {
+        concurrently = vis.concurrently;
+    }
+    
     /**
      * Returns {@code true} if the implementation is thread-safe and then
      * <b>a single visitor instance</b> can be applied to multiple mesh facets simultaneously.
-- 
GitLab