diff --git a/sequence_generation/Init.py b/sequence_generation/Init.py new file mode 100644 index 0000000..4824d23 --- /dev/null +++ b/sequence_generation/Init.py @@ -0,0 +1,79 @@ +import FreeCAD +import FreeCADGui + +FreeCADGui.addCommand(, my_function1) +FreeCADGui.addCommand(, my_function1) +FreeCADGui.addCommand(, my_function1) +FreeCADGui.addCommand(, my_function1) +FreeCADGui.addCommand(, my_function1) +FreeCADGui.addCommand(, my_function1) +FreeCADGui.addCommand(, my_function1) +FreeCADGui.addCommand(, my_function1) +FreeCADGui.addCommand(, my_function1) + + + +class MyWorkbenchGui: + def Initialize(self): + # Словарь с именами функций и путями к иконкам + commands_dict = { + "MyCommand1": (my_function1, "Path/to/icon1.svg"), + "MyCommand2": (my_function2, "Path/to/icon2.svg") + } + + # Регистрация команд и иконок + register_commands(commands_dict) + + # Создание панели инструментов и добавление команд с иконками + self.appendToolbar("My Tools", [("MyCommand1", "MyCommand1_icon"), ("MyCommand2", "MyCommand2_icon")]) + + def appendToolbar(self, toolbar_name, commands): + toolbar = FreeCADGui.ToolBar(toolbar_name) + for cmd, icon in commands: + toolbar.appendCommand(cmd, icon) + + +class MyWorkbench: + def __init__(self): + self.__class__.Icon = FreeCAD.getHomePath() + "Path\\to\\icon.svg" + self.__class__.MenuText = "Assembly Structure Analysis" + self.__class__.ToolTip = "Workbench made for structure analysis and assembly planning" + + def GetClassName(self): + return "Gui::AsmSAWorkbench" + + def Initialize(self): + # Create toolbar + self.appendToolbar("Preprocessing", ["Check Model", "Constraints Autogeneration", "Constraints Editing"]) + self.appendToolbar("Analysis", ["Generate AdjMatrix", "Generate Relationship Matrix", "Clusterisation", "StepByStepClusterisation"]) + self.appendToolbar("AssemblySequence", ["Generate Assembly Sequences", "Decomposition Step" ]) + + # Create menu + # self.appendMenu("My Menu", ["MySubMenu1", "MySubMenu2"]) + + def Activated(self): + # Code to run when the workbench is activated + pass + + def Deactivated(self): + # Code to run when the workbench is deactivated + pass + + def GetResources(self): + return {'Pixmap': self.__class__.Icon, 'MenuText': self.__class__.MenuText, 'ToolTip': self.__class__.ToolTip} + + def appendToolbar(self, toolbar_name, commands): + toolbar = FreeCADGui.ToolBar(toolbar_name) + for cmd in commands: + toolbar.appendCommand(cmd) + + def appendMenu(self, menu_name, commands): + menu = FreeCADGui.Menu(menu_name) + for cmd in commands: + menu.appendCommand(cmd) + +# Create instance of the workbench +my_workbench = MyWorkbench() + +# Register the workbench with FreeCAD +FreeCADGui.addWorkbench(my_workbench) \ No newline at end of file diff --git a/sequence_generation/InitGui.py b/sequence_generation/InitGui.py new file mode 100644 index 0000000..d254fcb --- /dev/null +++ b/sequence_generation/InitGui.py @@ -0,0 +1,45 @@ +import FreeCAD +import FreeCADGui + +def register_commands(commands_dict): + for cmd_name, (func, icon_path) in commands_dict.items(): + FreeCADGui.addCommand(cmd_name, func) + FreeCADGui.addIcon(cmd_name + "_icon", icon_path) + +class MyWorkbenchGui: + def Initialize(self): + pass + + def InitGui(self): + # Словарь с именами функций и путями к иконкам + commands_dict = { + 'Check Model': (my_function1, "Path/to/icon1.svg"), + 'Constraints Autogeneration': (my_function2, "Path/to/icon2.svg"), + 'Constraints Editing': (my_function1, "Path/to/icon1.svg"), + 'Generate AdjMatrix': (my_function1, "Path/to/icon1.svg"), + 'Generate Relationship Matrix': (my_function1, "Path/to/icon1.svg"), + 'Clusterisation': (my_function1, "Path/to/icon1.svg"), + 'StepByStepClusterisation': (my_function1, "Path/to/icon1.svg"), + 'Generate Assembly Sequences': (my_function1, "Path/to/icon1.svg"), + 'Decomposition Step': (my_function1, "Path/to/icon1.svg") + + } + + # Регистрация команд и иконок + register_commands(commands_dict) + + # Создание панели инструментов и добавление команд с иконками + self.appendToolbar("Preprocessing", ["Check Model", "Constraints Autogeneration", "Constraints Editing"]) + self.appendToolbar("Analysis", ["Generate AdjMatrix", "Generate Relationship Matrix", "Clusterisation", "StepByStepClusterisation"]) + self.appendToolbar("AssemblySequence", ["Generate Assembly Sequences", "Decomposition Step" ]) + + def appendToolbar(self, toolbar_name, commands): + toolbar = FreeCADGui.ToolBar(toolbar_name) + for cmd, icon in commands: + toolbar.appendCommand(cmd, icon) + +# Создание экземпляра верстака GUI +my_workbench_gui = MyWorkbenchGui() + +# Регистрация верстака +FreeCADGui.addWorkbench(my_workbench_gui) diff --git a/sequence_generation/Main.py b/sequence_generation/Main.py new file mode 100644 index 0000000..bc16ef2 --- /dev/null +++ b/sequence_generation/Main.py @@ -0,0 +1,109 @@ +import os +from extensions.list import CoreList +from extensions.dict import CoreDict +from helpers.freecadtest import FreeCadASPGenerationTestController +from models.adjacency_matrix_model import ( + AdjacencyMatrixModel, +) +from usecases.check_object_has_touches_use_case import ( + CheckObjectHasTouchesUseCase, +) +from usecases.clusterisation_sequences_use_case import ( + ClusterisationSequenceUseCase, +) +from usecases.check_sequence_use_case import ( + CheckSequenceUsecase, +) +from usecases.env_reader_use_case import ( + EnvReaderUseCase, +) +from usecases.exit_freecad_use_case import ( + ExitFreeCadUseCase, +) +from usecases.intersection_geometry_use_case import ( + IntersectionGeometryUseCase, +) +from usecases.open_freecad_document_use_case import ( + OpenFreeCadDocumentUseCase, +) +import FreeCad as App +import FreeCadGUI as Gui + +from mocks.mock_structure import bottle_jack_mock_structure, simple_cube_mock_structure + + +#Функционал для реализации в main +#Отсюда тянем необходимые для работы верстака функции + +""" 'Check Model': (my_function1, "Path/to/icon1.svg"), + 'Constraints Autogeneration': (my_function2, "Path/to/icon2.svg"), + 'Constraints Editing': (my_function1, "Path/to/icon1.svg"), + 'Generate AdjMatrix': (my_function1, "Path/to/icon1.svg"), + 'Generate Relationship Matrix': (my_function1, "Path/to/icon1.svg"), + 'Clusterisation': (my_function1, "Path/to/icon1.svg"), + 'StepByStepClusterisation': (my_function1, "Path/to/icon1.svg"), + 'Generate Assembly Sequences': (my_function1, "Path/to/icon1.svg"), + 'Decomposition Step': (my_function1, "Path/to/icon1.svg")""" + + +class PreprocessorUsecase: + def initActiveDocument(): + activeDoc = App.ActiveDocument + return activeDoc + + def checkModel(activeDoc): + IntersectionGeometryUseCase.call(activeDoc, out_path) + + def constrAutoGen(): + ConstraintsAutoGeneration.call(activeDoc) + + def + + + + + + + + + +def main(): + try: + EnvReaderUseCase.call().either( + leftF=lambda environment: ( + OpenFreeCadDocumentUseCase.call(environment.cadFilePath).either( + leftF=lambda _: ( + ( + CheckObjectHasTouchesUseCase() + .call(environment.solidBodyPadding) + .either( + leftF=lambda adjaxedMatrix: ( + adjaxedMatrix.sequencesToFileSystem( + environment.outPath, + environment.sequencesFixed, + ), + IntersectionGeometryUseCase.call( + adjaxedMatrix.matrixGetUniqueContact(), + environment.outPath, + ), + adjaxedMatrix.matrixToFileSystem( + environment.outPath, + ), + ClusterisationSequenceUseCase(environment.outPath), + ExitFreeCadUseCase.call(), + ), + rightF=lambda error: error.toFileSystem( + environment.outPath + ), + ), + ) + ), + rightF=lambda error: print(error), + ), + ), + rightF=lambda error: print(error), + ) + + except Exception as error: + print(error) + ExitFreeCadUseCase.call() diff --git a/sequence_generation/launch.py b/sequence_generation/launch.py new file mode 100644 index 0000000..e69de29 diff --git a/sequence_generation/usecases/__init__.py b/sequence_generation/usecases/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sequence_generation/usecases/check_object_has_touches_use_case.py b/sequence_generation/usecases/check_object_has_touches_use_case.py new file mode 100644 index 0000000..52ef66f --- /dev/null +++ b/sequence_generation/usecases/check_object_has_touches_use_case.py @@ -0,0 +1,50 @@ +from helpers.either import Either, Left, Right +from models.adjacency_matrix_model import ( + AdjacencyMatrixModel, +) +from models.error_string_model import ErrorStringModel +from repository.freecad_repository import ( + FreeCadRepository, +) +from usecases.get_first_detail_use_case import ( + GetFirstDetailUseCase, +) + + +class CheckObjectHasTouchesUseCase: + """Check touches between objects and returns matrix + + Returns: + dict: adjacency matrix + """ + + freeCadRepository = FreeCadRepository() + + def call(self, solidBodyPadding: float) -> Either: + try: + errorResult = [] + matrix = {} + for part in self.freeCadRepository.getAllSolids(): + matrix[part.Label] = [] + touches = FreeCadRepository().objectHasTouches( + part=part, solidBodyPadding=solidBodyPadding + ) + matrix[part.Label].extend(touches) + if errorResult.__len__() == 0: + return Left( + AdjacencyMatrixModel( + all_parts=self.freeCadRepository.getAllLabelsSolids(), + first_detail=GetFirstDetailUseCase().call(), + matrix=matrix, + ) + ) + else: + return Right( + ErrorStringModel( + error="Solids bodies have no recounts: " + ",".join(errorResult) + ) + ) + except Exception as error: + print(error) + print("CheckObjectHasTouchesUseCase error") + return Right(ErrorStringModel(error="CheckObjectHasTouchesUseCase error")) diff --git a/sequence_generation/usecases/check_sequence_use_case.py b/sequence_generation/usecases/check_sequence_use_case.py new file mode 100644 index 0000000..0644864 --- /dev/null +++ b/sequence_generation/usecases/check_sequence_use_case.py @@ -0,0 +1,11 @@ +from extensions.list import CoreList + +class CheckSequenceUsecase(list): + def isCorrectByParts(self, checkList) -> bool: + parts = self[len(self) - 1] + for part in parts: + part = str(part) + part = part[1:-1] + + return CoreList(self).equal(checkList) + diff --git a/sequence_generation/usecases/clasterisationsequences_usecase.py b/sequence_generation/usecases/clasterisationsequences_usecase.py new file mode 100644 index 0000000..dfb4d19 --- /dev/null +++ b/sequence_generation/usecases/clasterisationsequences_usecase.py @@ -0,0 +1,69 @@ +import os +import json +import networkx as nx +from repository.file_system_repository import FileSystemRepository + + +class GraphProcessor: + file_path: str + graph = None + + def __init__(self, file_path: str): + self.file_path = file_path + self.graph = self.load_graph_from_json() + + def load_graph_from_json(self): + with open(self.file_path, "r") as file: + data = json.load(file) + + G = nx.Graph() + + if "matrix" in data: + matrix = data["matrix"] + for part1, neighbors in matrix.items(): + for neighbor in neighbors: + G.add_edge(part1, neighbor) + + return G + + +class EdgeBetweennessClustering: + def __init__(self, graph): + self.graph = graph.copy() + self.clusters = [] + + def cluster(self): + while self.graph.number_of_edges() > 0: + edge_betweenness = nx.edge_betweenness_centrality(self.graph) + max_betweenness_edge = max(edge_betweenness, key=edge_betweenness.get) + + # Removing the edge with the highest centrality + self.graph.remove_edge(*max_betweenness_edge) + + # Formation of clusters after edge removal + components = list(nx.connected_components(self.graph)) + if components not in self.clusters: + self.clusters.append(components) + + def get_clusters(self): + return self.clusters + + +def clusterisationSequence(file_path): + #outFolder = os.path.dirname(__file__) + "/out/" + #file_path = outFolder + 'adjacency_matrix.json' + graph_processor = GraphProcessor(file_path + "adjacency_matrix.json") + G = graph_processor.load_graph_from_json() + ebc = EdgeBetweennessClustering(G) + ebc.cluster() + clusters = ebc.get_clusters() + + + + for i in range(len(clusters)): + for j in range(len(clusters[i])): + clusters[i][j] = list(clusters[i][j]) + + #print(clusters) + FileSystemRepository.writeFile(json.dumps(clusters, ensure_ascii=False, indent=2), file_path, "assembly_sequence.json") + return clusters \ No newline at end of file diff --git a/sequence_generation/usecases/clear_work_space_document_use_case.py b/sequence_generation/usecases/clear_work_space_document_use_case.py new file mode 100644 index 0000000..22f1ec9 --- /dev/null +++ b/sequence_generation/usecases/clear_work_space_document_use_case.py @@ -0,0 +1,16 @@ +class ClearWorkSpaceDocumentUseCase(object): + """Clear of the workspace + + Args: + object : active CAD-model + """ + + def call(self, detailSquares): + import FreeCAD as App + + for key in detailSquares: + for renderPrimitive in detailSquares[key]: + primitivePart = App.ActiveDocument.getObjectsByLabel( + renderPrimitive.cadLabel + )[0] + App.ActiveDocument.removeObject(primitivePart.Name) diff --git a/sequence_generation/usecases/clusterisation_sequences_use_case.py b/sequence_generation/usecases/clusterisation_sequences_use_case.py new file mode 100644 index 0000000..4963f72 --- /dev/null +++ b/sequence_generation/usecases/clusterisation_sequences_use_case.py @@ -0,0 +1,66 @@ +import os +import json +import networkx as nx +from repository.file_system_repository import FileSystemRepository + + +class GraphProcessor: + file_path: str + graph = None + + def __init__(self, file_path: str): + self.file_path = file_path + self.graph = self.load_graph_from_json() + + def load_graph_from_json(self): + with open(self.file_path, "r") as file: + data = json.load(file) + + G = nx.Graph() + + if "matrix" in data: + matrix = data["matrix"] + for part1, neighbors in matrix.items(): + for neighbor in neighbors: + G.add_edge(part1, neighbor) + + return G + + +class EdgeBetweensClustering: + def __init__(self, graph): + self.graph = graph.copy() + self.clusters = [] + + def cluster(self): + while self.graph.number_of_edges() > 0: + edge_betweens = nx.edge_betweenness_centrality(self.graph) + max_betweens_edge = max(edge_betweens, key=edge_betweens.get) + self.graph.remove_edge(*max_betweens_edge) + components = list(nx.connected_components(self.graph)) + if components not in self.clusters: + self.clusters.append(components) + return [] + + def get_clusters(self): + return self.clusters + + +class ClusterisationSequenceUseCase: + def call(self, file_path: str): + graph_processor = GraphProcessor(file_path + "adjacency_matrix.json") + G = graph_processor.load_graph_from_json() + ebc = EdgeBetweensClustering(G) + ebc.cluster() + clusters = ebc.get_clusters() + + for i in range(len(clusters)): + for j in range(len(clusters[i])): + clusters[i][j] = list(clusters[i][j]) + + FileSystemRepository.writeFile( + json.dumps(clusters, ensure_ascii=False, indent=2), + file_path, + "assembly_sequence.json", + ) + return clusters diff --git a/sequence_generation/usecases/env_reader_use_case.py b/sequence_generation/usecases/env_reader_use_case.py new file mode 100644 index 0000000..753b884 --- /dev/null +++ b/sequence_generation/usecases/env_reader_use_case.py @@ -0,0 +1,12 @@ +from repository.file_system_repository import FileSystemRepository +from helpers.either import Either, Left, Right +from models.env_model import EnvModel + + +class EnvReaderUseCase: + def call() -> Either: + try: + return Left(EnvModel.from_dict(FileSystemRepository.readJSON("env.json"))) + except: + print("env reader error") + return Right(None) diff --git a/sequence_generation/usecases/exit_freecad_use_case.py b/sequence_generation/usecases/exit_freecad_use_case.py new file mode 100644 index 0000000..d9fdd59 --- /dev/null +++ b/sequence_generation/usecases/exit_freecad_use_case.py @@ -0,0 +1,6 @@ +from repository.freecad_repository import FreeCadRepository + + +class ExitFreeCadUseCase: + def call(): + FreeCadRepository().closeIfOpenDocument() diff --git a/sequence_generation/usecases/get_all_parts_labels_use_case.py b/sequence_generation/usecases/get_all_parts_labels_use_case.py new file mode 100644 index 0000000..3449f35 --- /dev/null +++ b/sequence_generation/usecases/get_all_parts_labels_use_case.py @@ -0,0 +1,13 @@ +from repository.freecad_repository import ( + FreeCadRepository, +) + + +class GetAllPartsLabelsUseCase: + """Get all parts label in assembly""" + + def call(self): + parts = [] + for part in FreeCadRepository().getAllSolids(): + parts.append(part.Label) + return parts diff --git a/sequence_generation/usecases/get_collision_at_primitive_use_case.py b/sequence_generation/usecases/get_collision_at_primitive_use_case.py new file mode 100644 index 0000000..99c5368 --- /dev/null +++ b/sequence_generation/usecases/get_collision_at_primitive_use_case.py @@ -0,0 +1,44 @@ +from typing import List, Dict + + +def isUnique(array, element): + for i in array: + if i == element: + return False + + return True + + +class GetCollisionAtPrimitiveUseCase(object): + """Get collisions between primitives + + Args: + object: cad-model + + Returns: + dict: collision matrix + """ + + # Получение колизий примитивов + def call(self, freeCadMetaModels, detailSquares) -> Dict[str, List[str]]: + import FreeCAD as App + + 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 diff --git a/sequence_generation/usecases/get_first_detail_use_case.py b/sequence_generation/usecases/get_first_detail_use_case.py new file mode 100644 index 0000000..ea7242a --- /dev/null +++ b/sequence_generation/usecases/get_first_detail_use_case.py @@ -0,0 +1,8 @@ +from repository.freecad_repository import FreeCadRepository + + +class GetFirstDetailUseCase: + """Get label of first part in tree assembly""" + + def call(self): + return FreeCadRepository().getAllSolids()[0].Label diff --git a/sequence_generation/usecases/get_part_primitive_coordinates_use_case.py b/sequence_generation/usecases/get_part_primitive_coordinates_use_case.py new file mode 100644 index 0000000..6995047 --- /dev/null +++ b/sequence_generation/usecases/get_part_primitive_coordinates_use_case.py @@ -0,0 +1,27 @@ +from models.mesh_geometry_coordinate_model import ( + MeshGeometryCoordinateModel, +) + + +class GetPartPrimitiveCoordinatesUseCase(object): + """Get positions of parts in assembly + + Args: + object : cad-model + """ + + 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 diff --git a/sequence_generation/usecases/init_parts_parse_use_case.py b/sequence_generation/usecases/init_parts_parse_use_case.py new file mode 100644 index 0000000..11faa4f --- /dev/null +++ b/sequence_generation/usecases/init_parts_parse_use_case.py @@ -0,0 +1,17 @@ +from models.freecad_meta_model import FreeCadMetaModel +from repository.freecad_repository import ( + FreeCadRepository, +) + + +class InitPartsParseUseCase: + """Initialisation of parsing geometry models info""" + + 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 diff --git a/sequence_generation/usecases/intersection_computed_use_case.py b/sequence_generation/usecases/intersection_computed_use_case.py new file mode 100644 index 0000000..e2cf148 --- /dev/null +++ b/sequence_generation/usecases/intersection_computed_use_case.py @@ -0,0 +1,20 @@ +class IntersectionComputedUseCase: + def call(parts): + import FreeCAD as App + + App.activeDocument().addObject("Part::MultiCommon", "Common") + App.activeDocument().Common.Shapes = [parts[0], parts[1]] + App.activeDocument().getObject("Common").ViewObject.ShapeColor = getattr( + parts[0].getLinkedObject(True).ViewObject, + "ShapeColor", + App.activeDocument().getObject("Common").ViewObject.ShapeColor, + ) + App.activeDocument().getObject("Common").ViewObject.DisplayMode = getattr( + parts[0].getLinkedObject(True).ViewObject, + "DisplayMode", + App.activeDocument().getObject("Common").ViewObject.DisplayMode, + ) + App.ActiveDocument.recompute() + area = App.activeDocument().getObject("Common").Shape.Area + App.ActiveDocument.removeObject("Common") + return area diff --git a/sequence_generation/usecases/intersection_geometry_use_case.py b/sequence_generation/usecases/intersection_geometry_use_case.py new file mode 100644 index 0000000..56e1da8 --- /dev/null +++ b/sequence_generation/usecases/intersection_geometry_use_case.py @@ -0,0 +1,31 @@ +from repository.file_system_repository import FileSystemRepository +from usecases.intersection_computed_use_case import ( + IntersectionComputedUseCase, +) + +import json + + +class IntersectionGeometryUseCase: + """A class that checks bodies in an assembly for interference and returns the result of the check to a file""" + + def call(contacts, path): + import FreeCAD as App + + intersection_geometry = {"status": True, "recalculations": None} + for el in contacts: + child = App.ActiveDocument.getObjectsByLabel(el.get("child"))[0] + parent = App.ActiveDocument.getObjectsByLabel(el.get("parent"))[0] + area = IntersectionComputedUseCase.call([child, parent]) + if area != 0.0: + if intersection_geometry.get("recalculations") == None: + intersection_geometry["status"] = False + intersection_geometry["recalculations"] = [] + intersection_geometry["recalculations"].append( + {"area": area, "connect": el.get("child") + " " + el.get("parent")} + ) + FileSystemRepository.writeFile( + json.dumps(intersection_geometry, ensure_ascii=False, indent=4), + path, + "intersection_geometry.json", + ) diff --git a/sequence_generation/usecases/is_all_object_solids_check_use_case.py b/sequence_generation/usecases/is_all_object_solids_check_use_case.py new file mode 100644 index 0000000..107f41b --- /dev/null +++ b/sequence_generation/usecases/is_all_object_solids_check_use_case.py @@ -0,0 +1,14 @@ +from helpers.either import Either, Left, Right +from models.error_string_model import ErrorStringModel +from repository import freecad_repository + + +class IsAllObjectSolidsCheckUseCase: + def call() -> Either: + result = freecad_repository().isAllObjectsSolids() + if result.__len__() == 0: + return Left(None) + + return Right( + ErrorStringModel(error="Is not solid objects: " + ",".join(result)) + ) diff --git a/sequence_generation/usecases/open_freecad_document_use_case.py b/sequence_generation/usecases/open_freecad_document_use_case.py new file mode 100644 index 0000000..d426d6f --- /dev/null +++ b/sequence_generation/usecases/open_freecad_document_use_case.py @@ -0,0 +1,18 @@ +from helpers.either import Either, Left, Right +from repository.freecad_repository import ( + FreeCadRepository, +) + + +class OpenFreeCadDocumentUseCase: + """A class that checks open documents, closes them and opens the one with which the program will work""" + + def call(path: str) -> Either: + try: + FreeCadRepository().closeIfOpenDocument() + FreeCadRepository().openDocument(path) + return Left(None) + except Exception as e: + print(e) + print("OpenFreeCadDocumentUseCase error") + return Right(None) diff --git a/sequence_generation/usecases/read_file_system_and_get_instance_model_use_case.py b/sequence_generation/usecases/read_file_system_and_get_instance_model_use_case.py new file mode 100644 index 0000000..52e411c --- /dev/null +++ b/sequence_generation/usecases/read_file_system_and_get_instance_model_use_case.py @@ -0,0 +1,21 @@ +from repository.file_system_repository import FileSystemRepository +from helpers.either import Left, Right, Either + + +class ReadFileSystemAndGetInstanceModelUseCase: + def call(self, model, path) -> Either: + if hasattr(model, "from_dict") is False: + return Right( + "ReadFileSystemAndGetInstanceModelUseCase error:" + + model + + "is not have method" + + "from_dict()" + ) + try: + return Left(model.from_dict(FileSystemRepository.readJSON(path))) + except Exception as e: + print(e) + error = str(model) + " " + "from dict error " + "path: " + path + print("ReadFileSystemAndGetInstanceModelUseCase error" + error) + return Right(error) + pass diff --git a/sequence_generation/usecases/render_primitive_use_case.py b/sequence_generation/usecases/render_primitive_use_case.py new file mode 100644 index 0000000..57b5927 --- /dev/null +++ b/sequence_generation/usecases/render_primitive_use_case.py @@ -0,0 +1,15 @@ +from models.mesh_geometry_coordinate_model import MeshGeometryCoordinateModel + + +class RenderPrimitiveUseCase(object): + """Rendering primitives + + Args: + object: CAD-model + """ + + def call( + self, meshModels: list[MeshGeometryCoordinateModel], detailSquares + ) -> None: + for mesh in meshModels: + mesh.initializePrimitivesByCoordinate(detailSquares) diff --git a/sequence_generation/usecases/render_primitives_scenario.py b/sequence_generation/usecases/render_primitives_scenario.py new file mode 100644 index 0000000..9d8283f --- /dev/null +++ b/sequence_generation/usecases/render_primitives_scenario.py @@ -0,0 +1,41 @@ +from usecases.clear_work_space_document_use_case import ( + ClearWorkSpaceDocumentUseCase, +) +from geometric_feasibility_predicate.usecases.get_collision_at_primitive_use_case import ( + GetCollisionAtPrimitiveUseCase, +) +from usecases.get_part_primitive_coordinates_use_case import ( + GetPartPrimitiveCoordinatesUseCase, +) +from usecases.init_parts_parse_use_case import ( + InitPartsParseUseCase, +) +from usecases.render_primitive_use_case import ( + RenderPrimitiveUseCase, +) + + +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