Determine object visibility.

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
koirat
Posts: 66
Joined: Tue Oct 05, 2021 5:24 pm

Re: Determine object visibility.

Post by koirat »

TheMarkster wrote: Mon Oct 18, 2021 5:05 pm body.VisibleFeature will return the visible feature or None if none are visible.

(untested)

Code: Select all

visibleBodies = [body for body in FreeCAD.ActiveDocument.Objects if body.isDerivedFrom("PartDesign::Body") and body.VisibleFeature]
Unfortunately it also selects Body that got sketch under Revolution effect. Even when it's parent is disabled.
It also selects in some other cases when the body should not be visible.
User avatar
Roy_043
Veteran
Posts: 8450
Joined: Thu Dec 27, 2018 12:28 pm

Re: Determine object visibility.

Post by Roy_043 »

koirat wrote: Mon Oct 18, 2021 7:55 pm Here is the (I hope so) final solution
A visible Body can be nested in an invisible Std_Part...
koirat
Posts: 66
Joined: Tue Oct 05, 2021 5:24 pm

Re: Determine object visibility.

Post by koirat »

Latest Solution.
This script will select all visible bodies.

Code: Select all

def AreParentsVisible(obj):
	if len(obj.Parents)==0:
		 return True
	#print(obj)

	for parent in obj.Parents:
		#print(parent)
		if type(parent)==tuple:
			parent = parent[0]
			#print(parent.Name)
		if parent.Visibility:
			if AreParentsVisible(parent):
				return True
			

	return False

#print(AreParentsVisible(Gui.Selection.getSelection()[0]))

Gui.Selection.clearSelection()
for obj in FreeCAD.ActiveDocument.Objects:
	if obj.ViewObject.Visibility and  obj.isDerivedFrom("PartDesign::Body") and obj.VisibleFeature and AreParentsVisible(obj) :
		Gui.Selection.addSelection(obj)
User avatar
Roy_043
Veteran
Posts: 8450
Joined: Thu Dec 27, 2018 12:28 pm

Re: Determine object visibility.

Post by Roy_043 »

Code: Select all

def GetParents(obj):
    """Returns a list of parent objects. If there are none an empty list is returned."""
    parents = obj.Parents
    if len(parents) == 0:
        return []
    else:
        doc = obj.Document
        return [parents[0][0]] + [doc.getObject(name) for name in parents[0][1].split(".")[:-2]]


def AreParentsVisible(obj):
    for parent in GetParents(obj):
        if not parent.Visibility:
            return False
    return True


Gui.Selection.clearSelection()
for obj in FreeCAD.ActiveDocument.Objects:
    if obj.ViewObject.Visibility and obj.isDerivedFrom("PartDesign::Body") and obj.VisibleFeature and AreParentsVisible(obj):
        Gui.Selection.addSelection(obj)
koirat
Posts: 66
Joined: Tue Oct 05, 2021 5:24 pm

Re: Determine object visibility.

Post by koirat »

Roy_043 wrote: Tue Oct 19, 2021 5:29 pm

Code: Select all

def GetParents(obj):
    """Returns a list of parent objects. If there are none an empty list is returned."""
    parents = obj.Parents
    if len(parents) == 0:
        return []
    else:
        doc = obj.Document
        return [parents[0][0]] + [doc.getObject(name) for name in parents[0][1].split(".")[:-2]]


def AreParentsVisible(obj):
    for parent in GetParents(obj):
        if not parent.Visibility:
            return False
    return True


Gui.Selection.clearSelection()
for obj in FreeCAD.ActiveDocument.Objects:
    if obj.ViewObject.Visibility and obj.isDerivedFrom("PartDesign::Body") and obj.VisibleFeature and AreParentsVisible(obj):
        Gui.Selection.addSelection(obj)
You don't like my method ;)
I have to ask you for some explanation.
User avatar
Roy_043
Veteran
Posts: 8450
Joined: Thu Dec 27, 2018 12:28 pm

Re: Determine object visibility.

Post by Roy_043 »

It is not about liking. Your code will only check the visibility of the top parent.

Code: Select all

Part
  Part001
    Part002
      Body
If all objects in this nesting tree are visible except Part001, your code will select the Body.

The return from obj.Parents is a bit awkward. My guess is that the list can even contain more than one tuple:

Code: Select all

>>> obj = App.ActiveDocument.Body
>>> obj.Parents
[(<Part object>, 'Part001.Part002.Body.')]
The GetParents function in my code only checks the first tuple. It converts it to a list of objects.
koirat
Posts: 66
Joined: Tue Oct 05, 2021 5:24 pm

Re: Determine object visibility.

Post by koirat »

You are right it's not working as intended damn it.
Thank you for your input.

And yes Parenting in Freecad is totally awkward as you have said.
TheMarkster
Veteran
Posts: 5505
Joined: Thu Apr 05, 2018 1:53 am

Re: Determine object visibility.

Post by TheMarkster »

Code: Select all

def getParents(obj):
    if hasattr(obj,"Parents") and obj.Parents:
        return [obj.Parents[0][0]]+[FreeCAD.ActiveDocument.getObject(p) for p in obj.Parents[0][1].split('.') if obj != FreeCAD.ActiveDocument.getObject(p) and p != '']

def isVisible(obj):
    if not obj.ViewObject.Visibility:
        return False
    if not obj.VisibleFeature:
        return False
    parents = getParents(obj)
    for par in parents:
        if not par.ViewObject.Visibility:
            return False
    return True

bodies = [obj for obj in FreeCAD.ActiveDocument.Objects if obj.TypeId == "PartDesign::Body"]
FreeCADGui.Selection.clearSelection()
for body in bodies:
    if isVisible(body):
        FreeCADGui.Selection.addSelection(FreeCAD.ActiveDocument.Name,body.Name)
User avatar
Roy_043
Veteran
Posts: 8450
Joined: Thu Dec 27, 2018 12:28 pm

Re: Determine object visibility.

Post by Roy_043 »

Your getParents function can return None. You need to catch that in isVisible.
TheMarkster
Veteran
Posts: 5505
Joined: Thu Apr 05, 2018 1:53 am

Re: Determine object visibility.

Post by TheMarkster »

Roy_043 wrote: Fri Oct 22, 2021 7:46 am Your getParents function can return None. You need to catch that in isVisible.
Nothing happens in the for loop if getParents() returns None or an empty list. Do you have an example file that generates an exception?
Post Reply