Accessing face data

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
drmacro
Veteran
Posts: 8873
Joined: Sun Mar 02, 2014 4:35 pm

Accessing face data

Post by drmacro »

As with every time I want to drill down to a particular objects data, stumped again. :oops:

I can see that when a face of a Part Cube or Part Design Pad is selected the full name in the selection object is, for example:

Code: Select all

"(App.getDocument('Unnamed').getObject('Pad'),['Face2',])"
So, the user has selected Face2 and that really translates to object Faces[1].

But, how do I get to the Faces object so I could do, for example:

Code: Select all

myvector = myselface.Faces[1].CenterOfGravity
Naively I tried:

Code: Select all

myselface = App.getDocument('Unnamed').getObject('Pad'),['Face2',]
But, nope. :mrgreen:
Star Trek II: The Wrath of Khan: Spock: "...His pattern indicates two-dimensional thinking."
openBrain
Veteran
Posts: 9034
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Accessing face data

Post by openBrain »

Depends what you have as available information.
If the subelement is currently selected

Code: Select all

Gui.Selection.getSelectionEx()[0].SubObjects[0]
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Accessing face data

Post by edwilliams16 »

How about

Code: Select all

pd =App.getDocument('Unnamed').getObject('Pad')
fc = pd.Shape.Faces[1]  #Face2
myvector = fc.CenterOfGravity
vm4dim
Posts: 129
Joined: Tue Nov 23, 2021 1:05 am

Re: Accessing face data

Post by vm4dim »

Code: Select all

>>> for f in App.ActiveDocument.getObject("Box").Shape.Faces: print(f, f.CenterOfGravity);
... 
<Face object at 0x55b50de02f10> Vector (0.0, 5.0, 5.0)
<Face object at 0x55b51402bf10> Vector (10.0, 5.0, 5.0)
<Face object at 0x55b51401e8d0> Vector (5.0, 0.0, 5.0)
<Face object at 0x55b513738820> Vector (5.0, 10.0, 5.0)
<Face object at 0x55b514008380> Vector (5.0, 5.0, 0.0)
<Face object at 0x55b51441ef60> Vector (5.0, 5.0, 10.0)
drmacro
Veteran
Posts: 8873
Joined: Sun Mar 02, 2014 4:35 pm

Re: Accessing face data

Post by drmacro »

edwilliams16 wrote: Wed Dec 08, 2021 5:31 pm How about

Code: Select all

pd =App.getDocument('Unnamed').getObject('Pad')
fc = pd.Shape.Faces[1]  #Face2
myvector = fc.CenterOfGravity
This is all well and good if as a human I'm looking at a breakpoint in the code and see Face2 and know that is a count and not a 0 based index.

But, I wasn't clear how code it to access Faces[x].

In this case, I needed something like:

Code: Select all

sel = Gui.Selection.getSelectionEx()

if len(sel) == 1:
    subobjs = sel[0].SubObjects
    if len(subobjs) == 1:
        face = subobjs[0]
        if face.ShapeType == 'Face':
                COG=face.CenterOfGravity
                newvert = App.ActiveDocument.addObject("Part::Vertex","Vertex")
                newvert.X=COG.x
                newvert.Y=COG.y
                newvert.Z=COG.z
Though, shouldn't I be able to use the COG vector rather than it's constituent x,y,z?

And what does the message: "Warning: Wire is deprecated, please use OuterWire" mean... :?
Star Trek II: The Wrath of Khan: Spock: "...His pattern indicates two-dimensional thinking."
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Accessing face data

Post by edwilliams16 »

@drmacro Your OP seemed to suggest you were trying to access the face by its name. Accessing via selection is slightly different.
If you want to bundle the components into a vector

Code: Select all

COG=face.CenterOfGravity
newvert = App.ActiveDocument.addObject("Part::Vertex","Vertex")
(newvert.X, newvert.Y, newvert.Z) = COG
is tidier. It appears a vector is just a tuple of its components.
drmacro
Veteran
Posts: 8873
Joined: Sun Mar 02, 2014 4:35 pm

Re: Accessing face data

Post by drmacro »

edwilliams16 wrote: Wed Dec 08, 2021 6:51 pm @drmacro Your OP seemed to suggest you were trying to access the face by its name. Accessing via selection is slightly different.
Yes, bad description on my part. But, the debug let me see the name of "Face2" in the value of the SelectionObject
(i.e. sel[0].FullName), but it didn't click that the SubObject was the selected face.
If you want to bundle the components into a vector

Code: Select all

COG=face.CenterOfGravity
newvert = App.ActiveDocument.addObject("Part::Vertex","Vertex")
(newvert.X, newvert.Y, newvert.Z) = COG
is tidier. It appears a vector is just a tuple of its components.
Duh, obvious...pythonic (I guess). I just don't think in "programmer" any more I guess. :mrgreen:
Star Trek II: The Wrath of Khan: Spock: "...His pattern indicates two-dimensional thinking."
freedman
Veteran
Posts: 3441
Joined: Thu Mar 22, 2018 3:02 am
Location: Washington State, USA

Re: Accessing face data

Post by freedman »

I finally found what works the best for me, this is what I put in a SelObserver:

Code: Select all

self.ob1 =  Gui.Selection.getSelectionEx("",0)  
for sel in self.ob1:
	for subname in sel.SubElementNames:
		for obj in sel.Object.getSubObjectList(subname):
			if hasattr(obj,'Shape'):
				print("COG = ", obj.Shape.CenterOfGravity)
				print("Faces are ", obj.Shape.Faces) 
                              
	#		if obj.TypeId ==  "App::Link":
	#		if obj.TypeId == "App::LinkElement":
	#		if obj.TypeId == "PartDesign::Body":
	#		if obj.TypeId == "Sketcher::SketchObject":
Post Reply