Rationalising FreeCAD curve and surface workbenches

Have some feature requests, feedback, cool stuff to share, or want to know where FreeCAD is going? This is the place.
Forum rules
Be nice to others! Read the FreeCAD code of conduct!
User avatar
onekk
Veteran
Posts: 6197
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Rationalising FreeCAD curve and surface workbenches

Post by onekk »

From my point of view, if FreeCAD is able to do things, like BSplineSurfaces, it would be better to make two or three "working examples" that illustrate the current "state of the art".

I'm struggling to close a solid, made from shell created using BSplineSurfaces, but:

The surface seems good, but it is reversed, the inner face (that would be show in black is the outer face) see for a beginning of code:

https://forum.freecadweb.org/viewtopic.php?f=22&t=60545

Code: Select all

import FreeCAD
import Part

import math

from FreeCAD import Vector, Rotation

DOC = FreeCAD.activeDocument()

a_tol = 0.001

NO_X = 10
NO_Z = 10

X = 1
Y = 0.1
Z = 2


def ellipse(x, a, b):
    """Calculate the y-coordinate of an ellipse with the one apex at (0,0) and one at (2a,0)."""
    return b/a * math.sqrt(a**2 - (x-a)**2)


def parabola(x, a, b):
    """Calculate the y-coordinate of an parabola through the points (0,0), (a,b) and (2a,0)."""
    return b * (1 - ((x-a)/a)**2)


def points():
    """Generate the points of our surface."""
    array = []
    array1 = []
    for j in range(NO_Z):
        z = (j+10)/NO_Z * Z
        b = Z/10 - 0.02*z
        line = []
        # First side (back)
        for i in range(1, NO_X):
            x = i/NO_X * X
            y = parabola(x, X/2, 2*b) + ellipse(x, X/2, b)
            point = Vector(x, y, z)
            line.append(point)

        # Second side (face)
        for i in range(NO_X, 0, -1):
            x = i/NO_X * X
            y = parabola(x, X/2, 2*b) - ellipse(x, X/2, b)
            point = Vector(x, y, z)
            line.append(point)

        array.append(line)

    return array

array = points()

show_points = False

if show_points == True:
    for l_idx,line in enumerate(array):
        for p_idx, pt in enumerate(line):
            show_point(pt, l_idx, p_idx)

DOC.recompute()

sections = []

secs_open = False


if secs_open == True:
    for line in array:
        sec = Part.BSplineCurve()
        sec.approximate(line)

        sections.append(sec)
    
    bs1 = Part.BSplineSurface()
    bs1.buildFromNSections(sections)
    bs1.exchangeUV()
    
    alt_surf = bs1.toShape()
    show_curve(alt_surf, "alt_surf")


    
else:
    for line in array:
        sec = Part.BSplineCurve()
        sec.approximate(line)
        sec_sp = sec.StartPoint
        sec_ep = sec.EndPoint
        
        c_ln = Part.LineSegment(sec_ep, sec_sp)
    
        edges = Part.sortEdges([c_ln.toShape(), sec.toShape()])[0]
    
        prof = Part.Wire(edges)
            
        sections.append(prof)
    
    shapes = Part.makeLoft(sections,True)
    show_curve(shapes,"loft")
EDIT: I have modeified the code above


settings the secs_open to False it seems that the solid is correct, but the visualisation is not very correct as some faces are black
see:

solid_w.png
solid_w.png (2.87 KiB) Viewed 2480 times
solid_w1.png
solid_w1.png (3.22 KiB) Viewed 2480 times
solid_w2.png
solid_w2.png (5.88 KiB) Viewed 2480 times
Regards

Carlo D.

OS: Artix Linux (openbox)
Word size of FreeCAD: 64-bit
Version: 0.20.25288 (Git) AppImage
Build type: Release
Branch: master
Hash: bbb557aab6129efd9486d6df19f06c2976fdb7e5
Python version: 3.9.6
Qt version: 5.12.9
Coin version: 4.0.0
OCC version: 7.5.2
Locale: Italian/Italy (it_IT)
Last edited by Kunda1 on Thu Aug 05, 2021 9:35 am, edited 1 time in total.
Reason: Thread was split from "where do you see FreeCAD main focus go towards?" https://forum.freecadweb.org/viewtopic.php?f=8&t=60610
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
keithsloan52
Veteran
Posts: 2764
Joined: Mon Feb 27, 2012 5:31 pm

Re: where do you see FreeCAD main focus go towards?

Post by keithsloan52 »

For Curves related development is the lack of a Part::BezierSpline ( Or equivlant ) holding things back ( Same goes for Part::Surface)

I just created a 'Freehand_BSpline' in the curves workbench.

When in the python console I enter p=FreeCAD.ActiveDocument.getObject('Freehand_BSpline') followed by print(dir(p)) I get

Code: Select all

['Content', 'Data', 'DataType', 'Document', 'ExpressionEngine', 'Flags', 'FullName', 'ID', 'InList', 'InListRecursive', 'Label', 'Label2', 'LinearSegments', 'MemSize', 'Module', 'MustExecute', 'Name', 'NoTouch', 'OldLabel', 'OutList', 'OutListRecursive', 'Parametrization', 'Parents', 'Periodic', 'Placement', 'PropertiesList', 'Proxy', 'Removing', 'Shape', 'State', 'Support', 'Tangents', 'Tolerance', 'TypeId', 'ViewObject', 'Visibility', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'addExtension', 'addObject', 'addObjects', 'addProperty', 'adjustRelativeLinks', 'dumpContent', 'dumpPropertyContent', 'enforceRecompute', 'evalExpression', 'getAllDerivedFrom', 'getDocumentationOfProperty', 'getEditorMode', 'getEnumerationsOfProperty', 'getGlobalPlacement', 'getGroupOfProperty', 'getLinkedObject', 'getObject', 'getParentGeoFeatureGroup', 'getParentGroup', 'getPaths', 'getPathsByOutList', 'getPropertyByName', 'getPropertyNameOfGeometry', 'getPropertyOfGeometry', 'getPropertyStatus', 'getPropertyTouchList', 'getStatusString', 'getSubObject', 'getSubObjectList', 'getSubObjects', 'getTypeIdOfProperty', 'getTypeOfProperty', 'hasChildElement', 'hasExtension', 'hasObject', 'isDerivedFrom', 'isElementVisible', 'isValid', 'newObject', 'purgeTouched', 'recompute', 'removeObject', 'removeObjects', 'removeObjectsFromDocument', 'removeProperty', 'resolve', 'resolveSubElement', 'restoreContent', 'restorePropertyContent', 'setEditorMode', 'setElementVisible', 'setExpression', 'setObjects', 'setPropertyStatus', 'supportedProperties', 'touch']
and print(dir(p.Shape))

Code: Select all

['Area', 'BoundBox', 'CenterOfMass', 'Closed', 'CompSolids', 'Compounds', 'Content', 'Continuity', 'Curve', 'Degenerated', 'Edges', 'Faces', 'FirstParameter', 'LastParameter', 'Length', 'Mass', 'Matrix', 'MatrixOfInertia', 'MemSize', 'Module', 'Orientation', 'ParameterRange', 'Placement', 'PrincipalProperties', 'ShapeType', 'Shells', 'Solids', 'StaticMoments', 'SubShapes', 'Tag', 'Tolerance', 'TypeId', 'Vertexes', 'Volume', 'Wires', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 'ancestorsOfType', 'centerOfCurvatureAt', 'check', 'childShapes', 'cleaned', 'common', 'complement', 'copy', 'countElement', 'curvatureAt', 'curveOnSurface', 'cut', 'defeaturing', 'derivative1At', 'derivative2At', 'derivative3At', 'discretize', 'distToShape', 'dumpContent', 'dumpToString', 'exportBinary', 'exportBrep', 'exportBrepToString', 'exportIges', 'exportStep', 'exportStl', 'extrude', 'findPlane', 'firstVertex', 'fix', 'fixTolerance', 'fuse', 'generalFuse', 'getAllDerivedFrom', 'getElement', 'getFacesFromSubelement', 'getParameterByLength', 'getTolerance', 'globalTolerance', 'hashCode', 'importBinary', 'importBrep', 'importBrepFromString', 'inTolerance', 'isClosed', 'isCoplanar', 'isDerivedFrom', 'isEqual', 'isInfinite', 'isInside', 'isNull', 'isPartner', 'isSame', 'isSeam', 'isValid', 'lastVertex', 'limitTolerance', 'makeChamfer', 'makeFillet', 'makeOffset2D', 'makeOffsetShape', 'makeParallelProjection', 'makePerspectiveProjection', 'makeShapeFromMesh', 'makeThickness', 'makeWires', 'mirror', 'multiFuse', 'normalAt', 'nullify', 'oldFuse', 'optimalBoundingBox', 'overTolerance', 'parameterAt', 'parameters', 'project', 'proximity', 'read', 'reflectLines', 'removeInternalWires', 'removeShape', 'removeSplitter', 'replaceShape', 'restoreContent', 'reverse', 'reversed', 'revolve', 'rotate', 'rotated', 'scale', 'scaled', 'section', 'sewShape', 'slice', 'slices', 'split', 'tangentAt', 'tessellate', 'toNurbs', 'transformGeometry', 'transformShape', 'transformed', 'translate', 'translated', 'valueAt', 'writeInventor']
No mention of poles, knots or other related Bezier stuff.

If I create a Part Bezier with pb=Part.Bezier() and print(dir(pb)) I get

Code: Select all

['Content', 'Continuity', 'Degree', 'EndPoint', 'FirstParameter', 'LastParameter', 'MaxDegree', 'MemSize', 'Module', 'NbPoles', 'Rotation', 'StartPoint', 'Tag', 'TypeId', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'approximateBSpline', 'centerOfCurvature', 'clone', 'continuityWith', 'copy', 'curvature', 'deleteExtensionOfName', 'deleteExtensionOfType', 'discretize', 'dumpContent', 'getAllDerivedFrom', 'getD0', 'getD1', 'getD2', 'getD3', 'getDN', 'getExtensionOfName', 'getExtensionOfType', 'getExtensions', 'getPole', 'getPoles', 'getResolution', 'getWeight', 'getWeights', 'hasExtensionOfName', 'hasExtensionOfType', 'increase', 'insertPoleAfter', 'insertPoleBefore', 'interpolate', 'intersect', 'intersect2d', 'intersectCC', 'intersectCS', 'isClosed', 'isDerivedFrom', 'isPeriodic', 'isRational', 'length', 'makeRuledSurface', 'mirror', 'normal', 'parameter', 'parameterAtDistance', 'period', 'removePole', 'restoreContent', 'reverse', 'reversedParameter', 'rotate', 'scale', 'segment', 'setExtension', 'setPole', 'setPoles', 'setWeight', 'tangent', 'toBSpline', 'toNurbs', 'toShape', 'transform', 'translate', 'trim', 'value']
Which has Degree, NbPoles and functions related to a Bezier. But a Part is Not a FreeCAD Object it is a Shape.

I note that in ImportNURBS when it encounters a Bezier it creates a part.Bezier and creates a FreeCAD Object Part::Feature which it equates its Shape to, which is okay because it is a Shape, but it looses all the detailed Bezier NbPoles and functions.

So my question is. To make any real progress with the various Curve workbenches do we need Part Objects
  • Part::BSplineCurve - Object equivalent of Part.BSplineCurve Shape.
  • Part::BSplineSurface
  • Part::BezierCurve
  • Part::BezierSurface

So that all curve related workbenches can load/store the above and when the curves workbench creates a Part::BSplineCurve it can be used
directly used in one of the other curves workbenchs.
carlopav
Veteran
Posts: 2062
Joined: Mon Dec 31, 2018 1:49 pm
Location: Venice, Italy

Re: where do you see FreeCAD main focus go towards?

Post by carlopav »

keithsloan52 wrote: Mon Aug 02, 2021 8:48 pm and print(dir(p.Shape))

Code: Select all

['Area', 'BoundBox', 'CenterOfMass', 'Closed', 'CompSolids', 'Compounds', 'Content', 'Continuity', 'Curve', 'Degenerated', 'Edges', 'Faces', 'FirstParameter', 'LastParameter', 'Length', 'Mass', 'Matrix', 'MatrixOfInertia', 'MemSize', 'Module', 'Orientation', 'ParameterRange', 'Placement', 'PrincipalProperties', 'ShapeType', 'Shells', 'Solids', 'StaticMoments', 'SubShapes', 'Tag', 'Tolerance', 'TypeId', 'Vertexes', 'Volume', 'Wires', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 'ancestorsOfType', 'centerOfCurvatureAt', 'check', 'childShapes', 'cleaned', 'common', 'complement', 'copy', 'countElement', 'curvatureAt', 'curveOnSurface', 'cut', 'defeaturing', 'derivative1At', 'derivative2At', 'derivative3At', 'discretize', 'distToShape', 'dumpContent', 'dumpToString', 'exportBinary', 'exportBrep', 'exportBrepToString', 'exportIges', 'exportStep', 'exportStl', 'extrude', 'findPlane', 'firstVertex', 'fix', 'fixTolerance', 'fuse', 'generalFuse', 'getAllDerivedFrom', 'getElement', 'getFacesFromSubelement', 'getParameterByLength', 'getTolerance', 'globalTolerance', 'hashCode', 'importBinary', 'importBrep', 'importBrepFromString', 'inTolerance', 'isClosed', 'isCoplanar', 'isDerivedFrom', 'isEqual', 'isInfinite', 'isInside', 'isNull', 'isPartner', 'isSame', 'isSeam', 'isValid', 'lastVertex', 'limitTolerance', 'makeChamfer', 'makeFillet', 'makeOffset2D', 'makeOffsetShape', 'makeParallelProjection', 'makePerspectiveProjection', 'makeShapeFromMesh', 'makeThickness', 'makeWires', 'mirror', 'multiFuse', 'normalAt', 'nullify', 'oldFuse', 'optimalBoundingBox', 'overTolerance', 'parameterAt', 'parameters', 'project', 'proximity', 'read', 'reflectLines', 'removeInternalWires', 'removeShape', 'removeSplitter', 'replaceShape', 'restoreContent', 'reverse', 'reversed', 'revolve', 'rotate', 'rotated', 'scale', 'scaled', 'section', 'sewShape', 'slice', 'slices', 'split', 'tangentAt', 'tessellate', 'toNurbs', 'transformGeometry', 'transformShape', 'transformed', 'translate', 'translated', 'valueAt', 'writeInventor']
No mention of poles, knots or other related Bezier stuff.
The poles should be listed under the geometry, not under the shape. There Is a relevant difference between the two...

So, less or more: p.Shape.Edges[0].Geometry?
If you want to Edit poles or knots you Will obtain a new Edge, and you Will have to recompute the whole OCC shape tree...

Hope I was on topic... Cheers
follow my experiments on BIM modelling for architecture design
keithsloan52
Veteran
Posts: 2764
Joined: Mon Feb 27, 2012 5:31 pm

Re: where do you see FreeCAD main focus go towards?

Post by keithsloan52 »

carlopav wrote: Mon Aug 02, 2021 10:08 pm
keithsloan52 wrote: Mon Aug 02, 2021 8:48 pm and print(dir(p.Shape))

Code: Select all

['Area', 'BoundBox', 'CenterOfMass', 'Closed', 'CompSolids', 'Compounds', 'Content', 'Continuity', 'Curve', 'Degenerated', 'Edges', 'Faces', 'FirstParameter', 'LastParameter', 'Length', 'Mass', 'Matrix', 'MatrixOfInertia', 'MemSize', 'Module', 'Orientation', 'ParameterRange', 'Placement', 'PrincipalProperties', 'ShapeType', 'Shells', 'Solids', 'StaticMoments', 'SubShapes', 'Tag', 'Tolerance', 'TypeId', 'Vertexes', 'Volume', 'Wires', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 'ancestorsOfType', 'centerOfCurvatureAt', 'check', 'childShapes', 'cleaned', 'common', 'complement', 'copy', 'countElement', 'curvatureAt', 'curveOnSurface', 'cut', 'defeaturing', 'derivative1At', 'derivative2At', 'derivative3At', 'discretize', 'distToShape', 'dumpContent', 'dumpToString', 'exportBinary', 'exportBrep', 'exportBrepToString', 'exportIges', 'exportStep', 'exportStl', 'extrude', 'findPlane', 'firstVertex', 'fix', 'fixTolerance', 'fuse', 'generalFuse', 'getAllDerivedFrom', 'getElement', 'getFacesFromSubelement', 'getParameterByLength', 'getTolerance', 'globalTolerance', 'hashCode', 'importBinary', 'importBrep', 'importBrepFromString', 'inTolerance', 'isClosed', 'isCoplanar', 'isDerivedFrom', 'isEqual', 'isInfinite', 'isInside', 'isNull', 'isPartner', 'isSame', 'isSeam', 'isValid', 'lastVertex', 'limitTolerance', 'makeChamfer', 'makeFillet', 'makeOffset2D', 'makeOffsetShape', 'makeParallelProjection', 'makePerspectiveProjection', 'makeShapeFromMesh', 'makeThickness', 'makeWires', 'mirror', 'multiFuse', 'normalAt', 'nullify', 'oldFuse', 'optimalBoundingBox', 'overTolerance', 'parameterAt', 'parameters', 'project', 'proximity', 'read', 'reflectLines', 'removeInternalWires', 'removeShape', 'removeSplitter', 'replaceShape', 'restoreContent', 'reverse', 'reversed', 'revolve', 'rotate', 'rotated', 'scale', 'scaled', 'section', 'sewShape', 'slice', 'slices', 'split', 'tangentAt', 'tessellate', 'toNurbs', 'transformGeometry', 'transformShape', 'transformed', 'translate', 'translated', 'valueAt', 'writeInventor']
No mention of poles, knots or other related Bezier stuff.
The poles should be listed under the geometry, not under the shape. There Is a relevant difference between the two...

So, less or more: p.Shape.Edges[0].Geometry?
If you want to Edit poles or knots you Will obtain a new Edge, and you Will have to recompute the whole OCC shape tree...

Hope I was on topic... Cheers
print(dir(p.Shape.Edges[0])) No Geometry that I can see

Code: Select all

['Area', 'BoundBox', 'CenterOfMass', 'Closed', 'CompSolids', 'Compounds', 'Content', 'Continuity', 'Curve', 'Degenerated', 'Edges', 'Faces', 'FirstParameter', 'LastParameter', 'Length', 'Mass', 'Matrix', 'MatrixOfInertia', 'MemSize', 'Module', 'Orientation', 'ParameterRange', 'Placement', 'PrincipalProperties', 'ShapeType', 'Shells', 'Solids', 'StaticMoments', 'SubShapes', 'Tag', 'Tolerance', 'TypeId', 'Vertexes', 'Volume', 'Wires', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 'ancestorsOfType', 'centerOfCurvatureAt', 'check', 'childShapes', 'cleaned', 'common', 'complement', 'copy', 'countElement', 'curvatureAt', 'curveOnSurface', 'cut', 'defeaturing', 'derivative1At', 'derivative2At', 'derivative3At', 'discretize', 'distToShape', 'dumpContent', 'dumpToString', 'exportBinary', 'exportBrep', 'exportBrepToString', 'exportIges', 'exportStep', 'exportStl', 'extrude', 'findPlane', 'firstVertex', 'fix', 'fixTolerance', 'fuse', 'generalFuse', 'getAllDerivedFrom', 'getElement', 'getFacesFromSubelement', 'getParameterByLength', 'getTolerance', 'globalTolerance', 'hashCode', 'importBinary', 'importBrep', 'importBrepFromString', 'inTolerance', 'isClosed', 'isCoplanar', 'isDerivedFrom', 'isEqual', 'isInfinite', 'isInside', 'isNull', 'isPartner', 'isSame', 'isSeam', 'isValid', 'lastVertex', 'limitTolerance', 'makeChamfer', 'makeFillet', 'makeOffset2D', 'makeOffsetShape', 'makeParallelProjection', 'makePerspectiveProjection', 'makeShapeFromMesh', 'makeThickness', 'makeWires', 'mirror', 'multiFuse', 'normalAt', 'nullify', 'oldFuse', 'optimalBoundingBox', 'overTolerance', 'parameterAt', 'parameters', 'project', 'proximity', 'read', 'reflectLines', 'removeInternalWires', 'removeShape', 'removeSplitter', 'replaceShape', 'restoreContent', 'reverse', 'reversed', 'revolve', 'rotate', 'rotated', 'scale', 'scaled', 'section', 'sewShape', 'slice', 'slices', 'split', 'tangentAt', 'tessellate', 'toNurbs', 'transformGeometry', 'transformShape', 'transformed', 'translate', 'translated', 'valueAt', 'writeInventor']
Also don't see a problem with changing parameters and calling recompute, just don't see parameters.`

Plus would it not be a LOT LOT more easier to check the Objects type with Obj.TypeId and know you are dealing with a Part::BezierSpline

Attached file of two sample curves
SampleCurves.FCStd
(7.56 KiB) Downloaded 25 times
User avatar
onekk
Veteran
Posts: 6197
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: where do you see FreeCAD main focus go towards?

Post by onekk »

keithsloan52 wrote: Mon Aug 02, 2021 8:48 pm For Curves related development is the lack of a Part::BezierSpline ( Or equivlant ) holding things back ( Same goes for Part::Surface)

I just created a 'Freehand_BSpline' in the curves workbench.
Using the test file you posted and for :

Code: Select all

obj = App.getDocument("SampleCurves").getObject("Freehand_BSpline")

Code: Select all

print(dir(obj.Shape.Edges[0].Curve))

you will obtain the correct informations, the problem is:

Freehand_BSpline is

Code: Select all

>>> obj = App.getDocument("SampleCurves").getObject("Freehand_BSpline")
>>> print(obj.TypeId)
Part::FeaturePython
>>> print(obj.Shape.TypeId)
Part::TopoShape
>>> print(obj.Shape.Edges[0].TypeId)
Part::TopoShape
>>> print(obj.Shape.Edges[0].Curve.TypeId)
Part::GeomBSplineCurve
>>> 
You have to dig into the tree representation, but the informations are here.

IMHO

No need to complicate things with new objects, that would create more work to mantainers, better to use time to document things, at "low level" and "educational level" on "how FreeCAD works".

More tutorials, more examples, and less "abstraction" is not necessary to "ease things" better to concentrate on exposing more OCCT as pyhton methods (functions?) and document them with proper "minimal working examples" but with some "technical description included".

Regards

Carlo D.



Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
carlopav
Veteran
Posts: 2062
Joined: Mon Dec 31, 2018 1:49 pm
Location: Venice, Italy

Re: where do you see FreeCAD main focus go towards?

Post by carlopav »

Grazie Carlo, I was on my mobile :roll: :oops: Curve does the trick!

PS I always had the curiosity to try to implement some functions to act directly on the Part.Shape like this unfinished PR https://github.com/FreeCAD/FreeCAD/pull/3716
follow my experiments on BIM modelling for architecture design
keithsloan52
Veteran
Posts: 2764
Joined: Mon Feb 27, 2012 5:31 pm

Re: where do you see FreeCAD main focus go towards?

Post by keithsloan52 »

onekk wrote: Tue Aug 03, 2021 8:54 am
You have to dig into the tree representation, but the informations are here.
Sorry but it is a total Mess, one should not have to go digging
No need to complicate things with new objects, that would create more work to mantainers, better to use time to document things, at "low level" and "educational level" on "how FreeCAD works".
Disagree

Okay trying to change ImportNURBS to see if it would help to change to match curves workbench but it already matches
and objects are not inter usable, like I said a total Mess.

code is

Code: Select all

        if isinstance(geo, r3.PolyCurve):
           print("PolyCurve Object")
           obj = doc.addObject("Part::Feature","PolyCurve")
           obj.Shape = self.create_curve(geo).toShape()
           print(len(obj.Shape.Edges))
           print(obj.Shape.Edges[0].Curve.TypeId)
           obj.recompute()
           #print(dir(geo))
           return
What Rhino is calling a PolyCurve is a BezierSpline and create_curve returns a Part::GeomBSplineCurve.
Code as above outputs

Code: Select all

2:59:25  <class 'rhino3dm._rhino3dm.PolyCurve'>
12:59:25  PolyCurve Object
12:59:25  1
12:59:25  Part::GeomBSplineCurve
12:59:26  3DM File Imported
So PolyCurve has same attributes as Freehand_BSpline as created by curves but I cannot use it in the curves workbench :-(
User avatar
onekk
Veteran
Posts: 6197
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: where do you see FreeCAD main focus go towards?

Post by onekk »

keithsloan52 wrote: Tue Aug 03, 2021 12:09 pm
Sorry but it is a total Mess, one should not have to go digging

Okay trying to change ImportNURBS to see if it would help to change to match curves workbench but it already matches
and objects are not inter usable, like I said a total Mess.

So PolyCurve has same attributes as Freehand_BSpline as created by curves but I cannot use it in the curves workbench :-(

This is a consequences, on how the object is retrieved in curves WB, one of the disappointing things, of FreeCAD is the "approximation" when showing objects, that is quite high, so I've managed to write a "simple" method to assign the proper values to the view when inspecting objects:

Code: Select all

def show_curve(curve, c_name, psize=1, pcolor=(0.00, 1.0, 0.0 )):
    """Show the curve with the appropriate view approximation"""
    print("curve ti: ", curve.TypeId)
    if curve.TypeId in (
        "Part::GeomBSplineCurve", "Part::GeomCircle", "Part::GeomArcOfCircle", "Part::GeomLineSegment"):
        shape = curve.toShape()
    else:
        shape = curve
    scur = DOC.addObject("Part::Feature", c_name)
    scur.Shape = shape
    scur.ViewObject.Deviation = 0.010
    scur.ViewObject.AngularDeflection = '2.00 deg'


only to substitute the Part.show() method exposed in a similar way.

So I can see your point.

You want to use the curves WB from Chris_G, (me too but with scripting) but as the code is available, maybe trying to improve it would be a way, try to talk with Chris_G and see what came out.

One way I could see is to modify "Freehand_BSpline" method code to expose directly the Curve part as a property, so You could code something similar to:

Code: Select all

obj.Curve
to obtain directly the curve instead of the Shape.

But this involve to write the right class methods, it is not too difficult I think, but I've not done a similar thing.

Some methods used in curves WB has been integarted in the Part.BSplineSurface, now i don't remember what but approximate is very complete other than supplyin the "pointlist", see this code I'm using somewhere and is quite "configurable"

Code: Select all

bs = Part.BSplineSurface()
bsdmi = 2 # DegMin
bsdma = 5 # DegMax
bslw = 0.01 # LengthWeight
bscw = 0.05 # CurvatureWeight
bstw = 0.01 # TorsionWeight

array.reverse()
# Continuity: 0 : C0, 1 : C1, 2 : C2
bs.approximate(Points=array, DegMin=bsdmi, DegMax=bsdma, Tolerance=a_tol, Continuity=2,
    LengthWeight=bslw, CurvatureWeight=bscw, TorsionWeight=bstw)

base_surf = bs.toShape()
If I didn't remember wrong Chris_G itself has supplied some code to the main sources.

I don's see other way to solve problems other than showing some code, or text output, as the code is reproducible in an easy way.

I don't know if there is a manner to supply the curves to the surface, but:

Code: Select all

bs1 = Part.BSplineSurface()
bs1.buildFromNSections(sections)
bs1.exchangeUV()

alt_surf = bs1.toShape()
is working see maybe:

https://forum.freecadweb.org/viewtopic. ... 68#p521768

Hope it helps.

Best Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
User avatar
Kunda1
Veteran
Posts: 13434
Joined: Thu Jan 05, 2017 9:03 pm

Re: Rationalising FreeCAD curve and surface workbenches

Post by Kunda1 »

onekk wrote: Tue Aug 03, 2021 8:54 am
keithsloan52 wrote: Mon Aug 02, 2021 8:48 pm
carlopav wrote: Tue Aug 03, 2021 9:12 am
Hey folks, the topic was successfully split. Cheers!
Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
carlopav
Veteran
Posts: 2062
Joined: Mon Dec 31, 2018 1:49 pm
Location: Venice, Italy

Re: Rationalising FreeCAD curve and surface workbenches

Post by carlopav »

Kunda1 wrote: Thu Aug 05, 2021 9:37 am
onekk wrote: Tue Aug 03, 2021 8:54 am
keithsloan52 wrote: Mon Aug 02, 2021 8:48 pm
carlopav wrote: Tue Aug 03, 2021 9:12 am
Hey folks, the topic was successfully split. Cheers!
Thanks!
follow my experiments on BIM modelling for architecture design
Post Reply