← 输入框|github.com|刷新
Skip to content

Use 3rd degree NURBS for helical surfaces - #1814

Closed
phkahler wants to merge 1 commit into
solvespace:masterfrom
phkahler:helix
Closed

phkahler wants to merge 1 commit into
solvespace:masterfrom
phkahler:helix

Conversation

@phkahler

@phkahler phkahler commented Nov 8, 2026

Copy link
Copy Markdown
Member

Reduces the error over 2nd degree curves by over 40x for 90 degree sweeps.

Add SBezier::ConvertQuadraticToCubic(), which raises a quadratic to a cubic in place without changing the curve, in homogeneous coordinates so arcs stay exact. In SSurface::FromRevolutionOf(), a section that turns and moves along the axis gets each row raised to a cubic, and its two inner control points moved along the axis by dz * (2 sin(dtheta/2)/dtheta - w) / (1 + 2w), so the slope at each end matches the helix. Seen along the axis the rows stay exact circles. The axial error drops about 40 times for a 90 degree section, and about 200 times for a 41 degree one. Plain revolutions keep quadratic rows.

In SShell::MakeFromHelicalRevolutionOf(), build the edge curve between neighboring surfaces from the surface's whole first row, of whatever degree.

…so the surface follows the true helix far more closely.

Add SBezier::ConvertQuadraticToCubic(), which raises a quadratic to a cubic in place without changing the curve, in homogeneous coordinates so arcs stay exact. In SSurface::FromRevolutionOf(), a section that turns and moves along the axis gets each row raised to a cubic, and its two inner control points moved along the axis by dz * (2 sin(dtheta/2)/dtheta - w) / (1 + 2w), so the slope at each end matches the helix. Seen along the axis the rows stay exact circles. The axial error drops about 40 times for a 90 degree section, and about 200 times for a 41 degree one. Plain revolutions keep quadratic rows.

In SShell::MakeFromHelicalRevolutionOf(), build the edge curve between neighboring surfaces from the surface's whole first row, of whatever degree.
@phkahler

phkahler commented Nov 8, 2026

Copy link
Copy Markdown
Member Author

@ruevs compare with #1813 and let us know!

@phkahler phkahler linked an issue Nov 8, 2026 that may be closed by this pull request
@ruevs

ruevs commented Nov 9, 2026 •

Copy link
Copy Markdown
Member

@ruevs compare with #1813 and let us know!

OK I will.

@ruevs ruevs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I like #1813 more.

Comment thread src/srf/shell.cpp
sc.isExact = true;
sc.exact = SBezier::From(ss->ctrl[0][0], ss->ctrl[0][1], ss->ctrl[0][2]);
sc.exact.weight[1] = ss->weight[0][1];
sc.exact.deg = ss->degn;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment thread src/srf/surface.cpp
Vector c = ps.ClosestPointOnLine(pt, axis);
Vector ct = mid.Minus(c).ScaledBy(1 / (w * w)).Plus(c);

// not sure this is needed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@phkahler

phkahler commented Nov 9, 2026

Copy link
Copy Markdown
Member Author

@ruevs I thought it might be better (educational) to make it more explicit that each point is essentially converted to a curve, the curve is elevated in degree for helix and shifted axially, and the row of control points in the surface are the ones from that curve. For being compact and direct the other one is obviously better. Close this, merge that ;-)

@ruevs

ruevs commented Nov 9, 2026 •

Copy link
Copy Markdown
Member

@ruevs I thought it might be better (educational) to make it more explicit that each point is essentially converted to a curve, the curve is elevated in degree for helix and shifted axially, and the row of control points in the surface are the ones from that curve. For being compact and direct the other one is obviously better. Close this, merge that ;-)

You are right about the readability - yours is more readable. If you want - fix this:

// not sure this is needed
if(ps.Equals(pf)) {
ps = c;
ct = c;
pf = c;
}

to match

// 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)) {
ps = c;
ct = c;
pf = c;
}

And then your solution will be the same functionally and more readable.

Edit: and fix this #1813 (comment)

@ruevs

ruevs commented Nov 11, 2026

Copy link
Copy Markdown
Member

#1813 got merged.

@ruevs ruevs closed this Nov 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use 3rd degree NURBS surfaces for helix extrusions

2 participants