107 Commits
Author SHA1 Message Date
Emmett Lalish 7b33277245 Remove duplicate Smoothing APIs (#1814)
* almost updated scallop

* scallop working

* fixed scallop

* sharpened scallop

* removed some smoothing APIs

* fixed some tests

* tests passing

* updated bindings examples

* fix formatting

* fix more formatting
2026-09-07 12:44:38 +12:00
Zach Loafman c50001b82d Add CrossSection::EvenOdd for even-odd input fill (#1788) 2026-08-10 21:10:21 +12:00
Zach LoafmanandClaude Sonnet 4.6 bf47ebccc6 CrossSection: drop FillRule/Compose, add SetTolerance/GetTolerance (#1760)
* CrossSection API break (#1707): drop FillRule/Compose, const-ref Hull, tolerance API

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CrossSection API break (#1707): C bindings + test fixes

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CrossSection API break (#1707): Python + WASM bindings

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CrossSection API break (#1707): doc + example followups

- Drop stale @param fillrule from CrossSection(SimplePolygon) doc
- Replace CrossSection.compose with batch_boolean in all_apis.py
- Add get_tolerance/set_tolerance to all_apis.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* CrossSection API break (#1707): fix WASM JoinType::Bevel

'Bevel' was registered in the embind enum but missing from the
TypeScript type and from joinTypeToInt(), so passing 'Bevel' silently
fell through to 'Square' (0). Add it to both.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* CrossSection API break (#1707): tolerance API fixups

- Rect and Circle constructors now set tolerance_ via InferEps,
  consistent with the Polygons constructor. Previously GetTolerance()
  returned 0 for these paths.
- Hull(const SimplePolygon&): use the local sorted copy (points) for
  InferEps, not the original const-ref (pts).
- Move SetTolerance declaration to the Information doxygen group
  alongside GetTolerance.
- Add CBIND.cross_section_tolerance smoke test for
  manifold_cross_section_get/set_tolerance.
- Fix stale comment in SimplifyPostFiltersBoolean2Output referencing
  the old epsilon=1e-6 default.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* CrossSection API break (#1707): fix WASM compose/voronoi, doc Simplify default

- Remove 'compose' from crossSectionStaticFunctions in garbage-collector.ts
  (CrossSection.compose no longer exists; wrapping undefined crashed with
  "originalFn is not a function" in WASM TBB:OFF CI lanes)
- Add 'setTolerance' to crossSectionMemberFunctions (returns new CrossSection)
- Update voronoi.mjs to use CrossSection.union() instead of .compose()
- Fix stale @param epsilon / default 1e-6 in manifold-encapsulated-types.d.ts
  (parameter is now 'tolerance', default 0 uses the geometry's own tolerance)
- Add @param doc note to CrossSection::Simplify explaining that default 0
  resolves to tolerance_ (geometry-scale-derived, not a fixed 1e-6)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 21:00:22 +12:00
Zach LoafmanandClaude Opus 4.8 9008e157a1 Flatten the boolean2 engine into src/ and consolidate to fewer files (#1754)
* Move boolean2 engine files up to src/; rename to boolean2_* form

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Consolidate the nine boolean2 engine headers into src/boolean2.h

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Merge the boolean2 pipeline and containment sources into their targets

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Update gen_docs, Doxyfile, docs, and format.sh for the flat boolean2 layout

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Restore the module contract comments dropped by the source merges

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Fix Boolean2.md architecture table and two merge leftovers

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 22:27:35 +12:00
Zach LoafmanandClaude Opus 4.8 db042ab153 Cut over CrossSection from Clipper2 to boolean2 (#1751)
* Wire CrossSection to the boolean2 backend

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Simplify CrossSection via vertex decimation, not merge-tolerance snap

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Address wiring review: Hull/finite guards, inline mutex, signpost, asserts

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Migrate CrossSection wiring to ApplyFillRule; Simplify decimates only

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Defer transform tolerance scaling to GetPaths; fix Simplify comment

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Tidy wiring comments to house style; use la::isfinite for guards

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Cut over CrossSection from Clipper2 to boolean2

Replace the Clipper2-backed CrossSection implementation with the in-tree boolean2 one and drop the Clipper2 dependency, the MANIFOLD_CROSS_SECTION_BACKEND selector, and its CI and packaging plumbing. The public CrossSection API is unchanged: the FillRule argument is kept but only Positive construction is supported. Samples.Sponge4's degenerate-triangle bound is raised, since boolean2's Simplify leaves more near-collinear vertices (more benign zero-area tris; topology unchanged).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Delegate single-contour CrossSection ctor to the Polygons one

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Always build CrossSection; drop the MANIFOLD_CROSS_SECTION option

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Flatten manifold::boolean2 into manifold; unify JoinType

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Make SimplifyRing O(n log n) via min-heap with lazy invalidation

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Drop stale MANIFOLD_CROSS_SECTION flag from the PR perf guard script

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Scrub Clipper2 and the removed option from the new sanitizer CI script

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 08:06:37 +12:00
Robert Kossessa 8ba18a0417 Add Manifold::Contains(vec3) and Manifold::WindingNumber(vec3) (#1746)
* Add Manifold::Contains and Manifold::WindingNumber

Closes #1440.

Implements point-in-mesh containment testing via the Boolean winding
number kernel (Kernel02) already used by the CSG operations, giving
correct results for non-simply-connected shapes and overlapping regions
where simple ray-parity would be wrong.

Core: Manifold::Impl::PointWinding in boolean3.cpp
- Builds a minimal Impl for the query points (vertPos + zero normals)
- Pre-filters with the 3D bounding box - points outside return 0 immediately
- Queries the BVH with vec3 points, which triggers DoesOverlap(vec3) - an
  XY-projected check - so all faces with XY overlap are returned regardless
  of Z, enabling correct +Z winding accumulation above the query point
- Processes all points in a single parallel BVH traversal

Public API (include/manifold/manifold.h, src/manifold.cpp):
- int WindingNumber(vec3 point) const
- std::vector<int> WindingNumber(const std::vector<vec3>& points) const
- bool Contains(vec3 point) const
- std::vector<bool> Contains(const std::vector<vec3>& points) const

Bindings: C (scalar), Python (scalar + batch), WASM (scalar + TypeScript types)

Tests (test/measurement_test.cpp):
- ContainsTallBox: verifies XY-projected collider query (would fail with 3D Box)
- WindingWatertight: no double-counting at shared edges/vertices
- WindingHollowShell: real winding number, not just ray parity
- ContainsBatch: batch results match scalar for all points
- WindingMatchesRayCastParity: cross-checked against existing RayCast

* Fix clang-format violations and nanobind overload_cast in Python bindings

nanobind requires static_cast for overloaded member functions;
nb::overload_cast without return type doesn't resolve ambiguity.
Also wrap long comment lines to satisfy clang-format 20.

* Simplify winding number API
Remove scalar WindingNumber(vec3) and all Contains overloads from C++,
C, Python, and WASM bindings.

Rename `active` to `query2input` in PointWinding.

Plumb the
vector API through WASM instead of the previous single-point calls to
avoid per-point marshalling overhead.

* Fix clang-format-lint errors
2026-06-05 10:37:16 +12:00
Zach LoafmanandClaude Opus 4.8 e02471d211 Expose ExecutionContext factories in bindings (C/Python/WASM) (#1743)
The ctx-aware static factories (FromMeshGL / LevelSet / Smooth) had no
binding, so ops with no source Manifold to attach via WithContext - notably
MeshGL ingest - could not be observed or cancelled from the language
bindings. The ExecutionContext object and WithContext were already bound;
this adds the three factories as methods on the context, mirroring the plain
static factories.

- C: manifold_execution_context_{level_set,level_set_seq,of_meshgl,
  of_meshgl64,smooth,smooth64}. The level_set helper is generalized to run
  under an ExecutionContext; the SDF callback user-data is renamed sdf_context
  to keep it distinct from the ExecutionContext argument.
- Python: ExecutionContext.{from_mesh,level_set,smooth} mirroring the
  Manifold static-factory lambdas.
- WASM: ExecutionContext.{fromMesh,smooth,levelSet} (embind helpers in
  helpers.cpp, JS wrappers in bindings.js, .d.ts declarations).

Tests: CBIND.execution_context_factories (C), all_apis.py coverage (Python),
and an ExecutionContext-static-factories case (WASM). All build and pass
locally across the three layers.

Toward #971.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 20:50:45 +12:00
Emmett Lalish 9719c34993 fix docs and binding defaults (#1729) 2026-05-23 14:52:04 +12:00
Zach LoafmanandClaude Opus 4.7 bd56861de0 Record normals on Manifold; auto-substitute on GetMeshGL; round-trip via MeshGL (#1718)
* Record normals on Manifold; auto-substitute on GetMeshGL; roundtrip via MeshGLP

Following Emmett's #1712 direction: make "where are my normals?" a
property of the Manifold rather than something the caller threads
through every call. After CalculateNormals(), GetMeshGL() returns
solid-frame normals without needing the idx repeated; an ofMesh ->
getMesh roundtrip preserves the recording via a new optional
MeshGLP::hasNormals flag.

The standard slot is the first three extra-property channels (MeshGL
channels 3, 4, 5). CalculateNormals / SmoothByNormals / UpdateNormals
gain default normalIdx values (0 / 0 / -1 respectively) so the no-arg
call is the new preferred form; non-zero values are kept for
compatibility but flagged in the docs. Refine clears the recording
(interpolated normals are wrong).

Bindings updated in lock-step: Python (nb::arg defaults, has_normals
field on MeshGL/MeshGL64), WASM (JS wrapper for smoothByNormals,
helpers.cpp roundtrips hasNormals, .d.ts type updates), C (
manifold_meshgl{,64}_has_normals accessors). Single-signature shape
means no overload disambiguation needed in any binding.

Open follow-ups: [[deprecated]] attribute + internal caller migration,
SetProperties detection (flagged with TODO).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Record normals on Manifold; auto-apply transforms via runFlags bit 1

Fixes #1712, fixes #1719.

Make "where are my normals?" a property of the Manifold rather than
something the caller threads through every call. After CalculateNormals,
GetMeshGL returns world-frame normals without an explicit normalIdx, and
a MeshGL <-> Manifold round-trip preserves the recording per-run even
across mixed-input Booleans (e.g., a cube without normals composed with
a sphere that has them).

The #1712 repro from
  (sphere - sphere.Translate(10)).CalculateNormals().GetMeshGL()
now returns the expected outward-from-cavity normals. The underlying
cross-mesh seam-vert sign issue (#1719) is fixed in SetNormals.

Mechanism:

- runFlags becomes a bitmask: bit 0 = backside (existing), bit 1 =
  hasNormals (new). New MeshGLP::HasNormals(run) accessor mirrors
  Backside(run). Backside fixed from `runFlags[run] == 1` to `& 1` so
  it survives the addition of a second bit.

- CalculateNormals(0) marks the per-meshID Relation.hasNormals flag,
  which Impl::HasNormals() ANDs across to give the impl-wide answer.
  GetMeshGL(-1) auto-substitutes slot 0 on output when HasNormals() is
  true.

- Normals at the standard slot are stored world-frame on the Impl.
  Impl::Transform and csg_tree.cpp::Compose eager-transform
  properties_[0..2] per-meshID so the slot stays in sync with vertPos_
  and faceNormal_ across any sequence of transforms, including mixed-
  input Boolean/Compose outputs where some meshIDs carry normals and
  others don't. EagerTransformPropNormals is a shared helper.

- SetNormals multi-normal walk sign-flips cross(next, here) when it
  disagrees with faceNormal_[next.face]. This handles Boolean
  subtractee triangles (winding unchanged, faceNormal_ negated by the
  Boolean post-pass) without losing the existing "flair" curving for
  smooth surfaces. This is what fixes #1719.

- CreateProperties negates Q's slot 0..2 per source-meshID for
  subtractee cavity inversion.

- GetNormal returns properties_[0..2] directly when the meshID's
  Relation.hasNormals is true (world-frame already); applies the per-
  meshID inverse-normal-transform when false, preserving the master
  contract for hand-built MeshGL inputs that don't set the bit.

- Non-zero normalIdx to CalculateNormals uses the legacy deferred-
  transform path: stores per-mesh-frame, recovered to world-frame by
  GetMeshGL's per-run transform on export. Docstring notes this path
  will be removed in a future release.

API additions:

- MeshGLP::HasNormals(run) C++ accessor plus C and Python bindings.
- MeshGLP::Backside(run) C and Python bindings (previously C++-only).

Tests:

- Properties.CalculateNormals: previously-FIXME'd dot(pos, norm) > 0
  asserts enabled (#1719 regression).
- Manifold.CalculateNormalsRoundTripsThroughGetMeshGL: ofMesh+getMesh
  preserving the per-run flag, Rotate before and after CalculateNormals,
  no-arg invocation, non-zero idx.
- Manifold.GetNormalLegacyContract: per-mesh-frame fallback in
  GetNormal for MeshGLs without bit 1.
- Manifold.TransformMixedNormalsPerMeshID,
  Manifold.ComposeMixedNormalsPerMeshID,
  Manifold.BooleanSubtractMixedQPerMeshIDNegation: per-meshID iteration
  in Impl::Transform / Compose / CreateProperties for mixed-input
  Boolean outputs.
- Manifold.CalculateNormalsNonZeroIdxSurvivesTransform: legacy non-zero
  normalIdx path across post-calc transforms.
- CBIND.run_flag_accessors: exercises the new C accessors.

Known limitations:

- Hand-built MeshGL inputs that share propVerts across runs with
  differing hasNormals settings produce one-interpretation-wins
  behavior at the shared propVerts (the stored value can only have one
  semantic). Standard CalculateNormals / Boolean / Compose outputs
  never produce this shape. Documented on MeshGLP::HasNormals(run).
- Warp / WarpBatch / SetProperties keep the recording set; if the user
  replaces slot 0..2 or warps non-rigidly, the stored normals are stale
  until they call CalculateNormals again. Documented on each method.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Address PR #1718 review feedback

Substantive:

- Split CalculateNormalsRoundTripsThroughGetMeshGL into 8 named tests
  (NormalsCavity, NormalsRotateBefore/AfterCalc, NormalsAutoSubstitute,
  NormalsRoundTrip, NormalsRefinePreserved, NormalsSmoothByNormalsNoArg,
  NormalsNonStandardSlotNotRecorded). Pithier names per Emmett's request.
- Fix Backside(run) docstring: framework already orients stored normals
  on the standard flow, the bit is informational only.
- SafeNormalize during the eager-transform in
  Manifold::Impl::EagerTransformPropNormals so non-orthogonal transforms
  and barycentric interpolation don't leave non-unit values that compound
  downstream (e.g., at Boolean edges feeding SmoothByNormals).
- Add `backside(run)` and `hasNormals(run)` methods on the WASM Mesh
  class, plus runFlags field documentation in the .d.ts.
- Add a deliberately-failing test (NormalsSharedPropVertMixedFlags) that
  demonstrates the data-model conflict in the shared-propVert + mixed-
  hasNormals case. Hand-built MeshGL inputs with shared propVerts across
  runs of differing hasNormals can only store one slot 0..2 value;
  Impl::Transform picks one interpretation, corrupting the other. Test
  is intentionally red as a discussion-driver for PR #1718 review
  thread (whether to fix by splitting propVerts in the Manifold(MeshGL)
  ctor, or to document the constraint).

Trivial:

- Rename wasHasNormals -> hadNormals in Impl::InitializeOriginal.
- Drop verbose eager-transform comment block in Impl::Transform; the
  helper call site is self-documenting.
- Note AND-not-OR semantics on Impl::HasNormals(); rename hint covered
  by the new doc.
- TODOs at the legacy non-zero-normalIdx codepaths (the getTransform
  lambda in SetNormals, the legacy fallback in GetMeshGLImpl per-vert
  normalization) marking them for removal alongside the deprecated API.
- Deprecation notice on GetMeshGL/GetMeshGL64's explicit normalIdx
  parameter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Split shared propVerts across runs with mixed hasNormals

Addresses comment 3254084222 on PR #1718. When a single input propVert
is referenced by triangles from runs with differing hasNormals flags,
the eager-transform contract can't track both interpretations through
one slot 0..2: a Transform would rotate the hasNormals=true run's
normal and corrupt the hasNormals=false run's color (or vice versa).

The MeshGL ctor now duplicates such propVerts so each camp gets its
own slot. The first-seen camp keeps the original index; the opposite
camp gets an appended alt copy holding a snapshot of the original
property data. Subsequent triangles from each camp resolve through
their respective indices. DedupePropVerts already skips cross-meshID
pairs, so the duplicate survives ctor cleanup, and
EagerTransformPropNormals is gated on TriHasNormals per triangle, so
only the hasNormals camp's copy gets rotated.

Behaviour preserved for the existing numProp == 0 cases (the
single-array legacy push pattern is retained when there's no distinct
prop space). For numProp > 0 we always populate both triProp and
triVert now - prior code skipped triVert when prop2vert was empty, but
the split can introduce triProp values >= numVert that need triVert
for valid v0/v1 in CreateHalfedges.

Docs: re-add a paragraph to MeshGLP::HasNormals (and the WASM
hasNormals method) describing the auto-split, replacing the
"undefined for hand-built mixed-flag inputs" caveat that ce0e18d8
removed when it staged the failing test.

The new test NormalsSharedPropVertMixedFlags (added in ce0e18d8 as a
discussion-driver red test) now passes; its docstring is updated to
describe the fix rather than the failure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Fix clang-format on myHasN assignment

clang-format v20 (CI) wants the && wrapped onto a continuation rather
than aligned after `=`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Revert "Split shared propVerts across runs with mixed hasNormals"

Per discussion on PR #1718 (review comment 3254084222): the shared-
propVert + mixed-hasNormals input shape is genuinely weird (no standard
output produces it) and adding the auto-split to every MeshGL ingest
slows the import path - already a sore spot relative to Boolean - and
adds maintenance surface for a case users shouldn't be hitting.

Reverting cf8d898a (the split implementation + doc changes) and ce6e394a
(the clang-format follow-up that touched the same block). Test wording
and updated doc explaining the constraint follow in a separate commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Document undefined behavior for cross-run shared propVerts

Add a caveat paragraph on `MeshGLP::HasNormals` (C++ header) and the
WASM `hasNormals(run)` method noting:

- hasNormals is per-run, so different runs may set it differently
  (leading with this since the original removed-then-not-restored caveat
  was misread on review as forbidding mixed-flag runs).
- Behavior is undefined when a single propVert is shared by triangles
  from runs that disagree - a Transform rotates the slot on behalf of
  the hasNormals=true camp and clobbers any hasNormals=false sharer.
- Standard CalculateNormals / Boolean / Compose outputs never produce
  that shape - hand-built MeshGL inputs are the only way to hit it.

Repurpose the `NormalsSharedPropVertMixedFlagsUndefined` test (renamed
from `NormalsSharedPropVertMixedFlags`) to pin the documented
behaviour: assert the hasNormals camp's slot rotates as expected
(`run0Bad == 0`) and the no-normals camp's value is clobbered
(`run1Bad > 0`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 10:44:27 +12:00
Emmett Lalish 74ea61bd73 Some partial fixes for normals (#1716)
* fixed several bugs, updated bindings

* move MeshGL to its own header

* temporarily make test pass

* fix install
2026-05-16 22:49:23 +12:00
Zach LoafmanandClaude Opus 4.7 8606a8281d Attach ExecutionContext to Manifold; remove per-call Status(ctx) (#1704)
* Attach ExecutionContext to Manifold; remove per-call Status(ctx) variant

Replaces the per-call ExecutionContext parameter on Status() with a
data-attachment model: WithContext(ctx) returns a copy of the Manifold
with the context attached, and the no-arg Status() routes through any
attached context. Subsequent operations on the attached Manifold (and
the Manifolds they derive) inherit the attachment, so Translate,
Boolean, Hull and friends observe progress and cancellation without
needing extra parameters.

The attachment travels with the data: copying propagates it, and ops
returning a Manifold inherit from the primary operand (`*this` for
member ops, `manifolds[0]` for the static factories that combine
multiple Manifolds). WithoutContext() detaches; GetContext() returns
the attached context as std::optional<ExecutionContext> sharing state
with the original.

Removes the explicit Status(ExecutionContext&) overload from C++ and
its matching forms in the C / Python / WASM bindings
(manifold_status_with_context, .def("status", ctx), statusWithContext)
in favour of attach-then-Status(). Refine variants are left untouched
in this commit; that's the next one.

* Refine: route attached ExecutionContext through Subdivide post-pass (#1702)

The motivating example for per-call ctx parameters (PR #1702) was
mid-Refine cancellation. With ExecutionContext now attached to the
Manifold, that need can be served without changing public signatures.

Adds an optional ctx parameter to Manifold::Impl::Refine and threads
the cancel check between Subdivide and the post-pass
(SetNormalsAndCoplanar / CalculateVertNormals / SortGeometry), routing
SortGeometry through its existing ctx-aware overload. The public
Refine, RefineToLength and RefineToTolerance variants pass ctx_.get()
both into GetCsgLeafNode (input-tree evaluation) and into Impl::Refine
(post-Subdivide work).

Subdivide itself stays cancel-blind for now; the cancellation point is
at the granularity of "after Subdivide returns", which matches how
other ops in the codebase observe cancellation around their hot kernel.

* Refactor: collapse construct+inherit pattern into Derived() helper

Member ops returning a derived Manifold previously did:
    Manifold result(...);
    result.InheritContextFrom(*this);
    return result;

Replace with a templated private helper `Derived(T&& arg)` that
forwards `arg` to the appropriate Manifold ctor and inherits the
attached ExecutionContext from `*this`. Static factories that combine
multiple Manifolds use the lvalue form, e.g. `manifolds[0].Derived(...)`.

Templated to forward through shared_ptr-of-derived-CsgNode (e.g.
shared_ptr<CsgLeafNode>) which would otherwise need two user-defined
conversions to reach Manifold.

No behavior change. Saves ~40 lines across 17 call sites.

* Pivot ExecutionContext attach to "eager-reads-input, deferred-drops"

Per #1704 review: ctx is consumed only by the next eager op invoked
on the result (Status, Refine family). Deferred ops (Boolean,
transforms, batch ops) ignore any attached ctx; their result has no
ctx. Raw copy/assignment preserves the attachment.

Public surface trimmed to one method per binding (C++ With,
manifold_with_context, with_context, withContext); WithoutContext /
HasContext / GetContext and their mirrors are dropped -- under the
new model the user always knows what ctx they attached, so
introspection has no real use case. Internal Derived() helper and
InheritContextFrom go with the inheritance step; call sites use
plain Manifold(...) construction.

Test flips: deferred ops drop input ctx; Refine result has no ctx;
copy/assignment preservation checked behaviorally via Status()
routing rather than HasContext.

395/395 pass (was 397; net -2 dropped + 1 new test for the
(a+b).With(ctx).Status() idiom).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Cleanups around ExecutionContext attach

- Fix `Manifold(Manifold())` wart in `Mirror`'s degenerate-normal branch
  (search-and-replace leftover from collapsing the old `Derived(...)`
  helper into plain `Manifold(...)` construction). Should be just
  `Manifold()`.
- Remove dead `ExecutionContext(std::shared_ptr<Impl>)` ctor: it was
  used by the now-removed `GetContext()`. No live callers.
- Tighten the `With(ctx)` docstring to explicitly close the list of
  ctx-observing ops -- `Volume` / `GetMeshGL` / `BoundingBox` etc.
  force evaluation but do not currently observe attached ctx. The
  previous wording was positive-only and could mislead a casual reader.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Rename C++ `With` -> `WithContext` to match bindings

The bindings use `with_context` (C, Python) / `withContext` (WASM); the
C++ method had been the asymmetric shorter `With` on the rationale that
C++ overload resolution future-proofs the verb. Per Emmett's review on
#1704, the consistency tradeoff is small enough that matching the
bindings is the cleaner outcome.

Mechanical rename across 8 files (header decl, impl, bindings, tests,
docstring prose). No semantic changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Drop redundant Manifold(...) wrap around Minkowski return

`Impl::Minkowski` already returns a `Manifold`; wrapping it just invokes
the move ctor with no effect. Sed leftover from collapsing the old
`Derived(...)` helper into plain `Manifold(...)` construction. Same
class as the earlier Mirror fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 08:36:24 +12:00
Zach LoafmanandClaude Opus 4.7 adaf64c4a7 Add ExecutionContext language bindings (#1668)
* Add ExecutionContext language bindings

Mirrors the C++ ExecutionContext API (from #1663) in the C, Python, and
WASM bindings:

- C: opaque ManifoldExecutionContext with manifold_execution_context{,_
  cancel,_cancelled,_progress} and manifold_status_with_context; full
  size/alloc/destruct/delete plumbing.
- Python: ExecutionContext class with cancel/cancelled/progress; Status
  overload via nanobind overload dispatch.
- WASM: ExecutionContext embind class with the same methods; new
  Manifold.statusWithContext(ctx) that delegates to a shared
  ErrorToString helper (and adds the previously-missing Cancelled case).

Tests: C API round-trip (alloc, cancel, status-with-context); WASM
vitest smoke. Python smoke verified locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Clarify ExecutionContext.delete() docstring

Matches the existing wording used on Manifold.delete() and
CrossSection.delete(). Addresses review confusion on #1668.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Match ExecutionContext.delete() framing to peer APIs

Add "// Memory" section comment and @group Basics tag to match the
shape of Manifold.delete() and CrossSection.delete(). Follow-up to
elalish's comment on #1668 — the docstring wording was updated in
992bca54, but the surrounding framing still made delete() look like
an afterthought.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add real Python cancel assertion to all_apis.py

The pre-existing ExecutionContext block in all_apis.py was a smoke test
only — it called cancel()/status(ctx) on a leaf node (which skips CSG
evaluation entirely) and didn't assert the result. Add an assertion
using a CsgOpNode (Manifold.cube() + Manifold.sphere(1)) so a
regression in the Python status(ctx) overload — like the nanobind
overload-resolution break that tripped CI once during #1668 dev —
would actually fail the test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 14:02:20 +12:00
Zach LoafmanandClaude Opus 4.7 78f15825f4 Add ExecutionContext for boolean progress + cancellation (#1663)
* Add ExecutionContext for boolean progress + cancellation

Progress towards #971. Introduces ExecutionContext for observing progress
and requesting cancellation of long-running boolean evaluations via a new
Status(ExecutionContext&) overload; no other public API is affected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add cross-Manifold cancel tests

Cover three documented behaviors that weren't pinned down:
- Sticky cancel persists across different Manifolds evaluated with the
  same ctx.
- A fresh ExecutionContext is not contaminated by an earlier cancelled
  one; new evaluations can still complete.
- A cancelled ctx applied to an already-leaf Manifold returns the
  Manifold's real status, since no evaluation happens to short-circuit.

Also drop a stale comment in ExecutionContextCancelPermanent that hinted
at a cancel-clearing API we never added.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Disambiguate Status overload in Python binding

The new Status(ExecutionContext&) overload made &Manifold::Status
ambiguous in nanobind's .def() call. Cast to the no-arg overload
explicitly; the new overload is not yet exposed in bindings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Guard std::thread tests behind MANIFOLD_PAR == 1

Emscripten/WASM builds without pthreads cannot construct std::thread
and abort at runtime. The two tests that spawn a side thread to
observe progress or trigger cancellation mid-evaluation aren't
meaningful on a non-parallel build anyway — evaluation is synchronous.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Address #1663 review: iterative NumLeaves, poison stack on cancel, docs example

- NumLeaves: rewrite iteratively. Recursive version could stack-overflow
  on deep CsgOpNode trees (e.g. `m += m1 += m2 += ...` chains), which
  is the exact case the existing iterative ToLeafNode was written for.

- ToLeafNode cancel: poison every op_node currently on the stack, not
  just `this`. A sub-op may have had its impl_ partially mutated during
  its finalize (children replaced with an intermediate result); leaving
  its cache_ unset would let a later evaluation of a shared sub-op run
  against the partially-reduced tree. All frames now share one
  ErrorLeaf(Cancelled), which is safe because the empty-cancelled Impl
  is transform-invariant for error-status queries.

- ExecutionContext docstring: add a concrete observer-thread example.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 10:33:00 +08:00
Zach LoafmanandClaude Opus 4.6 cfe7b563ad Add ray casting language bindings (#1654)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 21:52:49 +12:00
Emmett Lalish 56110f65bd Smooth missing normals (#1651)
* smoothing cleanup

* needs debug

* test working

* need to sanitize halfedges

* sanitize quad tangents

* added missing error bindings

* testing passing

* fixed no normal verts

* fix build

* fix MSVC

* fix MSVC again
2026-04-13 22:31:33 +12:00
301c165a20 Add MinkowskiSum and MinkowskiDifference (#666)
* Add Naive Minkowski Sum Implementation

* Fix CI Bellyaching

* Add Python Minkowski Test

* Enable Determinism for the Failing CI Tests

* Fix Python Test

* Fix Python Test Again

* Make Python Test Cheaper so it doesn't segfault

* Add Insetting Option

* Update Python Binding Too

* Switch to a Member Function

* Remove the useThreading option

* Fix the Python Binding

* And the example

* Fix Formatting

* Split into Add/Subtract Functions, Add C Binding

* Make Methods const

* Update the tests; ensure that the inset operation works with convex shapes

* Fix Python Example Again

* Add JS Bindings

* Fix Formatting

* Fix Formatting Properly

* Change Function Names to Sum/Difference

* Fix formatting

* Move Tests to boolean_test

* Fix Formatting

* Fix NonConvexConvex Test

* Fix Formatting

* Add Surface Area

* passing the last test

* forgot these

* Fix Test?

* Fix for  Disconnected Manifolds

* Codify IsConvex, Make Python Cheaper

* Refactor to use Impl

* Remove Dangling Line Return

* Add another early exit

* Fix Glaring Bugs...

* Fix Formatting

* Again

* Fix Mesh Export

* Run SimplifyTopology on the output of Minkowski

* Update Tests

* Update Formatting

* Make more work multithreaded

* Fix formatting

* Disable test cheating?

* Revert "Disable test cheating?"

This reverts commit d1f35e2668bea54aec87727b3e8c8bce5ac0ebe4.

* Update to latest code

* Fix Formatting

* Break out the Convex/Convex MDifference

I just realized what was supposed to be a simple test was actually two tests, one with more complexity than the other...

* Fix Formatting

* Fix Formatting

* Relax Minkowski test tolerances for cross-platform consistency

The NonConvexConvexMinkowski and NonConvexNonConvexMinkowski tests had
tight tolerances (1e-5) that fail due to minor numerical variations
across platforms. Widened surface area tolerances to 1e-2 and volume
tolerances to 1e-3 to account for triangulation differences.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix Minkowski test CI failures

- Add processOverlaps=true to ConvexConvexMinkowskiD to handle
  duplicate/collinear points in triangulation
- Disable NonConvexNonConvexMinkowski test - produces non-manifold
  results on some platforms due to coplanar face handling issues
  in the naive Minkowski implementation (see issue #1430)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Re-enable NonConvexNonConvexMinkowski test

Re-enabled the test to properly debug the MinkowskiSum behavior
with coplanar faces from non-convex inputs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix MinkowskiDifference hang with tolerance-based coplanarity check

- Split NonConvexNonConvexMinkowski test into separate Sum and Difference tests
- Use tolerance-based coplanarity check (1e-15) instead of exact equality
  to handle floating-point precision issues from scaling operations
- Update test expected values to more precise measurements with 1e-5 tolerance
- Use ManifoldParamGuard for RAII-style parameter management in tests

The coplanarity check now uses dot product comparison instead of exact
floating-point equality (linalg::equal), which was failing for scaled
normals due to precision issues. The dot product of parallel unit vectors
should be 1.0, so we check if |dot - 1.0| < 1e-15 (near machine epsilon).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Address PR review feedback for Minkowski implementation

- Move IsConvex() from edge_op.cpp to properties.cpp for better organization
- Fix data race in IsConvex() by using all_of instead of for_each_n with
  shared anyConcave boolean (UB per pca006132's review)
- Remove unnecessary pImpl variable in IsConvex, use this directly
- Simplify convexity check to use > 0 instead of tolerance parameter
- Split NonConvexConvexMinkowski test into Sum and Difference for consistency
  with NonConvexNonConvex tests
- Add analytical volume/surface area formulas for ConvexConvex tests
- Truncate excessive precision in test expected values

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Run clang-format

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Move Minkowski implementation from Manifold to Impl

- Add Impl::Minkowski method in impl.cpp with batch processing optimization
- Manifold::Minkowski now delegates to Impl::Minkowski
- This is more consistent with the codebase style and avoids repeated
  GetCsgLeafNode().GetImpl() calls
- Includes BATCH_SIZE=1000 optimization for hull operations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add parallelization to NonConvex-NonConvex Minkowski case

- Flatten nested face pair loops into single index space
- Process pairs in parallel batches using for_each_n
- Use validHull flag array to handle coplanar face filtering
- Collect valid hulls after parallel execution for BatchBoolean

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Run clang-format

* Use periodic batch reduction for NC-NC Minkowski to handle large meshes

Replace face-pair batching with per-A-face processing and periodic
reduction every 200 faces. This approach:
- Processes A faces sequentially, creating B-face hulls in parallel
- Merges accumulated results every REDUCE_THRESHOLD faces
- Prevents memory from growing unboundedly with large meshes

Enables complex meshes like spoon (904 tris) to complete without
crashing while maintaining similar performance for smaller meshes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Address review feedback from PR #666

- Pre-allocate composedHulls vector
- Simplify validHulls loop by checking IsEmpty() instead of separate bool vector
- Add surface area check to ConvexConvexMinkowski test
- Remove private Minkowski wrapper function, call Impl directly
- Add performance warning to MinkowskiSum/MinkowskiDifference docs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Increase coplanarity tolerance in NC-NC Minkowski sum

Increase kCoplanarTol from 1e-15 to 1e-9 to more reliably skip
nearly-coplanar face pairs that could cause degenerate hull
computations and potential hangs.

This tolerance is conservative enough to skip genuinely coplanar
faces while still allowing valid near-coplanar face pairs to be
processed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Emmett Lalish <elalish@google.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 11:11:23 +13:00
pca006132 cadec11542 Deprecate compose (#1489)
* deprecate compose

* fix samples and tests

* avoid using compose for hull
2026-01-14 17:25:29 +08:00
darix 3124ad45e4 Use Python_EXECUTABLE from FindPython instead of hardcoding the command (#1328)
on many linux distributions /usr/bin/python would refer to python 2
which no longer exists. python 3.x is usually /usr/bin/python3.

The finder handles this for us.

Fixes #1327
2025-08-06 18:41:34 +08:00
pca006132 34afe21c31 fix odr violation (#1323)
* fix odr violation

* fix python binding docstring name
2025-08-06 08:55:21 +08:00
Henk 39e3cd3f6e Add JoinType.Bevel (#1299)
* Add JoinType.Bevel to Python binding

* Implement JoinType.Bevel

* Add JoinType.Bevel to other bindings

* Fix typo and test and formatting

* Fix formatting
2025-07-15 22:11:50 +08:00
Trzethandpca006132 c18032c31e fix stubgen path (#1301)
* add cmake check for fp related options

* fix

* update

* Revert "add cmake check for fp related options"

This reverts commit 4045cf3653f9376c42e16b58adc61fd494afb11f.

---------

Co-authored-by: pca006132 <john.lck40@gmail.com>
2025-07-15 22:07:23 +08:00
Trzeth da4997bd29 fix pyi vert_properties type (#1291)
* fix

* update doc

* fix pylance

* python postbuild

* fmt

* fmt

* update workflows to windows-2025 since windows-2019 deprecated

* fin
2025-07-02 15:44:31 +08:00
Jonathan Hogg 3a83b83ca3 Add missing Manifold.simplify() method to Python API (#1282)
Add missing Manifold.simplify() method to Python API (#1281)

* add binding to manifold3d.cpp

* add test call in all_apis.py
2025-06-10 17:10:34 +08:00
Emmett Lalishandpca006132 551e1a12cf v3.1 (#1259)
* bump version

* bindings: include string in manifold3d

---------

Co-authored-by: pca006132 <john.lck40@gmail.com>
2025-05-14 12:43:54 -07:00
Emmett Lalish 2cf3dfd0ec default offset to round (#1257) 2025-05-14 02:17:50 -07:00
Emmett Lalish 09fb03cff2 added MANIFOLD_ASSERT (#1225)
* added MANIFOLD_ASSERT and rearranged includes

* fixes

* fix format and compile

* uniform format

* update clang-format
2025-04-12 02:18:42 -07:00
Emmett Lalishandpca006132 954df798b2 New decimator (#1175)
* merging

* mostly working

* implemented, but crashes

* runs serially

* fix compile issues

* fixed empty meshes

* fix parallel error dumping

* fixed parallelization

* fix compiler

* run black

* improved triangulation

* remove unreferenced verts

* addressing feedback

---------

Co-authored-by: pca006132 <john.lck40@gmail.com>
2025-03-05 20:42:39 -08:00
pca006132andEmmett Lalish 7f298aa9db cmake changes (#1048)
* enable emscripten build with tbb enabled

* nix: fix emscripten build, add tbb build

* browser

* fix python build

* minor

* no parallel sdf for js

* disable test for emscripten-tbb

* add cache for nix python build

* cmake changes

* fix

* update

* update

* update

* update

* move python dependency handling

* more changes

* format

* fix broken format

* fix

* simplify

* allow emscripten with cbind

* build fetched dependencies as static libs

* fix static build

* fix rebuild

* fix extras

* remove parallel.h from public API

* update tests

* make dependencies private

* move parallel.h

* missing utils.h change

* fix

* fix...

* fix wasm tbb

* add more cmake consumer tests

* fix consumer

* add rpath

* Revert "add rpath"

This reverts commit 2e8a96c90b26f7044617953ccf0f6935e4de8fdf.

* rpath specific to macos

* use override

* forgot to set rpath...

* remove #1045 related changes

* integrate #1052

* allow version override

* minor improvements

* msvc changes

* fix typo

---------

Co-authored-by: Emmett Lalish <elalish@google.com>
2024-11-17 12:00:36 -08:00
pca006132 74f340a8e7 always use 64-bit integer for MeshGL64 (#1038)
* always use 64-bit integer for MeshGL64

* fix 2

* c binding fixes

* c binding fix 2

* fix
2024-11-13 09:57:19 -08:00
Emmett Lalish 82140d3479 Remove GetProperties() (#1022)
* organize member docs

* remove GetProperties

* updated WASM bindings
2024-11-05 13:34:45 -08:00
pca006132 f11ed8da6c bindings update (#1018)
* bindings: add MeshGL64 C bindings

* bindings: fix leak and address sanitizer issue

* bindings: add Mesh64 to python

* bindings: fix c binding 64 bit index type

* bindings: fix python 64 bit index type

* bindings: fix python again

* bindings: formatting
2024-11-02 13:59:12 +08:00
Emmett Lalish a8a90c7d34 switched property indexing from vector to scalar (#1016)
* switched property indexing from vector to scalar

* updated WASM bindings

* update python bindings
2024-11-01 11:45:32 -07:00
Emmett Lalish 80221a3511 Precision renaming (#1008)
* rename refineToPrecision

* rename kTolerance

* the precision rename
2024-10-22 15:28:09 -07:00
pca006132 5ba3c24112 [WIP] Add tolerance value (#997)
* renaming precision to uncertainty, and hiding

* add tolerance

* rename uncertainty to epsilon

* use epsilon instead of tolerance

* guard simplify topology for SetEpsilon

* format

* remove conflict markers

* fix builds

* use epsilon for barycentric

* prefer using epsilon

* update python bindings

* address comments

* format

* remove SetTolerance

Tolerance value is set before the mesh is created, when SimplfiyTopology
cannot be called.

* read/write MeshGL tolerance field
2024-10-22 08:29:11 -07:00
Emmett Lalish 54517b7546 Separate coplanarity from faceID (#991)
* separated faceID

* clean up tests

* fix AsOriginal

* reenable CreateFaces and keep mesh relation intact

* fix compilation

* updates docs
2024-10-19 10:04:08 -07:00
pca006132 e718288cbf fix python binding (#987)
* python: fix type casters and warp batch

* python: allow docstring override

* update nanobind version

* python: add docstring_override.txt

* python: fix example

* version limit for nanobind
2024-10-19 01:07:18 +08:00
Emmett Lalishandpca006132 e06765346e Replace GLM with linalg (#984)
* added linalg

* removed GLM

* fix matrix multiplication

* more matrix constructors

* fixed more functions

* fixed matrix notation

* more fixes

* fix ostream

* further fixes

* added more rotation functions

* compiles

* some fixes

* fix2

* fix build

* another warning...

* fix install

* for wasm?

* no warning for unknown options

* proper fix?

* remove legacy warning flags

* format

* misc constexpr

---------

Co-authored-by: pca006132 <john.lck40@gmail.com>
2024-10-15 11:22:03 -07:00
pca006132 bd52d301ff Minor cleanup (#988)
* documentation update

* remove some todo

* format
2024-10-16 00:58:49 +08:00
pca006132 658d3e037a format cmake files (#975)
* format cmake files

* update format.sh

* fix linker flags for emscripten

* update readme

* use gersemi

* actual format

* should be public instead of interface

* make test work without download

* simplification

* format
2024-10-05 00:36:24 +08:00
pca006132 cc1e97442a simple cleanup (#973)
* cleanup files

* hide some public APIs

* merged CMakeLists.txt for headers

* fix build

* include cleanup

* include cleanup again

* address #944

* python cmake install

* iostream is still needed

* fix nix
2024-10-03 00:10:07 +08:00
starseeker 5cab42f165 Attempt at simplifying the file structure and CMake build (#961)
* Initial file moves, stage logic for src/CMakeLists.txt rework

* Start working on getting reorganized files to build, as well as doing some rework on the CMake logic

* remove unused libs, propagate dependency includes

* Ignore common temporary files and build directories

* Just build the C bindings, since this is already a C++ compile - reduces complexity.

* Fixes for python binding building

* Require C++17, don't use extensions

* Remove C binding CMake file

* Remove extra libraries from link line

* Try to set up the manifoldConfig file to just find the required dependencies, without downloading

* Go looking for glm and Clipper2 installed with Manifold first (untested)

* Use a bundled Clipper2 copy instead of downloading

This preserves the ability to disable cross_section (and thus the use of
clipper) but replaces the Download-and-Build fetch with a bundled source
copy to avoid the network connection.  If we go this route, we're also
building Clipper2 directly into Manifold so client libraries don't have
to worry about linking it in.

* Remove option and directories no longer present

* Remove option no longer present.

* Put back the default .gitignore

* Add a few more patterns

* Revert "Use a bundled Clipper2 copy instead of downloading"

Feedback is we don't want to bundle clipper, so revert inclusion

This reverts commit 68e8e3ccceb35c87fc84626e28a95468781be8e3.

* Just build polygon as part of the main library

* Correct some library linkages

* Tweak exported target file install location - this seems to be what's expected on Linux, but will it work for other platforms?

* clang format fixes

* Just include FetchContent up front

* Fix include for minimize_testcase

* formatting

* Add sstream header

* Need to disable more code when cross_section is off

* Don't try to build the bindings unless MANIFOLD_CROSS_SECTION is on.

* formatting

* manifoldc folded into libmanifold

* Fix location of test-cmake.sh script

* Try using previous install dir for Apple/MSVC manifoldConfig.cmake file

Per https://cmake.org/cmake/help/latest/command/find_package.html it
looks like the search is different on different platforms.  Need to look
at the available patterns more closely, but for now try using what's
working for the tests in master branch.

* Fix conditional test, add namespace

* Fix header install

* Remove unused bindings filter from lcov line, Remove unused MANIFOLD_CBIND option.

* Don't do tests if downloads are off, since they require googletest.

* elalish spotted that this isn't a public header - fix.

* Try out CMake intenting based on vim + file footer with settings.

* Rename sh directory to scripts per suggestion from pca006132

* Per pca006132, remove unnecessary find_package call for oneDPL.

* Simplify MANIFOLD_PAR to an OFF/ON setting

Per suggestion from pca006132, changed CMake logic to be ON/OFF, and
simplified the C++ defines to test for defined/undefined vs. checking
for a specific value.

* conv.h is also a private header

* Hmm - looks like flake naming was coming from MANIFOLD_PAR - try translating the settings.

* Whoops - need to translate the active value not the cached value.

* OFF is still defined, so make sure we catch that case too

* Explain multiple calls to get_filename_component

* Move parallel.h to src

* Move iters.h to src

* Place optional components in subdirectories.

* Correct path in gen_docs.py

* Fix the file location for python bindings.

* Revert "Move iters.h to src"

parallel.h was apparently specifically public - undo hiding of iter.h

This reverts commit ce3e45a9a6af42393fbb4b220e9bb2c8ebabd901.

* Revert "Move parallel.h to src"

parallel.h was apparently specifically public

This reverts commit 08fbcdf8e95d6afd1eb3617eed9c90caa6744b0d.

* Footers, indenting adjustments for other CMake files
2024-09-29 10:23:42 -07:00
Emmett Lalish 4d7613bd4f Add RefineToPrecision (#938)
* added RefineToPrecision, but needs work

* fixed 1-d triangulations

* added test of precision

* fixed approximation

* added bindings

* cleanup

* forgot to include
2024-09-27 17:19:29 -07:00
pca006132 31d6da0973 use nanobind builtin stubgen (#949)
* use nanobind builtin stubgen

* fix formatting

* python format

* update nix for newer nanobind

* remove recursive clone flags

* fix extrude.py

* fix install

* add version checks for stubgen

* exclude_from_all

* fix python

* disable nix js variant for CI
2024-09-27 08:02:56 -07:00
Emmett Lalish ced53e2109 Make create faces optional (#935)
* avoid createFaces calls, need to separate relation from coplanarity

* simplified SetProperties

* fixed merge test

* simplified calculateCurvature

* fixed WASM + cleanup

* more cleanup
2024-09-17 14:59:05 -07:00
pca006132 9124a68032 change directory structure (#918)
* change directory structure

* expose parallel.h

* format

* missing functional

* format

* fix install
2024-09-10 07:56:43 -07:00
pca006132andEmmett Lalish 492c3a8b23 Double precision (#895)
* added configuration summary

* use custom math type

* use std function if possible

* build success

* fix js binding

* format

* use better primitives

* use old precision for polygon tests

* fix polygon CCW check

* temp-fix tests

* add simpler failing test case

* refactored CutKeyhole

* fixed tests

* more keyholing fixes

* truncate long debug output

* shrink SDF blobs test

* fixed WASM and disabled zebra

* fix hull

* cleanup a bit

* fix wasm

* CI cleanuo

* reenable zebra

* upped precision and fixed tests

* fix format

* disable zebra test on windows

---------

Co-authored-by: Emmett Lalish <elalish@google.com>
2024-09-03 10:19:11 -07:00
Emmett Lalish fbf07bf92a SDF collapse (#894)
* refactor to collapse verts

* fixed missing triangles

* tests pass

* cleanup, docs

* Moved LevelSet from MeshGL to Manifold

* update bindings

* minor fixes

* more python fixes

* update clang-format version

* updated sinesurface test

* revert unneeded change

* fixed WASM

* update Python

* remove opposed triangles

* update format version

* fix format

* remove unreferenced verts

* fix 4-manifolds

* reduce blob resolution

* avoid collapsing thin surfaces

* cleanup, tighten tests

* compromise heuristic

* update test

* slight heuristic tweak and update docs

* loosen genus test
2024-09-01 15:52:47 -07:00
Chris Mayo a37d59ef5b Use system nanobind if installed (#880)
* Use system nanobind if installed

* Add a pyproject.toml build-time dependency on nanobind

* Add nanobind to Nix buildInputs

* Replace nanobind submodule with FetchContent

* Remove nanobind directories from tool.scikit-build sdist.exclude

* Use Nix python3.withPackages for nanobind instead of buildInputs
2024-08-03 12:03:34 +08:00
Emmett Lalish 3bf7f4b33d SDF Refactor (#876)
* added static LevelSet

* removed Morton codes

* store voxels

* new levelset working

* cleanup

* moved LevelSet to MeshGL

* small updates

* removed sdf library

* updated WASM bindings

* cleanup FindSurface

* updated test

* fix formatting

* loosen test slightly

* off-by-one

* fix sizing

* tweak test
2024-07-26 09:17:51 -07:00
pca006132 610fd3a073 custom parallel algorithms based on tbb (#857)
* most of the algorithms done

* conditional compile tbb stuff

* format

* optimize a bit

* unique implementation

* tiny optimizations

* remaining ones

* update clang-format

* don't check version here

* radix sort

* fix compiler error

* fix another compiler error

* fix again

* again

* another fix

* add benchmark

* fix

* some changes

* format

* fix

* fix msvc

* misc

* remove uninitialized_fill and copy

* infer policy automatically

* tuned better?

* signedness thing

* format

* proper iter

* documentation and checks

* address comments

* fixed comments
2024-07-13 13:04:17 +08:00