Created
May 5, 2018 17:19
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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