OCC/Math Help re BSplines and Circles

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
wandererfan
Veteran
Posts: 6326
Joined: Tue Nov 06, 2012 5:42 pm
Contact:

OCC/Math Help re BSplines and Circles

Post by wandererfan »

The OCC Hidden Line Removal algorithms have a fondness for BSplines and often return one when a circle or straight line would be expected.

This causes problems in dimensioning when what looks like a circle can't have a radius or diameter assigned. For example the inner circle in the picture is actually a Geom_BSplineCurve with degree of 4 and 29 poles.

Is there a way to tell if a BSpline is arbitrarily close to being a circle?
Attachments
CircleAsSpline.png
CircleAsSpline.png (34.49 KiB) Viewed 2149 times
User avatar
easyw-fc
Veteran
Posts: 3633
Joined: Thu Jul 09, 2015 9:34 am

Re: OCC/Math Help re BSplines and Circles

Post by easyw-fc »

wandererfan wrote: Fri Aug 03, 2018 12:09 am The OCC Hidden Line Removal algorithms have a fondness for BSplines and often return one when a circle or straight line would be expected.

This causes problems in dimensioning when what looks like a circle can't have a radius or diameter assigned. For example the inner circle in the picture is actually a Geom_BSplineCurve with degree of 4 and 29 poles.

Is there a way to tell if a BSpline is arbitrarily close to being a circle?
Hi,
I use to simplify a Sketch from splines to arcs for my StepUp wb...

Here the code I use to convert spline edges to arcs

Code: Select all

if isinstance(e.Curve,Part.BSplineCurve):
    print('found BSpline')
    edges = []
    arcs = e.Curve.toBiArcs(precision)
    #print arcs
    for i in arcs:
        edges.append(Part.Edge(i))
    w = Part.Wire([Part.Edge(i) for i in edges])
    Part.show(w)
    
here a sample of a circle converted to 4 arcs, that can be assigned to a dimension quote
circle-to-spline.FCStd
(6.97 KiB) Downloaded 46 times
User avatar
wandererfan
Veteran
Posts: 6326
Joined: Tue Nov 06, 2012 5:42 pm
Contact:

Re: OCC/Math Help re BSplines and Circles

Post by wandererfan »

easyw-fc wrote: Fri Aug 03, 2018 9:40 am Here the code I use to convert spline edges to arcs
This looks really promising for the conversion, but how do you tell that a given spline is a candidate to be converted to arcs? Is there some property of the BSpline that says "I would make a good circle"? Derivatives, degree, continuity,....?

If the curve is "legitimately" a BSpline, I don't want to convert it.

Thanks,
wf
User avatar
Chris_G
Veteran
Posts: 2602
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: OCC/Math Help re BSplines and Circles

Post by Chris_G »

wandererfan wrote: Fri Aug 03, 2018 1:23 pm This looks really promising for the conversion, but how do you tell that a given spline is a candidate to be converted to arcs? Is there some property of the BSpline that says "I would make a good circle"? Derivatives, degree, continuity,....?
I would sample the curve to check for a constant curvature and fixed center of curvature.
If curvature is null, it is a line segment, else it is an arc of circle.
User avatar
wandererfan
Veteran
Posts: 6326
Joined: Tue Nov 06, 2012 5:42 pm
Contact:

Re: OCC/Math Help re BSplines and Circles

Post by wandererfan »

Chris_G wrote: Fri Aug 03, 2018 1:38 pm I would sample the curve to check for a constant curvature and fixed center of curvature.
If curvature is null, it is a line segment, else it is an arc of circle.
Sampled curvature at various points along the BSpline averages the right value (0.025) which gives appropriate radius (40). The center of curvature wanders a bit though. Close, but errors +/- 0.15 mm on radius of 40 for an error of about 0.3%. This is probably ok for drawings.

Converting to biArcs isn't as promising. I get 441 arcs returned. Don't think we want 441 Vertices around the "pseudo-circle".

If the curvature is constant over n points, I'll need to make a replacement circular curve and tag it somehow as an approximation, or add a dialog: "this curve is a BSpline. are you sure you want to make a radius/diameter dimension".

Thanks for the help.
User avatar
Chris_G
Veteran
Posts: 2602
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: OCC/Math Help re BSplines and Circles

Post by Chris_G »

I am not sure you really need to check for the fixed center of curvature.
This is only useful to avoid corner cases like below :
constant_curvature.png
constant_curvature.png (33.35 KiB) Viewed 2036 times

Code: Select all

import FreeCAD
from FreeCAD import Vector
import Part

def is_constant_curvature(e1, samples=20, tol=1e-7):
    par = [e1.FirstParameter + float(i)*(e1.LastParameter-e1.FirstParameter)/(samples-1) for i in range(samples)]
    curv = [e1.curvatureAt(t) for t in par]
    r = max(curv) - min(curv)
    if r < tol:
        return(True)
    else:
        return(False)


poles0 = [Vector (34.21438206257911, 23.10367201921499, 0.0), Vector (22.67646146586833, 8.22460119620848, 0.0), Vector (6.576066806796006, 17.98614062778186, 0.0), Vector (-9.536455664225732, 27.755033053925636, 0.0), Vector (-21.071925059496575, 12.856120830426926, 0.0), Vector (-32.60739445476892, -2.0427913930737085, 0.0), Vector (-19.1148578142296, -15.195589369798869, 0.0)]
weights0 = [1.0, 0.746426611263413, 0.9999999999999509, 0.7461776491418026, 1.0, 0.7461776491417781, 1.0]
knots0 = [-0.4306144885082732, 1.0257632432118662, 2.4827518844547907, 3.9397405256978564]
mults0 = [3L, 2L, 2L, 3L]
periodic0 = False
degree0 = 2
rational0 = True
bs0 = Part.BSplineCurve()
bs0.buildFromPolesMultsKnots(poles0, mults0, knots0, periodic0, degree0, weights0, rational0)
obj0 = FreeCAD.ActiveDocument.addObject("Part::Spline","BSplineCurve0")
obj0.Shape = bs0.toShape()

is_constant_curvature(obj0.Shape.Edge1)

User avatar
wandererfan
Veteran
Posts: 6326
Joined: Tue Nov 06, 2012 5:42 pm
Contact:

Re: OCC/Math Help re BSplines and Circles

Post by wandererfan »

Chris_G wrote: Sat Aug 04, 2018 3:55 pm I am not sure you really need to check for the fixed center of curvature.
I now have a "spline->isCircle()" function that seems reliable and Diameter/Radius dimensions that can use splines in development.

Thanks for your help.
xc22143
Posts: 139
Joined: Fri Dec 03, 2021 9:52 am

Re: OCC/Math Help re BSplines and Circles

Post by xc22143 »

hi! Can you post the code of "spline->isCircle()" function? Thank you.
User avatar
jnxd
Posts: 952
Joined: Mon Mar 30, 2015 2:30 pm
Contact:

Re: OCC/Math Help re BSplines and Circles

Post by jnxd »

wandererfan wrote: Sat Aug 04, 2018 12:31 pm Sampled curvature at various points along the BSpline averages the right value (0.025) which gives appropriate radius (40). The center of curvature wanders a bit though. Close, but errors +/- 0.15 mm on radius of 40 for an error of about 0.3%. This is probably ok for drawings.
Typically a B-Spline (and particularly a NURBS) should be able to exactly approximate a circle. Is there any way for you to extract the pole and knot information?
User avatar
wandererfan
Veteran
Posts: 6326
Joined: Tue Nov 06, 2012 5:42 pm
Contact:

Re: OCC/Math Help re BSplines and Circles

Post by wandererfan »

xc22143 wrote: Wed Mar 09, 2022 3:12 am hi! Can you post the code of "spline->isCircle()" function? Thank you.
isCircle() is in TechDraw/App/Geometry.cpp, but the hard work is done by this routine:

Code: Select all

void BSpline::getCircleParms(bool& isCircle, double& radius, Base::Vector3d& center, bool& isArc)
It is a bit long to put in a post. You can look at it on GitHub.

Mod edit:
Here's the link to exact line in the code: https://github.com/FreeCAD/FreeCAD/blob ... .cpp#L1328
Post Reply