Skip to content

Commit 37384be

Browse files
committed
add DeltoidalIcositetrahedronCreator with reference mesh and unit test
1 parent 3bbd5c3 commit 37384be

3 files changed

Lines changed: 405 additions & 0 deletions

File tree

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package mesh.creator.catalan;
2+
3+
import mesh.Mesh3D;
4+
import mesh.creator.IMeshCreator;
5+
6+
public class DeltoidalIcositetrahedronCreator implements IMeshCreator {
7+
8+
private float a = (float) Math.sqrt((2.0 - Math.sqrt(2.0)) / 2.0);
9+
10+
private float b = (float) (1.0 / Math.sqrt(2.0));
11+
12+
private float c = 1.0f;
13+
14+
@Override
15+
public Mesh3D create() {
16+
Mesh3D mesh = new Mesh3D();
17+
createVertices(mesh);
18+
createFaces(mesh);
19+
return mesh;
20+
}
21+
22+
private void createVertices(Mesh3D mesh) {
23+
createCubeVertices(mesh);
24+
createAxisVertices(mesh);
25+
createEdgeVertices(mesh);
26+
}
27+
28+
private void createCubeVertices(Mesh3D mesh) {
29+
mesh.addVertex(a, a, a);
30+
mesh.addVertex(a, a, -a);
31+
mesh.addVertex(a, -a, a);
32+
mesh.addVertex(-a, a, a);
33+
mesh.addVertex(a, -a, -a);
34+
mesh.addVertex(-a, a, -a);
35+
mesh.addVertex(-a, -a, a);
36+
mesh.addVertex(-a, -a, -a);
37+
}
38+
39+
private void createAxisVertices(Mesh3D mesh) {
40+
mesh.addVertex(0, 0, c);
41+
mesh.addVertex(0, 0, -c);
42+
mesh.addVertex(0, c, 0);
43+
mesh.addVertex(0, -c, 0);
44+
mesh.addVertex(c, 0, 0);
45+
mesh.addVertex(-c, 0, 0);
46+
}
47+
48+
private void createEdgeVertices(Mesh3D mesh) {
49+
// (±b, ±b, 0)
50+
mesh.addVertex(b, b, 0);
51+
mesh.addVertex(b, -b, 0);
52+
mesh.addVertex(-b, b, 0);
53+
mesh.addVertex(-b, -b, 0);
54+
55+
// (±b, 0, ±b)
56+
mesh.addVertex(b, 0, b);
57+
mesh.addVertex(b, 0, -b);
58+
mesh.addVertex(-b, 0, b);
59+
mesh.addVertex(-b, 0, -b);
60+
61+
// (0, ±b, ±b)
62+
mesh.addVertex(0, b, b);
63+
mesh.addVertex(0, b, -b);
64+
mesh.addVertex(0, -b, b);
65+
mesh.addVertex(0, -b, -b);
66+
}
67+
68+
private void createFaces(Mesh3D mesh) {
69+
mesh.addFace(8, 18, 0, 22);
70+
mesh.addFace(9, 23, 1, 19);
71+
mesh.addFace(2, 18, 8, 24);
72+
mesh.addFace(8, 22, 3, 20);
73+
mesh.addFace(9, 19, 4, 25);
74+
mesh.addFace(5, 23, 9, 21);
75+
mesh.addFace(6, 24, 8, 20);
76+
mesh.addFace(9, 25, 7, 21);
77+
78+
mesh.addFace(10, 22, 0, 14);
79+
mesh.addFace(1, 23, 10, 14);
80+
mesh.addFace(15, 2, 24, 11);
81+
mesh.addFace(3, 22, 10, 16);
82+
mesh.addFace(25, 4, 15, 11);
83+
mesh.addFace(10, 23, 5, 16);
84+
mesh.addFace(11, 24, 6, 17);
85+
mesh.addFace(7, 25, 11, 17);
86+
87+
mesh.addFace(14, 0, 18, 12);
88+
mesh.addFace(19, 1, 14, 12);
89+
mesh.addFace(18, 2, 15, 12);
90+
mesh.addFace(20, 3, 16, 13);
91+
mesh.addFace(15, 4, 19, 12);
92+
mesh.addFace(16, 5, 21, 13);
93+
mesh.addFace(17, 6, 20, 13);
94+
mesh.addFace(21, 7, 17, 13);
95+
}
96+
}
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
package mesh.creator.catalan;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertFalse;
5+
import static org.junit.jupiter.api.Assertions.assertNotNull;
6+
import static org.junit.jupiter.api.Assertions.assertTrue;
7+
import static org.junit.jupiter.api.Assumptions.assumeFalse;
8+
import static org.junit.jupiter.api.Assumptions.assumeTrue;
9+
10+
import java.io.File;
11+
import java.util.EnumSet;
12+
13+
import org.junit.jupiter.api.Test;
14+
15+
import math.Bounds;
16+
import math.Vector3f;
17+
import mesh.Face3D;
18+
import mesh.Mesh3D;
19+
import mesh.creator.IMeshCreator;
20+
import mesh.io.SimpleObjectReader;
21+
import mesh.util.MeshBoundsCalculator;
22+
import util.MeshTestUtil;
23+
24+
public class DeltoidalIcositetrahedronCreatorTest {
25+
26+
enum MeshCapabilities {
27+
HAS_FACES,
28+
IS_MANIFOLD,
29+
HAS_VOLUME,
30+
ALLOWS_LOOSE_VERTICES,
31+
CALCULATES_VERTEX_NORMALS
32+
}
33+
34+
private static final EnumSet<MeshCapabilities> CAPABILITIES =
35+
EnumSet.of(
36+
MeshCapabilities.HAS_FACES, MeshCapabilities.IS_MANIFOLD, MeshCapabilities.HAS_VOLUME);
37+
38+
private static final int DEFAULT_VERTEX_COUNT = 26;
39+
40+
private static final int DEFAULT_FACE_COUNT = 24;
41+
42+
private static final int EXPECTED_DEFAULT_TRIANGLE_COUNT = 0;
43+
44+
private static final int EXPECTED_DEFAULT_QUAD_COUNT = 24;
45+
46+
@Test
47+
public void testImplementsMeshCreatorInstance() {
48+
DeltoidalIcositetrahedronCreator creator = new DeltoidalIcositetrahedronCreator();
49+
assertTrue(creator instanceof IMeshCreator);
50+
}
51+
52+
@Test
53+
public void testCreatedMeshIsNotNullByDefault() {
54+
DeltoidalIcositetrahedronCreator creator = new DeltoidalIcositetrahedronCreator();
55+
assertNotNull(creator.create());
56+
}
57+
58+
@Test
59+
public void testVerticesContainNoNaNOrInfinity() {
60+
Mesh3D mesh = new DeltoidalIcositetrahedronCreator().create();
61+
for (Vector3f v : mesh.getVertices()) {
62+
assertFalse(Float.isNaN(v.x) || Float.isNaN(v.y) || Float.isNaN(v.z));
63+
assertFalse(Float.isInfinite(v.x) || Float.isInfinite(v.y) || Float.isInfinite(v.z));
64+
}
65+
}
66+
67+
@Test
68+
public void testMeshHasValidBoundingBox() {
69+
assumeTrue(CAPABILITIES.contains(MeshCapabilities.HAS_VOLUME));
70+
71+
Mesh3D mesh = new DeltoidalIcositetrahedronCreator().create();
72+
Bounds bounds = MeshBoundsCalculator.calculateBounds(mesh);
73+
74+
assertTrue(bounds.getWidth() > 0);
75+
assertTrue(bounds.getHeight() > 0);
76+
assertTrue(bounds.getDepth() > 0);
77+
}
78+
79+
@Test
80+
public void testCreatesUniqueInstances() {
81+
DeltoidalIcositetrahedronCreator creator = new DeltoidalIcositetrahedronCreator();
82+
Mesh3D mesh0 = creator.create();
83+
Mesh3D mesh1 = creator.create();
84+
Mesh3D mesh2 = creator.create();
85+
assertTrue(mesh0 != mesh1);
86+
assertTrue(mesh1 != mesh2);
87+
}
88+
89+
@Test
90+
public void testDefaultVertexCount() {
91+
Mesh3D mesh = new DeltoidalIcositetrahedronCreator().create();
92+
assertEquals(DEFAULT_VERTEX_COUNT, mesh.getVertexCount());
93+
assertEquals(DEFAULT_VERTEX_COUNT, mesh.getVertices().size());
94+
}
95+
96+
@Test
97+
public void testDefaultFaceCount() {
98+
Mesh3D mesh = new DeltoidalIcositetrahedronCreator().create();
99+
assertEquals(DEFAULT_FACE_COUNT, mesh.getFaceCount());
100+
assertEquals(DEFAULT_FACE_COUNT, mesh.getFaces().size());
101+
}
102+
103+
@Test
104+
public void testDefaultTriangleCount() {
105+
Mesh3D mesh = new DeltoidalIcositetrahedronCreator().create();
106+
int actual = 0;
107+
108+
for (Face3D face : mesh.getFaces()) {
109+
if (face.getVertexCount() == 3) {
110+
actual++;
111+
}
112+
}
113+
assertEquals(EXPECTED_DEFAULT_TRIANGLE_COUNT, actual);
114+
}
115+
116+
@Test
117+
public void testDefaultQuadCount() {
118+
Mesh3D mesh = new DeltoidalIcositetrahedronCreator().create();
119+
int actual = 0;
120+
121+
for (Face3D face : mesh.getFaces()) {
122+
if (face.getVertexCount() == 4) {
123+
actual++;
124+
}
125+
}
126+
assertEquals(EXPECTED_DEFAULT_QUAD_COUNT, actual);
127+
}
128+
129+
@Test
130+
public void testFacesReferenceValidVertices() {
131+
Mesh3D mesh = new DeltoidalIcositetrahedronCreator().create();
132+
int vertexCount = mesh.getVertexCount();
133+
134+
for (Face3D face : mesh.getFaces()) {
135+
for (int i = 0; i < face.getVertexCount(); i++) {
136+
int idx = face.getIndexAt(i);
137+
assertTrue(idx >= 0 && idx < vertexCount);
138+
}
139+
}
140+
}
141+
142+
@Test
143+
public void testVertexPositionsAreDeterministic() {
144+
DeltoidalIcositetrahedronCreator creator = new DeltoidalIcositetrahedronCreator();
145+
Mesh3D a = creator.create();
146+
Mesh3D b = creator.create();
147+
148+
for (int i = 0; i < a.getVertexCount(); i++) {
149+
assertEquals(a.getVertices().get(i), b.getVertices().get(i));
150+
}
151+
}
152+
153+
@Test
154+
public void testVertexDataIsNotSharedBetweenInstances() {
155+
DeltoidalIcositetrahedronCreator creator = new DeltoidalIcositetrahedronCreator();
156+
157+
Mesh3D mesh0 = creator.create();
158+
mesh0.clearVertices();
159+
160+
Mesh3D mesh1 = creator.create();
161+
162+
assertEquals(DEFAULT_VERTEX_COUNT, mesh1.getVertexCount());
163+
}
164+
165+
@Test
166+
public void testFaceDataIsNotSharedBetweenInstances() {
167+
DeltoidalIcositetrahedronCreator creator = new DeltoidalIcositetrahedronCreator();
168+
169+
Mesh3D mesh0 = creator.create();
170+
mesh0.clearFaces();
171+
172+
Mesh3D mesh1 = creator.create();
173+
174+
assertEquals(DEFAULT_FACE_COUNT, mesh1.getFaceCount());
175+
}
176+
177+
@Test
178+
public void testVertexListIsNotEmpty() {
179+
Mesh3D mesh = new DeltoidalIcositetrahedronCreator().create();
180+
assertFalse(mesh.getVertices().isEmpty());
181+
assertEquals(mesh.getVertexCount(), mesh.getVertices().size());
182+
}
183+
184+
@Test
185+
public void testMeshHasNoLooseVertices() {
186+
assumeFalse(CAPABILITIES.contains(MeshCapabilities.ALLOWS_LOOSE_VERTICES));
187+
188+
Mesh3D mesh = new DeltoidalIcositetrahedronCreator().create();
189+
assertTrue(MeshTestUtil.meshHasNoLooseVertices(mesh));
190+
}
191+
192+
@Test
193+
public void testVertexCountIsConsistent() {
194+
DeltoidalIcositetrahedronCreator creator = new DeltoidalIcositetrahedronCreator();
195+
Mesh3D mesh0 = creator.create();
196+
Mesh3D mesh1 = creator.create();
197+
assertEquals(mesh0.getVertexCount(), mesh1.getVertexCount());
198+
}
199+
200+
@Test
201+
public void testFaceCountIsConsistent() {
202+
DeltoidalIcositetrahedronCreator creator = new DeltoidalIcositetrahedronCreator();
203+
Mesh3D mesh0 = creator.create();
204+
Mesh3D mesh1 = creator.create();
205+
assertEquals(mesh0.getFaceCount(), mesh1.getFaceCount());
206+
}
207+
208+
@Test
209+
public void testMeshHasNoDuplicatedFaces() {
210+
Mesh3D mesh = new DeltoidalIcositetrahedronCreator().create();
211+
assertTrue(MeshTestUtil.meshHasNoDuplicatedFaces(mesh));
212+
}
213+
214+
@Test
215+
public void testIsManifold() {
216+
assumeTrue(CAPABILITIES.contains(MeshCapabilities.IS_MANIFOLD));
217+
218+
Mesh3D mesh = new DeltoidalIcositetrahedronCreator().create();
219+
assertTrue(MeshTestUtil.isManifold(mesh));
220+
}
221+
222+
@Test
223+
public void testCreatorDoesNotModifyFaceTags() {
224+
Mesh3D mesh = new DeltoidalIcositetrahedronCreator().create();
225+
String expected = "";
226+
227+
for (Face3D face : mesh.getFaces()) {
228+
String actual = face.getTag();
229+
assertEquals(expected, actual);
230+
}
231+
}
232+
233+
@Test
234+
public void testMatchesReferenceMesh() {
235+
File file =
236+
new File("./src/test/java/resources/characterization/DeltoidalIcositetrahedronCreator.obj");
237+
SimpleObjectReader reader = new SimpleObjectReader();
238+
Mesh3D referenceMesh = reader.read(file);
239+
Mesh3D actual = new DeltoidalIcositetrahedronCreator().create();
240+
241+
for (int i = 0; i < actual.getVertexCount(); i++) {
242+
Vector3f actualV = actual.getVertexAt(i);
243+
Vector3f referenceV = referenceMesh.getVertexAt(i);
244+
245+
assertEquals(referenceV.x, actualV.x, 0.0001f);
246+
assertEquals(referenceV.y, actualV.y, 0.0001f);
247+
assertEquals(referenceV.z, actualV.z, 0.0001f);
248+
}
249+
250+
for (int i = 0; i < actual.getFaceCount(); i++) {
251+
Face3D actualF = actual.getFaceAt(i);
252+
Face3D referenceF = referenceMesh.getFaceAt(i);
253+
for (int j = 0; j < actualF.getVertexCount(); j++) {
254+
assertEquals(referenceF.getIndexAt(j), actualF.getIndexAt(j));
255+
}
256+
}
257+
}
258+
}

0 commit comments

Comments
 (0)