Inconsistencies in Part API *At methods

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
crobar
Posts: 153
Joined: Fri Aug 29, 2014 1:26 pm

Inconsistencies in Part API *At methods

Postby crobar » Wed May 17, 2017 2:41 pm

I was attempting to improve the docstring for some Part api functions, but ran into some trouble. I've noticed that the behaviour of the valueAt, tangetAt etc. functions is not consistant. Consider the code and output below:

Code: Select all

import Draft
import Part
from FreeCAD import Vector

bez_edge = Draft.makeBezCurve([Vector (0.0, 0.0, 0.0), Vector (0.5, 0.0, 0.0), Vector (1.0, 0.5, 0.0), Vector (1.0, 1.0, 0.0)]).Shape.Edges[0]

print ("bez_edge.valueAt (1.0): {}".format (bez_edge.valueAt (1.0)))
print ("bez_edge.valueAt (1.0 * bez_edge.Length): {}".format (bez_edge.valueAt (1.0 * bez_edge.Length)))

line_edge = Part.makeLine (Vector (0.0, 0.0, 0.0), Vector (1.0, 1.0, 0.0))
Part.show (line_edge)

print ("line_edge.valueAt (1.0): {}".format (line_edge.valueAt (1.0)))
print ("line_edge.valueAt (1.0 * line_edge.Length): {}".format (line_edge.valueAt (1.0 * line_edge.Length)))

circle_edge = Part.makeCircle (1.0, Vector (1.0, 0.0, 0.0), Vector (0.0, 0.0, 1.0), 0, 90)
Part.show (circle_edge)

print ("Part.makeCircle (1.0, Vector (1.0, 0.0, 0.0), Vector (0.0, 0.0, 1.0), 0, 90)")
print ("circle_edge.valueAt (1.0): {}".format (circle_edge.valueAt (1.0)))
print ("circle_edge.valueAt (1.0 * circle_edge.Length): {}".format (circle_edge.valueAt (1.0 * circle_edge.Length)))


circle_edge = Part.makeCircle (1.0, Vector (2.0, 1.0, 0.0), Vector (0.0, 0.0, 1.0), 90, 180)
Part.show (circle_edge)

print ("Part.makeCircle (1.0, Vector (2.0, 1.0, 0.0), Vector (0.0, 0.0, 1.0), 90, 180)")
print ("circle_edge.valueAt (1.0): {}".format (circle_edge.valueAt (1.0)))
print ("circle_edge.valueAt (1.0 * circle_edge.Length): {}".format (circle_edge.valueAt (1.0 * circle_edge.Length)))
output

Code: Select all

bez_edge.valueAt (1.0): Vector (1.0, 1.0, 0.0)
bez_edge.valueAt (1.0 * bez_edge.Length): Vector (0.465441057817615, 1.7406270428980575, 0.0)
line_edge.valueAt (1.0): Vector (0.7071067811865475, 0.7071067811865475, 0.0)
line_edge.valueAt (1.0 * line_edge.Length): Vector (1.0, 1.0, 0.0)
Part.makeCircle (1.0, Vector (1.0, 0.0, 0.0), Vector (0.0, 0.0, 1.0), 0, 90)
circle_edge.valueAt (1.0): Vector (1.5403023058681398, 0.8414709848078965, 0.0)
circle_edge.valueAt (1.0 * circle_edge.Length): Vector (1.0, 1.0, 0.0)
Part.makeCircle (1.0, Vector (2.0, 1.0, 0.0), Vector (0.0, 0.0, 1.0), 90, 180)
circle_edge.valueAt (1.0): Vector (2.5403023058681398, 1.8414709848078965, 0.0)
circle_edge.valueAt (1.0 * circle_edge.Length): Vector (2.0, 2.0, 0.0)
The correct output in every case should be Vector (1.0, 1.0, 0.0), but the input argument expected differs in whether you must scale by the length of the curve or not, and the circle behavior is even less intuitive for arc segments. It still acts like the full circle.
wmayer
Site Admin
Posts: 14778
Joined: Thu Feb 19, 2009 10:32 am

Re: Inconsistencies in Part API *At methods

Postby wmayer » Wed May 17, 2017 3:21 pm

It seems you made the assumption that for the parameter 0 you get the curve's start point and with the value of its length you get the end point. This assumption is wrong!

The parameter range in which a curve is defined do you get with the attributes FirstParameter and LastParameter. It depends on the type of geometry what this range can be. E.g. for lines it's usually [0, length], for infinite curves like hyperbolas or parabolas it's always ]-inf, +inf[, for full ellipses or circles it's [0, 2*PI]. And for B-splines it can be everything.

So again never rely on geometry type or geometrical properties, all what counts is FirstParameter and LastParameter, nothing else.
crobar
Posts: 153
Joined: Fri Aug 29, 2014 1:26 pm

Re: Inconsistencies in Part API *At methods

Postby crobar » Wed May 17, 2017 3:36 pm

wmayer wrote:It seems you made the assumption that for the parameter 0 you get the curve's start point and with the value of its length you get the end point. This assumption is wrong!

The parameter range in which a curve is defined do you get with the attributes FirstParameter and LastParameter. It depends on the type of geometry what this range can be. E.g. for lines it's usually [0, length], for infinite curves like hyperbolas or parabolas it's always ]-inf, +inf[, for full ellipses or circles it's [0, 2*PI]. And for B-splines it can be everything.

So again never rely on geometry type or geometrical properties, all what counts is FirstParameter and LastParameter, nothing else.
ok, that clarifies things, thanks.