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