Skip to content

Commit 3989ddd

Browse files
committed
addin hull points
1 parent 34fcb39 commit 3989ddd

1 file changed

Lines changed: 49 additions & 0 deletions

File tree

bindings/java/src/main/java/com/cadoodlecad/manifold/ManifoldBindings.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,10 +477,59 @@ public ManifoldBindings(File cacheDirectory) throws Exception {
477477
ValueLayout.JAVA_LONG // arg6: size_t n_tris
478478
);
479479

480+
load("manifold_hull_pts", ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_LONG);
481+
480482
System.out.println("Available Manifold functions: " + functions.keySet());
481483

482484
}
483485

486+
/**
487+
* Computes the convex hull of a set of points.
488+
*
489+
* Each point is supplied as a {@code double[3]} of {x, y, z}. If fewer than
490+
* 4 points are provided, or all points are coplanar, an empty manifold is
491+
* returned (matching the C++ API's documented behaviour).
492+
*
493+
* The caller owns the returned MemorySegment and must eventually pass it
494+
* to {@link #delete(MemorySegment)} or {@link #safeDelete(MemorySegment)}.
495+
*
496+
* @param points list of points, each a double[3] of {x, y, z}
497+
* @return the convex hull as a ManifoldManifold* MemorySegment
498+
* @throws IllegalArgumentException if any point array has length != 3
499+
* @throws Throwable on native call failure
500+
*/
501+
public MemorySegment hullPoints(ArrayList<double[]> points) throws Throwable {
502+
if (points == null || points.isEmpty()) {
503+
return empty();
504+
}
505+
506+
// Validate all points up front before allocating any native memory.
507+
for (int i = 0; i < points.size(); i++) {
508+
if (points.get(i) == null || points.get(i).length != 3) {
509+
throw new IllegalArgumentException("Point at index " + i + " must be a double[3] of {x, y, z}");
510+
}
511+
}
512+
513+
// ManifoldVec3 is three packed doubles: {double x, double y, double z} = 24 bytes each.
514+
final long VEC3_BYTES = 3 * Double.BYTES;
515+
long count = points.size();
516+
517+
try (Arena arena = Arena.ofConfined()) {
518+
// Allocate a flat array of ManifoldVec3 structs in a temporary arena.
519+
MemorySegment ptsBuffer = arena.allocate(VEC3_BYTES * count);
520+
for (int i = 0; i < count; i++) {
521+
double[] pt = points.get(i);
522+
long base = i * VEC3_BYTES;
523+
ptsBuffer.set(ValueLayout.JAVA_DOUBLE, base, pt[0]); // x
524+
ptsBuffer.set(ValueLayout.JAVA_DOUBLE, base + Double.BYTES, pt[1]); // y
525+
ptsBuffer.set(ValueLayout.JAVA_DOUBLE, base + 2 * Double.BYTES, pt[2]); // z
526+
}
527+
528+
MemorySegment mem = (MemorySegment) functions.get("manifold_alloc_manifold").invoke();
529+
return (MemorySegment) functions.get("manifold_hull_pts").invoke(mem, ptsBuffer, count);
530+
}
531+
}
532+
484533
/**
485534
* Slices the manifold at the given Z height, returning the cross-section as a
486535
* list of polygon contours. Each contour is a list of (x, y) vertex pairs

0 commit comments

Comments
 (0)