framework/geometric_feasibility_predicate/main.py

359 lines
11 KiB
Python
Raw Normal View History

import FreeCAD as App
import uuid
import os
import json
from typing import List, Dict, Any, TypeVar, Callable, Type, cast
class FreeCadRepository:
_solids = []
def getAllSolids(self):
if (self._solids.__len__() == 0):
for part in App.ActiveDocument.Objects:
if (self.is_object_solid(part)):
self._solids.append(part)
return self._solids
def is_object_solid(self, obj):
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
T = TypeVar("T")
def from_list(f: Callable[[Any], T], x: Any) -> List[T]:
assert isinstance(x, list)
return [f(y) for y in x]
def from_str(x: Any) -> str:
assert isinstance(x, str)
return x
def from_dict(f: Callable[[Any], T], x: Any) -> Dict[str, T]:
assert isinstance(x, dict)
return {k: f(v) for (k, v) in x.items()}
def to_class(c: Type[T], x: Any) -> dict:
assert isinstance(x, c)
return cast(Any, x).to_dict()
class AdjacencyMatrix:
matrixError: Dict[str,str] = {}
all_parts: List[str]
first_detail: str
matrix: Dict[str, List[str]]
def __init__(self, all_parts: List[str], first_detail: str, matrix: Dict[str, List[str]]) -> None:
self.all_parts = all_parts
self.first_detail = first_detail
self.matrix = matrix
self.validateMatrix()
def whatPlaceLeadingPartIndex(self):
i = 0
for el in self.matrix:
if el == self.first_detail:
return i
i = +1
def validateMatrix(self):
for el in self.all_parts:
if(self.matrix.get(el) == None):
self.matrixError[el] = 'Not found adjacency ' + el
@staticmethod
def from_dict(obj: Any) -> 'AdjacencyMatrix':
assert isinstance(obj, dict)
all_pars = from_list(from_str, obj.get("allPars"))
first_detail = from_str(obj.get("firstDetail"))
matrix = from_dict(lambda x: from_list(from_str, x), obj.get("matrix"))
return AdjacencyMatrix(all_pars, first_detail, matrix)
def to_dict(self) -> dict:
result: dict = {}
result["allPars"] = from_list(from_str, self.all_parts)
result["firstDetail"] = from_str(self.first_detail)
result["matrix"] = from_dict(
lambda x: from_list(from_str, x), self.matrix)
if(self.matrixError.values().__len__() == 0):
result['matrixError'] = None
else:
result['matrixError'] = self.matrixError
return result
def getDictMatrix(self) -> dict:
result = {}
for k, v in self.matrix.items():
result[k] = {}
for el in v:
result[k][el] = el
return result
def adjacency_matrix_from_dict(s: Any) -> AdjacencyMatrix:
return AdjacencyMatrix.from_dict(s)
def adjacency_matrix_to_dict(x: AdjacencyMatrix) -> Any:
return to_class(AdjacencyMatrix, x)
class FreeCadMetaModel(object):
def __init__(self, label, vertex) -> None:
self.label = label
self.vertex = vertex
collision_squares_labels = []
class MeshGeometryCoordinateModel(object):
def __init__(self, x, y, z, label,):
self.x = x
self.y = y
self.z = z
self.label = label
self.cadLabel = ''
def initializePrimitivesByCoordinate(self, detailSquares):
uuidDoc = str(uuid.uuid1())
App.ActiveDocument.addObject("Part::Box", "Box")
App.ActiveDocument.ActiveObject.Label = uuidDoc
App.ActiveDocument.recompute()
part = App.ActiveDocument.getObjectsByLabel(uuidDoc)[0]
collision_squares_labels.append(uuidDoc)
part.Width = 2
part.Height = 2
part.Length = 2
part.Placement = App.Placement(
App.Vector(self.x - 1, self.y - 1, self.z - 1),
App.Rotation(App.Vector(0.00, 0.00, 1.00), 0.00))
if (detailSquares.get(self.label) is None):
detailSquares[self.label] = []
detailSquares[self.label].append(self)
self.cadLabel = uuidDoc
App.ActiveDocument.recompute()
class FS:
def readJSON(path: str):
return json.loads((open(path)).read())
def writeFile(data, filePath, fileName):
file_to_open = filePath + fileName
f = open(file_to_open, 'w', encoding='utf8')
f.write(data)
def readFile(path: str):
return open(path).read()
def readFilesTypeFolder(pathFolder: str, fileType='.json'):
filesJson = list(
filter(lambda x: x[-fileType.__len__():] == fileType, os.listdir(pathFolder)))
return filesJson
class GetAllPartsLabelsUseCase:
def call(self):
parts = []
for part in FreeCadRepository().getAllSolids():
parts.append(part.Label)
return parts
def isUnique(array, element):
for i in array:
if i == element:
return False
return True
class GetCollisionAtPrimitiveUseCase(object):
def call(self, freeCadMetaModels, detailSquares) -> Dict[str, List[str]]:
matrix: Dict[str, List[str]] = {}
for model in freeCadMetaModels:
activePart = App.ActiveDocument.getObjectsByLabel(model.label)[0]
for key in detailSquares:
if (model.label != key):
for renderPrimitive in detailSquares[key]:
primitivePart = App.ActiveDocument.getObjectsByLabel(
renderPrimitive.cadLabel)[0]
collisionResult: int = int(
activePart.Shape.distToShape(primitivePart.Shape)[0])
if (collisionResult == 0):
if matrix.get(model.label) == None:
matrix[model.label] = [renderPrimitive.label]
else:
if isUnique(matrix[model.label], renderPrimitive.label):
matrix[model.label].append(
renderPrimitive.label
)
return matrix
class GetFirstDetailUseCase:
def call(self):
return FreeCadRepository().getAllSolids()[0].Label
class GetPartPrimitiveCoordinatesUseCase(object):
def call(self, freeCadMetaModels):
meshCoordinates: list[MeshGeometryCoordinateModel] = []
for model in freeCadMetaModels:
vertexesDetail = model.vertex
labelDetail = model.label
for coords in vertexesDetail:
detailVertex = MeshGeometryCoordinateModel(
coords.X,
coords.Y,
coords.Z,
labelDetail,
)
meshCoordinates.append(detailVertex)
return meshCoordinates
class InitPartsParseUseCase():
def call(self):
product_details = []
for part in FreeCadRepository().getAllSolids():
if part is not None:
model = FreeCadMetaModel(part.Label, part.Shape.Vertexes)
if (model is not None):
product_details.append(model)
return product_details
class RenderPrimitiveUseCase(object):
def call(self, meshModels: list[MeshGeometryCoordinateModel], detailSquares) -> None:
for mesh in meshModels:
mesh.initializePrimitivesByCoordinate(detailSquares)
class ClearWorkSpaceDocumentUseCase(object):
def call(self, detailSquares):
for key in detailSquares:
for renderPrimitive in detailSquares[key]:
primitivePart = App.ActiveDocument.getObjectsByLabel(
renderPrimitive.cadLabel)[0]
App.ActiveDocument.removeObject(primitivePart.Name)
class RenderPrimitivesScenario(object):
def __init__(
self,
initPartsParseUseCase: InitPartsParseUseCase,
getPartPrimitiveCoordinatesUseCase: GetPartPrimitiveCoordinatesUseCase,
renderPrimitiveUseCase: RenderPrimitiveUseCase,
getCollisionAtPrimitives: GetCollisionAtPrimitiveUseCase,
clearWorkSpaceDocument: ClearWorkSpaceDocumentUseCase,
) -> None:
self.initPartsParseUseCase = initPartsParseUseCase
self.getPartPrimitiveCoordinatesUseCase = getPartPrimitiveCoordinatesUseCase
self.renderPrimitiveUseCase = renderPrimitiveUseCase
self.getCollisionAtPrimitives = getCollisionAtPrimitives
self.clearWorkSpaceDocument = clearWorkSpaceDocument
def call(self) -> None:
meshCoordinates = []
detailSquares = {}
parts = self.initPartsParseUseCase.call()
meshCoordinates = self.getPartPrimitiveCoordinatesUseCase.call(parts)
self.renderPrimitiveUseCase.call(meshCoordinates, detailSquares)
matrix = self.getCollisionAtPrimitives.call(parts, detailSquares)
self.clearWorkSpaceDocument.call(detailSquares)
return matrix
class ClearWorkSpaceDocumentUseCase(object):
def call(self, detailSquares):
for key in detailSquares:
for renderPrimitive in detailSquares[key]:
primitivePart = App.ActiveDocument.getObjectsByLabel(
renderPrimitive.cadLabel)[0]
App.ActiveDocument.removeObject(primitivePart.Name)
class CadAdjacencyMatrix:
def primitiveMatrix(self):
matrix = RenderPrimitivesScenario(
InitPartsParseUseCase(),
GetPartPrimitiveCoordinatesUseCase(),
RenderPrimitiveUseCase(),
GetCollisionAtPrimitiveUseCase(),
ClearWorkSpaceDocumentUseCase(),
).call()
return AdjacencyMatrix(
all_parts=GetAllPartsLabelsUseCase().call(),
first_detail=GetFirstDetailUseCase().call(),
matrix=matrix,
)
def matrixBySurfaces(self,):
adjaxed = {}
for part in FreeCadRepository().getAllSolids():
adjaxed[part.Label] = []
for nextPart in FreeCadRepository().getAllSolids():
if part.Label != nextPart.Label:
collisionResult: int = int(
part.Shape.distToShape(nextPart.Shape)[0])
if (collisionResult == 0):
adjaxed[part.Label].append(nextPart.Label)
return AdjacencyMatrix(all_parts=GetAllPartsLabelsUseCase(
).call(), first_detail=GetFirstDetailUseCase().call(),
matrix=adjaxed
)
def main():
env = FS.readJSON('env.json')
cadFile = env['cadFilePath']
outPath = env['outPath']
if (cadFile == None):
return TypeError('CadFile not found env.json')
App.open(u'' + cadFile)
matrixOut = CadAdjacencyMatrix().primitiveMatrix().to_dict()
import json
FS.writeFile(json.dumps(matrixOut, ensure_ascii=False, indent=4), outPath,'out.json')
main()