diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java index 28836f6c061c1b752392e37eb24b827d367dcf35..2776b098580aa772dc42fc9beb51ca87c1df0d9a 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java @@ -22,6 +22,7 @@ import java.io.InputStream; * Then the are informed about changes in the human automatically via methods * prescribed by the interface. * </p> + * <p> * Events fired by the class: * <ul> * <li>{@link cz.fidentis.analyst.mesh.events.MeshEvent} or its sub-type if diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java index f245e8690c03d508ee8f94e7907604939f2678f3..c2a3520f98e4110a4bbff851cc9c87ac9d2de471 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java @@ -89,7 +89,7 @@ public class SymmetryEstimator { */ public BoundingBox getBoundingBox() { if (boundingBox == null) { - BoundingBoxVisitor visitor = new BoundingBoxVisitor(); + BoundingBoxVisitor visitor = new BoundingBoxVisitor(true); facet.accept(visitor); boundingBox = visitor.getBoundingBox(); } diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/BoundingBoxVisitor.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/BoundingBoxVisitor.java index 25451855fce826da972a9c045dba61af895d2fd0..6a121d1f4b9647266009fd51eb34ab3f17089f52 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/BoundingBoxVisitor.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/BoundingBoxVisitor.java @@ -5,15 +5,28 @@ import cz.fidentis.analyst.mesh.core.MeshFacet; /** * Visitor that computes a 3D bounding box (cube). + * <p> + * This visitor is thread-safe. A single instance of the visitor can be used + * to inspect multiple mesh models or facets simultaneously. + * </p> * * @author Radek Oslejsek */ -public class BoundingBoxVisitor implements MeshVisitor { +public class BoundingBoxVisitor extends MeshVisitor { private BoundingBox bbox; + /** + * + * @param concurrently If {@code true} and this visitor is thread-safe, then + * the visitor is applied concurrently on multiple mesf facets. + */ + public BoundingBoxVisitor(boolean concurrently) { + super(concurrently); + } + @Override - public void visitMeshFacet(MeshFacet facet) { + protected synchronized void visitMeshFacet(MeshFacet facet) { if (bbox == null) { bbox = new BoundingBox(facet.getVertices()); } else { @@ -23,6 +36,7 @@ public class BoundingBoxVisitor implements MeshVisitor { /** * Returns computed bounding box. + * * @return Bounding box or null */ public BoundingBox getBoundingBox() { diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshTriVisitor.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshTriVisitor.java index e9befdb693da449252b4b2c931b483ec35660129..947ce338324aec6777e3f26340994eb10ecc97ca 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshTriVisitor.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshTriVisitor.java @@ -24,10 +24,12 @@ public class HausdorffDistMeshTriVisitor extends HausdorffDistMeshVisitor { * @param relativeDistance If true, then the visitor calculates the relative distances with respect * to the normal vectors of source facets (normal vectors have to present), * i.e., we can get negative distances. + * @param concurrently If {@code true} and this visitor is thread-safe, then + * the visitor is applied concurrently on multiple mesf facets. * @throws IllegalArgumentException if some parametr is wrong */ - public HausdorffDistMeshTriVisitor(Set<MeshFacet> mainFacets, boolean relativeDistance) { - super(mainFacets, relativeDistance); + public HausdorffDistMeshTriVisitor(Set<MeshFacet> mainFacets, boolean relativeDistance, boolean concurrently) { + super(mainFacets, relativeDistance, concurrently); } /** @@ -35,14 +37,16 @@ public class HausdorffDistMeshTriVisitor extends HausdorffDistMeshVisitor { * @param relativeDistance If true, then the visitor calculates the relative distances with respect * to the normal vectors of source facets (normal vectors have to present), * i.e., we can get negative distances. + * @param concurrently If {@code true} and this visitor is thread-safe, then + * the visitor is applied concurrently on multiple mesf facets. * @throws IllegalArgumentException if some parametr is wrong */ - public HausdorffDistMeshTriVisitor(MeshFacet mainFacet, boolean relativeDistance) { - super(mainFacet, relativeDistance); + public HausdorffDistMeshTriVisitor(MeshFacet mainFacet, boolean relativeDistance, boolean concurrently) { + super(mainFacet, relativeDistance, concurrently); } @Override - public void visitMeshFacet(MeshFacet comparedFacet) { + protected void visitMeshFacet(MeshFacet comparedFacet) { for (Map.Entry<MeshFacet, List<Double>> entry: getDistMap().entrySet()) { List<MeshPoint> vertices = entry.getKey().getVertices(); List<Double> distList = entry.getValue(); @@ -50,7 +54,7 @@ public class HausdorffDistMeshTriVisitor extends HausdorffDistMeshVisitor { boolean firstComparison = distList.isEmpty(); for (int i = 0; i < vertices.size(); i++) { - Point2MeshTriVisitor visitor = new Point2MeshTriVisitor(vertices.get(i), isRelativeDistance()); + Point2MeshTriVisitor visitor = new Point2MeshTriVisitor(vertices.get(i), isRelativeDistance(), concurrently()); comparedFacet.accept(visitor); double dist = visitor.getDistance(); updateDistances(distList, firstComparison, dist, i); diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshVisitor.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshVisitor.java index ef40c2d20891770baf00deaf4011692b44f158ea..3d66dcde5a99987d9aa890a3a87c41ae7c79e240 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshVisitor.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshVisitor.java @@ -19,7 +19,7 @@ import java.util.Set; * @author Matej Lukes * @author Radek Oslejsek */ -public class HausdorffDistMeshVisitor implements MeshVisitor { +public class HausdorffDistMeshVisitor extends MeshVisitor { private boolean relativeDistance; private Map<MeshFacet, List<Double>> distances = new HashMap<>(); @@ -29,9 +29,12 @@ public class HausdorffDistMeshVisitor implements MeshVisitor { * @param relativeDistance If true, then the visitor calculates the relative distances with respect * to the normal vectors of source facets (normal vectors have to present), * i.e., we can get negative distances. + * @param concurrently If {@code true} and this visitor is thread-safe, then + * the visitor is applied concurrently on multiple mesf facets. * @throws IllegalArgumentException if some parametr is wrong */ - public HausdorffDistMeshVisitor(Set<MeshFacet> mainFacets, boolean relativeDistance) { + public HausdorffDistMeshVisitor(Set<MeshFacet> mainFacets, boolean relativeDistance, boolean concurrently) { + super(concurrently); if (mainFacets == null) { throw new IllegalArgumentException("mainFacets"); } @@ -46,17 +49,19 @@ public class HausdorffDistMeshVisitor implements MeshVisitor { * @param relativeDistance If true, then the visitor calculates the relative distances with respect * to the normal vectors of source facets (normal vectors have to present), * i.e., we can get negative distances. + * @param concurrently If {@code true} and this visitor is thread-safe, then + * the visitor is applied concurrently on multiple mesf facets. * @throws IllegalArgumentException if some parametr is wrong */ - public HausdorffDistMeshVisitor(MeshFacet mainFacet, boolean relativeDistance) { - this(new HashSet<>(Collections.singleton(mainFacet)), relativeDistance); + public HausdorffDistMeshVisitor(MeshFacet mainFacet, boolean relativeDistance, boolean concurrently) { + this(new HashSet<>(Collections.singleton(mainFacet)), relativeDistance, concurrently); if (mainFacet == null) { throw new IllegalArgumentException("mainFacet"); } } @Override - public void visitMeshFacet(MeshFacet comparedFacet) { + protected void visitMeshFacet(MeshFacet comparedFacet) { for (Map.Entry<MeshFacet, List<Double>> entry: distances.entrySet()) { List<MeshPoint> vertices = entry.getKey().getVertices(); List<Double> distList = entry.getValue(); @@ -64,7 +69,7 @@ public class HausdorffDistMeshVisitor implements MeshVisitor { boolean firstComparison = distList.isEmpty(); for (int i = 0; i < vertices.size(); i++) { - Point2MeshVisitor visitor = new Point2MeshVisitor(vertices.get(i), relativeDistance); + Point2MeshVisitor visitor = new Point2MeshVisitor(vertices.get(i), relativeDistance, concurrently()); comparedFacet.accept(visitor); double dist = visitor.getDistance(); updateDistances(distList, firstComparison, dist, i); diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/KdTreeBuildVisitor.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/KdTreeBuildVisitor.java index 7538144f0bce7c8060f77dd6afb2d77e862ceae0..0c8d0af662d574d3582e552bb1a70fea59e9f572 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/KdTreeBuildVisitor.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/KdTreeBuildVisitor.java @@ -14,11 +14,21 @@ import java.util.List; * @author Maria Kocurekova */ -public class KdTreeBuildVisitor implements MeshVisitor { +public class KdTreeBuildVisitor extends MeshVisitor { + private List<MeshFacet> facets = new LinkedList<>(); + + /** + * + * @param concurrently If {@code true} and this visitor is thread-safe, then + * the visitor is applied concurrently on multiple mesf facets. + */ + public KdTreeBuildVisitor(boolean concurrently) { + super(concurrently); + } @Override - public void visitMeshFacet(MeshFacet facet) { + protected void visitMeshFacet(MeshFacet facet) { this.facets.add(facet); } diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/Point2MeshTriVisitor.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/Point2MeshTriVisitor.java index 050f68cb8462ca89e5d3e57a3f25af5ae10af784..2c7482801a65b42cdd4238c1c83fda7ae77d19a7 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/Point2MeshTriVisitor.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/Point2MeshTriVisitor.java @@ -13,16 +13,22 @@ import javax.vecmath.Vector3d; * In contrast to the {@code Point2MeshVisitor} visitor, * which computes pont-to-point distance, this implementation measures * the distance to the triangles. - * + * <p> * Because there can be multiple triangles with the same minimal distance, the visitor * returns a list of mesh facets and a list of indices corresponding * to the facets. - * + * </p> + * <p> * Returned lists have the same size. * {@code n = getIndices().get(i)} returns the index of the closest triangle on the i-th facet. * Then iterate into the n-th triangle of facet {@code getClosestFacets().get(i)} to get * the triangle instance. - * + * </p> +* <p> + * This visitor is thread-safe. A single instance of the visitor can be used + * to inspect multiple mesh models or facets simultaneously. + * </p> + * * @author Matej Lukes * @author Radek Oslejsek */ @@ -35,22 +41,26 @@ public class Point2MeshTriVisitor extends Point2MeshVisitor { * @param relativeDistance If true, the visitor calculates the distances with respect * to the normals of the source 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 mesf facets. * @throws IllegalArgumentException if some parametr is wrong */ - public Point2MeshTriVisitor(MeshPoint point, boolean relativeDistance) { - super(point, relativeDistance); + public Point2MeshTriVisitor(MeshPoint point, boolean relativeDistance, boolean concurrently) { + super(point, relativeDistance, concurrently); } /** * @param point 3D point of 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 mesf facets. * @throws IllegalArgumentException if some parametr is wrong */ - public Point2MeshTriVisitor(Vector3d point) { - this (new MeshPointImpl(point, null, null), true); + public Point2MeshTriVisitor(Vector3d point, boolean concurrently) { + this (new MeshPointImpl(point, null, null), true, concurrently); } @Override - public void visitMeshFacet(MeshFacet facet) { + protected void visitMeshFacet(MeshFacet facet) { Vector3d my = getMyPoint().getPosition(); int i = 0; for (MeshTriangle tri: facet) { diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/Point2MeshVisitor.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/Point2MeshVisitor.java index 5208e7e202a4a2033728ff4b91d4b3f15681d8b7..b93d34beceaf8fd4ba6bbfc47a2fe009fd084c81 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/Point2MeshVisitor.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/Point2MeshVisitor.java @@ -14,15 +14,20 @@ import javax.vecmath.Vector3d; * Because there can be multiple points with the same minimal distance, the visitor * returns a list of mesh facets and a list of indices corresponding * to the facets. - * -* Returned lists have the same size. + * <p> + * Returned lists have the same size. * {@code n = getIndices().get(i)} returns the index of the closest point on the i-th facet. * Then call {@code getClosestFacets().get(i).getVertex(n))} to get the closest point. - * + * </p> +* <p> + * This visitor is thread-safe. A single instance of the visitor can be used + * to inspect multiple mesh models or facets simultaneously. + * </p> + * * @author Matej Lukes * @author Radek Oslejsek */ -public class Point2MeshVisitor implements MeshVisitor { +public class Point2MeshVisitor extends MeshVisitor { private boolean relativeDist; private MeshPoint myPoint; @@ -36,9 +41,12 @@ public class Point2MeshVisitor implements MeshVisitor { * @param relativeDistance If true, the visitor calculates the distances with respect * to the normals of the source 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 mesf facets. * @throws IllegalArgumentException if some parametr is wrong */ - public Point2MeshVisitor(MeshPoint point, boolean relativeDistance) { + public Point2MeshVisitor(MeshPoint point, boolean relativeDistance, boolean concurrently) { + super(concurrently); if (point == null) { throw new IllegalArgumentException("point"); } @@ -51,14 +59,16 @@ public class Point2MeshVisitor implements MeshVisitor { /** * @param point 3D point of 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 mesf facets. * @throws IllegalArgumentException if some parametr is wrong */ - public Point2MeshVisitor(Vector3d point) { - this (new MeshPointImpl(point, null, null), true); + public Point2MeshVisitor(Vector3d point, boolean concurrently) { + this (new MeshPointImpl(point, null, null), true, concurrently); } @Override - public void visitMeshFacet(MeshFacet facet) { + protected void visitMeshFacet(MeshFacet facet) { List<MeshPoint> vertices = facet.getVertices(); for (int i = 0; i < vertices.size(); i++) { checkAndUpdateDistance(vertices.get(i).getPosition(), facet, i); @@ -112,19 +122,21 @@ public class Point2MeshVisitor implements MeshVisitor { sign = relativeDist ? (int) Math.signum(aux.dot(myPoint.getNormal())): 1; double dist = aux.length(); - if (dist > distance) { - return; - } + synchronized (this) { + if (dist > distance) { + return; + } - if (dist < distance) { // new closest point - distance = dist; - closestFacets.clear(); - indices.clear(); - closestFacets.add(facet); - indices.add(index); - } else { // the same distance - closestFacets.add(facet); - indices.add(index); + if (dist < distance) { // new closest point + distance = dist; + closestFacets.clear(); + indices.clear(); + closestFacets.add(facet); + indices.add(index); + } else { // the same distance + closestFacets.add(facet); + indices.add(index); + } } } } diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/TriangleListVisitor.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/TriangleListVisitor.java index bad7f8f962636bb68e0b31f2173fbdc140bb1328..d68315b17277833a1dfee477b3222f0e11cbd4bd 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/TriangleListVisitor.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/mesh/TriangleListVisitor.java @@ -10,16 +10,29 @@ import java.util.List; * A visitor that collects and returns a list of triangles. * It is usefull for collecting triangles of multiple mesh facets. * For iterating through triangles of a single facet, use the iterator instead. - * Or iterate through the facet in a for-each cycle. - * + * Or iterate through the facet in a for-each cycle. +* <p> + * This visitor is thread-safe. A single instance of the visitor can be used + * to inspect multiple mesh models or facets simultaneously. + * </p> + * * @author Radek Oslejsek */ -public class TriangleListVisitor implements MeshVisitor { +public class TriangleListVisitor extends MeshVisitor { private List<MeshTriangle> triangles = new ArrayList<>(); + + /** + * + * @param concurrently If {@code true} and this visitor is thread-safe, then + * the visitor is applied concurrently on multiple mesf facets. + */ + public TriangleListVisitor(boolean concurrently) { + super(concurrently); + } @Override - public void visitMeshFacet(MeshFacet facet) { + protected synchronized void visitMeshFacet(MeshFacet facet) { for (MeshTriangle tri : facet) { triangles.add(tri); } diff --git a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/BoundingBoxVisitorTest.java b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/BoundingBoxVisitorTest.java index f4ba298eccfae4528d9df881e79f9e9622e4861d..9fa2e80bfbf5e97c1bfca907a89b91398484e8a2 100644 --- a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/BoundingBoxVisitorTest.java +++ b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/BoundingBoxVisitorTest.java @@ -21,8 +21,8 @@ public class BoundingBoxVisitorTest { void icoSphereTest() throws IOException { MeshModel m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "IcoSphere-20.obj")); assertNotNull(m); - BoundingBoxVisitor visitor = new BoundingBoxVisitor(); - m.accept(visitor); + BoundingBoxVisitor visitor = new BoundingBoxVisitor(false); + m.compute(visitor); assertEquals(new Vector3d(0.8944249749183655, 1.0, 0.8506399989128113), visitor.getBoundingBox().getMaxPoint().getPosition()); assertEquals(new Vector3d(-0.8944249749183655, -1.0, -0.8506399989128113), visitor.getBoundingBox().getMinPoint().getPosition()); } @@ -31,12 +31,12 @@ public class BoundingBoxVisitorTest { void combinedTest() throws IOException { MeshModel m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "IcoSphere-20.obj")); assertNotNull(m); - BoundingBoxVisitor visitor = new BoundingBoxVisitor(); - m.accept(visitor); + BoundingBoxVisitor visitor = new BoundingBoxVisitor(false); + m.compute(visitor); m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "Tetrahedron.obj")); assertNotNull(m); - m.accept(visitor); + m.compute(visitor); assertEquals(new Vector3d(1.0, 1.0, 1.0), visitor.getBoundingBox().getMaxPoint().getPosition()); assertEquals(new Vector3d(-1.0, -1.0, -1.0), visitor.getBoundingBox().getMinPoint().getPosition()); diff --git a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshTriVisitorTest.java b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshTriVisitorTest.java index 6f6b4264778966afdf53d232f49c29051563831a..a7c2f5c67c1baabb7261ec1a5fa095e2febcb36d 100644 --- a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshTriVisitorTest.java +++ b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshTriVisitorTest.java @@ -31,7 +31,7 @@ public class HausdorffDistMeshTriVisitorTest { MeshFacet mainFacet = getTrivialFacet(1, 1); MeshFacet comparedFacet = getTrivialFacet(1.5, 1); - HausdorffDistMeshTriVisitor hausdorffDistance = new HausdorffDistMeshTriVisitor(mainFacet, false); + HausdorffDistMeshTriVisitor hausdorffDistance = new HausdorffDistMeshTriVisitor(mainFacet, false, false); hausdorffDistance.visitMeshFacet(comparedFacet); Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances(); @@ -46,7 +46,7 @@ public class HausdorffDistMeshTriVisitorTest { MeshFacet mainFacet = getTrivialFacet(1, 1); MeshFacet comparedFacet = getTrivialFacet(-1.5, 1); - HausdorffDistMeshTriVisitor hausdorffDistance = new HausdorffDistMeshTriVisitor(mainFacet, false); + HausdorffDistMeshTriVisitor hausdorffDistance = new HausdorffDistMeshTriVisitor(mainFacet, false, false); hausdorffDistance.visitMeshFacet(comparedFacet); Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances(); @@ -61,7 +61,7 @@ public class HausdorffDistMeshTriVisitorTest { MeshFacet mainFacet = getTrivialFacet(1, 1); MeshFacet comparedFacet = getTrivialFacet(1.5, 1); - HausdorffDistMeshTriVisitor hausdorffDistance = new HausdorffDistMeshTriVisitor(mainFacet, true); + HausdorffDistMeshTriVisitor hausdorffDistance = new HausdorffDistMeshTriVisitor(mainFacet, true, false); hausdorffDistance.visitMeshFacet(comparedFacet); Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances(); @@ -76,7 +76,7 @@ public class HausdorffDistMeshTriVisitorTest { MeshFacet mainFacet = getTrivialFacet(1, 1); MeshFacet comparedFacet = getTrivialFacet(-1.5, 1); - HausdorffDistMeshTriVisitor hausdorffDistance = new HausdorffDistMeshTriVisitor(mainFacet, true); + HausdorffDistMeshTriVisitor hausdorffDistance = new HausdorffDistMeshTriVisitor(mainFacet, true, false); hausdorffDistance.visitMeshFacet(comparedFacet); Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances(); diff --git a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshVisitorTest.java b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshVisitorTest.java index ffa1210c0e2db3391d3a7dd27182856040a4eedd..5ad6f5d49c6575faaf2690bc460f7b4b3f2b9d4d 100644 --- a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshVisitorTest.java +++ b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/HausdorffDistMeshVisitorTest.java @@ -31,7 +31,7 @@ public class HausdorffDistMeshVisitorTest { MeshFacet mainFacet = getTrivialFacet(1, 1); MeshFacet comparedFacet = getTrivialFacet(1.5, 1); - HausdorffDistMeshVisitor hausdorffDistance = new HausdorffDistMeshVisitor(mainFacet, false); + HausdorffDistMeshVisitor hausdorffDistance = new HausdorffDistMeshVisitor(mainFacet, false, false); hausdorffDistance.visitMeshFacet(comparedFacet); Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances(); @@ -46,7 +46,7 @@ public class HausdorffDistMeshVisitorTest { MeshFacet mainFacet = getTrivialFacet(1, 1); MeshFacet comparedFacet = getTrivialFacet(-1.5, 1); - HausdorffDistMeshVisitor hausdorffDistance = new HausdorffDistMeshVisitor(mainFacet, false); + HausdorffDistMeshVisitor hausdorffDistance = new HausdorffDistMeshVisitor(mainFacet, false, false); hausdorffDistance.visitMeshFacet(comparedFacet); Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances(); @@ -61,7 +61,7 @@ public class HausdorffDistMeshVisitorTest { MeshFacet mainFacet = getTrivialFacet(1, 1); MeshFacet comparedFacet = getTrivialFacet(1.5, 1); - HausdorffDistMeshVisitor hausdorffDistance = new HausdorffDistMeshVisitor(mainFacet, true); + HausdorffDistMeshVisitor hausdorffDistance = new HausdorffDistMeshVisitor(mainFacet, true, false); hausdorffDistance.visitMeshFacet(comparedFacet); Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances(); @@ -76,7 +76,7 @@ public class HausdorffDistMeshVisitorTest { MeshFacet mainFacet = getTrivialFacet(1, 1); MeshFacet comparedFacet = getTrivialFacet(-1.5, 1); - HausdorffDistMeshVisitor hausdorffDistance = new HausdorffDistMeshVisitor(mainFacet, true); + HausdorffDistMeshVisitor hausdorffDistance = new HausdorffDistMeshVisitor(mainFacet, true, false); hausdorffDistance.visitMeshFacet(comparedFacet); Map<MeshFacet, List<Double>> map = hausdorffDistance.getDistances(); diff --git a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/KdTreeBuildVisitorTest.java b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/KdTreeBuildVisitorTest.java index 660ed33aed36afaa016e8a57d6227549e15b2aeb..599c56acb339c5372cde6157862a1f456bd63e79 100644 --- a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/KdTreeBuildVisitorTest.java +++ b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/KdTreeBuildVisitorTest.java @@ -21,8 +21,8 @@ public class KdTreeBuildVisitorTest { void testCreateVisitorsAndGetKdTree() throws IOException { MeshModel m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "IcoSphere-20.obj")); assertNotNull(m); - KdTreeBuildVisitor visitor = new KdTreeBuildVisitor(); - m.accept(visitor); + KdTreeBuildVisitor visitor = new KdTreeBuildVisitor(false); + m.compute(visitor); assertEquals(1, m.getFacets().size()); List<MeshPoint> points = new LinkedList<>(); @@ -45,8 +45,8 @@ public class KdTreeBuildVisitorTest { void testCreateVisitorsAndGetKdTreeDuplicate() throws IOException { MeshModel m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "IcoSphere-20.obj")); assertNotNull(m); - KdTreeBuildVisitor visitor = new KdTreeBuildVisitor(); - m.accept(visitor); + KdTreeBuildVisitor visitor = new KdTreeBuildVisitor(false); + m.compute(visitor); assertEquals(1, m.getFacets().size()); List<MeshPoint> points = new LinkedList<>(); diff --git a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/Point2MeshTriVisitorTest.java b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/Point2MeshTriVisitorTest.java index bb3a99054bc862537821fb3d94562a8001c0ddd8..dbc1a722eaeb995a1baa7dac685328a54e08223b 100644 --- a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/Point2MeshTriVisitorTest.java +++ b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/Point2MeshTriVisitorTest.java @@ -38,7 +38,7 @@ public class Point2MeshTriVisitorTest { MeshFacet facet = getTrivialFacet(1.5, 1); MeshPoint point = new MeshPointImpl(new Vector3d(0,0,0), new Vector3d(0,0,-1), new Vector3d()); - Point2MeshVisitor vis = new Point2MeshTriVisitor(point, false); + Point2MeshVisitor vis = new Point2MeshTriVisitor(point, false, false); facet.accept(vis); assertEquals(1.5, vis.getDistance()); @@ -57,7 +57,7 @@ public class Point2MeshTriVisitorTest { MeshFacet facet = getTrivialFacet(1.5, 1); MeshPoint point = new MeshPointImpl(new Vector3d(0,0,0), new Vector3d(0,0,-1), new Vector3d()); - Point2MeshVisitor vis = new Point2MeshTriVisitor(point, true); + Point2MeshVisitor vis = new Point2MeshTriVisitor(point, true, false); facet.accept(vis); assertEquals(-1.5, vis.getDistance()); @@ -78,7 +78,7 @@ public class Point2MeshTriVisitorTest { System.out.println(facet.getVertices()); - Point2MeshVisitor vis = new Point2MeshTriVisitor(point, false); + Point2MeshVisitor vis = new Point2MeshTriVisitor(point, false, false); facet.accept(vis); assertEquals(0, vis.getDistance()); @@ -112,7 +112,7 @@ public class Point2MeshTriVisitorTest { ); args[1] = triangle; - Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false, false); Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); Assertions.assertEquals(0d, result.x); @@ -138,7 +138,7 @@ public class Point2MeshTriVisitorTest { ); args[1] = triangle; - Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false, false); Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); Assertions.assertEquals(0d, result.x); @@ -164,7 +164,7 @@ public class Point2MeshTriVisitorTest { ); args[1] = triangle; - Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false, false); boolean result = (boolean) method.invoke(hausdorffDistance, args); Assertions.assertTrue(result); @@ -188,7 +188,7 @@ public class Point2MeshTriVisitorTest { ); args[1] = triangle; - Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false, false); boolean result = (boolean) method.invoke(hausdorffDistance, args); Assertions.assertFalse(result); @@ -212,7 +212,7 @@ public class Point2MeshTriVisitorTest { ); args[1] = triangle; - Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false, false); Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); Assertions.assertEquals(1d, result.x); @@ -238,7 +238,7 @@ public class Point2MeshTriVisitorTest { ); args[1] = triangle; - Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false, false); Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); Assertions.assertEquals(1d, result.x); @@ -261,7 +261,7 @@ public class Point2MeshTriVisitorTest { args[1] = new Vector3d(1, 2, 0); args[2] = new Vector3d(1, 0, 0); - Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false, false); Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); Assertions.assertEquals(1d, result.x); @@ -284,7 +284,7 @@ public class Point2MeshTriVisitorTest { args[1] = new Vector3d(1, 2, 0); args[2] = new Vector3d(1, 0, 0); - Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false, false); Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); Assertions.assertEquals(1d, result.x); @@ -307,7 +307,7 @@ public class Point2MeshTriVisitorTest { args[1] = new Vector3d(1, 2, 0); args[2] = new Vector3d(1, 0, 0); - Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false); + Point2MeshTriVisitor hausdorffDistance = new Point2MeshTriVisitor(new MeshPointImpl(new Vector3d(), null, null), false, false); Vector3d result = (Vector3d) method.invoke(hausdorffDistance, args); Assertions.assertEquals(1d, result.x); diff --git a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/Point2MeshVisitorTest.java b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/Point2MeshVisitorTest.java index 7e60cf1d25dc3a0fae7bb06b149348b7332afa8c..d36d119d23a23543129383f4e0aee693f20d8aab 100644 --- a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/Point2MeshVisitorTest.java +++ b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/Point2MeshVisitorTest.java @@ -30,7 +30,7 @@ public class Point2MeshVisitorTest { MeshFacet facet = getTrivialFacet(1.5, 1); MeshPoint point = new MeshPointImpl(new Vector3d(0,0,0), new Vector3d(0,0,-1), new Vector3d()); - Point2MeshVisitor vis = new Point2MeshVisitor(point, false); + Point2MeshVisitor vis = new Point2MeshVisitor(point, false, false); facet.accept(vis); assertEquals(1.5, vis.getDistance()); @@ -49,7 +49,7 @@ public class Point2MeshVisitorTest { MeshFacet facet = getTrivialFacet(1.5, 1); MeshPoint point = new MeshPointImpl(new Vector3d(0,0,0), new Vector3d(0,0,-1), new Vector3d()); - Point2MeshVisitor vis = new Point2MeshVisitor(point, true); + Point2MeshVisitor vis = new Point2MeshVisitor(point, true, false); facet.accept(vis); assertEquals(-1.5, vis.getDistance()); @@ -70,7 +70,7 @@ public class Point2MeshVisitorTest { System.out.println(facet.getVertices()); - Point2MeshVisitor vis = new Point2MeshVisitor(point, false); + Point2MeshVisitor vis = new Point2MeshVisitor(point, false, false); facet.accept(vis); assertEquals(0, vis.getDistance()); diff --git a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/TriangleListVisitorTest.java b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/TriangleListVisitorTest.java index 2cb0a5ed1054cb1c5796280737397c7ec26fe27c..c1688f5b5734e4d27d18b8591dfe93d16bb3c8d3 100644 --- a/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/TriangleListVisitorTest.java +++ b/Comparison/src/test/java/cz/fidentis/analyst/visitors/mesh/TriangleListVisitorTest.java @@ -21,8 +21,8 @@ public class TriangleListVisitorTest { void icoSphereTest() throws IOException { MeshModel m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "IcoSphere-20.obj")); assertNotNull(m); - TriangleListVisitor visitor = new TriangleListVisitor(); - m.accept(visitor); + TriangleListVisitor visitor = new TriangleListVisitor(false); + m.compute(visitor); assertEquals(20, visitor.getTriangles().size()); } @@ -30,12 +30,12 @@ public class TriangleListVisitorTest { void combinedTest() throws IOException { MeshModel m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "IcoSphere-20.obj")); assertNotNull(m); - TriangleListVisitor visitor = new TriangleListVisitor(); - m.accept(visitor); + TriangleListVisitor visitor = new TriangleListVisitor(false); + m.compute(visitor); m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "Tetrahedron.obj")); assertNotNull(m); - m.accept(visitor); + m.compute(visitor); assertEquals(24, visitor.getTriangles().size()); } 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 3abe008e1ec91c792e3b34341611f2533e9659a7..123157803b824ff50bfc44fb01d02dd2dd85b452 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/MeshVisitor.java +++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/MeshVisitor.java @@ -1,34 +1,96 @@ package cz.fidentis.analyst.mesh; import cz.fidentis.analyst.mesh.core.MeshFacet; -import cz.fidentis.analyst.mesh.core.MeshModel; +import java.util.concurrent.Callable; /** - * An object, when instantiated, can be applied to multiple meshes. - * It inspects the state of the meshes one by one, and (cumulatevely) computes results. - * + * A functional object. When instantiated, it can be applied to multiple mesh facets. + * It inspects the state of the mesh facets one by one, and (cumulatevely) computes results. + * <p> * Implement this interface whenever you want to define new algorithm over a mesh. + * </p> + * <p> + * There are two visitation strategies available. + * The {@link cz.fidentis.analyst.mesh.mesh.MeshVisitor#visitMeshFacet} inspects + * the facet immediately. On the contrary, + * the {@link cz.fidentis.analyst.mesh.MeshVisitor#visitConcurrently} enable to + * inspect multiple facets concurretly. The later has to be called from a code like this: + * </p> * * @author Radek Oslejsek */ -public interface MeshVisitor { +public abstract class MeshVisitor implements Callable<MeshVisitor> { + + private boolean concurrently; + + /** + * Facet stored temporarily for later cuncurrent inspection via + * the {@link cz.fidentis.analyst.mesh.MeshVisitor#call} method. + */ + private MeshFacet facet; + + + /** + * + * @param concurrently If {@code true} and this visitor is thread-safe, then + * the visitor is applied concurrently on multiple mesh facets. + */ + public MeshVisitor(boolean concurrently) { + this.concurrently = concurrently; + } /** - * Visits a mesh model. This method visits all facets of the model - * automatically by default. + * Returns {@code true} if the implementation is thread-safe and then + * a single visitor instance can be applied to multiple mesh facets simultaneously. + * If the visitor is not thread-safe, the concurrent inspection + * via the {@link cz.fidentis.analyst.mesh.MeshVisitor#visitConcurrently} + * is still possible, but with multiple visitor instances - one for each facet. + * <p> + * Thread-safe implementation means that any read or write from/to the visitor's + * state is implemented as {@code synchronized}. + * </p> * - * @param model Mesh model to be visited. + * @return {@code true} if the implementation is thread-safe. */ - default void visitMeshModel(MeshModel model) { - for (MeshFacet facet: model.getFacets()) { - facet.accept(this); - } + public boolean isThreadSafe() { + return true; } - + /** - * Visits a mesh facet. + * Returns {@code true} if this visitor is to be applied concurrently, i.e., + * if the concurrency parameter was set and the visitor is thread-safe. + * + * @return {@code true} if this visitor is to be applied concurrently, i.e., + * if the concurrency parameter was set and the visitor is thread-safe. + */ + public boolean concurrently() { + return this.concurrently && isThreadSafe(); + } + + /** + * The inspection method to be implememted by specific visitors. * * @param facet Mesh facet to be visited. */ - void visitMeshFacet(MeshFacet facet); + protected abstract void visitMeshFacet(MeshFacet facet); + + /** + * The main visitation method + * + * @param facet Mesh facet to be visited. + */ + public void visit(MeshFacet facet) { + if (concurrently && isThreadSafe()) { + this.facet = facet; + } else { + visitMeshFacet(facet); + } + } + + @Override + public MeshVisitor call() throws Exception { + visitMeshFacet(facet); + return this; + } + } diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java index 31417b07d7cc579f6318a4e969992930cb9e522f..a70f32d036bcfc3352a538bddc292a600de0d38a 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java +++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java @@ -4,7 +4,9 @@ import java.util.List; import cz.fidentis.analyst.mesh.MeshVisitor; /** - * An ancapsulated mesh plate (with shared vertices). + * An ancapsulated mesh plate, i.e., multiple triangles sharing vertices. + * Mesh facet is iterable (triangle as returned) and visitable by + * {@link cz.fidentis.analyst.mesh.MeshVisitor}s. * * @author Matej Lukes */ @@ -65,9 +67,9 @@ public interface MeshFacet extends Iterable<MeshTriangle> { int getNumTriangles(); /** - * Entry point for visitors. + * Visits this facet. * * @param visitor Visitor */ - void accept(MeshVisitor visitor); + void accept(MeshVisitor visitor); } diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacetImpl.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacetImpl.java index 53dfb144ea91775cde00e565d303d6c7b28d1c0f..058d18edccb15cf33f87f41b98430426dadac180 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacetImpl.java +++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacetImpl.java @@ -19,7 +19,7 @@ public class MeshFacetImpl implements MeshFacet { private List<MeshPoint> vertices = new ArrayList<>(); private CornerTable cornerTable; - + /** * Constructor of MeshFacet */ @@ -39,9 +39,9 @@ public class MeshFacetImpl implements MeshFacet { @Override public void accept(MeshVisitor visitor) { - visitor.visitMeshFacet(this); + visitor.visit(this); } - + @Override public MeshPoint getVertex(int index) { return vertices.get(index); @@ -102,6 +102,7 @@ public class MeshFacetImpl implements MeshFacet { } } + @Override public int getNumTriangles() { return cornerTable.getSize(); } diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java index 7545d83bb5984b162979858c49b8ed6cbfdd1224..6d3711eb4a8f5d1229d54e67455cf51a64e18ac6 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java +++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java @@ -7,48 +7,22 @@ import cz.fidentis.analyst.mesh.MeshVisitor; import cz.fidentis.analyst.mesh.events.FacetAddedEvent; import java.util.Collections; import cz.fidentis.analyst.mesh.events.MeshListener; -import java.util.concurrent.Callable; +import java.util.LinkedList; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.logging.Level; +import java.util.logging.Logger; /** * The main object for triangular meshes. Each mesh model consists * of one or more mesh facets. * <p> - * This class implements the <i>Visitor</i> design pattern for exploration. - * Internal structure can be explored by using an object implementing - * {@link cz.fidentis.analyst.mesh.MeshVisitor}. To methods are available. - * Standard {@link cz.fidentis.analyst.mesh.core.MeshModel#visit} invokes - * the exploration immediately, and the {@link cz.fidentis.analyst.mesh.core.MeshModel#visitConcurrently}, - * which enables parallel processing. The second method has to be called from a code like this: - * <pre> - * int threads = Runtime.getRuntime().availableProcessors(); - * ExecutorService executor = Executors.newFixedThreadPool(threards); - * List<Future<NeshVisitor>> resultList = new LinkedList<>(); - * - * for (...) { - * Future<MeshVisitor> results = executor.submit(meshModel.acceptConcurrently(new ConcreteMeshVisitor())); - * } - * - * executor.shutdown(); - * - * for(Future<MeshVisitor> f : resultList){ - * try { - * MeshVisitor vis = f.get(); - * vis.getResult(); // process the partial results - * } catch (InterruptedException | ExecutionException ex) { - * Logger.getLogger(this.class.getName()).log(Level.SEVERE, null, ex); - * } - * } - * </pre> - * Don't use the same instance of the {@code ConcreteMeshVisitor} inside the for-cycle unless - * you are sure that the visitor's {@code visitMeshModel()} and {@code visitMeshFacet()} - * methods are atomic. - * </p> - * <p> * This class implements the publish-subscribe notifications to changes. * However, the {@link cz.fidentis.analyst.face.HumanFace} class provides similar * functionality at the higher level of abstraction. Therefore, we recomend * to monitor this class when you want to be informed about changes in concrete human face. - * </p> * <p> * Events fired by the class: * <ul> @@ -59,7 +33,7 @@ import java.util.concurrent.Callable; * @author Matej Lukes * @author Radek Oslejsek */ -public class MeshModel implements Callable<MeshVisitor> { +public class MeshModel { private final List<MeshFacet> facets = new ArrayList<>(); @@ -110,30 +84,51 @@ public class MeshModel implements Callable<MeshVisitor> { } /** - * Entry point for visitors. + * Applies the visitor to all mesh facets, either sequentially or in parallel. * - * @param visitor Visitor + * @param visitor Visitor to be apllied for the computation + * @param exec Exisitng executor. If {@code null}, then a new private executor is used. + * @throws {@code NullPointerException} if the visitor is {@code null} */ - public void accept(MeshVisitor visitor) { - visitor.visitMeshModel(this); + public void compute(MeshVisitor visitor, ExecutorService exec) { + if (visitor.concurrently()) { + ExecutorService executor = exec; + if (executor == null) { + int threads = Runtime.getRuntime().availableProcessors(); + executor = Executors.newFixedThreadPool(threads); + } + + List<Future<MeshVisitor>> results = new LinkedList<>(); + + for (MeshFacet f: this.facets) { + f.accept(visitor); + Future<MeshVisitor> result = executor.submit(visitor); // fork and continue + results.add(result); + } + + //executor.shutdown(); + + try { + for (Future<MeshVisitor> f : results) { + f.get(); // wait ntil all computations are finished + } + } catch (InterruptedException | ExecutionException ex) { + Logger.getLogger(MeshModel.class.getName()).log(Level.SEVERE, null, ex); + } + } else { + for (MeshFacet f: this.facets) { + f.accept(visitor); + } + } } /** - * Stores the visitor for concurrent exploration. - * The visitor's invocation has to done via the - * {@link java.util.concurrent.ExecutorService}, which invokes - * {@link cz.fidentis.analyst.mesh.core.MeshModel#call} method. + * Applies the visitor to all mesh facets, either sequentially or in parallel. * - * @param visitor Visitor + * @param visitor Visitor to be apllied */ - public void acceptConcurrently(MeshVisitor visitor) { - this.visitor = visitor; - } - - @Override - public MeshVisitor call() throws Exception { - visitor.visitMeshModel(this); - return visitor; + public void compute(MeshVisitor visitor) { + compute(visitor, null); } /** diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/events/FacetAddedEvent.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/events/FacetAddedEvent.java index b0c2a8f7bb6837f96a041a31704a01f0a5984e55..03d3523c68172db1efbd8eb24f5d97cffa77f58f 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/events/FacetAddedEvent.java +++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/events/FacetAddedEvent.java @@ -12,6 +12,10 @@ public class FacetAddedEvent implements MeshEvent { private final MeshFacet facet; + /** + * + * @param facet Mesdh Facet + */ public FacetAddedEvent(MeshFacet facet) { this.facet = facet; }