Discretize for wires, curves

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
jreinhardt
Posts: 329
Joined: Mon Sep 09, 2013 6:08 pm

Discretize for wires, curves

Postby jreinhardt » Tue Aug 12, 2014 8:29 am

(This post is a summary of the discussion starting about here:
viewtopic.php?f=9&t=3914&start=60#p52330)

A while ago when working on the WebGL exporter I found that the docstring of Wire.discretize was inconsistent with its implementation. The same applies to Curves and Edges. This function can either be called with an integer or with a float. If called with an integer, this is interpreted as the number of vertices for the approximation. The docstring claims that a float is interpreted as the deflection of the discretization. The implementation however produces points that are uniformly spaced.

There is code out there that relies on this behaviour (viewtopic.php?f=9&t=3914&start=70#p52464)

I see multiple possibilities how to proceed:
  • Leave discretize as it is, adjust its docstring and potentially add a new function discretize_deflection for the deflection discretization. This keeps compatibility and exposes deflection discretizations.
  • Change discretize, leave docstring as it is. This breaks compatibility for those who relied on the current behaviour of discretize. Getting uniform discretizations of curves can still be done manually rather easily:

    Code: Select all

    [curve.value(u) for u in np.linspace(curve.FirstParameter,curve.Lastparameter,n_points)]
    or (without dependency on numpy)

    Code: Select all

    du = (curve.LastParameter-curve.FirstParameter)/(n_points-1)
    points = []
    for i in range(n_points):
      points.append(curve.value(curve.LastParameter+i*du))
    
    while doing discretizations with uniform deflection is much more difficult.
  • Change discretize to do both things, e.g. discretize(int or float,bool=false), where discretize(int) and discretize(float) give the current behaviour, and discretize(float,true) discretizes with constant deflection. This keeps compatibility and allows to handle rounded edges in WebGL, but is not really nice, as the bool parameter only applies to calls where the first parameter is a float.
I am fine with all possibilities, with a preference for the second one, as it results in the cleanest API. I can try to do the implementation, if there is a consensus about what to do.
BOLTS, standard parts library for FreeCAD Thread, Help with Translation
wmayer
Site Admin
Posts: 15478
Joined: Thu Feb 19, 2009 10:32 am

Re: Discretize for wires, curves

Postby wmayer » Tue Aug 12, 2014 12:44 pm

A fourth option might be to use keywords.

Code: Select all

wire.discretize(Number=1000)
wire.discretize(Abscissa = 1.0)
wire.discretize(Deflection = 0.01)
Without the keyword we can leave the current behaviour but change the doc string.

OCC offers a couple of different discretizing algorithms:
* GCPnts_UniformAbscissa (currently used)
* GCPnts_UniformDeflection
* GCPnts_TangentialDeflection
* GCPnts_QuasiUniformDeflection
* GCPnts_QuasiUniformAbscissa
wmayer
Site Admin
Posts: 15478
Joined: Thu Feb 19, 2009 10:32 am

Re: Discretize for wires, curves

Postby wmayer » Thu Aug 14, 2014 8:34 am

Checkout git commit 3d2a2b06f0c8a00338dfe1982aadd2173422ba7d.

The doc string is now fixed to describe the actual behaviour. Additionally, the keywords "Number", "Distance" (both has the same behaviour is if using no keyword), "Deflection" or "Angular" and "Curvature" (new methods) are supported.
jreinhardt
Posts: 329
Joined: Mon Sep 09, 2013 6:08 pm

Re: Discretize for wires, curves

Postby jreinhardt » Thu Aug 14, 2014 8:45 am

Thanks a lot! I was just right now reading up on how to handle keyword arguments... :? You are just too quick :D
BOLTS, standard parts library for FreeCAD Thread, Help with Translation
wmayer
Site Admin
Posts: 15478
Joined: Thu Feb 19, 2009 10:32 am

Re: Discretize for wires, curves

Postby wmayer » Thu Aug 14, 2014 9:24 am

Additionally the keywords "First" and "Last" are supported to define a sub-range of the parameter range. As an example see:

Code: Select all

import Part
c=Part.Circle()
c.Radius=5
p=c.discretize(Number=50,First=3.14)
s=Part.Compound([Part.Vertex(i) for i in p])
Part.show(s)


p=c.discretize(Angular=0.09,Curvature=0.01,Last=3.14,Minimum=100)
s=Part.Compound([Part.Vertex(i) for i in p])
Part.show(s)
For now I only used the classes GCPnts_UniformAbscissa, GCPnts_UniformDeflection, GCPnts_TangentialDeflection and skipped GCPnts_QuasiUniformDeflection and GCPnts_QuasiUniformAbscissa.
jreinhardt
Posts: 329
Joined: Mon Sep 09, 2013 6:08 pm

Re: Discretize for wires, curves

Postby jreinhardt » Thu Aug 14, 2014 10:04 am

If I understand correctly, the Quasi* variants scale much better performancewise, for the expense of slightly more points in the discretization:

http://dev.opencascade.org/doc/refman/h ... ction.html

For my application (WebGL export) that tradeoff would be perfectly fine.

Here is a branch that removes the option that was introduced in the WebGL exporter to work around the problems created by my use of the old discretize and uses the new one. This gives nice wireframes and small files:

https://github.com/jreinhardt/FreeCAD_s ... discretize
BOLTS, standard parts library for FreeCAD Thread, Help with Translation
wmayer
Site Admin
Posts: 15478
Joined: Thu Feb 19, 2009 10:32 am

Re: Discretize for wires, curves

Postby wmayer » Thu Aug 14, 2014 3:02 pm

So, do you want to see the Quasi methods, too? Your branch can it be merged into master?
wmayer
Site Admin
Posts: 15478
Joined: Thu Feb 19, 2009 10:32 am

Re: Discretize for wires, curves

Postby wmayer » Thu Aug 14, 2014 5:15 pm

git commit 7eaa4ff adds the Quasi methods.

Example:

Code: Select all

import Part
V=App.Vector

e1=Part.makeCircle(5,V(0,0,0),V(0,0,1),0,180)
e2=Part.makeCircle(5,V(10,0,0),V(0,0,1),180,360)
w=Part.Wire([e1,e2])

p=w.discretize(Number=50)
s=Part.Compound([Part.Vertex(i) for i in p])
Part.show(s)

p=w.discretize(QuasiNumber=50)
s=Part.Compound([Part.Vertex(i) for i in p])
Part.show(s)


p=w.discretize(Deflection=0.05)
s=Part.Compound([Part.Vertex(i) for i in p])
Part.show(s)

p=w.discretize(QuasiDeflection=0.05)
s=Part.Compound([Part.Vertex(i) for i in p])
Part.show(s)
jreinhardt
Posts: 329
Joined: Mon Sep 09, 2013 6:08 pm

Re: Discretize for wires, curves

Postby jreinhardt » Thu Aug 14, 2014 6:01 pm

Thanks! I adapted my code to make use of the QuasiDeflection method. I amended the last commit, so take care if you had already fetched it.
BOLTS, standard parts library for FreeCAD Thread, Help with Translation
wmayer
Site Admin
Posts: 15478
Joined: Thu Feb 19, 2009 10:32 am

Re: Discretize for wires, curves

Postby wmayer » Thu Aug 14, 2014 9:35 pm

Merged.