discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Re: SynapsCAD, alternative implementations, language extensions

CC
Cory Cross
Fri, Jul 24, 2026 3:59 PM

If someone wants curves, there's curv3d. https://curv3d.org/

Which, iiuc, evolved from the OpenSCAD codebase.

(Hmm, self-note, I wonder if there's a tolerance-based meshing algorithm in there?)

On July 24, 2026 7:18:22 AM PDT, Jordan Brown via Discuss discuss@lists.openscad.org wrote:

An important consideration is how tolerant the geometry engine is of "invalid" geometry - degenerate triangles, micro-gaps, non-manifold, et cetera.  I don't know the details, but Manifold seems to be much more tolerant than CGAL.  I also don't know how Manifold gains its tolerance; it might be through the fuzzy matching that you are trying to avoid.

You talk about performance comparisons with CGAL.  In OpenSCAD's usage, Manifold is far faster than CGAL; even beating CGAL by several times would not put you in the same ballpark as Manifold. I haven't looked at any benchmarks, but my guestimate is that one order of magnitude is too low, and that two orders of magnitude might well be in the right range.

Changing subjects, you talk about doing operations on curves.

That's an area that interests me (though as a user, not as a theoretician).  OpenSCAD currently always reduces curves to line segments, and then operates on the resulting polygons and polyhedra.  Using true curves seems appealing since it could radically reduce the complexity of the model - but doing geometric operations on curves is harder than the already-hard operations on polyhedra.  Do you allow operations on true curves, or do you reduce them to line segments?


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

If someone wants curves, there's curv3d. https://curv3d.org/ Which, iiuc, evolved from the OpenSCAD codebase. (Hmm, self-note, I wonder if there's a tolerance-based meshing algorithm in there?) On July 24, 2026 7:18:22 AM PDT, Jordan Brown via Discuss <discuss@lists.openscad.org> wrote: >An important consideration is how tolerant the geometry engine is of "invalid" geometry - degenerate triangles, micro-gaps, non-manifold, et cetera.  I don't know the details, but Manifold seems to be much more tolerant than CGAL.  I also don't know how Manifold gains its tolerance; it might be through the fuzzy matching that you are trying to avoid. > >You talk about performance comparisons with CGAL.  In OpenSCAD's usage, Manifold is far faster than CGAL; even beating CGAL by several times would not put you in the same ballpark as Manifold. I haven't looked at any benchmarks, but my guestimate is that one order of magnitude is too low, and that two orders of magnitude might well be in the right range. > > >Changing subjects, you talk about doing operations on curves. > >That's an area that interests me (though as a user, not as a theoretician).  OpenSCAD currently always reduces curves to line segments, and then operates on the resulting polygons and polyhedra.  Using true curves seems appealing since it could radically reduce the complexity of the model - but doing geometric operations on curves is harder than the already-hard operations on polyhedra.  Do you allow operations on true curves, or do you reduce them to line segments? > >_______________________________________________ >OpenSCAD mailing list >To unsubscribe send an email to discuss-leave@lists.openscad.org
CC
Cory Cross
Fri, Jul 24, 2026 4:26 PM

On July 24, 2026 6:31:01 AM PDT, Tim Schmidt via Discuss discuss@lists.openscad.org wrote:

The general direction is to redesign geometric algorithms around exact
computation rather than attempt to repair an approximate algorithm
afterward.

Here's a common place that falls down: import an STL with a value approximating an irrational number, and work with it.

What can be eliminated is the habit of forcing an unjustified
yes-or-no answer and then silently constructing topology from it.

Why does that matter? If you get the same end result as Manifold but take two orders of magnitude more time to do it, what was the point? Ultimately OpenSCAD is a triangulated mesh approximating CSG. If you're not doing that, it's something else, like curv3d, which is really neat, or B-rep. There's no need to be able to accurately model the entire solar system and accurately measure the distance between two subatomic particles in it, so two vertices which are very close to one another should just be considered in the same location. This causes no problems in any actual use of OpenSCAD and solves several precision issues you hit working with things in real life.

  • Cory
On July 24, 2026 6:31:01 AM PDT, Tim Schmidt via Discuss <discuss@lists.openscad.org> wrote: >The general direction is to redesign geometric algorithms around exact >computation rather than attempt to repair an approximate algorithm >afterward. Here's a common place that falls down: import an STL with a value approximating an irrational number, and work with it. >What can be eliminated is the habit of forcing an unjustified >yes-or-no answer and then silently constructing topology from it. Why does that matter? If you get the same end result as Manifold but take two orders of magnitude more time to do it, what was the point? Ultimately OpenSCAD is a triangulated mesh approximating CSG. If you're not doing that, it's something else, like curv3d, which is really neat, or B-rep. There's no need to be able to accurately model the entire solar system and accurately measure the distance between two subatomic particles in it, so two vertices which are very close to one another should just be considered in the same location. This causes no problems in any actual use of OpenSCAD and solves several precision issues you hit working with things in real life. - Cory
RW
Raymond West
Fri, Jul 24, 2026 4:37 PM

Hi Jordan,

However far you drill down into precision, since we are dealing with
digital computing, and the 'real world' is mainly analogue, there will
eventually be errors, or the necessity for tolerances. There are
apparently half a dozen or so versions of cgal kernels, and some of
them, afaik allow more exact results than manifold.

In my DSL, I  use EPECK kernel for cgal, it is slow. My 'diff' takes in 
a manifold shape, and returns a manifold shape (if possible), so I can't
show exactly what cgal does internally. My 'difference' works purely in
manifold.

But a simple test of two cylinders, one slightly tilted, shows
differences in differences, so to speak.

a=cylinder(d=20,h=50,segments=4)
b=rotate(a,[0,0.0001,0])
print("a diff b")
c=diff([a,b])
show_viewer(c)
print("a difference b")
d=difference([a,b])
show_viewer(d)
print("b diff a")
e=diff([b,a])
show_viewer(e)
print(" b difference a")
f=difference([b,a])
show_viewer(f)
dm=translate(d,[30,0,0])
show_viewer([c,dm])

console output :-

a diff b
[diff] Using CGAL exact arithmetic for boolean difference
[diff] Subtracting shape 1 of 1
[diff] CGAL difference complete: 20 verts, 36 tris
[show_viewer] shapes.size() = 1
[show_viewer] Shape: mesh verts=20 tris=36 | raw_mesh verts=60 tris=108
a difference b
[show_viewer] shapes.size() = 1
[show_viewer] Shape: mesh verts=14 tris=20 | raw_mesh verts=42 tris=60
b diff a
[diff] Using CGAL exact arithmetic for boolean difference
[diff] Subtracting shape 1 of 1
[diff] CGAL difference complete: 18 verts, 28 tris
[show_viewer] shapes.size() = 1
[show_viewer] Shape: mesh verts=18 tris=28 | raw_mesh verts=54 tris=84
 b difference a
[show_viewer] shapes.size() = 1
[show_viewer] Shape: mesh verts=14 tris=20 | raw_mesh verts=42 tris=60
[show_viewer] shapes.size() = 2
[show_viewer] Shape: mesh verts=20 tris=36 | raw_mesh verts=60 tris=108
[show_viewer] Shape: mesh verts=14 tris=20 | raw_mesh verts=42 tris=60

you can see the different number of verts/tris  between the cgal and
manifold calculations

and here is the visual comparison between the two meshes c and d. It
shows one face has extra tris and duplicated vertices (well ones that
are combine/ignored in the manifold version).

I've attached the scad output, so if you wish, you can see what the mesh
actually is, in both cases.

Best wishes,

Ray

On 24/07/2026 15:18, Jordan Brown via Discuss wrote:

An important consideration is how tolerant the geometry engine is of
"invalid" geometry - degenerate triangles, micro-gaps, non-manifold,
et cetera.  I don't know the details, but Manifold seems to be much
more tolerant than CGAL.  I also don't know how Manifold gains its
tolerance; it might be through the fuzzy matching that you are trying
to avoid.

You talk about performance comparisons with CGAL.  In OpenSCAD's
usage, Manifold is far faster than CGAL; even beating CGAL by several
times would not put you in the same ballpark as Manifold. I haven't
looked at any benchmarks, but my guestimate is that one order of
magnitude is too low, and that two orders of magnitude might well be
in the right range.

Changing subjects, you talk about doing operations on curves.

That's an area that interests me (though as a user, not as a
theoretician).  OpenSCAD currently always reduces curves to line
segments, and then operates on the resulting polygons and polyhedra. 
Using true curves seems appealing since it could radically reduce the
complexity of the model - but doing geometric operations on curves is
harder than the already-hard operations on polyhedra.  Do you allow
operations on true curves, or do you reduce them to line segments?


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Hi Jordan, However far you drill down into precision, since we are dealing with digital computing, and the 'real world' is mainly analogue, there will eventually be errors, or the necessity for tolerances. There are apparently half a dozen or so versions of cgal kernels, and some of them, afaik allow more exact results than manifold. In my DSL, I  use EPECK kernel for cgal, it is slow. My 'diff' takes in  a manifold shape, and returns a manifold shape (if possible), so I can't show exactly what cgal does internally. My 'difference' works purely in manifold. But a simple test of two cylinders, one slightly tilted, shows differences in differences, so to speak. a=cylinder(d=20,h=50,segments=4) b=rotate(a,[0,0.0001,0]) print("a diff b") c=diff([a,b]) show_viewer(c) print("a difference b") d=difference([a,b]) show_viewer(d) print("b diff a") e=diff([b,a]) show_viewer(e) print(" b difference a") f=difference([b,a]) show_viewer(f) dm=translate(d,[30,0,0]) show_viewer([c,dm]) console output :- a diff b [diff] Using CGAL exact arithmetic for boolean difference [diff] Subtracting shape 1 of 1 [diff] CGAL difference complete: 20 verts, 36 tris [show_viewer] shapes.size() = 1 [show_viewer] Shape: mesh verts=20 tris=36 | raw_mesh verts=60 tris=108 a difference b [show_viewer] shapes.size() = 1 [show_viewer] Shape: mesh verts=14 tris=20 | raw_mesh verts=42 tris=60 b diff a [diff] Using CGAL exact arithmetic for boolean difference [diff] Subtracting shape 1 of 1 [diff] CGAL difference complete: 18 verts, 28 tris [show_viewer] shapes.size() = 1 [show_viewer] Shape: mesh verts=18 tris=28 | raw_mesh verts=54 tris=84  b difference a [show_viewer] shapes.size() = 1 [show_viewer] Shape: mesh verts=14 tris=20 | raw_mesh verts=42 tris=60 [show_viewer] shapes.size() = 2 [show_viewer] Shape: mesh verts=20 tris=36 | raw_mesh verts=60 tris=108 [show_viewer] Shape: mesh verts=14 tris=20 | raw_mesh verts=42 tris=60 you can see the different number of verts/tris  between the cgal and manifold calculations and here is the visual comparison between the two meshes c and d. It shows one face has extra tris and duplicated vertices (well ones that are combine/ignored in the manifold version). I've attached the scad output, so if you wish, you can see what the mesh actually is, in both cases. Best wishes, Ray On 24/07/2026 15:18, Jordan Brown via Discuss wrote: > An important consideration is how tolerant the geometry engine is of > "invalid" geometry - degenerate triangles, micro-gaps, non-manifold, > et cetera.  I don't know the details, but Manifold seems to be much > more tolerant than CGAL.  I also don't know how Manifold gains its > tolerance; it might be through the fuzzy matching that you are trying > to avoid. > > You talk about performance comparisons with CGAL.  In OpenSCAD's > usage, Manifold is far faster than CGAL; even beating CGAL by several > times would not put you in the same ballpark as Manifold. I haven't > looked at any benchmarks, but my guestimate is that one order of > magnitude is too low, and that two orders of magnitude might well be > in the right range. > > > Changing subjects, you talk about doing operations on curves. > > That's an area that interests me (though as a user, not as a > theoretician).  OpenSCAD currently always reduces curves to line > segments, and then operates on the resulting polygons and polyhedra.  > Using true curves seems appealing since it could radically reduce the > complexity of the model - but doing geometric operations on curves is > harder than the already-hard operations on polyhedra.  Do you allow > operations on true curves, or do you reduce them to line segments? > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org
JB
Jordan Brown
Fri, Jul 24, 2026 4:58 PM

On 7/24/2026 8:30 AM, Tim Schmidt wrote:

Hypercurve is currently strictly two-dimensional. Spatial curves,
trimmed surfaces, and three-dimensional curve/surface relationships
belong in HyperBREP which is less than finished at the moment.

OK, so headed in the right direction but for 3d modeling not there yet. 
Thanks.

On 7/24/2026 8:30 AM, Tim Schmidt wrote: > Hypercurve is currently strictly two-dimensional. Spatial curves, > trimmed surfaces, and three-dimensional curve/surface relationships > belong in HyperBREP which is less than finished at the moment. OK, so headed in the right direction but for 3d modeling not there yet.  Thanks.
JB
Jordan Brown
Fri, Jul 24, 2026 5:05 PM

On 7/24/2026 9:37 AM, Raymond West via Discuss wrote:

However far you drill down into precision, since we are dealing with
digital computing, and the 'real world' is mainly analogue, there will
eventually be errors, or the necessity for tolerances.

First, I wouldn't say that we're dealing with the real world. We're
dealing with the mathematical world.  The mathematical world is also
analog, but in the real world below a certain threshold you don't care,
while in the mathematical world everything is infinite precision.

But aside from that, the "digital" issues are precisely what Tim is
trying to address, by representing values in alternative ways that
maintain mathematical accuracy as much as possible.  I believe, for
instance, that he can precisely represent 1/3, which neither ordinary
human-friendly decimal nor machine-friendly binary can precisely represent.

On 7/24/2026 9:37 AM, Raymond West via Discuss wrote: > > However far you drill down into precision, since we are dealing with > digital computing, and the 'real world' is mainly analogue, there will > eventually be errors, or the necessity for tolerances. > First, I wouldn't say that we're dealing with the real world. We're dealing with the mathematical world.  The mathematical world is also analog, but in the real world below a certain threshold you don't care, while in the mathematical world everything is infinite precision. But aside from that, the "digital" issues are precisely what Tim is trying to address, by representing values in alternative ways that maintain mathematical accuracy as much as possible.  I believe, for instance, that he can precisely represent 1/3, which neither ordinary human-friendly decimal nor machine-friendly binary can precisely represent.
TS
Tim Schmidt
Fri, Jul 24, 2026 5:12 PM

Cory,

That STL case is real, and it marks an important boundary:

If you import an approximate STL, Hyper can be exact about the
approximation. It cannot reconstruct the exact shape that was
discarded before the STL was written.

The file no longer contains the original circle, NURBS surface,
irrational coordinate, or intended coincidence. It contains a
collection of finite coordinates and triangles. Hyper can preserve
those coordinates exactly as they appeared in the file and avoid
adding further rounding error, but no number representation can
recover design intent that is no longer present.

For that kind of input, a tolerance-based import or repair policy is
entirely reasonable. I am not trying to prohibit tolerances. I am
trying to distinguish:

mathematically proved equality

from:

an application has deliberately chosen to treat these values as
equivalent at a particular resolution.

An OpenSCAD-compatible import mode might say:

preserve the imported coordinates exactly;
then regularize the complete mesh at this declared tolerance.

The regularization should operate globally on complete candidate
features and equivalence classes rather than independently snapping
pairs of vertices. That makes it deterministic and avoids as much
partial-weld behavior as possible.

So exactness is not absolutism. A strict mode can preserve the input
literally. A compatibility, preview, or manufacturing mode can apply a
declared tolerance. The important part is knowing which happened and
not silently promoting the latter into a mathematical fact.

Why does that matter? If you get the same end result as Manifold but
take two orders of magnitude more time to do it, what was the point?

If Manifold produces the desired result under the desired policy and
does so much faster, then for that workload there may be no point in
using a slower path. I am quite willing to use the best available
backend for a particular representation and task.

I have not yet benchmarked csgrs against Manifold, so the CGAL results
do not answer that question. Manifold is the obvious next comparison
for OpenSCAD-style triangulated Boolean work. The current csgrs
results show that exact-aware geometry is not automatically condemned
to being orders of magnitude slower, but they do not establish that it
is faster than Manifold. That needs to be measured.

The Hyper stack is also young. csgrs is a little over two years old,
about a year went into investigating and replacing its numerical
basis, and the Hyper crates themselves are roughly six months old.
End-to-end optimization has only recently begun. HyperCurve gained
approximately two orders of magnitude on several workloads in the last
few days. That does not prove it will beat Manifold, but it is enough
that Manifold does not look like an unreachable target.

I do think "treating nearby vertices as the same causes no problems"
is too strong, though. It is often a very useful policy, especially
for imported print meshes, but it can also:

close an intended gap;
erase a thin wall or small channel;
merge separate shells;
change a clearance;
produce scale-dependent results;
or make the answer depend on the units in which the model happened
to be expressed.

A gap that is irrelevant in a meter-scale printed bracket might be the
feature of interest in a microfluidic part, PCB, or metrology
workflow. There is no universal epsilon that captures all of those
intents.  I've actually encountered this problem with
https://github.com/atomCAD/atomCAD

That does not mean the end user should be asked to decide every
ambiguous weld. The application should choose an appropriate policy
for its domain. OpenSCAD can have sensible print-oriented defaults. A
PCB DRC tool, a BREP importer, and a machine controller may make
different choices.

The proof-versus-policy distinction matters because it lets those
systems share one kernel without pretending that one tolerance policy
is a law of geometry.

Ultimately OpenSCAD is a triangulated mesh approximating CSG.

That is its current output representation, but it does not require
every internal representation to be triangulated from the beginning.

A compiler ultimately emits machine code, but that does not mean it
should discard its higher-level intermediate representation before
optimization. A printer ultimately emits integer motor steps, but that
does not mean the CAD system should convert a circle into steps before
performing intersections, offsets, and Booleans.

Keeping curves and analytic surfaces native until the final finite handoff can:

preserve design intent;
reduce the number of geometric elements;
avoid accumulated segmentation error;
keep exact tangency and continuity;
and allow tessellation to be chosen for the actual display or
machine resolution.

The final result can still be an STL. The difference is that the
approximation happens once, deliberately, at the output boundary
rather than repeatedly throughout the modeling process.

So my current position is not:

every approximate mesh workflow should be replaced by an exact one.

It is:

retain exact structure where it still exists; introduce tolerance
explicitly where the source data or physical process requires it; and
choose the fastest suitable backend for each representation.

For imported STL, the honest answer may be a Manifold-style finite and
tolerant path.

For authored curves, exact CSG, BREP, DRC, CAM, and repeated geometric
transformations, preserving the richer structure can be valuable both
for correctness and, increasingly, for performance.

The user-facing requirement remains the same either way:

Put two cubes next to each other, and it should just work.

The argument is about how the kernel makes that happen without turning
one convenient default into an invisible assumption everywhere else.

--tim

Cory, That STL case is real, and it marks an important boundary: If you import an approximate STL, Hyper can be exact about the approximation. It cannot reconstruct the exact shape that was discarded before the STL was written. The file no longer contains the original circle, NURBS surface, irrational coordinate, or intended coincidence. It contains a collection of finite coordinates and triangles. Hyper can preserve those coordinates exactly as they appeared in the file and avoid adding further rounding error, but no number representation can recover design intent that is no longer present. For that kind of input, a tolerance-based import or repair policy is entirely reasonable. I am not trying to prohibit tolerances. I am trying to distinguish: mathematically proved equality from: an application has deliberately chosen to treat these values as equivalent at a particular resolution. An OpenSCAD-compatible import mode might say: preserve the imported coordinates exactly; then regularize the complete mesh at this declared tolerance. The regularization should operate globally on complete candidate features and equivalence classes rather than independently snapping pairs of vertices. That makes it deterministic and avoids as much partial-weld behavior as possible. So exactness is not absolutism. A strict mode can preserve the input literally. A compatibility, preview, or manufacturing mode can apply a declared tolerance. The important part is knowing which happened and not silently promoting the latter into a mathematical fact. Why does that matter? If you get the same end result as Manifold but take two orders of magnitude more time to do it, what was the point? If Manifold produces the desired result under the desired policy and does so much faster, then for that workload there may be no point in using a slower path. I am quite willing to use the best available backend for a particular representation and task. I have not yet benchmarked csgrs against Manifold, so the CGAL results do not answer that question. Manifold is the obvious next comparison for OpenSCAD-style triangulated Boolean work. The current csgrs results show that exact-aware geometry is not automatically condemned to being orders of magnitude slower, but they do not establish that it is faster than Manifold. That needs to be measured. The Hyper stack is also young. csgrs is a little over two years old, about a year went into investigating and replacing its numerical basis, and the Hyper crates themselves are roughly six months old. End-to-end optimization has only recently begun. HyperCurve gained approximately two orders of magnitude on several workloads in the last few days. That does not prove it will beat Manifold, but it is enough that Manifold does not look like an unreachable target. I do think "treating nearby vertices as the same causes no problems" is too strong, though. It is often a very useful policy, especially for imported print meshes, but it can also: close an intended gap; erase a thin wall or small channel; merge separate shells; change a clearance; produce scale-dependent results; or make the answer depend on the units in which the model happened to be expressed. A gap that is irrelevant in a meter-scale printed bracket might be the feature of interest in a microfluidic part, PCB, or metrology workflow. There is no universal epsilon that captures all of those intents. I've actually encountered this problem with https://github.com/atomCAD/atomCAD That does not mean the end user should be asked to decide every ambiguous weld. The application should choose an appropriate policy for its domain. OpenSCAD can have sensible print-oriented defaults. A PCB DRC tool, a BREP importer, and a machine controller may make different choices. The proof-versus-policy distinction matters because it lets those systems share one kernel without pretending that one tolerance policy is a law of geometry. Ultimately OpenSCAD is a triangulated mesh approximating CSG. That is its current output representation, but it does not require every internal representation to be triangulated from the beginning. A compiler ultimately emits machine code, but that does not mean it should discard its higher-level intermediate representation before optimization. A printer ultimately emits integer motor steps, but that does not mean the CAD system should convert a circle into steps before performing intersections, offsets, and Booleans. Keeping curves and analytic surfaces native until the final finite handoff can: preserve design intent; reduce the number of geometric elements; avoid accumulated segmentation error; keep exact tangency and continuity; and allow tessellation to be chosen for the actual display or machine resolution. The final result can still be an STL. The difference is that the approximation happens once, deliberately, at the output boundary rather than repeatedly throughout the modeling process. So my current position is not: every approximate mesh workflow should be replaced by an exact one. It is: retain exact structure where it still exists; introduce tolerance explicitly where the source data or physical process requires it; and choose the fastest suitable backend for each representation. For imported STL, the honest answer may be a Manifold-style finite and tolerant path. For authored curves, exact CSG, BREP, DRC, CAM, and repeated geometric transformations, preserving the richer structure can be valuable both for correctness and, increasingly, for performance. The user-facing requirement remains the same either way: Put two cubes next to each other, and it should just work. The argument is about how the kernel makes that happen without turning one convenient default into an invisible assumption everywhere else. --tim
TS
Tim Schmidt
Fri, Jul 24, 2026 5:27 PM

On Fri, Jul 24, 2026 at 1:06 PM Jordan Brown via Discuss
discuss@lists.openscad.org wrote:

First, I wouldn't say that we're dealing with the real world. We're
dealing with the mathematical world.  The mathematical world is also
analog, but in the real world below a certain threshold you don't care,
while in the mathematical world everything is infinite precision.

But aside from that, the "digital" issues are precisely what Tim is
trying to address, by representing values in alternative ways that
maintain mathematical accuracy as much as possible.  I believe, for
instance, that he can precisely represent 1/3, which neither ordinary
human-friendly decimal nor machine-friendly binary can precisely represent.

Agreed on all counts.  And I will add that the algorithms the stack
uses to evaluate these richer numbers is exactly the superset of
algorithms which cover all the component and primitive representations
contained within.  The stack performs as many safe deterministic
inexpensive reductions to all those component representations as I
have found, which improves performance, equality checks, memory
consumption, etc.  And the stack automatically uses the richer
information it stores with each number to dynamically dispatch to the
fastest of the superset of algorithms available to perform the
computation.  Including a sizeable set of fused ops and special forms
identified by Yap as particularly favorable to geometric computations.

The stack saves computational effort by avoiding computing on the
fully approximated representation of any value whenever possible.  It
uses stored known / unknown exact zero, sign, and magnitude, observed
at value construction, to answer most geometric questions.  Then
effectively mathematical filter after filter to answer an increasing
percentage of the answerable set for more and more complex values.  I
believe SynapsCAD terminates in a 512bit approximate equality
evaluation, which happens so rarely the bit depth has virtually no
effect on performance.

--tim

On Fri, Jul 24, 2026 at 1:06 PM Jordan Brown via Discuss <discuss@lists.openscad.org> wrote: > First, I wouldn't say that we're dealing with the real world. We're > dealing with the mathematical world. The mathematical world is also > analog, but in the real world below a certain threshold you don't care, > while in the mathematical world everything is infinite precision. > > But aside from that, the "digital" issues are precisely what Tim is > trying to address, by representing values in alternative ways that > maintain mathematical accuracy as much as possible. I believe, for > instance, that he can precisely represent 1/3, which neither ordinary > human-friendly decimal nor machine-friendly binary can precisely represent. Agreed on all counts. And I will add that the algorithms the stack uses to evaluate these richer numbers is exactly the superset of algorithms which cover all the component and primitive representations contained within. The stack performs as many safe deterministic inexpensive reductions to all those component representations as I have found, which improves performance, equality checks, memory consumption, etc. And the stack automatically uses the richer information it stores with each number to dynamically dispatch to the fastest of the superset of algorithms available to perform the computation. Including a sizeable set of fused ops and special forms identified by Yap as particularly favorable to geometric computations. The stack saves computational effort by avoiding computing on the fully approximated representation of any value whenever possible. It uses stored known / unknown exact zero, sign, and magnitude, observed at value construction, to answer most geometric questions. Then effectively mathematical filter after filter to answer an increasing percentage of the answerable set for more and more complex values. I believe SynapsCAD terminates in a 512bit approximate equality evaluation, which happens so rarely the bit depth has virtually no effect on performance. --tim
TS
Tim Schmidt
Fri, Jul 24, 2026 5:58 PM

I might also add that, while I don't use it within the stack, instead
preferring once-visiting algorithms, cascading predicate tests, etc.
Hyperreal does offer an optional compile-time f32/f64 cache.  So if
you wanted to design your algorithm in a way that treated
approximation as if it were inexpensive, or were adapting another
algorithm which made that assumption, you can make repeated reads
almost entirely free while keeping the values in hyperreal.  Not sure
how useful that feature is, but it's not much code, and that's why its
feature flag is default disabled.

I might also add that, while I don't use it within the stack, instead preferring once-visiting algorithms, cascading predicate tests, etc. Hyperreal does offer an optional compile-time f32/f64 cache. So if you wanted to design your algorithm in a way that treated approximation as if it were inexpensive, or were adapting another algorithm which made that assumption, you can make repeated reads almost entirely free while keeping the values in hyperreal. Not sure how useful that feature is, but it's not much code, and that's why its feature flag is default disabled.
JB
Jordan Brown
Fri, Jul 24, 2026 6:08 PM

[ Caveat:  it looks like the vertex-matching behavior changed between
CGAL and Manifold, and that may have fixed a lot of problems. With our
CGAL support we had grid snapping at around 10^-6, only a little below
practical values and so vulnerable to false-equals, but our Manifold
support does not seem to have grid snap.  I put two cubes 10^-15 apart,
and they were still distinct.  So maybe that problem has been fixed.]

On 7/24/2026 9:26 AM, Cory Cross via Discuss wrote:

Here's a common place that falls down: import an STL with a value approximating an irrational number, and work with it.

For our purposes, I think that's a matter of how tolerant we are of
incorrect STLs.

If the STL's vertexes all match exactly, nobody cares whether they
started out as irrationals, because in the STL they are by definition
rational and precisely represented in binary, and that's all we care about.

If the STL's vertexes don't match, then we're into fuzzy matching,
with all of its problems.  But that's also the best that we can do,
since STL doesn't carry any topology information.  But maybe we could
limit that problem to imported STLs, instead of encountering it on
internally-generated shapes too.

What can be eliminated is the habit of forcing an unjustified
yes-or-no answer and then silently constructing topology from it.

Why does that matter?

Our twin problems are false-not-equals, where two points that are
mathematically identical end up with slightly different binary
representations, and false-equals, where two points that are
mathematically different end up being considered to be the same point.

It sounds like Tim's approach addresses many of the false-not-equals
cases.  If it could address all of the false-not-equals cases, we
might be able to get away with dropping fuzzy matching (grid snap), and
that might well take false-equals cases with it.

Unfortunately, since it can't address all of the false-not-equals cases,
I'm not sure how much of a win there is.  Cases that by simple equality
are false-not-equals cases are probably also addressed by fuzzy
matching.  Once there needs to be fuzzy matching, there's the
possibility of false-equal cases.  But: since Tim keeps track of the
error bars, he can probably use a very small amount of fuzz, and that
can reduce false-equals.

If you get the same end result as Manifold but take two orders of magnitude more time to do it, what was the point?

We say that a bunch of our geometry problems are caused by floating
point inaccuracy.  Tim's trying to eliminate that as a factor.  If we
assume for a moment that we could get mathematically-correct arithmetic,
what would that do to our ability to reliably create correct geometry? 
If we could get more correct arithmetic, what would that do for
geometry?

Ultimately OpenSCAD is a triangulated mesh approximating CSG.

That is the way it is today, but I don't think it should be the goal. 
If we can get true curves into the picture, I think we should.

There's no need to be able to accurately model the entire solar system and accurately measure the distance between two subatomic particles in it, so two vertices which are very close to one another should just be considered in the same location. This causes no problems in any actual use of OpenSCAD and solves several precision issues you hit working with things in real life.

Indeed, the 16 digits of 64-bit floating point is well more than we need
for any practical purpose.

I think many or most of our problems historically do not arise from
inaccuracy out at one part in 10^16, but rather arise from the grid snap
that we use with CGAL to try to force "very close" points together. 
That grid snap is only at around 10^-6 (absolute), so for typical
coordinates in the 0-1000 range it's at around 9 digits, rather than the
16 that 64-bit floating point gives us.  If you have two points that are
10^-7 apart, they'll get snapped together (give or take the sharp lines
at snap boundaries), and if they weren't intended to be together, that
can cause problems.

But, as noted above, Manifold does not seem to have this snapping and
that probably helps a lot.

[ Caveat:  it looks like the vertex-matching behavior changed between CGAL and Manifold, and that may have fixed a lot of problems. With our CGAL support we had grid snapping at around 10^-6, only a little below practical values and so vulnerable to false-equals, but our Manifold support does not seem to have grid snap.  I put two cubes 10^-15 apart, and they were still distinct.  So maybe that problem has been fixed.] On 7/24/2026 9:26 AM, Cory Cross via Discuss wrote: > Here's a common place that falls down: import an STL with a value approximating an irrational number, and work with it. For our purposes, I think that's a matter of how tolerant we are of incorrect STLs. If the STL's vertexes all match exactly, nobody cares whether they started out as irrationals, because in the STL they are by definition rational and precisely represented in binary, and that's all we care about. If the STL's vertexes *don't* match, then we're into fuzzy matching, with all of its problems.  But that's also the best that we can do, since STL doesn't carry any topology information.  But maybe we could limit that problem to imported STLs, instead of encountering it on internally-generated shapes too. >> What can be eliminated is the habit of forcing an unjustified >> yes-or-no answer and then silently constructing topology from it. > Why does that matter? Our twin problems are false-not-equals, where two points that are mathematically identical end up with slightly different binary representations, and false-equals, where two points that are mathematically different end up being considered to be the same point. It sounds like Tim's approach addresses many of the false-not-equals cases.  If it could address *all* of the false-not-equals cases, we might be able to get away with dropping fuzzy matching (grid snap), and that might well take false-equals cases with it. Unfortunately, since it can't address all of the false-not-equals cases, I'm not sure how much of a win there is.  Cases that by simple equality are false-not-equals cases are probably also addressed by fuzzy matching.  Once there needs to be fuzzy matching, there's the possibility of false-equal cases.  But: since Tim keeps track of the error bars, he can probably use a very small amount of fuzz, and *that* can reduce false-equals. > If you get the same end result as Manifold but take two orders of magnitude more time to do it, what was the point? We say that a bunch of our geometry problems are caused by floating point inaccuracy.  Tim's trying to eliminate that as a factor.  If we assume for a moment that we could get mathematically-correct arithmetic, what would that do to our ability to reliably create correct geometry?  If we could get *more* correct arithmetic, what would *that* do for geometry? > Ultimately OpenSCAD is a triangulated mesh approximating CSG. That is the way it is today, but I don't think it should be the goal.  If we can get true curves into the picture, I think we should. > There's no need to be able to accurately model the entire solar system and accurately measure the distance between two subatomic particles in it, so two vertices which are very close to one another should just be considered in the same location. This causes no problems in any actual use of OpenSCAD and solves several precision issues you hit working with things in real life. Indeed, the 16 digits of 64-bit floating point is well more than we need for any practical purpose. I think many or most of our problems historically do not arise from inaccuracy out at one part in 10^16, but rather arise from the grid snap that we use with CGAL to try to force "very close" points together.  That grid snap is only at around 10^-6 (absolute), so for typical coordinates in the 0-1000 range it's at around 9 digits, rather than the 16 that 64-bit floating point gives us.  If you have two points that are 10^-7 apart, they'll get snapped together (give or take the sharp lines at snap boundaries), and if they weren't intended to be together, that can cause problems. But, as noted above, Manifold does not seem to have this snapping and that probably helps a lot.
TS
Tim Schmidt
Fri, Jul 24, 2026 6:18 PM

On Fri, Jul 24, 2026 at 2:09 PM Jordan Brown via Discuss
discuss@lists.openscad.org wrote:

I think many or most of our problems historically do not arise from
inaccuracy out at one part in 10^16, but rather arise from the grid snap
that we use with CGAL to try to force "very close" points together.
That grid snap is only at around 10^-6 (absolute), so for typical
coordinates in the 0-1000 range it's at around 9 digits, rather than the
16 that 64-bit floating point gives us.  If you have two points that are
10^-7 apart, they'll get snapped together (give or take the sharp lines
at snap boundaries), and if they weren't intended to be together, that
can cause problems.

This is exactly the range I ended up with for epsilon in csgrs and I
did have to expose it as a user tunable so that users atomCAD and
SynapsCAD could use the same kernel.  None of that with the new
numerics.

I understand the appropriate levels of mathematical skepticism,
because it's been a wild ride of what-ifs to get here.  What if we had
better math for our geometry indeed.

--tim

On Fri, Jul 24, 2026 at 2:09 PM Jordan Brown via Discuss <discuss@lists.openscad.org> wrote: > I think many or most of our problems historically do not arise from > inaccuracy out at one part in 10^16, but rather arise from the grid snap > that we use with CGAL to try to force "very close" points together. > That grid snap is only at around 10^-6 (absolute), so for typical > coordinates in the 0-1000 range it's at around 9 digits, rather than the > 16 that 64-bit floating point gives us. If you have two points that are > 10^-7 apart, they'll get snapped together (give or take the sharp lines > at snap boundaries), and if they weren't intended to be together, that > can cause problems. This is exactly the range I ended up with for epsilon in csgrs and I did have to expose it as a user tunable so that users atomCAD and SynapsCAD could use the same kernel. None of that with the new numerics. I understand the appropriate levels of mathematical skepticism, because it's been a wild ride of what-ifs to get here. What if we had better math for our geometry indeed. --tim