FreeCAD: Workbench Refactor
This commit is contained in:
parent
037827669a
commit
a58dcdafb1
386 changed files with 997 additions and 64533 deletions
53
freecad_workbench/usecases/asm4parser_usecase.py
Normal file
53
freecad_workbench/usecases/asm4parser_usecase.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
import FreeCAD as App
|
||||
|
||||
class Asm4StructureParseUseCase:
|
||||
_parts = []
|
||||
_label = []
|
||||
|
||||
def getSubPartsLabel(self, group):
|
||||
groupLabel = []
|
||||
for el in group:
|
||||
if str(el) == '<Part::PartFeature>':
|
||||
groupLabel.append(el.Label)
|
||||
return groupLabel
|
||||
|
||||
def parseLabel(self, nextGroup, label, level=2, nextGroupParse=0):
|
||||
if nextGroup.__len__() == nextGroupParse:
|
||||
return
|
||||
else:
|
||||
groupParts = []
|
||||
|
||||
for el in nextGroup:
|
||||
if str(el) == '<App::Link object>':
|
||||
groupParts.append(el)
|
||||
|
||||
for el in groupParts:
|
||||
if str(el) == '<App::Link object>':
|
||||
label.append({
|
||||
"level": level,
|
||||
"attachedTo": el.AttachedTo.split('#'),
|
||||
"label": el.Label,
|
||||
"axis": self.getSubPartsLabel(el.Group)
|
||||
})
|
||||
|
||||
def initParse(self):
|
||||
|
||||
model = App.ActiveDocument.RootObjects[1]
|
||||
self._label.append({
|
||||
"level": 1,
|
||||
"attachedTo": "Parent Assembly",
|
||||
"label": model.Label,
|
||||
"axis": self.getSubPartsLabel(model.Group)
|
||||
})
|
||||
for parent in model.Group:
|
||||
if str(parent) == '<App::Link object>':
|
||||
self._label.append({
|
||||
"level": 1,
|
||||
"attachedTo": parent.AttachedTo.split('#'),
|
||||
"label": parent.Label,
|
||||
"axis": self.getSubPartsLabel(parent.Group)
|
||||
})
|
||||
print(self._label)
|
||||
|
||||
|
||||
|
58
freecad_workbench/usecases/assembly_parse_usecase.py
Normal file
58
freecad_workbench/usecases/assembly_parse_usecase.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
import FreeCAD as App
|
||||
def is_object_solid(obj):
|
||||
"""If obj is solid return True"""
|
||||
if not isinstance(obj, App.DocumentObject):
|
||||
return False
|
||||
if hasattr(obj, 'Group'):
|
||||
return False
|
||||
|
||||
if not hasattr(obj, 'Shape'):
|
||||
return False
|
||||
# if not hasattr(obj.Shape, 'Mass'):
|
||||
# return False
|
||||
if not hasattr(obj.Shape, 'Solids'):
|
||||
return False
|
||||
|
||||
if len(obj.Shape.Solids) == 0:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class AssemblyParseUseCase:
|
||||
_parts = []
|
||||
|
||||
_asm = []
|
||||
|
||||
def getAsm(self):
|
||||
return self._asm
|
||||
|
||||
def __init__(self) -> None:
|
||||
if (self._asm.__len__() == 0):
|
||||
self.initParse()
|
||||
pass
|
||||
|
||||
def initParse(self):
|
||||
for el in App.ActiveDocument.Objects:
|
||||
if (is_object_solid(el)):
|
||||
self._asm.append(el.Label)
|
||||
|
||||
def toJson(self):
|
||||
return str(self._asm).replace('\'', "\"")
|
||||
|
||||
def getSubPartsLink(self, group):
|
||||
groupLink = {}
|
||||
for el in group:
|
||||
if (is_object_solid(el)):
|
||||
if str(el.Shape).find('Solid') != -1:
|
||||
if groupLink.get(el.Label) == None:
|
||||
groupLink[el.Label] = []
|
||||
for i in el.Group:
|
||||
if str(i).find('Pad') != -1:
|
||||
groupLink[el.Label].append(i)
|
||||
if groupLink.__len__() == 0:
|
||||
return None
|
||||
return groupLink
|
||||
|
||||
def getLinkedProperty(self):
|
||||
return self._asm
|
|
@ -0,0 +1,92 @@
|
|||
|
||||
|
||||
from typing import List
|
||||
import FreeCAD as App
|
||||
import Part
|
||||
from model.join_mesh_model import JoinMeshModel
|
||||
from model.mesh_part_model import MeshPartModel
|
||||
from helper.fs import FS
|
||||
from helper.is_solid import is_object_solid
|
||||
from model.simple_copy_part_model import SimpleCopyPartModel
|
||||
from model.files_generator import FolderGenerator
|
||||
from usecases.assembly_parse_usecase import AssemblyParseUseCase
|
||||
import importOBJ
|
||||
import os
|
||||
import json
|
||||
|
||||
|
||||
class ExportAssemblyThemAllUseCase:
|
||||
|
||||
def call(self, path):
|
||||
assembly = AssemblyParseUseCase().getAsm()
|
||||
asmStructure = {}
|
||||
inc = 0
|
||||
for el in assembly:
|
||||
if (inc != 0):
|
||||
asmStructure[inc] = {
|
||||
"child": el,
|
||||
"parents": assembly[0:inc]
|
||||
}
|
||||
inc += 1
|
||||
objectsFreeCad = App.ActiveDocument.Objects
|
||||
asmSolids = {}
|
||||
for k, v in asmStructure.items():
|
||||
assemblyParentList = v['parents']
|
||||
assemblyChild = v['child']
|
||||
for el in assemblyParentList:
|
||||
for solid in objectsFreeCad:
|
||||
if (el == solid.Label):
|
||||
if (asmSolids.get(k) is None):
|
||||
|
||||
asmSolids[k] = {'parents': [], 'child': list(
|
||||
filter(lambda x: x.Label == assemblyChild, objectsFreeCad))[0]}
|
||||
|
||||
asmSolids[k]['parents'].append(solid)
|
||||
|
||||
inc = 0
|
||||
for k, v in asmSolids.items():
|
||||
geometry = {"0": [], "1": []}
|
||||
if (k != 0):
|
||||
App.activeDocument().addObject("Part::Compound", "Compound")
|
||||
|
||||
copyLinks = list(
|
||||
map(lambda el: SimpleCopyPartModel(el), v['parents']))
|
||||
|
||||
if copyLinks != None:
|
||||
App.activeDocument().Compound.Links = list(
|
||||
map(lambda el: el.getPart(), copyLinks))
|
||||
|
||||
object = App.activeDocument().getObject('Compound')
|
||||
boundBox = object.Shape.BoundBox
|
||||
geometry['0'].append(boundBox.XMax)
|
||||
geometry['0'].append(boundBox.YMax)
|
||||
geometry['0'].append(boundBox.ZMax)
|
||||
|
||||
os.makedirs(
|
||||
path + FolderGenerator.ASSEMBlY.value + '/' + '0000' + str(k))
|
||||
boundBoxChild = v['child'].Shape.BoundBox
|
||||
geometry['1'].append(boundBoxChild.XMax)
|
||||
geometry['1'].append(boundBoxChild.YMax)
|
||||
geometry['1'].append(boundBoxChild.ZMax)
|
||||
meshParents = []
|
||||
|
||||
for el in v['parents']:
|
||||
meshParents.append(MeshPartModel(el))
|
||||
joinMesh = JoinMeshModel(meshParents)
|
||||
for el in meshParents:
|
||||
el.remove()
|
||||
importOBJ.export(joinMesh.mesh, path + FolderGenerator.ASSEMBlY.value +
|
||||
'/' + '0000' + str(k) + '/' + str(1) + '.obj')
|
||||
joinMesh.remove()
|
||||
importOBJ.export(v['child'], path + FolderGenerator.ASSEMBlY.value +
|
||||
'/' + '0000' + str(k) + '/' + str(0) + '.obj')
|
||||
FS.writeFile(json.dumps(geometry), path + FolderGenerator.ASSEMBlY.value +
|
||||
'/' + '0000' + str(k) + '/', 'translation.json')
|
||||
|
||||
App.ActiveDocument.removeObject("Compound")
|
||||
for el in copyLinks:
|
||||
el.remove()
|
||||
App.activeDocument().recompute()
|
||||
inc += 1
|
||||
|
||||
|
36
freecad_workbench/usecases/export_usecase.py
Normal file
36
freecad_workbench/usecases/export_usecase.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
import importDAE
|
||||
import importOBJ
|
||||
import Mesh
|
||||
import FreeCAD as App
|
||||
from model.files_generator import FolderGenerator
|
||||
from helper.is_solid import is_object_solid
|
||||
from enum import Enum
|
||||
|
||||
class EXPORT_TYPES(Enum):
|
||||
STL = 'STL'
|
||||
DAO = 'DAO'
|
||||
OBJ = 'OBJ'
|
||||
|
||||
#экспорт stl и urdf из freecad
|
||||
class ExportUseCase:
|
||||
def call(path: str, type: EXPORT_TYPES):
|
||||
meshes = {}
|
||||
for el in App.ActiveDocument.Objects:
|
||||
if (is_object_solid(el)):
|
||||
match type.value:
|
||||
case EXPORT_TYPES.STL.value:
|
||||
Mesh.export([el], path + '/' + FolderGenerator.SDF.value +
|
||||
'/' + FolderGenerator.MESHES.value + '/' + el.Label + '.stl')
|
||||
meshes[el.Label] = '/' + FolderGenerator.MESHES.value + \
|
||||
'/' + el.Label + '.stl'
|
||||
|
||||
case EXPORT_TYPES.DAO.value:
|
||||
importDAE.export([el], path + '/' + FolderGenerator.SDF.value +
|
||||
'/' + FolderGenerator.MESHES.value + '/' + el.Label + '.dae')
|
||||
case EXPORT_TYPES.OBJ.value:
|
||||
importOBJ.export([el], path + '/' + FolderGenerator.SDF.value +
|
||||
'/' + FolderGenerator.MESHES.value + '/' + el.Label + '.obj')
|
||||
meshes[el.Label] = '/' + FolderGenerator.MESHES.value + \
|
||||
'/' + el.Label + '.obj'
|
||||
|
||||
return meshes
|
58
freecad_workbench/usecases/geometry_usecase.py
Normal file
58
freecad_workbench/usecases/geometry_usecase.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
|
||||
import FreeCAD as App
|
||||
from helper.is_solid import is_object_solid
|
||||
|
||||
|
||||
class GeometryUseCase:
|
||||
def call() -> dict:
|
||||
labels = []
|
||||
Error = False
|
||||
for el in App.ActiveDocument.Objects:
|
||||
try:
|
||||
|
||||
if is_object_solid(el):
|
||||
labels.append(el.Label)
|
||||
|
||||
geometry = {
|
||||
"euler": {
|
||||
"x": None,
|
||||
"y": None,
|
||||
"z": None
|
||||
},
|
||||
"position": {
|
||||
"x": None,
|
||||
"y": None,
|
||||
"z": None
|
||||
},
|
||||
"rotation": {
|
||||
"x": None,
|
||||
"y": None,
|
||||
"z": None
|
||||
},
|
||||
"center": {
|
||||
"x": None,
|
||||
"y": None,
|
||||
"z": None
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
boundBox = el.Shape.BoundBox
|
||||
geometry["center"]["x"] = boundBox.Center.x
|
||||
geometry["center"]["y"] = boundBox.Center.y
|
||||
geometry["center"]["z"] = boundBox.Center.z
|
||||
geometry["position"]['x'] = boundBox.XMax
|
||||
geometry["position"]['y'] = boundBox.YMax
|
||||
geometry["position"]['z'] = boundBox.ZMax
|
||||
rotation = el.Placement.Rotation
|
||||
geometry["rotation"]['x'] = rotation.Axis.z
|
||||
geometry["rotation"]['y'] = rotation.Axis.y
|
||||
geometry["rotation"]['z'] = rotation.Axis.z
|
||||
euler = el.Placement.Rotation.toEuler()
|
||||
geometry["euler"]['x'] = euler[0]
|
||||
geometry["euler"]['y'] = euler[1]
|
||||
geometry["euler"]['z'] = euler[2]
|
||||
except Exception as e:
|
||||
print(e)
|
||||
# App.Console.PrintMessage("Clicked on position: ("+str(pos[0])+", "+str(pos[1])+")\n")
|
||||
return {"geometry": geometry, "labels": labels, "label": el.Label}
|
81
freecad_workbench/usecases/get_sdf_geometry_usecase.py
Normal file
81
freecad_workbench/usecases/get_sdf_geometry_usecase.py
Normal file
|
@ -0,0 +1,81 @@
|
|||
import FreeCAD as App
|
||||
from model.sdf_geometry_model import SdfGeometryModel
|
||||
|
||||
from helper.is_solid import is_object_solid
|
||||
|
||||
|
||||
class SdfGeometryUseCase:
|
||||
ShapePropertyCheck = ['Mass','MatrixOfInertia','Placement', ]
|
||||
PartPropertyCheck = ['Shape']
|
||||
def call(self, stlPaths:dict) -> list[SdfGeometryModel]:
|
||||
materialSolid = {}
|
||||
for el in App.ActiveDocument.Objects:
|
||||
if str(el) == '<App::MaterialObjectPython object>':
|
||||
friction = el.Material.get('SlidingFriction')
|
||||
for i in el.References:
|
||||
materialSolid[i[0].Label] = friction
|
||||
geometry = []
|
||||
try:
|
||||
for el in App.ActiveDocument.Objects:
|
||||
if is_object_solid(el):
|
||||
for prop in self.PartPropertyCheck:
|
||||
if prop in el:
|
||||
App.Console.PrintMessage(el.Label + ' ' + 'Dont exists property: ' + prop)
|
||||
return
|
||||
for prop in self.ShapePropertyCheck:
|
||||
if prop in el.Shape:
|
||||
App.Console.PrintMessage(el.Label + ' ' + 'Dont exists property: ' + prop)
|
||||
return
|
||||
# com = el.Shape.CenterOfMass or el.Shape.CenterOfGravity
|
||||
# if "Shape" in el:
|
||||
# App.Console.PrintMessage(el.Label + ' ' + 'Dont exists Shape')
|
||||
# return
|
||||
# if "Mass" in el.Shape:
|
||||
|
||||
mass = el.Shape.Mass
|
||||
inertia = el.Shape.MatrixOfInertia
|
||||
pos = el.Shape.Placement
|
||||
inertia = el.Shape.MatrixOfInertia
|
||||
name = el.Label
|
||||
ixx = str(inertia.A11 / 1000000)
|
||||
ixy = str(inertia.A12 / 1000000)
|
||||
ixz = str(inertia.A13 / 1000000)
|
||||
iyy = str(inertia.A22 / 1000000)
|
||||
iyz = str(inertia.A23 / 1000000)
|
||||
izz = str(inertia.A33 / 1000000)
|
||||
massSDF = str(mass / 1000000)
|
||||
posX = str(pos.Base[0] / 1000000)
|
||||
posY = str(pos.Base[1] / 1000000)
|
||||
posZ = str(pos.Base[2] / 1000000)
|
||||
eulerX = str(pos.Rotation.toEuler()[0])
|
||||
eulerY = str(pos.Rotation.toEuler()[1])
|
||||
eulerZ = str(pos.Rotation.toEuler()[2])
|
||||
|
||||
geometry.append(
|
||||
SdfGeometryModel(
|
||||
stl=stlPaths.get(el.Label),
|
||||
name=name,
|
||||
ixx=ixx,
|
||||
ixz=ixz,
|
||||
ixy=ixy,
|
||||
iyy=iyy,
|
||||
iyz=iyz,
|
||||
izz=izz,
|
||||
massSDF=massSDF,
|
||||
posX=posX,
|
||||
posY=posY,
|
||||
posZ=posZ,
|
||||
eulerX=eulerX,
|
||||
eulerY=eulerY,
|
||||
eulerZ=eulerZ,
|
||||
friction=materialSolid.get(el.Label) or '',
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
print(200)
|
||||
return geometry
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue