OCC/Math Help re BSplines and Circles
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
- wandererfan
- Veteran
- Posts: 6326
- Joined: Tue Nov 06, 2012 5:42 pm
- Contact:
OCC/Math Help re BSplines and Circles
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?
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 (34.49 KiB) Viewed 2149 times
Re: OCC/Math Help re BSplines and Circles
Hi,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?
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)
- wandererfan
- Veteran
- Posts: 6326
- Joined: Tue Nov 06, 2012 5:42 pm
- Contact:
Re: OCC/Math Help re BSplines and Circles
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
Re: OCC/Math Help re BSplines and Circles
I would sample the curve to check for a constant curvature and fixed center of curvature.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,....?
If curvature is null, it is a line segment, else it is an arc of circle.
- wandererfan
- Veteran
- Posts: 6326
- Joined: Tue Nov 06, 2012 5:42 pm
- Contact:
Re: OCC/Math Help re BSplines and Circles
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.
Re: OCC/Math Help re BSplines and Circles
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 :
This is only useful to avoid corner cases like below :
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)
- wandererfan
- Veteran
- Posts: 6326
- Joined: Tue Nov 06, 2012 5:42 pm
- Contact:
Re: OCC/Math Help re BSplines and Circles
hi! Can you post the code of "spline->isCircle()" function? Thank you.
Re: OCC/Math Help re BSplines and Circles
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?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.
- wandererfan
- Veteran
- Posts: 6326
- Joined: Tue Nov 06, 2012 5:42 pm
- Contact:
Re: OCC/Math Help re BSplines and Circles
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)
Mod edit:
Here's the link to exact line in the code: https://github.com/FreeCAD/FreeCAD/blob ... .cpp#L1328