FreeCAD: Workbench Refactor

This commit is contained in:
Mark Voltov 2024-04-14 18:54:47 +00:00 committed by Igor Brylyov
parent 037827669a
commit a58dcdafb1
386 changed files with 997 additions and 64533 deletions

View 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)

View 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

View file

@ -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

View 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

View 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}

View 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