Skip to content

Instantly share code, notes, and snippets.

@easyw
Created May 5, 2018 17:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save easyw/049e0a2f82751963b9c27b918bfbfb94 to your computer and use it in GitHub Desktop.
Save easyw/049e0a2f82751963b9c27b918bfbfb94 to your computer and use it in GitHub Desktop.
a FreeCAD utility to convert an assembly to a Part Hierarchy of objects, simply removing all the constraints (Requirements realthunder Assembly3 build)
#!/usr/bin/python
# -*- coding: utf-8 -*-
# asm3_to_part_hierarchy.py
__Author__ = 'easyw Maurice'
__License__ = 'LGPL2+ https://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License'
'''
a FreeCAD utility to convert an assembly to a Part Hierarchy of objects,
simply removing all the constraints
Requirements realthunder Assembly3 build
https://github.com/realthunder/FreeCAD_assembly3
'''
# partially based on 'galou_breizh' 'Deep Copy' Macro
# __Web__ = 'https://www.freecadweb.org/wiki/index.php?title=Macro_DeepCopy'
# Gui.activateWorkbench("Assembly3Workbench")
# a=App.ActiveDocument.getObject('Assembly')
# a.Group
# p=a.Group[2]
# p.Group
# p.Group[2].Label
# p.Group[2].TypeId
# p.Group[2].Name
import FreeCAD as app
import FreeCADGui as gui
__a2pversion__ = '1.1.1'
def fcc_prn(message):
FreeCAD.Console.PrintMessage('{}\n'.format(message))
def fcc_wprn(message):
FreeCAD.Console.PrintWarning('{}\n'.format(message))
Links_available = False
try:
from freecad.asm3 import assembly as asm
Links_available = True
fcc_prn('A3 available')
except:
fcc_wprn('A3 not available')
###
def get_all_subobjs(o):
"""Recursively get all subobjects
Subobjects of objects having a Shape attribute are not included otherwise each
single feature of the object would be copied. The result is that bodies,
compounds, and the result of boolean operations will be converted into a
simple copy of their shape.
"""
# Depth-first search algorithm.
discovered = []
# We do not need an extra copy for stack because OutList is already a copy.
if hasattr(o,'Group') and o.TypeId != 'App::Part':
fcc_prn('Assembly container');
#fcc_prn(o.Label)
stack = o.Group[2].Group
else:
fcc_prn('Part or Body container')
stack = o.OutList
#stack = o.OutList
#for s in stack:
# fcc_prn(s.Label)
while stack:
v = stack.pop(0)
if v not in discovered:
discovered.append(v)
if (not hasattr(v, 'Shape') or v.Name.startswith('Assembly')):
stack += v.OutList
#fcc_wprn(discovered)
return discovered
###
def deep_simply_assy_sel(doc):
for sel_object in gui.Selection.getSelectionEx():
deep_simply_assy(doc, sel_object.Object)
###
def deep_simply_assy(doc, part):
if part.TypeId != 'Part::FeaturePython' and not part.Name.startswith('Assembly') and part.TypeId != 'App::Part':
# Part is not an Assembly part, return.
fcc_prn('found Body, not Assembly or Part DN')
return 0
copied_subobjects = []
part_containers = []
doc.Tip = FreeCAD.activeDocument().addObject('App::Part',part.Name+'_copy')
pName = part.Name+'_copy'
gui.activeView().setActiveObject('part', doc.getObject(pName))
doc.getObject(pName).Label = part.Label+'_copy'
doc.getObject(pName).Placement = part.Placement
part_containers.append([doc.getObject(pName),part])
for o in get_all_subobjs(part):
cs, pc = simple_copy_subobj(doc, o)
copied_subobjects += cs
part_containers += pc
make_compound = True #False
#if make_compound:
# compound = doc.addObject('Part::Compound', part.Label + '.copy')
# compound.Links = copied_subobjects
#stop
copy_inside=True
if copy_inside:
for p in part_containers: #adding Parts containers
#fcc_prn(p[0].Label)
if p[1].Name.startswith('Assembly'):
outlist = p[1].OutList[2].OutList #Parts of Assembly
else:
outlist = p[1].OutList
for o in outlist: #Recursive:
if o.TypeId == 'App::Part':
#fcc_prn(o.Label); fcc_wprn(o.Name);fcc_wprn(p[0].Label)
if o in outlist:
doc.getObject(p[0].Name).addObject(doc.getObject(o.Name+'_copy'))
for p in part_containers:
#fcc_prn(p[0].Label)
if p[1].Name.startswith('Assembly'):
outlist = p[1].OutList[2].OutList #Parts of Assembly
else:
outlist = p[1].OutList
for o in outlist:
if o.TypeId != 'App::Origin' and o.TypeId != 'Sketcher::SketchObject' \
and o.TypeId != 'App::Plane' and o.TypeId != 'App::Line'\
and o.TypeId != 'App::Part'\
and doc.getObject(o.Name+'_copy') is not None:
if o in outlist:
#fcc_prn(o.Label); fcc_wprn(o.Name);fcc_wprn(p[0].Label)
doc.getObject(p[0].Name).addObject(doc.getObject(o.Name+'_copy'))
doc.recompute()
return 1
##
def simple_copy_subobj(doc, o):
"""Copy the shape of an object
Some GUI attributes are also copied
"""
copied_object = []
prt_containers = []
if (not hasattr(o, 'Shape') or o.Shape.isNull()) and o.TypeId != 'App::Link': # or not o.Name.startswith('Assembly'):
if o.TypeId == 'App::Part' or (hasattr(o,'Group') and o.Name.startswith('Assembly')):
doc.Tip = App.activeDocument().addObject('App::Part',o.Name+'_copy')
pName = o.Name+'_copy'
gui.activeView().setActiveObject('part', doc.getObject(pName))
#pName = doc.ActiveObject.Name
# doc.getObject(pName).Label = o.Label + '_copy'
prt_containers.append([doc.getObject(pName),o])
doc.getObject(pName).Placement = o.Placement
doc.getObject(pName).Label = o.Label+'_copy'
#print ('running Part here')
#print (prt_containers)
return copied_object, prt_containers
vo_o = o.ViewObject
if o.TypeId != 'Sketcher::SketchObject':# and o.TypeId != 'App::Link':
try:
#if 1:
#print ('running here'); print(o.Label); print (o.Name); print (o.TypeId)
copy = doc.addObject('Part::Feature', o.Name + '_copy')
if o.TypeId != 'App::Link':
copy.Shape = o.Shape #.copy()
else:
#fcc_wprn(o.TypeId)
#fcc_wprn (o.OutList[0].Label)
#FreeCAD.ActiveDocument.recompute()
copy.Shape = Part.getShape(o.OutList[0]) #.copy()
#copy.Shape = o.Outlist[0].Shape
vo_o = o.OutList[0].ViewObject
#s = Part.getShape(o)
copy.Placement = o.Placement
#Part.show(copy.Shape)
#print ('running again here')
copy.Label = o.Label + '_copy'
# copy.Placement = o.getGlobalPlacement()
# copy.Placement = Part.getShape(o).Placement
vo_copy = copy.ViewObject
vo_copy.ShapeColor = vo_o.ShapeColor
vo_copy.LineColor = vo_o.LineColor
vo_copy.PointColor = vo_o.PointColor
vo_copy.DiffuseColor = vo_o.DiffuseColor
vo_copy.Transparency = vo_o.Transparency
if 0:
fcc_prn('Obj:')
fcc_prn(o.Label)
fcc_prn('InList:')
for ob in o.InList:
fcc_prn(ob.Label)
fcc_prn('InListRecursive:')
for ob in o.InListRecursive:
fcc_prn(o.Label)
#if Links_available:
# fcc_wprn(o.Label)
# fcc_prn(o.isElementVisible(o.Name))
# if o.isElementVisible(o.Name) == 1:
# vo_copy.Visibility = True
# else:
# vo_copy.Visibility = False
#else:
# vo_copy.Visibility = vo_o.Visibility #gui.activeDocument().getObject(o.Name).Visibility
#print(o.Label);print(gui.activeDocument().getObject(o.Name).Visibility)
except AttributeError:
fcc_wprn('ERROR')
pass
else:
copied_object = [copy]
return copied_object, prt_containers
###
import time
doc = app.activeDocument()
sel = FreeCADGui.Selection.getSelection()
selEx = FreeCADGui.Selection.getSelectionEx()
current_milli_time = lambda: int(round(time.time() * 1000))
start_milli_time = current_milli_time()
## deep_copy_assy_sel(doc)
fcc_prn('Assembly to PartDN release '+__a2pversion__)
sel = FreeCADGui.Selection.getSelection()
if not sel:
fcc_wprn("Select an Assembly container to simplify it to Part Design Next container(s)")
else:
#deep_simply_assy_sel(doc)
for sel_object in gui.Selection.getSelectionEx():
result=deep_simply_assy(doc, sel_object.Object)
if result:
gui.activeDocument().getObject(sel_object.Object.Name).Visibility = False
#gui.Selection.setVisible()
fcc_prn(sel_object.Object.Label + ' Assembly container copied')
end_milli_time = current_milli_time()
running_time=(end_milli_time-start_milli_time)/1000
fcc_wprn('running time:'+str(running_time))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment