Skip to content

Commit d81da27

Browse files
committed
use the Hull operation to skin the sphere
1 parent 9f31aac commit d81da27

1 file changed

Lines changed: 43 additions & 37 deletions

File tree

src/main/java/eu/mihosoft/vrl/v3d/Sphere.java

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,13 @@
3434
package eu.mihosoft.vrl.v3d;
3535

3636
import java.util.ArrayList;
37+
import java.util.Arrays;
38+
import java.util.HashMap;
3739
import java.util.List;
40+
import java.util.Map;
41+
import java.util.function.Function;
42+
43+
import eu.mihosoft.vrl.v3d.ext.quickhull3d.HullUtil;
3844

3945
// Auto-generated Javadoc
4046
/**
@@ -163,48 +169,48 @@ private void init() {
163169
private Vertex sphereVertex(Vector3d c, double r, double theta, double phi) {
164170
theta *= Math.PI * 2;
165171
phi *= Math.PI;
172+
173+
// Clamp poles to exact values to avoid sin(PI) floating point error
174+
if (phi <= 0)
175+
return new Vertex(c.plus(new Vector3d(0, r, 0)));
176+
if (phi >= Math.PI)
177+
return new Vertex(c.plus(new Vector3d(0, -r, 0)));
178+
166179
Vector3d dir = new Vector3d(Math.cos(theta) * Math.sin(phi), Math.cos(phi), Math.sin(theta) * Math.sin(phi));
167180
return new Vertex(c.plus(dir.times(r)));
168181
}
169182

170-
/*
171-
* (non-Javadoc)
172-
*
173-
* @see eu.mihosoft.vrl.v3d.Primitive#toPolygons()
174-
*/
175-
@Override
176183
public List<Polygon> toPolygons() {
177-
if (radius <= 0)
178-
throw new NumberFormatException("radius can not be negative");
179-
List<Polygon> polygons = new ArrayList<>();
180-
for (int i = 0; i < numSlices; i++) {
181-
for (int j = 0; j < numStacks; j++) {
182-
183-
Vertex v0 = sphereVertex(center, radius, i / (double) numSlices, j / (double) numStacks);
184-
Vertex v1 = sphereVertex(center, radius, (i + 1) / (double) numSlices, j / (double) numStacks);
185-
Vertex v2 = sphereVertex(center, radius, (i + 1) / (double) numSlices, (j + 1) / (double) numStacks);
186-
Vertex v3 = sphereVertex(center, radius, i / (double) numSlices, (j + 1) / (double) numStacks);
187-
188-
if (j == 0) {
189-
addPolygon(polygons, v0, v3, v2);
190-
} else if (j == numStacks - 1) {
191-
addPolygon(polygons, v0, v2, v1);
192-
} else {
193-
addPolygon(polygons, v0, v3, v1);
194-
addPolygon(polygons, v1, v3, v2);
195-
}
184+
List<Vector3d> points = new ArrayList<>();
185+
186+
// 1. Add the Poles explicitly (avoiding the loop to ensure they are clean)
187+
points.add(new Vector3d(center.x, center.y + radius, center.z)); // North
188+
points.add(new Vector3d(center.x, center.y - radius, center.z)); // South
189+
190+
// 2. Generate the rings (excluding the pole stacks)
191+
for (int j = 1; j < numStacks; j++) {
192+
double phi = Math.PI * j / numStacks;
193+
double y = Math.cos(phi);
194+
double rRing = Math.sin(phi);
195+
196+
for (int i = 0; i < numSlices; i++) {
197+
double theta = 2.0 * Math.PI * i / numSlices;
198+
199+
double x = Math.cos(theta) * rRing;
200+
double z = Math.sin(theta) * rRing;
201+
202+
// Micro-snapping to zero for stability
203+
if (Math.abs(x) < 1e-12)
204+
x = 0;
205+
if (Math.abs(z) < 1e-12)
206+
z = 0;
207+
208+
points.add(new Vector3d(center.x + x * radius, center.y + y * radius, center.z + z * radius));
196209
}
197210
}
198-
return polygons;
211+
return HullUtil.hull(points, getProperties()).getPolygons();
199212
}
200213

201-
private void addPolygon(List<Polygon> polygons, Vertex... verts) {
202-
try {
203-
polygons.add(new Polygon(List.of(verts), getProperties()));
204-
} catch (ColinearPointsException e) {
205-
e.printStackTrace();
206-
}
207-
}
208214

209215
/**
210216
* Gets the center.
@@ -262,8 +268,8 @@ public int getNumSlices() {
262268
* the numSlices to set
263269
*/
264270
public Sphere setNumSlices(int numSlices) {
265-
if (numSlices > (NUM_SLICES * 4))
266-
System.out.println("Very large sphere! this may crash!");
271+
// if (numSlices > (NUM_SLICES * 4))
272+
// System.out.println("Very large sphere! this may crash!");
267273
this.numSlices = numSlices;
268274
return this;
269275
}
@@ -284,8 +290,8 @@ public int getNumStacks() {
284290
* the numStacks to set
285291
*/
286292
public Sphere setNumStacks(int numStacks) {
287-
if (numStacks > (NUM_STACKS * 4))
288-
System.out.println("Very large sphere! this may crash!");
293+
// if (numStacks > (NUM_STACKS * 4))
294+
// System.out.println("Very large sphere! this may crash!");
289295
this.numStacks = numStacks;
290296
return this;
291297
}

0 commit comments

Comments
 (0)