[SOLVED] How to find the faces that are adjacent to the same face?

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
stefankorisnik3
Posts: 101
Joined: Sun Jul 24, 2022 12:49 pm

[SOLVED] How to find the faces that are adjacent to the same face?

Post by stefankorisnik3 »

UPDATE:
OLD TITLE:How to find the faces that share same vertex or edge in shell?

Does the FreeCAD store the information aboud shared vertices or edges between faces in one shell?
If not is there some easier way to compute it beside for looping through all faces?

Code: Select all

OS: Windows 10 Version 2009
Word size of FreeCAD: 64-bit
Version: 0.20.29177 (Git)
Build type: Release
Branch: releases/FreeCAD-0-20
Python 3.8.10, Qt 5.15.2, Coin 4.0.1, Vtk 8.2.0, OCC 7.6.2
Locale: English/United Kingdom (en_GB)
Installed mods: 
  * CurvedShapes 1.0.3
  * Curves 0.5.2
Last edited by stefankorisnik3 on Tue Aug 02, 2022 4:32 pm, edited 2 times in total.
edwilliams16
Veteran
Posts: 3179
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: How to find the faces that share same vertex or edge in shell?

Post by edwilliams16 »

Code: Select all

def getSubShapeIndex(shp, sub):
    '''
    shp : a shape
    sub : a subshape (Vertex, Edge or Face)
    returns the index i of sub in shp 
    e.g if sub is a Vertex in shp
    sub = shp.Vertexes[i]
    '''
    if sub.ShapeType == 'Vertex':
        for i, f in enumerate(shp.Vertexes):
            if f.isEqual(sub):
                return i 
    elif sub.ShapeType == 'Edge':
        for i, f in enumerate(shp.Edges):
            if f.isEqual(sub):
                return i 
    elif sub.ShapeType == 'Face':
        for i, f in enumerate(shp.Faces):
            if f.isEqual(sub):
                return i 
    else:
        return -1
    return -1

obj = App.ActiveDocument.addObject("Part::Box","Box")
App.ActiveDocument.recompute()
vindex = 0 #pick one
v = obj.Shape.Vertexes[vindex] 
prstring = f'Vertex{vindex + 1}\n'
facesContainingV = obj.Shape.ancestorsOfType(v, Part.Face)
facesContainingV   #[<Face object at 0x7fa1aa86de50>, <Face object at 0x7fa19ce26a90>, <Face object at 0x7fa18c5cfe00>]
for face in facesContainingV:
    prstring += f'Face{getSubShapeIndex(obj.Shape, face) + 1}  '

print(prstring)

ancestorsOfType() is the key method. The above code finds the faces that contain Vertexes[vindex]
User avatar
mfro
Posts: 666
Joined: Sat Sep 23, 2017 8:15 am

Re: How to find the faces that share same vertex or edge in shell?

Post by mfro »

I think there is a simpler method to obtain same information:

Code: Select all

theFace = p.Faces[0]
for theEdge in theFace.Edges:
    for face in p.Faces[1:]:
        for edge in face.Edges:
            if (theEdge.isPartner(edge)):
                print('edge ', theEdge, ' on face ', theFace, 'connect to ')
                print('edge', edge, 'on face', face)
?
The code checks for a given face of part p which edges of it are shared with others ('isPartner()' does exactly that). The same can be done for vertexes.
Cheers,
Markus
stefankorisnik3
Posts: 101
Joined: Sun Jul 24, 2022 12:49 pm

Re: How to find the faces that share same vertex or edge in shell?

Post by stefankorisnik3 »

Thanks you all.
The later answer help me because i didn't make a good question.
I was looking for how to find the faces that are adjacent to the same face.
I will change the title of my question
edwilliams16
Veteran
Posts: 3179
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: [SOLVED] How to find the faces that are adjacent to the same face?

Post by edwilliams16 »

Finding the faces shared by a vertex was basically a one-liner

Code: Select all

facesContainingV = obj.Shape.ancestorsOfType(v, Part.Face)
However, finding the adjacent faces to a given face is a little more complicated using the ancestorsOfType() method.

Code: Select all

def adjacentFaces(shp, face):
	'''
	shp : a shape
	face : a face in shp.Faces
	return adjacent faces ie that those share an edge
	'''
    adjFaces = []
    edges = face.Edges
    for edge in edges:
        commonFaces = shp.ancestorsOfType(edge, Part.Face) #faces that share edge
        adjFaces += [f for f in commonFaces if not face.isSame(f)] #exclude copies of 'face'
    return adjFaces
The only advantage I see is that it avoids a (potentially slow) python loop over all the faces of the object.

It isn't clear to me where isSame() or isPartner() is the more precise comparison. See https://forum.freecadweb.org/viewtopic. ... d8#p536241

When can the shared TShape have different Placements? @mfro
User avatar
mfro
Posts: 666
Joined: Sat Sep 23, 2017 8:15 am

Re: [SOLVED] How to find the faces that are adjacent to the same face?

Post by mfro »

edwilliams16 wrote: Tue Aug 02, 2022 6:30 pm It isn't clear to me where isSame() or isPartner() is the more precise comparison. See [url]https://forum.freecadweb.org/viewtopic.php? When can the shared TShape have different Placements? @mfro
I understand e.g. an edge shared by two faces could be backwards and still visually have the same geometry (inverse parameter flow).
No idea if OpenCascade creates topologies like this, but probably the method wouldn't be there otherwise?
Cheers,
Markus
edwilliams16
Veteran
Posts: 3179
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: [SOLVED] How to find the faces that are adjacent to the same face?

Post by edwilliams16 »

mfro wrote: Tue Aug 02, 2022 6:49 pm
edwilliams16 wrote: Tue Aug 02, 2022 6:30 pm It isn't clear to me where isSame() or isPartner() is the more precise comparison. See https://forum.freecadweb.org/viewtopic. ... d8#p536241 When can the shared TShape have different Placements? @mfro
I understand e.g. an edge shared by two faces could be backwards and still visually have the same geometry (inverse parameter flow).
No idea if OpenCascade creates topologies like this, but probably the method wouldn't be there otherwise?
But that doesn't address my question. Both isSame() and isPartner allow edges to be oppositely oriented according to the post I quoted.
User avatar
mfro
Posts: 666
Joined: Sat Sep 23, 2017 8:15 am

Re: [SOLVED] How to find the faces that are adjacent to the same face?

Post by mfro »

Hmmm.

Looked into the OCCT sources and found the following:
  • isPartner(), isSame() and isEqual() do exactly as documented:
    • isPartner() returns true if the TShape is exactly the same object (checks address, so there is no check for geometrical equalness as I originally assumed, inverted edges are neither considered partners, same or equal). Location and orientation aren't checked.
    • isSame() returns true if the TShape is exactly the same object *and* both the TopLoc_Locations have equal values
  • isEqual() checks for isPartner() *and* isSame() + same orientation
Bottom line is that one should probably use the most simple incarnation that's "equal enough" for your use case.

isPartner() isn't used at a lot of places inside OCCT (strangely, there are even few places where isPartner() and isSame() are both checked which seems redundant, so not even OCCT developers appear to be sure about what they need to use), isEqual() and isSame() have about the same number of occurences.

[edit: found at least one piece of code where an OCC algorithm appears to duplicate the seam edge of a closed shape (apparently to account for tolerances). In this case, neither of the tests would consider these faces adjacent. I assume these can be found only by checking for isClosed() which would make the first and last edge equal even if they aren't]
Cheers,
Markus
edwilliams16
Veteran
Posts: 3179
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: [SOLVED] How to find the faces that are adjacent to the same face?

Post by edwilliams16 »

Thanks @mfro for the research. I understand it a tiny bit more.

Being unfamiliar with OCCT and the C++ side of things I'm unclear on the role of TopLoc_Location. It seems the same piece of geometry, with a given address in memory - let us say a line segment of length 10 mm, can be shared between multiple edges with different locations? How do I create an example of an object with edges that are isPartner, but not isEqual?
Maybe this is complexity that lies in OCCT, but not exposed in FreeCAD, so the distinction is moot?
wmayer
Founder
Posts: 20298
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: [SOLVED] How to find the faces that are adjacent to the same face?

Post by wmayer »

edwilliams16 wrote: Tue Aug 02, 2022 6:30 pm When can the shared TShape have different Placements?
This usually happens for pad operations. As a test create a rectangular sketch and pad it. Hover over the bottom and top face to get their indexes. Assuming it's 5 and 6 then

Code: Select all

pad = App.ActiveDocument.Pad.Shape
pad.Face5.isPartner(pad.Face6)
will return true.

Checking their placements:

Code: Select all

pad.Face5.Placement # Placement [Pos=(0,0,0), Yaw-Pitch-Roll=(0,0,0)]
pad.Face6.Placement # Placement [Pos=(0,0,10), Yaw-Pitch-Roll=(0,0,0)]
It isn't clear to me where isSame() or isPartner() is the more precise comparison.
From the above example you can easily see that isPartner() would lead to a false-positive check. So, you really must use isSame().
edwilliams16 wrote: Wed Aug 03, 2022 8:08 am How do I create an example of an object with edges that are isPartner, but not isEqual?
That's fairly easy. Simply create a standard box. By hovering the mouse over two adjacent faces you can see that Face2 and Face6 share a common edge.

Code: Select all

box = App.ActiveDocument.Box.Shape
f2 = box.Face2
f6 = box.Face6

# by testing 16 possible cases you will find this shared edge
f2.Edge2.isPartner(f6.Edge3) # True
In this case isSame() will also return true because the faces are topologically connected.

Code: Select all

f2.Edge2.isSame(f6.Edge3) # True
However, isEqual() will return false.

Code: Select all

f2.Edge2.isEqual(f6.Edge3) # False
If you have two adjacent faces with consistent orientation then isEqual() will always return false for their shared edge.
Post Reply