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

How to make unfold sketch updated on base geometry changes #40

Closed
ceremcem opened this issue Aug 31, 2018 · 11 comments · Fixed by #70
Closed

How to make unfold sketch updated on base geometry changes #40

ceremcem opened this issue Aug 31, 2018 · 11 comments · Fixed by #70
Labels

Comments

@ceremcem
Copy link
Contributor

This is the current unfold output:

image

When I changed the geometry, for example as in the following way:

image

I expect the unfold sketch to be updated accordingly. How can I achieve this, either automatically (this is preferred) or by manually running some code?

@ceremcem ceremcem changed the title How to make unfold update on base geometry changes How to make unfold sketch updated on base geometry changes Aug 31, 2018
@shaise
Copy link
Owner

shaise commented Sep 1, 2018

The unfold is a single one time task and not linked to the object. There is no way to update it, you need to delete the existing and create a new one.

@ceremcem
Copy link
Contributor Author

ceremcem commented Sep 1, 2018

Do you think this is a wontfix or might be a feature request?

@shaise
Copy link
Owner

shaise commented Sep 1, 2018

There are 2 reason why it is not connected (and probably will not):

  1. the unfold is not automatic - it involves selecting a base face. Making changes to the original body in many cases changes the base face naming hence breaking the unfold
  2. the unfold process can be processor intensive, so if the unfold is automatically updated with every change it can lead to annoying cpu hangs.

@ceremcem
Copy link
Contributor Author

ceremcem commented Sep 1, 2018

the unfold process can be processor intensive, so if the unfold is automatically updated with every change it can lead to annoying cpu hangs.

Based on this reason, it might be an option to handle the update with a button.

the unfold is not automatic - it involves selecting a base face. Making changes to the original body in many cases changes the base face naming hence breaking the unfold

I'm new to FreeCAD, but I think this depends on how correctly you designed a part. So the "update" button might generate an error if name is changed, else it would be performed smoothly.

@shaise
Copy link
Owner

shaise commented Sep 1, 2018

If you have to press a button to refresh you can as well press the unfold button again...
and in many cases no mater how correctly you design a part, the naming will change. So I think it does not worth the effort of making it automatic. But this is only my opinion.

@ceremcem
Copy link
Contributor Author

ceremcem commented Sep 1, 2018

When a TechDraw page is created based on the unfold sketch, the TechDraw requires the same source sketch too. That makes things complex if you have more than one solid to unfold where their TechDraw pages are already generated, because you need to take care of correct namings too.

@shaise
Copy link
Owner

shaise commented Sep 1, 2018

This is a good point...

@ceremcem
Copy link
Contributor Author

Making changes to the original body in many cases changes the base face naming hence breaking the unfold

I think this depends on how correctly you designed a part.

I was wrong. The name of the face keeps changing even if you never perform an operation that changes the face geometry. However, there might be a way to go with Assembly3: realthunder/FreeCAD_assembly3#236

@ceremcem
Copy link
Contributor Author

Here is the proof of concept that works only with Assembly3:

  1. Patch sheetmetal to add SMUnfoldUnattended command:
diff --git a/SheetMetalUnfolder.py b/SheetMetalUnfolder.py
index d6b8821..05655c3 100644
--- a/SheetMetalUnfolder.py
+++ b/SheetMetalUnfolder.py
@@ -2456,3 +2456,42 @@ class SMUnfoldCommandClass():
 
 Gui.addCommand('SMUnfold',SMUnfoldCommandClass())
 
+class SMUnfoldUnattendedCommandClass():
+  """Unfold object"""
+
+  def GetResources(self):
+    __dir__ = os.path.dirname(__file__)
+    iconPath = os.path.join( __dir__, 'Resources', 'icons' )
+    return {'Pixmap'  : os.path.join( iconPath , 'SMUnfold.svg') , # the name of a svg file available in the resources
+            'MenuText': "Unfold" ,
+            'ToolTip' : "Flatten folded sheet metal object"}
+
+  def Activated(self):
+    SMMessage(["unattended unfold..."])
+    taskd = SMUnfoldTaskPanel()
+    pg = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/sheetmetal")
+    if pg.GetBool("bendSketch"):
+        taskd.checkSeparate.setCheckState(QtCore.Qt.CheckState.Checked)
+    else:
+        taskd.checkSeparate.setCheckState(QtCore.Qt.CheckState.Unchecked)
+    if pg.GetBool("genSketch"):
+        taskd.checkSketch.setCheckState(QtCore.Qt.CheckState.Checked)
+    else:
+        taskd.checkSketch.setCheckState(QtCore.Qt.CheckState.Unchecked)
+    taskd.bendColor.setColor(pg.GetString("bendColor"))
+    taskd.genColor.setColor(pg.GetString("genColor"))
+    taskd.internalColor.setColor(pg.GetString("intColor"))
+    taskd.accept()
+    return
+
+  def IsActive(self):
+    if len(Gui.Selection.getSelection()) != 1 or len(Gui.Selection.getSelectionEx()[0].SubElementNames) != 1:
+      return False
+    selobj = Gui.Selection.getSelection()[0]
+    selFace = Gui.Selection.getSelectionEx()[0].SubObjects[0]
+    if type(selFace) != Part.Face:
+      return False
+    return True
+
+
+Gui.addCommand("SMUnfoldUnattended",SMUnfoldUnattendedCommandClass())
  1. Use the following macro to update the unfolded sketches and related TechDraw ProjGroup sources:
"""
Usage:

1. Put your processed object into an assembly container.
2. Create an "Element" for the unfold face
3. Rename the element to "foo_unfold_face"
4. Run this macro
5. See "foo_unfold" sketch is created properly.
6. See any TechDraw ProjGroup source is updated properly
"""

import FreeCAD
import re

echo = FreeCAD.Console.PrintMessage
warn = FreeCAD.Console.PrintWarning

prev_workbench = Gui.activeWorkbench().name()
Gui.activateWorkbench("SMWorkbench")
if prev_workbench:
    Gui.activateWorkbench(prev_workbench)

doc = App.ActiveDocument
unfold_sketch_regex = re.compile('.+_unfold_face')

for o in doc.Objects:
    if o.TypeId == 'Part::FeaturePython':
        match = unfold_sketch_regex.match(o.Label)
        if match:
            output_name = o.Label[:-5]  # remove "_face" postfix
            echo("Found unfold job: " + output_name + " \n")

            related_views = []
            for x in doc.Objects:
                if x.TypeId == 'TechDraw::DrawPage':
                    for view in x.Views:
                        try:
                            _src = view.Source[0]
                        except:
                            continue
                        #print("source of ", x.Name, view.Name, " is: ", _src.Label)
                        if _src.Label == output_name:
                            # This view uses our unfolded output, update this view at the end
                            print("Found related TechDraw ProjGroup: " + view.Name)
                            related_views.append(view)

            try:
                old = doc.getObjectsByLabel(output_name)[0].Name
                doc.removeObject(old)
                doc.recompute()
            except:
                pass

            # Get the unfold face id
            # TODO: This extraction (achieving `unfold_face_id`) is a very dirty hack. Tidy up ASAP.
            face_elem = doc.getObjectsByLabel(output_name + '_face')[0]
            asm_container = face_elem.Parents[0][0]
            target_obj_path = asm_container.getSubObjects()[0]
            unfold_face_id = (asm_container.Name, target_obj_path + face_elem.LinkedObject[1].split('.')[-1])

            # Unfold the object
            Gui.Selection.clearSelection()
            Gui.Selection.addSelection(doc.Name, unfold_face_id[0], unfold_face_id[1])
            Gui.runCommand('SMUnfoldUnattended')

            # Remove unnecessary unfolded solid
            doc.removeObject('Unfold')

            # Properly rename the output
            sketch = doc.getObjectsByLabel('Unfold_Sketch')[0]
            sketch.Label = output_name
            sketch.Visibility = False

            # Update the source of related views
            for view in related_views:
                echo("Updating " + view.Name + " source.")
                view.Source = [sketch]

doc.recompute()
Gui.Selection.clearSelection()

@realthunder
Copy link
Contributor

  1. the unfold is not automatic - it involves selecting a base face. Making changes to the original body in many cases changes the base face naming hence breaking the unfold

There is new topo naming algorithm implemented in my branch, which auto tracks the changing face index. For simple usage, just add a App::PropertyLinkSub as usual, and the face reference inside will auto change when the geometry changes, and it is fully backward compatible with upstream. For advanced use, there is TopoShape.getRelatedElement() function in case the geometry changes significantly that the new topo name changes as well. In many cases, simple usage is enough.

  1. the unfold process can be processor intensive, so if the unfold is automatically updated with every change it can lead to annoying cpu hangs.

You can add another property to enable/disable auto update. And maybe offer a context menu action in your ViewObject to let user manually update.

@ceremcem
Copy link
Contributor Author

Screencast

refresh-unfold-example

ceremcem pushed a commit to ceremcem/FreeCAD_SheetMetal that referenced this issue Apr 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants