From 709115a80966d4bad3f0183b00786204133f3455 Mon Sep 17 00:00:00 2001
From: Maria Kocurekova <xkocure1@fi.muni.cz>
Date: Fri, 9 Apr 2021 13:38:54 +0200
Subject: [PATCH] #36 - method getTransformedFacet

---
 .../java/cz/fidentis/analyst/icp/Icp.java     | 64 ++++++++++++-------
 1 file changed, 40 insertions(+), 24 deletions(-)

diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/Icp.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/Icp.java
index 1ae79eec..c5c860ec 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/icp/Icp.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/Icp.java
@@ -1,6 +1,7 @@
 package cz.fidentis.analyst.icp;
 
 import cz.fidentis.analyst.mesh.core.MeshFacet;
+import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
 import cz.fidentis.analyst.mesh.core.MeshPoint;
 import cz.fidentis.analyst.visitors.mesh.HausdorffDistance;
 
@@ -16,29 +17,47 @@ import java.util.Objects;
 /**
  * Icp represents class for computing the ICP (Iterative closest point) algorithm.
  * It is used to minimize the distance between two {@link cz.fidentis.analyst.mesh.core.MeshFacet}s.
- * This class does not have parameterized constructor, for running ICP algorithm use public method initIcp.
+ * This class does not have parameterized constructor, for running ICP algorithm use public method getTransformedFacet.
+ * (In case you want change default setup use public method setParameters.)
  *
  * @author Maria Kocurekova
  */
 public class Icp {
 
     private final List<IcpTransformation> transformations = new LinkedList<>();
+    private MeshFacet transformedFacet = null;
+    private  int maxIteration = 10;
+    private boolean scale;
+    private double error = 0.05;
+
 
     /**
-     * InitIcp represents running of the ICP algorithm. It use methods for computing and applying transformations.
+     * Change default setup for max count of iteration, scale and error.
+     *
+     * @param maxIteration Max count of running iterations
+     *                     (it includes computing new transformation and applying it).
+     * @param scale In case there is scale, scale factor is also computed.
+     * @param e Max error which is allowed.
+     */
+    public void setParameters(int maxIteration, boolean scale, double e){
+        this.maxIteration = maxIteration;
+        this.scale = scale;
+        this.error = e;
+    }
+
+    /**
+     * GetTransformedFacet represents running of the ICP algorithm. It use methods for computing and applying transformations.
      * It is running until count of iterations is lower than maxIteration or until we reach lower distance
      * between two objects than allowed error.
      *
      * @param mainFacet MainFacet represents fix faced.
      *                  We want to align computedFacet according to MainFacet.
      * @param comparedFacet Facet we want to be aligned.
-     * @param maxIteration Max count of running iterations
-     *                     (it includes computing new transformation and applying it).
-     * @param scale In case there is scale, scale factor is also computed.
-     * @param e Max error which is allowed.
-     * @return Return comparedFacet with new coordinates.
+     * @return Return transformed facet with new coordinates.
      */
-    public MeshFacet initIcp(MeshFacet mainFacet, MeshFacet comparedFacet, int maxIteration, boolean scale, double e){
+    public MeshFacet getTransformedFacet(MeshFacet mainFacet, MeshFacet comparedFacet){
+        transformedFacet = new MeshFacetImpl(comparedFacet);
+
         HausdorffDistance hausdorffDist = new HausdorffDistance(mainFacet, HausdorffDistance.Strategy.POINT_TO_POINT, false, false);
 
         int currentIteration = 0;
@@ -47,23 +66,23 @@ public class Icp {
         double prevMeanD = Double.POSITIVE_INFINITY;
 
         while ((currentIteration < maxIteration) &&
-                (Double.isInfinite(prevMeanD) ||  Math.abs(prevMeanD - Objects.requireNonNull(transformation).getMeanD() ) > e )){
+                (Double.isInfinite(prevMeanD) ||  Math.abs(prevMeanD - Objects.requireNonNull(transformation).getMeanD() ) > error )){
 
-            hausdorffDist.visitMeshFacet(comparedFacet);
-            List<Double> distances = hausdorffDist.getDistances().get(comparedFacet);
-            List<Vector3d> nearestPoints = hausdorffDist.getNearestPoints().get(comparedFacet);
+            hausdorffDist.visitMeshFacet(transformedFacet);
+            List<Double> distances = hausdorffDist.getDistances().get(transformedFacet);
+            List<Vector3d> nearestPoints = hausdorffDist.getNearestPoints().get(transformedFacet);
 
             if(transformation != null){
                 prevMeanD = transformation.getMeanD();
             }
 
-            transformation = computeIcpTransformation(nearestPoints, distances, comparedFacet.getVertices(),scale);
+            transformation = computeIcpTransformation(nearestPoints, distances);
             transformations.add(transformation);
-            applyTransformation(comparedFacet.getVertices(), transformation, scale);
+            applyTransformation(transformation);
             currentIteration ++;
         }
 
-        return comparedFacet;
+        return transformedFacet;
     }
     
     /**
@@ -75,6 +94,7 @@ public class Icp {
         return Collections.unmodifiableList(transformations);
     }
 
+
     /***********************************************************
      *  PRIVATE METHODS
      ***********************************************************/
@@ -84,12 +104,10 @@ public class Icp {
      *
      * @param nearestPoints List of nearest points computed by Hausdorff distance.
      * @param distances list of distances computed by Hausdorff distance
-     * @param comparedPoints List of points of compared facet.
-     *                       List of points which transformation we are compute according list of nearest points.
-     * @param scale In case there is scale, scale factor is also computed.
      * @return Return Icp transformation which is represented by computed parameters.
      */
-    private IcpTransformation computeIcpTransformation(List<Vector3d> nearestPoints, List<Double> distances, List<MeshPoint>comparedPoints, boolean scale) {
+    private IcpTransformation computeIcpTransformation(List<Vector3d> nearestPoints, List<Double> distances) {
+        List<MeshPoint>comparedPoints = transformedFacet.getVertices();
         double x, y, z;
         double meanX = 0;
         double meanY = 0;
@@ -174,22 +192,20 @@ public class Icp {
     /**
      * Apply computed transformation to compared facet.
      *
-     * @param comparedPoints List of points on which we want to apply transformation.
      * @param transformation Computed transformation.
-     * @param scale In case there is a scale we use scale factor for computing new coordinate of point.
      */
-    private void applyTransformation(List<MeshPoint> comparedPoints, IcpTransformation transformation, boolean scale) {
+    private void applyTransformation(IcpTransformation transformation) {
         Vector3d meshPointPosition;
         Quat4d rotationCopy = new Quat4d();
         Quat4d conjugateRotation = new Quat4d();
 
 
-        for (MeshPoint comparedPoint : comparedPoints) {
+        for (MeshPoint comparedPoint : transformedFacet.getVertices()) {
             meshPointPosition = comparedPoint.getPosition();
 
             Quat4d point = new Quat4d(meshPointPosition.x, meshPointPosition.y, meshPointPosition.z, 1);
 
-            if (comparedPoints.size() > 1) {
+            if (transformedFacet.getVertices().size() > 1) {
                 conjugateRotation.conjugate(transformation.getRotation());
                 rotationCopy.mul(point, conjugateRotation);
                 rotationCopy.mul(transformation.getRotation(), rotationCopy);
-- 
GitLab