GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Use cubic NURBS surfaces for helical sweeps by alken1t15 · Pull Request #1813 · solvespace/solvespace

Conversation

@alken1t15

@alken1t15 alken1t15 commented Nov 8, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Helical sweeps currently vary in pitch within each rational quadratic patch. This uses degree-elevated rational cubic arcs with axial controls chosen to match the analytic helix tangent at both endpoints. Ordinary revolutions keep their quadratic surfaces. Longitudinal shell trim curves now use the surface boundary's actual degree and weights.

For a 90° patch, a 10,001-sample comparison against the analytic helix reduces maximum axial error from about 2.11% to 0.0493% of patch height, while preserving the circular projection. The resulting helix is still an approximation.

For comparison, two quadratic half-patches have about 0.2512% maximum axial error relative to the original patch height. These are sampled errors, not formal bounds or a runtime benchmark.

Validation: Release build with GCC 11.4; 306 test cases and 12,375 checks passed locally, including additional checks for pitch/radius, reverse and small sweeps, endpoint tangents, adjacent patches, a rational profile with an arbitrary axis, ordinary revolutions, watertight shell triangulation, STEP serialization and a Boolean cut. The additional tests are kept locally and are not included in this PR, as requested. Interactive GUI validation and external STEP re-import have not been performed.

Fixes #1448.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@alken1t15
Use rational cubic patches for helical sweeps
9747b88
@alken1t15
alken1t15 marked this pull request as ready for review November 8, 2026 18:50
@alken1t15 alken1t15 mentioned this pull request Nov 8, 2026
Use 3rd degree NURBS surfaces for helix extrusions #1448
Closed
@alken1t15

alken1t15 commented Nov 8, 2026

Copy link
Copy Markdown
Contributor Author

@phkahler Could you take a look when you have a chance? This follows the approach discussed in #1448. I'd appreciate your feedback on the axial control-point formula and whether the regression coverage is sufficient.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@phkahler

phkahler commented Nov 8, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

@alken1t15 Good job. I wasn't sure if you were going to do this one or not, so I did #1814 myself. The only thing I don't like with yours is the tests. While it does need some testing, I don't think we need to commit a unit test to the repository.

I also see you found the incomplete copying in MakeFromHelicalRevolutionOf(). That was a surprise for me too. Every thing went red and I was confused. Claude found the problem in couple minutes. I'm guessing you used some AI for this, or that bug probably would have taken a long time to find - even I would have had trouble finding it and I wrote the helix code ;-)

Yours is more compact. Mine adds a new function in ratpoly.

@ruevs which do you prefer?

EDIT: Your test of distf and dists to determine degree 2 or 3 may need a tolerance, but also for revolve they are both zero so that should be OK.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@phkahler
phkahler requested a review from ruevs November 8, 2026 19:50
@phkahler phkahler mentioned this pull request Nov 8, 2026
Use 3rd degree NURBS for helical surfaces #1814
Closed
@alken1t15
Keep helix regression checks local as requested
7d711a2
@alken1t15

alken1t15 commented Nov 8, 2026

Copy link
Copy Markdown
Contributor Author

@phkahler Thanks for looking! I've removed the tests from the PR and kept them locally. The diff now only touches surface.cpp and shell.cpp.

The two approaches use the same degree-elevated arc and endpoint slope condition. Here the cubic control points are computed directly in FromRevolutionOf(), rather than adding a general conversion method. I'm happy to use the separate helper if that fits the kernel better.

I left the distance comparison exact for now: ordinary revolutions have equal offsets, while a nonzero axial displacement takes the cubic path. The formula also has a finite zero-angle limit (axial = 1/3), giving a straight translation. For helical sweeps I also skip the existing ps.Equals(pf) collapse, since nearby endpoints at a small angle need not lie on the axis. A tolerance would be reasonable if we want to deliberately treat sufficiently small axial displacements as revolutions.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ruevs

ruevs commented Nov 9, 2026

Copy link
Copy Markdown
Member

@ruevs which do you prefer?

Bot(h) fail the Turing test ;-) Give the "I" (without "A") a bit of time :-)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

ruevs
ruevs approved these changes Nov 9, 2026
View reviewed changes

@ruevs ruevs left a comment •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this more than #1814.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/srf/surface.cpp
if(ps.Equals(pf)) {
// Keep the existing handling of degenerate ordinary revolutions.
// A small helical sweep can have nearby ends without lying on the axis.
if(ret.degn == 2 && ps.Equals(pf)) {

@ruevs ruevs Nov 9, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is important and therefore this PR wins.
This fixes an existing problem with helixes rotated by a very small angle - they will be "mistreated undeservedly" :-).

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/srf/surface.cpp
SSurface ret = {};
ret.degm = sb->deg;
ret.degn = 2;
ret.degn = (dists == distf) ? 2 : 3;

@ruevs ruevs Nov 9, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this - even though dists and distf will probably be bit identical doubles.
But just in case - steal the code from here:
https://github.com/solvespace/solvespace/pull/1814/changes#diff-deec245a10911b7fc46369d2f1d19541c6ba4616ea90aeff8cf3b24749f01005R83

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@ruevs

ruevs commented Nov 9, 2026

Copy link
Copy Markdown
Member

Just out of curiosity I (this "I") ran it's "AI" on the battle of #1813 vs. #1814.
My "AI" agrees with me (this "I").


Thinking:

I prefer #1813 as currently submitted. The two PRs produce essentially the same approximation for ordinary helices, but #1813 is more narrowly scoped and handles small/zero-angle sweeps better.

I compared heads 7d711a2 (#1813) and 84bd1a5 (#1814), including the surrounding shell-generation code.

The deciding difference: endpoint collapse

#1814 retains this existing code:

if(ps.Equals(pf)) {
    ps = c;
    ct = c;
    pf = c;
}

Nearby rotational endpoints do not imply that the point lies on the axis. They can simply mean the sweep angle is small.

For example, take a control point at (100, 0, 0), revolve about the z-axis through zero angle, and translate axially by 10:

Start Finish
Correct result / #1813 (100, 0, 0) (100, 0, 10)
#1814 (0, 0, 0) (0, 0, 10)

The same collapse occurs for sufficiently small nonzero angles. It is a potentially large positional error, not merely an error within tolerance.

This is inherited from master, not introduced by #1814, but #1813 explicitly fixes it for sweeps with axial displacement. Its axial formula also handles the zero-angle limit correctly.

The principal mathematics is equivalent

Both implementations:

  • Degree-elevate the rational circular arc to a cubic.
  • Preserve its circular projection.
  • Adjust the axial controls to match the analytic helix tangent at both endpoints.
  • Keep ordinary revolutions quadratic.

With w = cos(dtheta/2) and dz = distf - dists, the inner control’s axial displacement from its endpoint is, in both cases:

dz * (2*sin(dtheta/2)/dtheta) / (1 + 2*w)

#1813 computes that directly. #1814 obtains it through degree elevation followed by an axial correction.

Independent numerical sampling reproduced the advertised improvement:

Patch angle Original quadratic axial error Cubic error, either PR
90° 2.1088% 0.04930%
41° 0.41594% 0.001988%

Errors are relative to patch height. The two implementations agreed to floating-point roundoff in the nondegenerate cases I sampled, including reverse sweeps and an arbitrary axis. Accuracy on normal helices is not a reason to choose between them.

Implementation tradeoffs

#1813’s exact distance comparison is defensible. I would not add a tolerance merely because these are doubles. This selects quadratic versus cubic representation; it does not divide by the displacement or require it to be appreciably nonzero. The ordinary-revolution callers explicitly supply equal offsets, and the cubic formula remains well-behaved for tiny displacement and angle.

#1814’s helper is legitimate, but optional. ConvertQuadraticToCubic() correctly expresses a reusable homogeneous degree-elevation operation. That separation is its strongest advantage. Here, however, it adds an API and a temporary-curve/conversion/copying path for one caller. I slightly prefer #1813’s direct construction for this targeted change.

Both make the necessary trim fix. Copying the surface boundary’s actual degree, control points, and all weights in shell.cpp is correct in both PRs.

Recommendation

Merge #1813, perhaps borrowing #1814’s explanatory derivation comment. If you prefer the reusable-helper architecture, #1814 is a reasonable alternative after adopting the small/zero-angle handling from #1813.

Neither current diff includes regression tests—#1813’s were removed following the discussion—so I would not use committed test coverage as a differentiator.

Validation here was source review and independent numerical reproduction, not builds of both PRs or GUI/STEP round-trip testing.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@phkahler

phkahler commented Nov 9, 2026

Copy link
Copy Markdown
Member

Here, however, it adds an API and a temporary-curve/conversion/copying path for one caller.

I missed that in 1814. I asked it to declare the curve object outside the loop and wanted it to simply assign the points to it rather than call a constructor for each one. I do need to slow down...

ruevs reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ruevs

ruevs commented Nov 9, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Here, however, it adds an API and a temporary-curve/conversion/copying path for one caller.

I missed that in 1814. I asked it to declare the curve object outside the loop and wanted it to simply assign the points to it rather than call a constructor for each one. I do need to slow down...

Who's going to read all that generated code? - as I keep asking - not specifically in SolveSpace - for the whole planet :-) And I'm generating more as I write this :-/

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@alken1t15

alken1t15 commented Nov 9, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

@ruevs Thanks for reviewing both versions. What specific changes, if any, would you like in this PR before it can be merged? In particular:

  • For the distance comparison, should I use fabs(distf - dists) > LENGTH_EPS to select cubic rows while preserving the small/zero-angle handling? Your inline comment asks for a tolerance, while the later comparison says the exact check is defensible, so I'd like to confirm your preference.
  • Would expanding the derivation comment be sufficient to improve readability, or would you prefer a change to the function's structure?

Please let me know if anything else is missing or needs correcting, and I'll update the PR.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@phkahler

phkahler commented Nov 10, 2026

Copy link
Copy Markdown
Member

@alken1t15 Can you use the comment explanation from the other PR in this one. Then we can merge this one and drop the other completely.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@alken1t15
Explain the axial control offsets for helical patches
fbb0c94
@alken1t15

alken1t15 commented Nov 10, 2026

Copy link
Copy Markdown
Contributor Author

@phkahler Done in fbb0c94. I've brought over the explanation from #1814 and adapted it to the direct calculation here, including the axial offsets, endpoint slope condition and error reduction. Only comments changed; the implementation is unchanged.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@phkahler

phkahler commented Nov 10, 2026

Copy link
Copy Markdown
Member

@alken1t15 thank you for the contribution!

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@phkahler
phkahler merged commit abf33ac into solvespace:master Nov 10, 2026
4 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@alken1t15

alken1t15 commented Nov 10, 2026

Copy link
Copy Markdown
Contributor Author

@phkahler You're welcome, and thanks for the review and guidance! Are there any open, unclaimed issues of moderate to high difficulty that you'd particularly like help with at the moment? Geometry, NURBS or solver work would interest me. Ideally something reported within the last six months, with a reasonably clear scope. I've also asked about #1723 and #1774; if either would be useful to take on, I'd be happy to start there.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@phkahler

phkahler commented Nov 11, 2026

Copy link
Copy Markdown
Member

@alken1t15 I'm not sure if this PR caused it, but the CI tests on Ununtu are failing on master. All the regression tests pass but it's failing with a memory leak when built with sanitizers on. Could you have a look?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ruevs

ruevs commented Nov 11, 2026

Copy link
Copy Markdown
Member

https://github.com/solvespace/solvespace/actions/workflows/cd.yml

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@alken1t15 alken1t15 mentioned this pull request Nov 11, 2026
Release linked sketch caches during UI cleanup #1817
Merged
@alken1t15

alken1t15 commented Nov 11, 2026

Copy link
Copy Markdown
Contributor Author

@phkahler @ruevs I reproduced the leak and opened #1817 with a one-line cleanup fix. SolveSpaceUI::Clear() wasn't releasing the linked-sketch caches.

Running group/link/normal_roundtrip alone reproduces the same 45,428-byte leak in 17 allocations, including with the pre-#1813 code from b34d744, so it predates this PR. The shuffled order explains why it appeared in this run: that linked-file test ran last.

With the cleanup call added, the isolated test and all 300 tests (1,246 checks) pass with sanitizers, leak detection and OpenMP enabled, using the failing CI seed 2062209549.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@ruevs ruevs ruevs approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Use 3rd degree NURBS surfaces for helix extrusions

Uh oh!

There was an error while loading. Please reload this page.

3 participants

@alken1t15 @phkahler @ruevs
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.