Commit 55e33200 authored by Radek Ošlejšek's avatar Radek Ošlejšek
Browse files

Merge branch '128-support-segmentation-of-a-profile-curve' into 'master'

Resolve "Support segmentation of a profile curve"

Closes #128

See merge request grp-fidentis/analyst2!142
parents 06678872 ede1e5c3
Loading
Loading
Loading
Loading
+18 −24
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ import cz.fidentis.analyst.kdtree.KdTree;
import cz.fidentis.analyst.face.events.KdTreeCreated;
import cz.fidentis.analyst.face.events.KdTreeDestroyed;
import cz.fidentis.analyst.face.events.MeshChangedEvent;
import cz.fidentis.analyst.face.events.SymmetryPlaneChangedEvent;
import cz.fidentis.analyst.mesh.core.MeshFacet;
import cz.fidentis.analyst.mesh.core.MeshModel;
import cz.fidentis.analyst.mesh.io.MeshObjLoader;
@@ -55,8 +56,6 @@ public class HumanFace implements Serializable {
    
    private MeshFacet symmetryPlaneMesh;

    private MeshFacet cuttingPlane;
    
    private List<FeaturePoint> featurePoints;
    
    private final transient EventBus eventBus = new EventBus();
@@ -91,8 +90,10 @@ public class HumanFace implements Serializable {
    }
    
    /**
     * Sets the mesh model. 
     * Triggers {@link cz.fidentis.analyst.face.events.MeshChangedEvent}.
     * 
     * @param meshModel new mesh model
     * @param meshModel new mesh model, must not be {@code null}
     * @throws IllegalArgumentException if new model is missing
     */
    public void setMeshModel(MeshModel meshModel) {
@@ -100,7 +101,7 @@ public class HumanFace implements Serializable {
            throw new IllegalArgumentException("meshModel");
        }
        this.meshModel = meshModel;
        eventBus.post(new MeshChangedEvent(this, getShortName(), this));
        announceEvent(new MeshChangedEvent(this, getShortName(), this));
    }

    /**
@@ -127,20 +128,29 @@ public class HumanFace implements Serializable {
     * 
     * @param evt Event to be triggered.
     */
    public void annouceEvent(HumanFaceEvent evt) {
    public void announceEvent(HumanFaceEvent evt) {
        if (evt != null) {
            eventBus.post(evt);
        }
    }

    /**
     * Sets the symmetry plane. If both arguments are {@code null}, then removes the plane.
     * Triggers {@link cz.fidentis.analyst.face.events.SymmetryPlaneChangedEvent}.
     * 
     * @param plane The new symmetry plane
     * @param planeFacet The symmetry plane mesh
     * @param plane The new symmetry plane; Must not be {@code null}
     * @param planeFacet The symmetry plane mesh; Must not be {@code null}
     */
    public void setSymmetryPlane(Plane plane, MeshFacet planeFacet) {
        if (plane == null) {
            throw new IllegalArgumentException("plane");
        }
        if (planeFacet == null) {
            throw new IllegalArgumentException("planeFacet");
        }
        this.symmetryPlane = plane;
        this.symmetryPlaneMesh = planeFacet;
        this.announceEvent(new SymmetryPlaneChangedEvent(this, getShortName(), this));
    }

    /**
@@ -155,22 +165,6 @@ public class HumanFace implements Serializable {
        return this.symmetryPlaneMesh;
    }

    /**
     *
     * @param facet MeshFacet of the new cutting plane
     */
    public void setCuttingPlane(MeshFacet facet) {
        cuttingPlane = facet;
    }

    /**
     *
     * @return The face's cutting plane
     */
    public MeshFacet getCuttingPlane() {
        return cuttingPlane;
    }
    
    /**
     * 
     * @param points List of feature points
+3 −3
Original line number Diff line number Diff line
@@ -3,11 +3,11 @@ package cz.fidentis.analyst.face.events;
import cz.fidentis.analyst.face.HumanFace;

/**
 * New symmetry plane has been computed.
 * New symmetry plane has been changed.
 * 
 * @author Radek Oslejsek
 */
public class SymmetryPlaneComputed extends HumanFaceEvent {
public class SymmetryPlaneChangedEvent extends HumanFaceEvent {
    
    /**
     * Constructor.
@@ -15,7 +15,7 @@ public class SymmetryPlaneComputed extends HumanFaceEvent {
     * @param name Event name provided by issuer
     * @param issuer The issuer
     */
    public SymmetryPlaneComputed(HumanFace face, String name, Object issuer) {
    public SymmetryPlaneChangedEvent(HumanFace face, String name, Object issuer) {
        super(face, name, issuer);
    }
    
+62 −61
Original line number Diff line number Diff line
@@ -8,9 +8,11 @@ import cz.fidentis.analyst.symmetry.Plane;

import javax.vecmath.Point3d;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


/**
@@ -20,11 +22,13 @@ import java.util.Set;
 * </p>
 *
 * @author Dominik Racek
 * @author Radek Oslejsek
 */
public class CrossSectionZigZag extends MeshVisitor {
    private List<Point3d> points;
    private List<List<Point3d>> segments;
    private Set<Point3d> usedPoints;
    private Set<MeshTriangle> visited;
    private Set<MeshTriangle> toVisit;

    private Plane plane;

@@ -35,23 +39,24 @@ public class CrossSectionZigZag extends MeshVisitor {
     */
    public CrossSectionZigZag(Plane plane) {
        this.plane = plane;
        this.points = new ArrayList<>();
        //this.points = new ArrayList<>();
        this.segments = new ArrayList<>();
        this.usedPoints = new HashSet<>();
    }

    private void addPoint(Point3d p, boolean direction) {
    private void addPoint(Point3d p, boolean direction, int segment) {
        if (!usedPoints.contains(p)) {
            usedPoints.add(p);

            if (direction) {
                points.add(p);
                segments.get(segment).add(p);
            } else {
                points.add(0, p);
                segments.get(segment).add(0, p);
            }
        }
    }

    private void visitMeshFacetRec(MeshFacet facet, int p1, int p2, MeshTriangle previous, boolean direction) {
    private void visitMeshFacetRec(MeshFacet facet, int p1, int p2, MeshTriangle previous, boolean direction, int segment) {
        List<MeshTriangle> triangles = facet.getAdjacentTriangles(p1, p2);
        triangles.remove(previous);
        if (triangles.isEmpty()) {
@@ -60,6 +65,7 @@ public class CrossSectionZigZag extends MeshVisitor {

        //Find the next intersected edge
        MeshTriangle current = triangles.get(0);
        toVisit.remove(current);

        if (visited.contains(current)) {
            return;
@@ -84,78 +90,73 @@ public class CrossSectionZigZag extends MeshVisitor {
            intersection = plane.getIntersectionWithLine(facet.getVertex(p2).getPosition(),
                    facet.getVertex(p3).getPosition());

            addPoint(intersection, direction);
            visitMeshFacetRec(facet, p2, p3, current, direction);
            addPoint(intersection, direction, segment);
            visitMeshFacetRec(facet, p2, p3, current, direction, segment);
        } else {
            addPoint(intersection, direction);
            visitMeshFacetRec(facet, p1, p3, current, direction);
            addPoint(intersection, direction, segment);
            visitMeshFacetRec(facet, p1, p3, current, direction, segment);
        }

    }

    @Override
    public void visitMeshFacet(MeshFacet facet) {
        Logger out = Logger.measureTime();
        //Logger out = Logger.measureTime();

        // Find all candidates
        visited = new HashSet<>();
        toVisit = facet.getTriangles().parallelStream()
                .filter(t -> t.checkIntersectionWithPlane(plane.getNormal(), plane.getDistance()))
                .collect(Collectors.toSet());
        
        synchronized (this) {

            // Find the first triangle
            MeshTriangle first = null;
            for (MeshTriangle tri : facet) {
                if (tri.checkIntersectionWithPlane(plane.getNormal(), plane.getDistance())) {
                    first = tri;
                    break;
                }
            }

            if (first == null) {
                return;
            }

            visited.add(first);
            while (!toVisit.isEmpty()) {
                MeshTriangle tri = toVisit.iterator().next();
                toVisit.remove(tri);
                segments.add(new ArrayList<>());
                int segment = segments.size() - 1;
                
                // Figure out which lines are intersected
            Point3d intersection1 = plane.getIntersectionWithLine(first.getVertex1(), first.getVertex2());
            Point3d intersection2 = plane.getIntersectionWithLine(first.getVertex2(), first.getVertex3());
            Point3d intersection3 = plane.getIntersectionWithLine(first.getVertex3(), first.getVertex1());
                Point3d intersection1 = plane.getIntersectionWithLine(tri.getVertex1(), tri.getVertex2());
                Point3d intersection2 = plane.getIntersectionWithLine(tri.getVertex2(), tri.getVertex3());
                Point3d intersection3 = plane.getIntersectionWithLine(tri.getVertex3(), tri.getVertex1());
                
                if (intersection1 != null) {
                    //Intersection 1
                addPoint(intersection1, true);
                visitMeshFacetRec(facet, first.index1, first.index2, first, true);
                    addPoint(intersection1, true, segment);
                    visitMeshFacetRec(facet, tri.index1, tri.index2, tri, true, segment);
                    if (intersection2 != null) {
                        //Intersection 1 and 2
                    addPoint(intersection2, false);
                    visitMeshFacetRec(facet, first.index2, first.index3, first, false);
                        addPoint(intersection2, false, segment);
                        visitMeshFacetRec(facet, tri.index2, tri.index3, tri, false, segment);
                    } else if (intersection3 != null) {
                        //Intersection 1 and 3
                    addPoint(intersection3, false);
                    visitMeshFacetRec(facet, first.index3, first.index1, first, false);
                        addPoint(intersection3, false, segment);
                        visitMeshFacetRec(facet, tri.index3, tri.index1, tri, false, segment);
                    }
                } else if (intersection2 != null) {
                    //Intersection 2
                addPoint(intersection2, true);
                visitMeshFacetRec(facet, first.index2, first.index3, first, true);
                    addPoint(intersection2, true, segment);
                    visitMeshFacetRec(facet, tri.index2, tri.index3, tri, true, segment);
                    if (intersection3 != null) {
                        //Intersection 2 and 3
                    addPoint(intersection3, false);
                    visitMeshFacetRec(facet, first.index3, first.index1, first, false);
                        addPoint(intersection3, false, segment);
                        visitMeshFacetRec(facet, tri.index3, tri.index1, tri, false, segment);
                    }

                } else if (intersection3 != null) {
                    //Intersection 3 only
                addPoint(intersection3, true);
                visitMeshFacetRec(facet, first.index3, first.index1, first, true);
                    addPoint(intersection3, true, segment);
                    visitMeshFacetRec(facet, tri.index3, tri.index1, tri, true, segment);
                }
                //No intersection
            }
        }

        out.printDuration("Cross section with zigzag method");
        //out.printDuration("Cross section with zigzag method");
    }

    public List<Point3d> getPoints() {
        return points;
    public List<List<Point3d>> getSegments() {
        return Collections.unmodifiableList(segments);
    }
}
+15 −15
Original line number Diff line number Diff line
@@ -59,24 +59,24 @@ public class CrossSectionTest {

        CrossSectionZigZag cs = new CrossSectionZigZag(cuttingPlane);
        model.compute(cs);
        List<Point3d> points = cs.getPoints();
        List<List<Point3d>> points = cs.getSegments();

        //They can be ordered two ways, check both
        Assertions.assertEquals(points.size(), 6);
        Assertions.assertEquals(points.get(0).size(), 6);
        if (points.get(0).equals(new Point3d(0.5, 0, 0))) {
            Assertions.assertEquals(points.get(0), new Point3d(0.5, 0, 0));
            Assertions.assertEquals(points.get(1), new Point3d(0.5, 0.5, 0));
            Assertions.assertEquals(points.get(2), new Point3d(0.5, 1, 0));
            Assertions.assertEquals(points.get(3), new Point3d(0.5, 1.5, 0));
            Assertions.assertEquals(points.get(4), new Point3d(0.5, 2, 0));
            Assertions.assertEquals(points.get(5), new Point3d(0.5, 2.5, 0));
        } else if (points.get(0).equals(new Point3d(0.5, 2.5, 0))) {
            Assertions.assertEquals(points.get(0), new Point3d(0.5, 2.5, 0));
            Assertions.assertEquals(points.get(1), new Point3d(0.5, 2, 0));
            Assertions.assertEquals(points.get(2), new Point3d(0.5, 1.5, 0));
            Assertions.assertEquals(points.get(3), new Point3d(0.5, 1, 0));
            Assertions.assertEquals(points.get(4), new Point3d(0.5, 0.5, 0));
            Assertions.assertEquals(points.get(5), new Point3d(0.5, 0, 0));
            Assertions.assertEquals(points.get(0).get(0), new Point3d(0.5, 0, 0));
            Assertions.assertEquals(points.get(0).get(1), new Point3d(0.5, 0.5, 0));
            Assertions.assertEquals(points.get(0).get(2), new Point3d(0.5, 1, 0));
            Assertions.assertEquals(points.get(0).get(3), new Point3d(0.5, 1.5, 0));
            Assertions.assertEquals(points.get(0).get(4), new Point3d(0.5, 2, 0));
            Assertions.assertEquals(points.get(0).get(5), new Point3d(0.5, 2.5, 0));
        } else if (points.get(0).get(0).equals(new Point3d(0.5, 2.5, 0))) {
            Assertions.assertEquals(points.get(0).get(0), new Point3d(0.5, 2.5, 0));
            Assertions.assertEquals(points.get(0).get(1), new Point3d(0.5, 2, 0));
            Assertions.assertEquals(points.get(0).get(2), new Point3d(0.5, 1.5, 0));
            Assertions.assertEquals(points.get(0).get(3), new Point3d(0.5, 1, 0));
            Assertions.assertEquals(points.get(0).get(4), new Point3d(0.5, 0.5, 0));
            Assertions.assertEquals(points.get(0).get(5), new Point3d(0.5, 0, 0));
        } else {
            Assertions.fail();
        }
+3 −1
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ public abstract class ComboSlider extends JPanel {
     * Connects the specified listener witch the input field.
     * The listener is invoked on the input field change, which is affected
     * by the {@link #setContinousSync(boolean)}.
     * Event's source is set to {@code JFormattedTextField}
     *
     * @param listener the action listener to be added
     */
@@ -68,6 +69,7 @@ public abstract class ComboSlider extends JPanel {
    
    /**
     * Connects the specified listener witch the slider.
     * Event's source is set to {@code JSlider}
     *
     * @param listener the action listener to be added
     */
Loading