From dde3bde235560e43f3ed90922c358433d226325d Mon Sep 17 00:00:00 2001 From: IDONTSUDO Date: Wed, 21 Jun 2023 14:45:09 +0300 Subject: [PATCH] adding cad adjaxed matrix predicate --- geometric_feasibility_predicate/README.MD | 1 + geometric_feasibility_predicate/env.json | 4 + geometric_feasibility_predicate/main.py | 358 ++++++++++++++++++++++ 3 files changed, 363 insertions(+) create mode 100644 geometric_feasibility_predicate/README.MD create mode 100644 geometric_feasibility_predicate/env.json create mode 100644 geometric_feasibility_predicate/main.py diff --git a/geometric_feasibility_predicate/README.MD b/geometric_feasibility_predicate/README.MD new file mode 100644 index 0000000..7185164 --- /dev/null +++ b/geometric_feasibility_predicate/README.MD @@ -0,0 +1 @@ +freecadcmd main.py \ No newline at end of file diff --git a/geometric_feasibility_predicate/env.json b/geometric_feasibility_predicate/env.json new file mode 100644 index 0000000..2375211 --- /dev/null +++ b/geometric_feasibility_predicate/env.json @@ -0,0 +1,4 @@ +{ + "cadFilePath":"", + "outPath":"" +} \ No newline at end of file diff --git a/geometric_feasibility_predicate/main.py b/geometric_feasibility_predicate/main.py new file mode 100644 index 0000000..8623d7c --- /dev/null +++ b/geometric_feasibility_predicate/main.py @@ -0,0 +1,358 @@ +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()