Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can we depend on "Element"s to track the ID of a face on geometry changes? #236

Closed
ceremcem opened this issue Apr 16, 2019 · 3 comments
Closed

Comments

@ceremcem
Copy link
Collaborator

ceremcem commented Apr 16, 2019

Fully deterministic ID generation for Faces, Edges and Vertexes of an object is impossible and the enumeration starts from beginning after any geometry change.

However, I noticed that the Elements does track its Linked Object as much as possible, which exactly fits my needs. Question 1/2: Can we depend on this behavior?

Intention and problem

I'm trying to provide a solution to shaise/FreeCAD_SheetMetal#40, basically a script that will re-unfold a processed object after every geometry change by using a manually provided face ID, such as Gui.Selection.addSelection('Unnamed','Cut','Face11').

image

Even though we don't touch the geometry of the selected face with a careful development, ID's may change:

image

Possible approach

  1. Add the object into an Assembly Container
  2. Create an Element for the face
  3. Use the LinkedObject property to determine the ID of the previous face:
>>> App.ActiveDocument.getObjectsByLabel('unfold_face')[0].LinkedObject
(<Part::PartFeature>, ';#11f;:T559:4:F.Face12')

element-tracks-id

Question 2/2: If it's a valid usage, how can I properly translate ';#11f;:T559:4:F.Face12' to 'Assembly','Parts.Cut.Face12'?

@ceremcem ceremcem changed the title Can we depend on elements to track the ID of a face Can we depend on "Element"s to track the ID of a face on geometry changes? Apr 17, 2019
@ceremcem
Copy link
Collaborator Author

@realthunder Could you please take a look at this?

Briefly, I'm asking how to add the face that an Element points, to the selection via Gui.Selection.addSelection(...).

@realthunder
Copy link
Owner

It is a bit complicated. Element.LinkedObject stores the linked object and subname. But an Element can point to other Element down the hierarchy. You can use Element.Proxy.getElementSubName(True) to recursively resolve the subname to the actual geometry. The subname is relative to the PartGroup of the same assembly that contains this Element

So assuming the Element you want is named simply as Element, then

element = App.ActiveDocument.Element.Proxy
partGroup = element.getAssembly().getPartGroup()
subname = element.getElementSubname(True)
Gui.Selection.addSelection(partGroup, subname)

There are two complications. 1) The returned subname is flattened, meaning that any plain group you created will not be in it. So tree view sync may not work. 2) The element you want may not in the current document. It may be external linked.

Alternatively, you may want to try using two asm3 commands. You need to first select the element you want in the tree view, then run

Gui.runCommand('Std_LinkSelectLinked',0)

This is equivalent to click the Select linked object toolbar button. To go to the deepest link

Gui.runCommand('Std_LinkSelectLinked',1)

@ceremcem
Copy link
Collaborator Author

ceremcem commented Jun 30, 2020

The problem with Gui.runCommand('Std_LinkSelectLinked',0) or ..., 1) is that this command selects the whole object, not the face.

The example for the element Element works nicely on Python console. However, it wasn't working in Macro, for multiple documents. Turns out it works only for the active document. Here is the working version for anyone needs it:

doc_name="driver_base"
elem_label="wall_unfold_face"
# ------------------------------------------------------------
Gui.ActiveDocument=Gui.getDocument(doc_name)
App.ActiveDocument=App.getDocument(doc_name)
App.setActiveDocument(App.ActiveDocument.Name) # Interesting. Why do we need to assign this manually?
doc=App.ActiveDocument
element = doc.getObjectsByLabel(elem_label)[0].Proxy
partGroup = element.getAssembly().getPartGroup()
subname = element.getElementSubname(True)
Gui.Selection.addSelection(partGroup, subname)

Works pretty well for now. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants