Skip to content

Commit b8647cd

Browse files
committed
add DisdyakisDodecahedronCreator with reference mesh and unit test
1 parent 37384be commit b8647cd

3 files changed

Lines changed: 445 additions & 0 deletions

File tree

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

0 commit comments

Comments
 (0)