diff --git a/freecad_workbench/freecad/robossembler/clusterisation_sequences.py b/freecad_workbench/freecad/robossembler/clusterisation_sequences.py new file mode 100644 index 0000000..77fa5f3 --- /dev/null +++ b/freecad_workbench/freecad/robossembler/clusterisation_sequences.py @@ -0,0 +1,82 @@ +import networkx as nx + + +class GraphProcessor: + graph = None + + def __init__(self, adjacency_matrix): + self.adjacency_matrix = adjacency_matrix + self.graph = self.load_graph_from_data() + + def load_graph_from_data(self): + G = nx.Graph() + + for part1, neighbors in self.adjacency_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, adjacency_matrix): + graph_processor = GraphProcessor(adjacency_matrix) + G = graph_processor.load_graph_from_data() + 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]) + + # Создание списка последовательностей сборки + assembly_sequences = [] + for cluster in clusters: + sequence = [] + for component in cluster: + sequence.extend(component) + assembly_sequences.append(sequence) + + return assembly_sequences + + +# # Вызов функции +# adjacency_matrix = { +# 'body_down': ['sol_gear', 'planet_gear', 'planet_gear003', 'planet_gear004', 'planet_gear005', 'planet_gear002', 'body_up', 'bolt', 'bolt2', 'bolt3', 'bolt4'], +# 'sol_gear': ['body_down', 'output_shaft', 'planet_gear', 'planet_gear003', 'planet_gear004', 'planet_gear005', 'planet_gear002'], +# 'output_shaft': ['sol_gear', 'planet_gear', 'planet_gear003', 'planet_gear004', 'planet_gear005', 'planet_gear002', 'body_up'], +# 'planet_gear': ['body_down', 'sol_gear', 'output_shaft'], +# 'planet_gear003': ['body_down', 'sol_gear', 'output_shaft'], +# 'planet_gear004': ['body_down', 'sol_gear', 'output_shaft'], +# 'planet_gear005': ['body_down', 'sol_gear', 'output_shaft'], +# 'planet_gear002': ['body_down', 'sol_gear', 'output_shaft'], +# 'body_up': ['body_down', 'output_shaft', 'bolt', 'bolt2', 'bolt3', 'bolt4'], +# 'bolt': ['body_down', 'body_up'], +# 'bolt2': ['body_down', 'body_up'], +# 'bolt3': ['body_down', 'body_up'], +# 'bolt4': ['body_down', 'body_up'] +# } +# print(adjacency_matrix) +# use_case = ClusterisationSequenceUseCase() +# assembly_sequences = use_case.call(adjacency_matrix) +# print(assembly_sequences) diff --git a/freecad_workbench/freecad/robossembler/solve_optimizer.py b/freecad_workbench/freecad/robossembler/solve_optimizer.py index c7a3449..41d5807 100644 --- a/freecad_workbench/freecad/robossembler/solve_optimizer.py +++ b/freecad_workbench/freecad/robossembler/solve_optimizer.py @@ -7,6 +7,7 @@ import json import FreeCAD as App from geometric_feasibility_predicate.main import main as asm_analysis from constraints_operator import collect_assembly_settings +from clusterisation_sequences import ClusterisationSequenceUseCase # === Для работы с json-файлами. Работает. === @@ -94,42 +95,80 @@ def simplify_adjacency_matrix(assembly_settings, adjacency_matrix): } for part in adjacency_matrix["allParts"]: - if part not in fasteners: - simplified_matrix["allParts"].append(part) - neighbors = [ - neighbor for neighbor in adjacency_matrix["matrix"].get(part, []) - if neighbor not in fasteners - ] - if neighbors or part not in fasteners: - simplified_matrix["matrix"][part] = neighbors + # Добавляем все детали, включая крепеж, в simplified_matrix["allParts"] + simplified_matrix["allParts"].append(part) + + # Получаем соседей, исключая только крепежные элементы + neighbors = [ + neighbor for neighbor in adjacency_matrix["matrix"].get(part, []) + if neighbor not in fasteners + ] + + # Если у части есть соседи, добавляем их в матрицу + if neighbors: + simplified_matrix["matrix"][part] = neighbors return simplified_matrix -def restore_full_sequence(assembly_settings, sequence): - full_sequence = [] - sequence_set = set(sequence) - for item in sequence: - full_sequence.append(item) +def restore_full_sequence(assembly_settings, sequences): + full_sequences = [] + + for sequence in sequences: + full_sequence = [] + sequence_set = set(sequence) + + # Сначала добавляем все детали в полную последовательность + for item in sequence: + full_sequence.append(item) + + # Теперь добавляем крепежные элементы после элемента с наибольшим порядковым номером for setting in assembly_settings: if setting.get("Type") == "fastener_set": parent = setting["Parent"] child = setting["Child"] - if parent in sequence_set and child in sequence_set: - full_sequence.append(setting["Fasteners"]) + fasteners = setting["Fasteners"] + + # Проверяем, если родитель и ребенок в последовательности + if (parent in sequence_set) and (child in sequence_set): + # Находим индексы родителя и ребенка в полной последовательности + parent_index = full_sequence.index(parent) + child_index = full_sequence.index(child) + + # Находим максимальный индекс между родителем и ребенком + max_index = max(parent_index, child_index) + + # Проверяем, содержатся ли крепежные элементы уже в последовательности + if not any(fastener in full_sequence for fastener in fasteners): + # Добавляем крепежные элементы после элемента child + full_sequence[max_index + 1:max_index + 1] = fasteners + + full_sequences.append(full_sequence) + + return full_sequences + + + + - return full_sequence def main(): - + App.open('/home/markvoltov/GitProjects/framework/test_models/test_reductor.FCStd') if App.ActiveDocument: intersection_geometry, sequences, topologyMatrix = asm_analysis() - print(sequences) - assembly_settings = collect_assembly_settings() + + assembly_settings = collect_assembly_settings() + print(assembly_settings) simplified_matrix = simplify_adjacency_matrix(assembly_settings, topologyMatrix) - + + assembly_sequences = ClusterisationSequenceUseCase().call(topologyMatrix['matrix']) + # print('Последовательности 1', assembly_sequences) + assembly_sequences_simplified= ClusterisationSequenceUseCase().call(simplified_matrix['matrix']) + # print('Последовательности 2',assembly_sequences_simplified) + assembly_sequences_restored = restore_full_sequence(assembly_settings, assembly_sequences_simplified) + print('Последовательности 3',assembly_sequences_restored) else: print('Ошибка. Нет активного документа!') diff --git a/test_models/test_reductor.FCStd b/test_models/test_reductor.FCStd index 62c6450..20a8698 100644 Binary files a/test_models/test_reductor.FCStd and b/test_models/test_reductor.FCStd differ