Commit 88f873d8 authored by Radek Ošlejšek's avatar Radek Ošlejšek
Browse files

Merge branch '292-refactor-meshalgorithms' into 'master'

Resolve "Refactor MeshAlgorithms"

Closes #292

See merge request grp-fidentis/analyst2!317
parents 578d4146 8efeba7f
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -120,6 +120,11 @@
            <artifactId>MeshAlgorithms</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>LandmarksAlgorithms</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.vecmath</groupId>
            <artifactId>vecmath</artifactId>
+6 −5
Original line number Diff line number Diff line
package cz.fidentis.analyst.gui.app.tools;

import cz.fidentis.analyst.avgmesh.AvgMeshConstructorOctree;
import cz.fidentis.analyst.avgmesh.AvgMeshConfig;
import cz.fidentis.analyst.avgmesh.AvgMeshVisitor;
import cz.fidentis.analyst.face.HumanFace;
import cz.fidentis.analyst.face.HumanFaceFactory;
import cz.fidentis.analyst.gui.task.batch.Stopwatch;
import cz.fidentis.analyst.mesh.MeshIO;
import cz.fidentis.analyst.registration.RegistrationUtils;
import cz.fidentis.analyst.sampling.RandomSampling;
import cz.fidentis.analyst.sampling.PointSamplingConfig;

import java.io.File;
import java.io.IOException;
@@ -65,7 +66,7 @@ public class BatchOctreeTestsMultipleFaces {
        HumanFace initFace = factory.getFace(initFaceId);
        LOAD_TIME.stop();

        AvgMeshConstructorOctree avgFaceConstructorOctree = null;
        AvgMeshVisitor avgFaceConstructorOctree = null;

        for (int i = 0; i < faces.size(); i++) {

@@ -85,7 +86,7 @@ public class BatchOctreeTestsMultipleFaces {
                            100, // max iterations
                            false,
                            0.3, // error
                            new RandomSampling(undersampling),
                            new PointSamplingConfig(PointSamplingConfig.Method.RANDOM, undersampling),
                            false, // drop k-d tree, if exists
                            1 // crop partially overlaid parts since the second iteration
                    );
@@ -99,7 +100,7 @@ public class BatchOctreeTestsMultipleFaces {

                    AVG_FACE_COMPUTATION_TIME.start();
                    if (avgFaceConstructorOctree == null) {
                        avgFaceConstructorOctree = new AvgMeshConstructorOctree(initFace.getMeshModel(), false);
                        avgFaceConstructorOctree = (new AvgMeshConfig(initFace.getMeshModel())).getRayCastingVisitor();
                    }
                    face.getOctree().accept(avgFaceConstructorOctree);
                    AVG_FACE_COMPUTATION_TIME.stop();
+3 −2
Original line number Diff line number Diff line
package cz.fidentis.analyst.gui.app.tools;

import cz.fidentis.analyst.avgmesh.AvgMeshConstructorOctree;
import cz.fidentis.analyst.avgmesh.AvgMeshConfig;
import cz.fidentis.analyst.avgmesh.AvgMeshVisitor;
import cz.fidentis.analyst.face.HumanFace;
import cz.fidentis.analyst.face.HumanFaceFactory;
import cz.fidentis.analyst.gui.task.batch.Stopwatch;
@@ -80,7 +81,7 @@ public class BatchOctreeTestsTwoFaces {
        OCTREE_CONSTRUCTION_TIME.stop();

        AVG_FACE_COMPUTATION_TIME.start();
        AvgMeshConstructorOctree avgFaceConstructorOctree = new AvgMeshConstructorOctree(mainFace.getMeshModel(), false);
        AvgMeshVisitor avgFaceConstructorOctree = (new AvgMeshConfig(mainFace.getMeshModel())).getRayCastingVisitor();
        avgFaceConstructorOctree.visitOctree(secondFace.getOctree());
        AVG_FACE_COMPUTATION_TIME.stop();

+19 −21
Original line number Diff line number Diff line
package cz.fidentis.analyst.gui.app.tools;

import cz.fidentis.analyst.distance.MeshDistanceServices;
import cz.fidentis.analyst.distance.MeshDistanceConfig;
import cz.fidentis.analyst.face.HumanFace;
import cz.fidentis.analyst.registration.RegistrationUtils;
import cz.fidentis.analyst.distance.surface2surface.MeshDistanceNN;
import cz.fidentis.analyst.sampling.NoSampling;
import cz.fidentis.analyst.sampling.PointSamplingConfig;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
@@ -140,7 +142,7 @@ public class BatchSimilarityGroundTruth {
                100, // max iterations
                false,// scale
                0.05, // error
                new NoSampling(), // no undersampling
                new PointSamplingConfig(PointSamplingConfig.Method.NO_SAMPLING, 0),
                false, // drop k-d tree, if exists
                CROP_ICP // crop partially overlaid parts
        );
@@ -150,26 +152,22 @@ public class BatchSimilarityGroundTruth {

        //long hdTime = System.currentTimeMillis();
        // compute HD from secondary to primary:
        MeshDistanceNN hd = new MeshDistanceNN(
        distances[j][i] = MeshDistanceServices.measure(
                trFace.getMeshModel(),
                new MeshDistanceConfig(
                        MeshDistanceConfig.Method.POINT_TO_POINT_NEAREST_NEIGHBORS,
                        priFace.getKdTree(),
                MeshDistanceNN.Strategy.POINT_TO_TRIANGLE_APPROXIMATE,
                false, // relative distance
                true, // parallel
                CROP_DIST_MEASUREMENT // crop
        );
        trFace.getMeshModel().compute(hd);
        distances[j][i] = hd.getDistancesOfVisitedFacets().getDistanceStats().getAverage();
                        false,
                        CROP_DIST_MEASUREMENT)).getDistanceStats().getAverage();

        // compute HD from primary to secondary:
        hd = new MeshDistanceNN(
        distances[i][j] = MeshDistanceServices.measure(
                priFace.getMeshModel(),
                new MeshDistanceConfig(
                        MeshDistanceConfig.Method.POINT_TO_POINT_NEAREST_NEIGHBORS,
                        trFace.getKdTree(),
                MeshDistanceNN.Strategy.POINT_TO_TRIANGLE_APPROXIMATE,
                false, // relative distance
                true, // parallel
                CROP_DIST_MEASUREMENT // crop
        );
        priFace.getMeshModel().compute(hd);
        distances[i][j] = hd.getDistancesOfVisitedFacets().getDistanceStats().getAverage();
                        false,
                        CROP_DIST_MEASUREMENT)).getDistanceStats().getAverage();

        //hdComputationTime += System.currentTimeMillis() - hdTime;
    }
+17 −52
Original line number Diff line number Diff line
package cz.fidentis.analyst.gui.app.tools;

import cz.fidentis.analyst.distance.surface2surface.MeshDistanceNN;
import cz.fidentis.analyst.distance.MeshDistanceServices;
import cz.fidentis.analyst.distance.MeshDistanceConfig;
import cz.fidentis.analyst.face.HumanFace;
import cz.fidentis.analyst.gui.task.batch.Stopwatch;
import cz.fidentis.analyst.mesh.MeshFacet;
import cz.fidentis.analyst.mesh.MeshFactory;
import cz.fidentis.analyst.mesh.MeshModel;
import cz.fidentis.analyst.mesh.MeshTriangle;
import cz.fidentis.analyst.registration.RegistrationUtils;
import cz.fidentis.analyst.sampling.*;
import cz.fidentis.analyst.sampling.PointSamplingConfig;

import java.io.File;
import java.io.IOException;
@@ -16,8 +15,6 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;

import static cz.fidentis.analyst.distance.surface2surface.MeshDistanceNN.Strategy.POINT_TO_TRIANGLE_APPROXIMATE;

/**
 * This class evaluates efficiency (time) and precision of the ICP registration if different
 * sub-sampling algorithms with different strength are used.
@@ -33,7 +30,7 @@ public class IcpDownsampling {
    /**
     * Sub-sampling strategy
     */
    private static final Strategy STRATEGY = Strategy.POISSON;
    private static final PointSamplingConfig.Method STRATEGY = PointSamplingConfig.Method.POISSON;

    /**
     * Surface smoothing strategy for the Poisson disk sampling
@@ -72,19 +69,10 @@ public class IcpDownsampling {
    private static final boolean REGISTRATION_SCALE = false;
    private static final int REGISTRATION_IGNORE_PARTIALLY_OVERLAID_PARTS = 1;

    private static final MeshDistanceNN.Strategy SIMILARITY_STRATEGY = POINT_TO_TRIANGLE_APPROXIMATE;
    private static final MeshDistanceConfig.Method SIMILARITY_STRATEGY = MeshDistanceConfig.Method.POINT_TO_POINT_NEAREST_NEIGHBORS;
    private static final boolean SIMILARITY_RELATIVE_DISTANCE = false;
    private static final boolean SIMILARITY_AUTO_CROP = true;

    /**
     * Sub-sampling strategies.
     *
     * @author Radek Oslejsek
     */
    private enum Strategy {
        RANDOM, GAUSSIAN, UNIFORM_SPACE, UNIFORM_MESH, POISSON
    }

    private static String veryDifferentFaces = "";
    
    /**
@@ -162,21 +150,9 @@ public class IcpDownsampling {
                    MeshFactory.cloneMeshModel(secFaceFromFile.getMeshModel()),
                    secFaceFromFile.getId());
            
            PointSampling secSampling;
            if (numSamples == 0) { // skip sub-sampling, use full resolution
                secSampling = new NoSampling();
            } else {
                switch (STRATEGY) {
                    case RANDOM -> secSampling = new RandomSampling(numSamples);
                    case GAUSSIAN -> secSampling = new CurvatureSampling(CurvatureSampling.CurvatureAlg.GAUSSIAN, numSamples);
                    case UNIFORM_SPACE -> secSampling = new UniformSpaceSampling(numSamples);
                    case UNIFORM_MESH -> secSampling = new UniformSurfaceSampling(numSamples);
                    case POISSON -> secSampling = new PoissonDiskSubSampling(numSamples, SMOOTHING);
                    default -> {
                        return;
                    }
                }
            }
            PointSamplingConfig secSampling = (numSamples == 0) // skip sub-sampling, use full resolution
                    ? new PointSamplingConfig(PointSamplingConfig.Method.NO_SAMPLING, 0)
                    : new PointSamplingConfig(STRATEGY, numSamples, SMOOTHING);

            efficiency.computeIfAbsent(numSamples, k-> new Stopwatch("")).start();
            RegistrationUtils.alignMeshes(
@@ -192,16 +168,14 @@ public class IcpDownsampling {
            efficiency.get(numSamples).stop();
            
            System.out.println("Second face: " + secSampling);

            MeshDistanceNN hd = new MeshDistanceNN(
                    priFace.getKdTree(),
            double dist = MeshDistanceServices.measure(
                    secFace.getMeshModel(),
                    new MeshDistanceConfig(
                            SIMILARITY_STRATEGY,
                            priFace.getKdTree(),
                            SIMILARITY_RELATIVE_DISTANCE,
                    true,
                            SIMILARITY_AUTO_CROP
            );
            secFace.getMeshModel().compute(hd);
            double dist = hd.getDistancesOfVisitedFacets().getDistanceStats().getAverage();
                    )).getDistanceStats().getAverage();
            precision.computeIfAbsent(numSamples, k -> new ArrayList<>()).add(dist);

            if (numSamples > 0) { // best achieved similarity with sub-sampling in action
@@ -216,13 +190,4 @@ public class IcpDownsampling {
        System.out.println();
    }

    private static HumanFace downsamplePriFace(HumanFace priFace, PointSampling sampling) {
        sampling.visitMeshFacet(priFace.getMeshModel().getFacets().get(0));
        MeshFacet reducedFacet = MeshFactory.createPointCloudFacet(sampling.getSamples());
        MeshModel model = MeshFactory.createEmptyMeshModel();
        model.setFacets(List.of(reducedFacet));
        HumanFace ret = new HumanFace(model, priFace.getId());
        return ret;
    }

}
Loading