Слияние веток 91 и path2pddl
This commit is contained in:
parent
44ee21414b
commit
e86914dba1
24 changed files with 732 additions and 0 deletions
79
sequence_generation/Init.py
Normal file
79
sequence_generation/Init.py
Normal file
|
@ -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)
|
45
sequence_generation/InitGui.py
Normal file
45
sequence_generation/InitGui.py
Normal file
|
@ -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)
|
109
sequence_generation/Main.py
Normal file
109
sequence_generation/Main.py
Normal file
|
@ -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()
|
0
sequence_generation/launch.py
Normal file
0
sequence_generation/launch.py
Normal file
0
sequence_generation/usecases/__init__.py
Normal file
0
sequence_generation/usecases/__init__.py
Normal file
|
@ -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"))
|
11
sequence_generation/usecases/check_sequence_use_case.py
Normal file
11
sequence_generation/usecases/check_sequence_use_case.py
Normal file
|
@ -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)
|
||||
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
12
sequence_generation/usecases/env_reader_use_case.py
Normal file
12
sequence_generation/usecases/env_reader_use_case.py
Normal file
|
@ -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)
|
6
sequence_generation/usecases/exit_freecad_use_case.py
Normal file
6
sequence_generation/usecases/exit_freecad_use_case.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from repository.freecad_repository import FreeCadRepository
|
||||
|
||||
|
||||
class ExitFreeCadUseCase:
|
||||
def call():
|
||||
FreeCadRepository().closeIfOpenDocument()
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
17
sequence_generation/usecases/init_parts_parse_use_case.py
Normal file
17
sequence_generation/usecases/init_parts_parse_use_case.py
Normal file
|
@ -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
|
|
@ -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
|
|
@ -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",
|
||||
)
|
|
@ -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))
|
||||
)
|
|
@ -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)
|
|
@ -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
|
15
sequence_generation/usecases/render_primitive_use_case.py
Normal file
15
sequence_generation/usecases/render_primitive_use_case.py
Normal file
|
@ -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)
|
41
sequence_generation/usecases/render_primitives_scenario.py
Normal file
41
sequence_generation/usecases/render_primitives_scenario.py
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue