Browse Source

Added possibility to annotate parts of sub-assemblies

dev/better-annotations
Youen 2 years ago
parent
commit
d6fb938d96
  1. 6
      InitGui.py
  2. 53
      ahb_cmd_view_annotate.py
  3. 60
      ahb_cmd_view_annotate_detail.py
  4. 92
      ahb_techdraw_extensions.py

6
InitGui.py

@ -1,4 +1,5 @@
sys.path.append('/usr/local/lib/python3.9/dist-packages/')
#sys.path.append('/usr/local/lib/python3.9/dist-packages/')
sys.path.append('/home/youen/.FreeCAD/Mod/assembly_handbook/pydev')
#import pydevd
#pydevd.settrace()
@ -89,6 +90,9 @@ class AssemblyHandbookWorkbench(Gui.Workbench):
self.importModule('ahb_cmd_view_annotate')
toolbox.append("AHB_view_annotate")
self.importModule('ahb_cmd_view_annotate_detail')
toolbox.append('AHB_view_annotate_detail')
self.importModule('ahb_cmd_view_edit_source_parts')
toolbox.append("AHB_view_edit_source_parts")
toolbox.append("AHB_view_add_source_parts")

53
ahb_cmd_view_annotate.py

@ -29,12 +29,27 @@ class AHB_View_Annotate:
if page is None:
raise Exception("Can't find page in which the selected view is located")
def list_sub_parts(parts):
result = []
for part in parts:
if part.TypeId == 'App::Link':
result.append(part)
elif part.TypeId == 'Part::FeaturePython' and hasattr(part, 'LinkedObject'): # variant link
result.append(part)
if hasattr(part, 'Group'):
result.extend(list_sub_parts(part.Group))
return result
all_parts = list_sub_parts(view.XSource)
# Remove balloons referencing missing objects
for balloon in page.Views:
if balloon.TypeId == 'TechDraw::DrawViewBalloon' and "Assembly_handbook_Source" in balloon.PropertiesList:
if balloon.SourceView != view and balloon.SourceView != overlay_view: continue
partLink = workbench.techDrawExtensions.getBalloonSourcePart(balloon)
if partLink is None or partLink not in view.XSource:
if partLink is None or partLink not in all_parts:
ref_name = "<no ref>"
try:
ref_name = balloon.Assembly_handbook_Source[1]
@ -44,41 +59,7 @@ class AHB_View_Annotate:
doc.removeObject(balloon.Name)
for partLink in view.XSource:
balloon = None
# Search an existing balloon to update
for obj in page.Views:
if obj.TypeId == 'TechDraw::DrawViewBalloon' and workbench.techDrawExtensions.getBalloonSourcePart(obj) == partLink:
if obj.SourceView != overlay_view: continue
balloon = obj
# Create a new balloon if needed
if balloon is None:
if workbench.techDrawExtensions.isNewPartInView(view, partLink):
partName = partLink.Name
balloonName = partName + "_Balloon"
balloon = doc.addObject("TechDraw::DrawViewBalloon", balloonName)
balloon.SourceView = overlay_view
balloon.addProperty("App::PropertyXLink", "Assembly_handbook_Source", "Assembly_handbook")
balloon.Assembly_handbook_Source = (partLink, partLink.Name)
balloon.addProperty("App::PropertyFloat", "Assembly_handbook_OriginOffsetX", "Assembly_handbook")
balloon.addProperty("App::PropertyFloat", "Assembly_handbook_OriginOffsetY", "Assembly_handbook")
page.addView(balloon)
workbench.techDrawExtensions.updateBalloon(balloon)
balloon.X = int(balloon.OriginX) + 20
balloon.Y = int(balloon.OriginY) + 20
if not workbench.techDrawExtensions.isNewPartInView(view, partLink):
balloon.ViewObject.Visibility = False
else:
workbench.techDrawExtensions.updateBalloon(balloon)
workbench.techDrawExtensions.add_or_update_balloon(view, partLink, '')
from ahb_command import AHB_CommandWrapper
AHB_CommandWrapper.addGuiCommand('AHB_view_annotate', AHB_View_Annotate())

60
ahb_cmd_view_annotate_detail.py

@ -0,0 +1,60 @@
import FreeCADGui as Gui
import FreeCAD as App
class AHB_View_Annotate_Detail:
def GetResources(self):
return {"MenuText": "Add annotation details",
"ToolTip": "Annotates each part of a sub-assembly",
"Pixmap": ""
}
def IsActive(self):
return True
def Activated(self):
workbench = Gui.getWorkbench("AssemblyHandbookWorkbench") #: :type workbench: AssemblyHandbookWorkbench
if len(Gui.Selection.getSelection()) == 0:
raise Exception("Please select at least one annotation balloon")
view = None
for balloon in Gui.Selection.getSelection():
if balloon.TypeId != 'TechDraw::DrawViewBalloon' or "Assembly_handbook_Source" not in balloon.PropertiesList:
raise Exception("All selected objects must be annotation balloons")
if view is not None and view != balloon.SourceView or balloon.SourceView is None:
raise Exception("Please only select balloons from the same view")
view = balloon.SourceView
overlay_view = workbench.techDrawExtensions.getOverlayView(view)
doc = view.Document
page = workbench.techDrawExtensions.getViewPage(view)
if page is None:
raise Exception("Can't find page in which the selected view is located")
balloons_to_split = Gui.Selection.getSelection()
for balloon in balloons_to_split:
sub_assembly_link = workbench.techDrawExtensions.getBalloonSourcePart(balloon)
sub_assembly = sub_assembly_link.LinkedObject
if sub_assembly.TypeId != 'App::Part': continue
def list_first_level_sub_parts(group):
results = []
for obj in group.Group:
if obj.TypeId == 'App::Link':
results.append(obj)
elif obj.TypeId == 'Part::FeaturePython' and hasattr(obj, 'LinkedObject'): # variant link
results.append(obj)
elif hasattr(obj, 'Group'):
results.extend(list_first_level_sub_parts(obj))
return results
parts = list_first_level_sub_parts(sub_assembly)
for part in parts:
workbench.techDrawExtensions.add_or_update_balloon(view, part, workbench.techDrawExtensions.getBalloonSourcePartPath(balloon))
from ahb_command import AHB_CommandWrapper
AHB_CommandWrapper.addGuiCommand('AHB_view_annotate_detail', AHB_View_Annotate_Detail())

92
ahb_techdraw_extensions.py

@ -431,7 +431,7 @@ class TechDrawExtensions:
obj = self.getBalloonSourcePart(balloon)
view = balloon.SourceView
center = self.computePartCenter(view, obj)
center = self.computePartCenter(view, obj, self.getBalloonSourcePartPath(balloon))
balloon.Assembly_handbook_OriginOffsetX = new_pos.x - center.x
balloon.Assembly_handbook_OriginOffsetY = new_pos.y - center.y
@ -455,16 +455,67 @@ class TechDrawExtensions:
self.updating_balloon = True
self.updateBalloon(obj)
self.updating_balloon = False
def add_or_update_balloon(self, view, part, parent_path):
page = self.getViewPage(view)
overlay_view = self.getOverlayView(view)
doc = page.Document
path = parent_path
if path == '':
path = part.Document.Name + '#' + part.Name
else:
path += '.'
path += part.Name
# Search an existing balloon to update
balloon = None
for obj in page.Views:
if obj.TypeId == 'TechDraw::DrawViewBalloon' and self.getBalloonSourcePart(obj) == part and self.getBalloonSourcePartPath(obj) == path:
if obj.SourceView != overlay_view: continue
balloon = obj
# Create a new balloon if needed
if balloon is None:
if self.isNewPartInView(view, part):
partName = part.Name
balloonName = partName + "_Balloon"
balloon = doc.addObject("TechDraw::DrawViewBalloon", balloonName)
balloon.SourceView = overlay_view
balloon.addProperty("App::PropertyXLink", "Assembly_handbook_Source", "Assembly_handbook")
balloon.Assembly_handbook_Source = (part, part.Name)
balloon.addProperty("App::PropertyString", "Assembly_handbook_SourcePath", "Assembly_handbook")
balloon.Assembly_handbook_SourcePath = path
balloon.addProperty("App::PropertyFloat", "Assembly_handbook_OriginOffsetX", "Assembly_handbook")
balloon.addProperty("App::PropertyFloat", "Assembly_handbook_OriginOffsetY", "Assembly_handbook")
page.addView(balloon)
self.updateBalloon(balloon)
balloon.X = int(balloon.OriginX) + 20
balloon.Y = int(balloon.OriginY) + 20
if not self.isNewPartInView(view, part):
balloon.ViewObject.Visibility = False
else:
self.updateBalloon(balloon)
def updateBalloon(self, balloon):
workbench = Gui.getWorkbench("AssemblyHandbookWorkbench") #: :type workbench: AssemblyHandbookWorkbench
view = balloon.SourceView
obj = self.getBalloonSourcePart(balloon)
path = self.getBalloonSourcePartPath(balloon)
partDisplayName = 'Inconnu' if obj is None else self.getPartDisplayName(obj)
objectCenterView = workbench.techDrawExtensions.computePartCenter(view, obj)
objectCenterView = workbench.techDrawExtensions.computePartCenter(view, obj, path)
balloon.OriginX = objectCenterView.x + balloon.Assembly_handbook_OriginOffsetX
balloon.OriginY = objectCenterView.y + balloon.Assembly_handbook_OriginOffsetY
@ -480,6 +531,15 @@ class TechDrawExtensions:
return balloon.Assembly_handbook_Source[0]
except:
return None
def getBalloonSourcePartPath(self, balloon):
try:
return balloon.Assembly_handbook_SourcePath
except:
part = self.getBalloonSourcePart(balloon)
if part is None:
return ''
return part.Document.Name + '#' + part.Name
def isPartLink(self, obj):
if obj.TypeId == 'App::Link':
@ -584,17 +644,39 @@ class TechDrawExtensions:
overlay = view.Document.getObject(view.Name + '_overlay')
return overlay if overlay is not None else view
def computePartCenter(self, view, obj):
def computePartCenter(self, view, obj, path = None):
view = self.getSourceView(view)
mat = App.Matrix()
if path is not None:
path_parts = path.split('.')
path_parts.pop()
parent = None
for part in path_parts:
if parent is None:
doc_obj = part.split('#')
doc = App.getDocument(doc_obj[0])
link = doc.getObject(doc_obj[1])
else:
link = parent.Document.getObject(part)
mat = link.LinkPlacement * mat
parent = link.LinkedObject
if obj.TypeId == 'App::Link':
partLink = obj
objectCenterWorld = partLink.LinkPlacement.Matrix.multiply(partLink.LinkedObject.Shape.CenterOfGravity)
mat = mat.multiply(partLink.LinkPlacement.Matrix)
objectCenterWorld = partLink.LinkedObject.Shape.CenterOfGravity
elif obj.TypeId == 'Part::FeaturePython' and hasattr(obj, 'LinkedObject'): # variant link
partLink = obj
objectCenterWorld = partLink.Placement.Matrix.multiply(partLink.LinkedObject.Shape.CenterOfGravity)
mat = mat.multiply(partLink.Placement.Matrix)
objectCenterWorld = partLink.LinkedObject.Shape.CenterOfGravity
else:
objectCenterWorld = obj.Shape.CenterOfGravity
objectCenterWorld = mat.multiply(objectCenterWorld)
'''view_cache = self.getViewCache(view)

Loading…
Cancel
Save