True projection (not cut)

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
chennes
Veteran
Posts: 3914
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

True projection (not cut)

Post by chennes »

I'm working on finishing up the OpenSCAD workbench's CSG import, and one of the final functions that OpenSCAD supports is projection. We have an implementation for a "cut" projection, which is straightforward, but now I'd like to implement true projection, e.g. generating basically the "shadow" of an object on the XY plane. I thought that by creating a Part::Plane object and then using plane.Shape.project(stuff_to_project) would do it, but either that's not what project does, or I'm using it wrong.

Code: Select all

>>> sphere = Part.makeSphere(10)
>>> plane = Part.makePlane(100,100)
>>> projection = plane.project([sphere])
>>> projection.Wires
[]
Suggestions, or alternate ways of going about it?
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
User avatar
Roy_043
Veteran
Posts: 8573
Joined: Thu Dec 27, 2018 12:28 pm

Re: True projection (not cut)

Post by Roy_043 »

maybe look at:

Code: Select all

projection.Edges
User avatar
chennes
Veteran
Posts: 3914
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Re: True projection (not cut)

Post by chennes »

So interestingly, there are two edges, but their bounding boxes appear to be zero (ish):

Code: Select all

>>> projection.Edges
[<Edge object at 000001AAECF828A0>, <Edge object at 000001AAECF84A20>]
>>> projection.Edges[0].BoundBox
BoundBox (0, 0, 0, 3.06162e-15, 4.49928e-31, 0)
>>> projection.Edges[1].BoundBox
BoundBox (0, 0, 0, 3.06162e-15, 4.49928e-31, 0)
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
User avatar
Roy_043
Veteran
Posts: 8573
Joined: Thu Dec 27, 2018 12:28 pm

Re: True projection (not cut)

Post by Roy_043 »

I am not sure what is going on, but this seems to work OK:

Code: Select all

box = Part.makeBox(10,5,2)
plane = Part.makePlane(100,100)
projection = plane.project([box])
projection.Edges[2].BoundBox
=> BoundBox (10, 0, 0, 10, 5, 0)
jmcornil
Posts: 133
Joined: Mon Nov 02, 2020 9:16 am
Location: Versailles (France)
Contact:

Re: True projection (not cut)

Post by jmcornil »

Hello

From the tries I made, I think that the projection() method projects the edges of the shape which is to be projected.

Please run each of the following exampes in a new (fresh) FreeCAD file !

Example 1 : a box rotated

Code: Select all

box = App.ActiveDocument.addObject("Part::Box","Box")
box.Placement = App.Placement(App.Vector(0,0,20),App.Rotation(App.Vector(0.29582,-0.714173,-0.634388),66))

plane = App.ActiveDocument.addObject("Part::Plane","Plane")
plane.Length=60.00
plane.Width=60.00
plane.Placement=App.Placement(App.Vector(-30.00,-30.00,0.00),App.Rotation(App.Vector(0.00,0.00,1.00),0.00))
plane.ViewObject.Transparency=80

App.ActiveDocument.recompute()

proj = plane.Shape.project([box.Shape])
Part.show(proj)

App.ActiveDocument.recompute()
Example 2 : a sphere just translated the project of which seems to be a point.

Code: Select all

sph = App.ActiveDocument.addObject("Part::Sphere","Sphere")
sph.Placement =  App.Placement(App.Vector(0,0,20),App.Rotation(App.Vector(0,0,1),0))

plane = App.ActiveDocument.addObject("Part::Plane","Plane")
plane.Length=60.00
plane.Width=60.00
plane.Placement=App.Placement(App.Vector(-30.00,-30.00,0.00),App.Rotation(App.Vector(0.00,0.00,1.00),0.00))
plane.ViewObject.Transparency=80

App.ActiveDocument.recompute()

proj = plane.Shape.project([sph.Shape])
Part.show(proj)

App.ActiveDocument.recompute()
Example 3 : the same sphere rotated so that its "boundary half circle" is parallel to the plane ;
it is this half circle which is projected

Code: Select all

sph = App.ActiveDocument.addObject("Part::Sphere","Sphere")
sph.Placement =  App.Placement(App.Vector(0,0,20),App.Rotation(App.Vector(1,0,0),90))

plane = App.ActiveDocument.addObject("Part::Plane","Plane")
plane.Length=60.00
plane.Width=60.00
plane.Placement=App.Placement(App.Vector(-30.00,-30.00,0.00),App.Rotation(App.Vector(0.00,0.00,1.00),0.00))
plane.ViewObject.Transparency=80

App.ActiveDocument.recompute()

proj = plane.Shape.project([sph.Shape])
Part.show(proj)

App.ActiveDocument.recompute()
By the way, I had a look to the Edges of a sphere and I found something I don't understand :

Code: Select all

e0,e1,e2 = sph.Shape.Edges

e0.BoundBox
# BoundBox (3.06162e-16, -7.4988e-32, 25, 3.06162e-16, -7.4988e-32, 25)

e1.BoundBox
# BoundBox (3.06162e-16, -1.22465e-15, 15, 5, -7.4988e-32, 25)

e2.BoundBox
# BoundBox (3.06162e-16, -7.4988e-32, 15, 3.06162e-16, -7.4988e-32, 15)
If e1 seems to be correct and I can see its Curve (the half circle)

Code: Select all

e1.Curve
#Circle (Radius : 5, Position : (0, 0, 20), Direction : (-2.44929e-16, -2.22045e-16, -1))
I don't understand e0 and e2, the Curve of which gvinig error

Code: Select all

e0.Curve
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: undefined curve type
I also have a look at the definition f the project() method : line 1983 of the file
https://github.com/FreeCAD/FreeCAD/blob ... ePyImp.cpp
but I must admit that I am not up to par on this sort of thing. If anyone could help it would be welcome (may be @Chris_G).

Unfortunately the only information I could find in the automatic documentation of python modules is:
"project (...)
Project a list of shapes on this shape "

Sorry to have made such a long post but I would like to understand and progress ...
User avatar
onekk
Veteran
Posts: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: True projection (not cut)

Post by onekk »

from https://github.com/FreeCAD/FreeCAD/blob ... hapePy.xml

Seem to be also this costruct:

Code: Select all

    <Methode Name="makeParallelProjection" Const="true">
      <Documentation>
        <UserDocu>Parallel projection of an edge or wire on this shape
makeParallelProjection(shape, dir) -> Shape
        </UserDocu>
Hope it helps

Sources, mention:

Code: Select all

# include <BRepProj_Projection.hxx>

and 

# include <BRepAlgo_NormalProjection.hxx>
I suppose that these are OCCT things, maybe inspecting the OCCT sources or documentation will make some light on the matter, or maybe ask to @wmayer?

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
Chris_G
Veteran
Posts: 2601
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: True projection (not cut)

Post by Chris_G »

jmcornil wrote: Wed Mar 31, 2021 9:20 am I don't understand e0 and e2, the Curve of which gvinig error
An edge is a topological wrapper around one, or more, geometry curves.
These curves can be both a 3D curve, and / or 2D curves defined on a 3D surface (called p-curves).
Let's explore more deeply the 3 edges of a sphere.
Copy / paste the following scripts in the python console.
The first edge :

Code: Select all

sphere = Part.makeSphere(10)

# The 3D curve is undefined
sphere.Edge1.Curve

# Its length is 0
sphere.Edge1.Length

# Does it have a p-curve ?
curve2d, surface, placement, first_param, last_param = sphere.Edge1.curveOnSurface(0)
print("{} on {}".format(curve2d, surface))

# It is a 2D line on a Spherical surface
# What are the endpoints of this line ?
curve2d.value(first_param)
curve2d.value(last_param)
This is the 2D representation of the face of a OCCT Sphere :
2D_sphere.png
2D_sphere.png (10.16 KiB) Viewed 1587 times
The above edge corresponds to the upper horizontal edge of the square.
It is the north pole of the sphere : a line in the 2D space of the sphere that vanishes to a 3D point in the 3D space

Let's have a look the second edge :

Code: Select all

sphere.Edge2.Curve
sphere.Edge2.Length
# This edge has a valid 3D curve

# Does it have also p-curves ?
curve2d, surface, placement, first_param, last_param = sphere.Edge2.curveOnSurface(0)
print("{} on {}".format(curve2d, surface))
curve2d.value(first_param)
curve2d.value(last_param)
# this edge corresponds to the right vertical edge of the square

# Does it have another p-curve ?
curve2d, surface, placement, first_param, last_param = sphere.Edge2.curveOnSurface(1)
print("{} on {}".format(curve2d, surface))
curve2d.value(first_param)
curve2d.value(last_param)
# So this edge is also the representation of the left vertical edge of the square
So, this "Greenwich meridian" edge is a wrapper around 3 different geometric entities :
- a 3D curve (a circle)
- the 2 lines2D in the parametric space of the sphere that are sewed together to form the seam of the sphere

The third edge is pretty similar to the first one, but represents the south pole of the sphere, and the lower horizontal edge of the square :

Code: Select all

sphere.Edge3.Curve
sphere.Edge3.Length
curve2d, surface, placement, first_param, last_param = sphere.Edge3.curveOnSurface(0)
print("{} on {}".format(curve2d, surface))
curve2d.value(first_param)
curve2d.value(last_param)
User avatar
chennes
Veteran
Posts: 3914
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Re: True projection (not cut)

Post by chennes »

So it seems that the "project()" function is not going to give me quite what I need here. Obviously the TechDraw WB is able to get the 2D projection, so there's code someplace that does this, but I can't figure out where. Can any of our TD or BRep experts point me in the right direction?
wmayer wrote: Ping
uwestoehr wrote: Ping
aapo wrote: Ping
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
jmcornil
Posts: 133
Joined: Mon Nov 02, 2020 9:16 am
Location: Versailles (France)
Contact:

Re: True projection (not cut)

Post by jmcornil »

Thank you very much @Chris_G for this good explanation !

But for the parameters of a sphere wouldn't it be rather
0 <= U <= 3.14 and -1.57 <= V <= 1.57
as we find with :

Code: Select all

sphere.Faces[0] .ParameterRange 
User avatar
Chris_G
Veteran
Posts: 2601
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: True projection (not cut)

Post by Chris_G »

This is not what I get :

Code: Select all

sphere = Part.makeSphere(10)
sphere.Faces[0] .ParameterRange 
# ---> (0.0, 6.283185307179586, -1.5707963267948966, 1.5707963267948966)
Post Reply