Skip to content
Snippets Groups Projects
Commit b3306fc6 authored by Radek Ošlejšek's avatar Radek Ošlejšek
Browse files

Computation of BoundingBox refactored as Visitor

parent 2ac3b911
No related branches found
No related tags found
No related merge requests found
Showing
with 190 additions and 67 deletions
......@@ -3,10 +3,11 @@ package cz.fidentis.analyst.symmetry;
import cz.fidentis.analyst.mesh.core.CornerTableRow;
import cz.fidentis.analyst.mesh.core.MeshFacet;
import cz.fidentis.analyst.mesh.core.MeshPoint;
import cz.fidentis.analyst.mesh.core.BoundingBox;
import cz.fidentis.analyst.mesh.visitors.BoundingBox;
import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
import cz.fidentis.analyst.mesh.core.MeshPointImpl;
import cz.fidentis.analyst.mesh.core.MeshTriangle;
import cz.fidentis.analyst.mesh.visitors.BoundingBoxVisitor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
......@@ -15,11 +16,6 @@ import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.ProgressMonitor;
import javax.swing.UIManager;
//import javax.swing.ImageIcon;
//import javax.swing.JOptionPane;
//import javax.swing.JPanel;
//import javax.swing.ProgressMonitor;
//import javax.swing.UIManager;
import javax.vecmath.Vector3d;
/**
......@@ -40,8 +36,6 @@ public class SymmetryEstimator {
private List<MeshTriangle> triangles; // Helping array of triangles computed from corner table
//private JPanel panel; // panel for configuration of symmetry counting
private final Config config;
/**
......@@ -60,8 +54,6 @@ public class SymmetryEstimator {
for (int i = 0; i < areas.length; i++) {
areas[i] = computeTriangleVertexAreas(triangles.get(i));
}
boundingBox = facet.getBoundingBox();
}
/**
......@@ -83,22 +75,6 @@ public class SymmetryEstimator {
return config;
}
/**
*
* @return panel for configuration of symmetry counting
*/
//public JPanel getPanel() {
// return panel;
//}
/**
*
* @param panel new panel for configuration of symmetry counting
*/
//public void setPanel(JPanel panel) {
// this.panel = panel;
//}
/**
*
* @return Facet of the model on which symmetry is computed
......@@ -108,13 +84,15 @@ public class SymmetryEstimator {
}
/**
* If bounding box is not created yet, it creates new one.
* If bounding box is not created yet, it's created now.
*
* @return Represent min-max box of the boundries of the model.
*/
public BoundingBox getBoundingBox() {
if (boundingBox == null) {
boundingBox = facet.getBoundingBox();
BoundingBoxVisitor visitor = new BoundingBoxVisitor();
facet.accept(visitor);
boundingBox = visitor.getBoundingBox();
}
return boundingBox;
}
......@@ -126,8 +104,6 @@ public class SymmetryEstimator {
*/
public Plane getApproxSymmetryPlane(JPanel panel) {
///UIManager.put("ProgressMonitor.progressText", "Counting symmetry...");
ArrayList<ApproxSymmetryPlane> planes = new ArrayList<>();
//List<Vector3d> normals = calculateNormals();
if (!facet.hasVertexNormals()) {
......@@ -215,7 +191,7 @@ public class SymmetryEstimator {
config.getMinCurvRatio(),
config.getMinAngleCos(),
config.getMinNormAngleCos(),
boundingBox.getMaxDiag() * config.getMaxRelDistance());
getBoundingBox().getMaxDiag() * config.getMaxRelDistance());
planes.add(new ApproxSymmetryPlane(newPlane, currentVotes));
......@@ -241,7 +217,6 @@ public class SymmetryEstimator {
finalPlanes.add(planes.get(i));
}
}
//Plane finalPlane = new Plane(0, 0, 0, 0);
double newA = 0, newB = 0, newC = 0, newD = 0;
Vector3d refDir = finalPlanes.get(0).getNormal();
for (int i = 0; i < finalPlanes.size(); i++) {
......@@ -279,7 +254,7 @@ public class SymmetryEstimator {
*/
public SymmetryEstimator mergeWithPlane(Plane plane) {
Vector3d normal = plane.getNormal();
Vector3d midPoint = boundingBox.getMidPoint().getPosition();
Vector3d midPoint = getBoundingBox().getMidPoint().getPosition();
double alpha = -((normal.x * midPoint.x) +
(normal.y * midPoint.y) + (normal.z * midPoint.z) +
......@@ -307,7 +282,7 @@ public class SymmetryEstimator {
b.normalize();
SymmetryEstimator planeMesh = new SymmetryEstimator(midPointOnPlane, a, b,
(boundingBox.getMaxPoint().subtractPosition(boundingBox.getMinPoint())).getPosition().x);
(getBoundingBox().getMaxPoint().subtractPosition(getBoundingBox().getMinPoint())).getPosition().x);
return mergeMeshWith(planeMesh);
}
......
......@@ -19,6 +19,7 @@
<publicPackages> <!-- expose API/packages to other modules -->
<publicPackage>cz.fidentis.analyst.mesh.core.*</publicPackage>
<publicPackage>cz.fidentis.analyst.mesh.io.*</publicPackage>
<publicPackage>cz.fidentis.analyst.mesh.visitors.*</publicPackage>
<!--<publicPackage>cz.fidentis.analyst.mesh.core.MeshFacet</publicPackage>-->
<!--<publicPackage>cz.fidentis.analyst.mesh.core.MeshPoint</publicPackage>-->
</publicPackages>
......
package cz.fidentis.analyst.mesh.core;
import cz.fidentis.analyst.mesh.visitors.BoundingBox;
import cz.fidentis.analyst.mesh.visitors.Visitor;
import java.util.List;
/**
......@@ -51,12 +53,6 @@ public interface MeshFacet {
*/
List<MeshTriangle> asTriangles();
/**
* Computes and returns bounding box of the mesh facet.
* @return bounding box of the mesh facet.
*/
BoundingBox getBoundingBox();
/**
* Returns true if normals of vertices are calculated.
* @return true if normals of vertices are calculated.
......@@ -67,4 +63,11 @@ public interface MeshFacet {
* Calculates normals of vertices from normals of triangles.
*/
void calculateVertexNormals();
/**
* Entry point for visitors.
*
* @param visitor Visitor
*/
public void accept(Visitor visitor);
}
package cz.fidentis.analyst.mesh.core;
import cz.fidentis.analyst.mesh.visitors.BoundingBox;
import cz.fidentis.analyst.mesh.visitors.Visitor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
......@@ -33,6 +35,11 @@ public class MeshFacetImpl implements MeshFacet {
vertices.addAll(facet.getVertices()); // encapsulation preserved - vertices MeshPoints are immutable)
cornerTable = new CornerTable(facet.getCornerTable());
}
@Override
public void accept(Visitor visitor) {
visitor.visitMeshFacet(this);
}
@Override
public MeshPoint getVertex(int index) {
......@@ -71,11 +78,6 @@ public class MeshFacetImpl implements MeshFacet {
return ret;
}
@Override
public BoundingBox getBoundingBox() {
return new BoundingBox(this.vertices);
}
@Override
public boolean hasVertexNormals() {
return !this.vertices.isEmpty() && this.vertices.get(0).getNormal() != null;
......
package cz.fidentis.analyst.mesh.core;
import cz.fidentis.analyst.mesh.visitors.Visitor;
import java.util.ArrayList;
import java.util.List;
......@@ -9,7 +10,7 @@ import java.util.List;
* @author Matej Lukes
*/
public class MeshModel {
private List<MeshFacet> facets = new ArrayList<>();
private final List<MeshFacet> facets = new ArrayList<>();
/**
* Constructor of MeshModel
......@@ -46,4 +47,13 @@ public class MeshModel {
public void addFacet(MeshFacet facet) {
facets.add(facet);
}
/**
* Entry point for visitors.
*
* @param visitor Visitor
*/
public void accept(Visitor visitor) {
visitor.visitMeshModel(this);
}
}
......@@ -9,7 +9,7 @@ import javax.vecmath.Vector3d;
*/
public class MeshPointImpl implements MeshPoint {
private final Vector3d position, normal, texCoord;
private Vector3d position, normal, texCoord;
/**
* constructor of meshPoint
......@@ -20,12 +20,18 @@ public class MeshPointImpl implements MeshPoint {
*/
public MeshPointImpl(Vector3d position, Vector3d normal, Vector3d texCoord) {
if (position == null) {
throw new NullPointerException("position cannot be null");
throw new IllegalArgumentException("position cannot be null");
} else {
this.position = new Vector3d(position);
}
this.position = new Vector3d(position);
this.normal = new Vector3d(normal);
this.texCoord = new Vector3d(texCoord);
if (normal != null) {
this.normal = new Vector3d(normal);
}
if (texCoord != null) {
this.texCoord = new Vector3d(texCoord);
}
}
/**
......@@ -197,4 +203,10 @@ public class MeshPointImpl implements MeshPoint {
return position.hashCode() + normal.hashCode() + texCoord.hashCode();
}
@Override
public String toString() {
return "position " + position + ", " +
"normal " + normal + ", " +
"tex-coord " + texCoord;
}
}
package cz.fidentis.analyst.mesh.core;
package cz.fidentis.analyst.mesh.visitors;
import cz.fidentis.analyst.mesh.core.MeshPoint;
import cz.fidentis.analyst.mesh.core.MeshPointImpl;
import java.util.List;
import javax.vecmath.Vector3d;
......@@ -11,13 +13,12 @@ import javax.vecmath.Vector3d;
public class BoundingBox {
private final MeshPoint maxPoint;
private final MeshPoint minPoint;
private final MeshPoint midPoint;
private final double maxDiag;
private MeshPoint maxPoint;
private MeshPoint minPoint;
/**
* Creates bounding box from given mesh points.
*
* @param points List of mesh points, must not be null or empty
* @throws IllegalArgumentException if the @code{points} param is null or empty
*/
......@@ -26,9 +27,22 @@ public class BoundingBox {
throw new IllegalArgumentException("points");
}
minPoint = new MeshPointImpl(new Vector3d(Double.POSITIVE_INFINITY,Double.POSITIVE_INFINITY,Double.POSITIVE_INFINITY), null, null);
minPoint = new MeshPointImpl(new Vector3d(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY), null, null);
maxPoint = new MeshPointImpl(new Vector3d(Double.NEGATIVE_INFINITY,Double.NEGATIVE_INFINITY,Double.NEGATIVE_INFINITY), null, null);
compute(points);
}
/**
* Creates bounding box from given mesh points, possibly extends the existing BB.
*
* @param points List of mesh points, must not be null or empty
*/
public void compute(List<MeshPoint> points) {
if (points == null || points.isEmpty()) {
return;
}
for (int i = 0; i < points.size(); i++) {
MeshPoint point = points.get(i);
......@@ -40,10 +54,6 @@ public class BoundingBox {
maxPoint.getPosition().y = Math.max(maxPoint.getPosition().y, point.getPosition().y);
maxPoint.getPosition().z = Math.max(maxPoint.getPosition().z, point.getPosition().z);
}
midPoint = (minPoint.addPosition(maxPoint)).multiplyPosition(0.5);
MeshPoint diag = maxPoint.subtractPosition(minPoint);
this.maxDiag = diag.abs();
}
/**
......@@ -59,7 +69,7 @@ public class BoundingBox {
* @return middle point of the bounding box
*/
public MeshPoint getMidPoint() {
return midPoint;
return (minPoint.addPosition(maxPoint)).multiplyPosition(0.5);
}
/**
......@@ -75,7 +85,7 @@ public class BoundingBox {
* @return maximal diagonal of bounding box
*/
public double getMaxDiag() {
return maxDiag;
return maxPoint.subtractPosition(minPoint).abs();
}
/**
......@@ -89,8 +99,6 @@ public class BoundingBox {
str += System.lineSeparator();
str += "\t" + "- min point : " + this.minPoint + System.lineSeparator();
str += "\t" + "- max point : " + this.maxPoint + System.lineSeparator();
str += "\t" + "- mid point : " + this.midPoint + System.lineSeparator();
str += "\t" + "- max diag : " + this.maxDiag + System.lineSeparator();
return str;
}
}
\ No newline at end of file
package cz.fidentis.analyst.mesh.visitors;
import cz.fidentis.analyst.mesh.core.MeshFacet;
import cz.fidentis.analyst.mesh.core.MeshModel;
/**
* Computes a 3D bounding box (cube).
*
* @author oslejsek
*/
public class BoundingBoxVisitor implements Visitor {
private BoundingBox bbox;
@Override
public void visitMeshFacet(MeshFacet facet) {
if (bbox == null) {
bbox = new BoundingBox(facet.getVertices());
} else {
bbox.compute(facet.getVertices());
}
}
/**
* Returns computed bounding box.
* @return Bounding box or null
*/
public BoundingBox getBoundingBox() {
return bbox;
}
}
package cz.fidentis.analyst.mesh.visitors;
import cz.fidentis.analyst.mesh.core.MeshFacet;
import cz.fidentis.analyst.mesh.core.MeshModel;
/**
* Visitor for the traversal of @code{MeshModel} and @code{MeshFacet}.
*
* @author oslejsek
*/
public interface Visitor {
/**
* Visits a mesh model.
*
* @param model Mesh model to be visited.
*/
default void visitMeshModel(MeshModel model) {
for (MeshFacet facet: model.getFacets()) {
facet.accept(this);
}
}
/**
* Visits a mesh facet.
*
* @param facet Mesh facet to be visited.
*/
void visitMeshFacet(MeshFacet facet);
}
package cz.fidentis.analyst.mesh.visitors;
import cz.fidentis.analyst.mesh.core.MeshModel;
import cz.fidentis.analyst.mesh.io.MeshObjLoader;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.vecmath.Vector3d;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author Radek Oslejsek
*/
public class BoundingBoxVisitorTest {
Path testFileDirectory = Paths.get("src", "test", "resources", "cz", "fidentis", "analyst", "mesh", "io");
@Test
void moreObjectFileTest() { //TODO: Not testing in loader
File moreObjects = new File(testFileDirectory.toFile(), "MoreObjects.obj");
Exception ex = assertThrows(IOException.class, () -> MeshObjLoader.read(moreObjects));
}
@Test
void icoSphereTest() throws IOException {
MeshModel m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "IcoSphere-20.obj"));
assertNotNull(m);
BoundingBoxVisitor visitor = new BoundingBoxVisitor();
m.accept(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());
}
@Test
void combinedTest() throws IOException {
MeshModel m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "IcoSphere-20.obj"));
assertNotNull(m);
BoundingBoxVisitor visitor = new BoundingBoxVisitor();
m.accept(visitor);
m = MeshObjLoader.read(new File(testFileDirectory.toFile(), "Tetrahedron.obj"));
assertNotNull(m);
m.accept(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());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment