Created
September 2, 2021 08:35
-
-
Save CsatiZoltan/f4fd10bf20923143ba0e0678ea1d3d61 to your computer and use it in GitHub Desktop.
Python interface for projection onto a surface in FreeCAD
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Projection: | |
"""Projection of a curve onto a surface. | |
This class implements parametric projection, i.e. whenever there is a change in the curve | |
to be projected, in the surface on which we project, or in direction of the projection, | |
the projection is redone automatically. | |
As a typical workflow: | |
1. The user gives either programmatically or via the GUI the curve and the surface as FreeCAD | |
document objects of type `Part.Feature`, moreover the direction of the projection as a | |
tuple/list of three numbers. | |
2. The user creates a new FreeCAD document object of type `Part::FeaturePython`, which will | |
serve as a container to hold the projected curve. | |
3. The user instantiates the :class:`Projection` class by passing the container, the curve, | |
the surface and the direction of the projection. | |
The rest is managed by this class. Specifically, whenever any of the three parameters change, | |
the new projected curve is automatically computed and is replotted on the screen when in GUI | |
mode. | |
If you are only interested in the projection functionality, use its :meth:`project` | |
method directly. | |
For the description of the projection, see the :meth:`project` method. | |
Parameters | |
---------- | |
doc : FreeCAD.Document with TypeId of Part::FeaturePython | |
The document object that will contain this :class:`Projection` object. Such an object | |
can be created by :code:`FreeCAD.ActiveDocument.addObject('Part::FeaturePython', '...')`. | |
curve : Part.Feature | |
Curve that we project. | |
surface : Part.Feature | |
Surface we project onto. | |
direction : tuple of float | |
Direction of the projection. | |
Notes | |
----- | |
Projecting a curve onto a surface is available in the `Part` workbench of FreeCAD. However, | |
it has two shortcomings: | |
1. It cannot be fine-tuned without the GUI, as it is not exposed to Python. | |
2. The projection is not parametric. | |
This class solves both of these issues: | |
1. We rely on PythonOCC to use the underlying projection implemented in OpenCASCADE. The | |
PythonOCC object is then converted to a Part object, which can be used from within FreeCAD | |
as usual. | |
2. This class is a so-called scripted object, allowing a parametric workflow. | |
""" | |
def __init__(self, doc, curve, surface, direction): | |
if doc.TypeId != 'Part::FeaturePython': | |
raise TypeError('The document object must have TypeId of "Part::FeaturePython".') | |
if not isinstance(curve, Part.Feature): | |
raise TypeError('The curve must be a Part Feature object.') | |
if not isinstance(surface, Part.Feature): | |
raise TypeError('The surface must be a Part Feature object.') | |
doc.addProperty('App::PropertyLink', 'Curve', 'Parameters', 'Curve to project') | |
doc.addProperty('App::PropertyLink', 'Surface', 'Parameters', 'Surface to project onto') | |
doc.addProperty('App::PropertyDirection', 'Direction', 'Parameters', | |
'Direction of projection') | |
doc.Curve = curve | |
doc.Surface = surface | |
doc.Direction = direction | |
doc.Proxy = self | |
def execute(self, doc): | |
"""Recomputes the projection. | |
Parameters | |
---------- | |
doc : FreeCAD.Document with TypeId of Part::FeaturePython | |
The document object that contains this :class:`Projection` object. | |
Returns | |
------- | |
None | |
""" | |
projection_direction = (doc.Direction.x, doc.Direction.y, doc.Direction.z) | |
projected_curve = self.project(doc.Curve.Shape, doc.Surface.Shape, projection_direction) | |
doc.Shape = projected_curve | |
doc.recompute() | |
@staticmethod | |
def project(curve, surface, direction): | |
"""Cylindrical projection of a curve onto a surface. | |
Parameters | |
---------- | |
curve : Part.Wire | |
Curve to be projected. | |
surface : Part.Face | |
Surface to project onto. | |
direction : tuple of float | |
Direction vector of the projection, tuple of three numbers. | |
Returns | |
------- | |
Part.Compound | |
A compound object, containing the parts of the projected curve. | |
Raises | |
------ | |
Exception | |
If the projection algorithm of OpenCASCADE fails. This typically happens if the | |
projected curve would not lie on the surface. | |
Notes | |
----- | |
This function is a wrapper around the cylindrical projection functionality available in | |
OpenCASCADE. For details, see its documentation: | |
https://dev.opencascade.org/doc/refman/html/class_b_rep_proj___projection.html | |
""" | |
curve = Part.__toPythonOCC__(curve) | |
surface = Part.__toPythonOCC__(surface) | |
projection_direction = gp_Dir(*direction) | |
proj = BRepProj_Projection(curve, surface, projection_direction) | |
if not proj.IsDone(): | |
raise Exception('Projection failed.') | |
return Part.__fromPythonOCC__(proj.Shape()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment