2023-07-04 07:19:55 +00:00
|
|
|
|
import FreeCAD as App
|
|
|
|
|
import uuid
|
|
|
|
|
import os
|
|
|
|
|
import json
|
|
|
|
|
from typing import List, Dict, Any, TypeVar, Callable, Type, cast
|
2023-07-13 19:55:18 +00:00
|
|
|
|
from itertools import repeat
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def isInListRange(listIn, index):
|
|
|
|
|
try:
|
|
|
|
|
listIn[index]
|
|
|
|
|
return False
|
|
|
|
|
except:
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AllSequences:
|
|
|
|
|
all_sequences = None
|
|
|
|
|
adj_matrix = None
|
|
|
|
|
topologyIds = None
|
|
|
|
|
adj_matrix_names = None
|
|
|
|
|
|
|
|
|
|
def __init__(self, adj_matrix) -> None:
|
|
|
|
|
self.adj_matrix = adj_matrix
|
|
|
|
|
self.all_possible_sequences(self.adj_matrix)
|
|
|
|
|
self.matrix_by_name()
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def matrix_by_name(self):
|
|
|
|
|
result = self.all_sequences
|
|
|
|
|
inc = 0
|
|
|
|
|
for matrix in self.all_sequences:
|
|
|
|
|
for index in range(len(matrix)):
|
|
|
|
|
result[inc][index] = list(filter(lambda el: el.get(
|
|
|
|
|
'number') == matrix[index]+1, self.topologyIds))[0].get('name')
|
|
|
|
|
inc += 1
|
|
|
|
|
self.adj_matrix_names = result
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def find_all_sequences(self, adj_matrix):
|
|
|
|
|
sequences = []
|
|
|
|
|
num_vertices = len(adj_matrix)
|
|
|
|
|
|
|
|
|
|
def dfs(vertex, sequence):
|
|
|
|
|
sequence.append(vertex)
|
|
|
|
|
|
|
|
|
|
if len(sequence) == num_vertices:
|
|
|
|
|
sequences.append(sequence)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
for i in range(num_vertices):
|
|
|
|
|
if adj_matrix[vertex][i] == 1 and i not in sequence:
|
|
|
|
|
dfs(i, sequence.copy())
|
|
|
|
|
|
|
|
|
|
for i in range(num_vertices):
|
|
|
|
|
dfs(i, [])
|
|
|
|
|
|
|
|
|
|
self.all_sequences = sequences
|
|
|
|
|
|
|
|
|
|
def findId(self, listMatrix, id):
|
|
|
|
|
def filter_odd_num(in_num):
|
|
|
|
|
if in_num['name'] == id:
|
|
|
|
|
return True
|
|
|
|
|
else:
|
|
|
|
|
return False
|
|
|
|
|
return list(filter(filter_odd_num, listMatrix))[0]['number']
|
|
|
|
|
|
|
|
|
|
def iter_paths(self, adj, min_length=6, path=None):
|
|
|
|
|
if not path:
|
|
|
|
|
for start_node in range(len(adj)):
|
|
|
|
|
yield from self.iter_paths(adj, min_length, [start_node])
|
|
|
|
|
else:
|
|
|
|
|
if len(path) >= min_length:
|
|
|
|
|
yield path
|
|
|
|
|
if path[-1] in path[:-1]:
|
|
|
|
|
return
|
|
|
|
|
current_node = path[-1]
|
|
|
|
|
for next_node in range(len(adj[current_node])):
|
|
|
|
|
if adj[current_node][next_node] == 1:
|
|
|
|
|
yield from self.iter_paths(adj, min_length, path + [next_node])
|
|
|
|
|
|
|
|
|
|
def allUnique(self, x):
|
|
|
|
|
seen = set()
|
|
|
|
|
return not any(i in seen or seen.add(i) for i in x)
|
|
|
|
|
|
|
|
|
|
def all_possible_sequences(self, matrix):
|
|
|
|
|
topologyIds = []
|
|
|
|
|
topologyMatrixNumber = {}
|
|
|
|
|
inc = 0
|
|
|
|
|
for k, v in matrix.items():
|
|
|
|
|
inc += 1
|
|
|
|
|
topologyIds.append({"name": k, "number": inc})
|
|
|
|
|
inc = 0
|
|
|
|
|
for k, v in matrix.items():
|
|
|
|
|
inc += 1
|
|
|
|
|
topologyMatrixNumber[inc] = list(
|
|
|
|
|
map(lambda el: self.findId(topologyIds, el), v))
|
|
|
|
|
self.topologyIds = topologyIds
|
|
|
|
|
adj = []
|
|
|
|
|
matrixSize = matrix.keys().__len__()
|
|
|
|
|
inc = 0
|
|
|
|
|
for k, v in topologyMatrixNumber.items():
|
|
|
|
|
adj.append(list(repeat(0, matrixSize)))
|
|
|
|
|
for el in v:
|
|
|
|
|
adj[inc][el-1] = 1
|
|
|
|
|
inc += 1
|
|
|
|
|
return self.find_all_sequences(adj)
|
|
|
|
|
|
2023-07-04 07:19:55 +00:00
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
|
2023-07-05 14:14:36 +00:00
|
|
|
|
# Вспомогательный класс который делает генрацию JSON на основе пайтон обьектов
|
2023-07-13 19:55:18 +00:00
|
|
|
|
|
|
|
|
|
|
2023-07-04 07:19:55 +00:00
|
|
|
|
class AdjacencyMatrix:
|
2023-07-13 19:55:18 +00:00
|
|
|
|
matrixError: Dict[str, str] = {}
|
2023-07-04 07:19:55 +00:00
|
|
|
|
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
|
2023-07-13 19:55:18 +00:00
|
|
|
|
|
2023-07-04 07:19:55 +00:00
|
|
|
|
def validateMatrix(self):
|
|
|
|
|
for el in self.all_parts:
|
2023-07-13 19:55:18 +00:00
|
|
|
|
if (self.matrix.get(el) == None):
|
2023-07-04 07:19:55 +00:00
|
|
|
|
self.matrixError[el] = 'Not found adjacency ' + el
|
2023-07-13 19:55:18 +00:00
|
|
|
|
|
2023-07-04 07:19:55 +00:00
|
|
|
|
@staticmethod
|
|
|
|
|
def from_dict(obj: Any) -> 'AdjacencyMatrix':
|
|
|
|
|
assert isinstance(obj, dict)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
all_pars = from_list(from_str, obj.get("allParts"))
|
2023-07-04 07:19:55 +00:00
|
|
|
|
first_detail = from_str(obj.get("firstDetail"))
|
|
|
|
|
matrix = from_dict(lambda x: from_list(from_str, x), obj.get("matrix"))
|
2023-07-13 19:55:18 +00:00
|
|
|
|
|
2023-07-04 07:19:55 +00:00
|
|
|
|
return AdjacencyMatrix(all_pars, first_detail, matrix)
|
|
|
|
|
|
|
|
|
|
def to_dict(self) -> dict:
|
|
|
|
|
result: dict = {}
|
2023-09-12 19:09:33 +00:00
|
|
|
|
result["allParts"] = from_list(from_str, self.all_parts)
|
2023-07-04 07:19:55 +00:00
|
|
|
|
result["firstDetail"] = from_str(self.first_detail)
|
|
|
|
|
result["matrix"] = from_dict(
|
|
|
|
|
lambda x: from_list(from_str, x), self.matrix)
|
2023-07-13 19:55:18 +00:00
|
|
|
|
if (self.matrixError.values().__len__() == 0):
|
2023-07-04 07:19:55 +00:00
|
|
|
|
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)
|
|
|
|
|
|
2023-07-13 19:55:18 +00:00
|
|
|
|
# Вспомогательный класс для работы с Freecad
|
|
|
|
|
|
|
|
|
|
|
2023-07-04 07:19:55 +00:00
|
|
|
|
class FreeCadMetaModel(object):
|
|
|
|
|
|
|
|
|
|
def __init__(self, label, vertex) -> None:
|
|
|
|
|
self.label = label
|
|
|
|
|
self.vertex = vertex
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
collision_squares_labels = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MeshGeometryCoordinateModel(object):
|
2023-07-05 13:33:45 +00:00
|
|
|
|
# Получение геометрии мешей
|
2023-07-04 07:19:55 +00:00
|
|
|
|
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:
|
2023-07-05 13:33:45 +00:00
|
|
|
|
# Получение всех названий деталей
|
2023-07-04 07:19:55 +00:00
|
|
|
|
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):
|
2023-07-05 13:33:45 +00:00
|
|
|
|
# Получение колизий примитивов
|
2023-07-04 07:19:55 +00:00
|
|
|
|
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:
|
2023-07-05 13:33:45 +00:00
|
|
|
|
# Получение первой детали
|
2023-07-04 07:19:55 +00:00
|
|
|
|
def call(self):
|
|
|
|
|
return FreeCadRepository().getAllSolids()[0].Label
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GetPartPrimitiveCoordinatesUseCase(object):
|
2023-07-05 13:33:45 +00:00
|
|
|
|
# Получение координат примитивов
|
2023-07-04 07:19:55 +00:00
|
|
|
|
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():
|
2023-07-05 16:03:51 +03:00
|
|
|
|
# Инициализация парсинга
|
2023-07-04 07:19:55 +00:00
|
|
|
|
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):
|
2023-07-05 16:03:51 +03:00
|
|
|
|
# Рендеринг премитивов
|
2023-07-04 07:19:55 +00:00
|
|
|
|
def call(self, meshModels: list[MeshGeometryCoordinateModel], detailSquares) -> None:
|
|
|
|
|
for mesh in meshModels:
|
|
|
|
|
mesh.initializePrimitivesByCoordinate(detailSquares)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ClearWorkSpaceDocumentUseCase(object):
|
2023-07-05 16:03:51 +03:00
|
|
|
|
# Очистка рабочего простарнства
|
2023-07-04 07:19:55 +00:00
|
|
|
|
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):
|
2023-07-05 13:33:45 +00:00
|
|
|
|
# Очистака рабочего пространства
|
2023-07-04 07:19:55 +00:00
|
|
|
|
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:
|
2023-07-05 16:03:51 +03:00
|
|
|
|
# Матрица основанная на соприкосновении примитива с обьектами
|
2023-07-04 07:19:55 +00:00
|
|
|
|
def primitiveMatrix(self):
|
2023-07-05 16:03:51 +03:00
|
|
|
|
# Получение матрицы
|
2023-07-04 07:19:55 +00:00
|
|
|
|
matrix = RenderPrimitivesScenario(
|
|
|
|
|
InitPartsParseUseCase(),
|
|
|
|
|
GetPartPrimitiveCoordinatesUseCase(),
|
|
|
|
|
RenderPrimitiveUseCase(),
|
|
|
|
|
GetCollisionAtPrimitiveUseCase(),
|
|
|
|
|
ClearWorkSpaceDocumentUseCase(),
|
|
|
|
|
).call()
|
|
|
|
|
return AdjacencyMatrix(
|
|
|
|
|
all_parts=GetAllPartsLabelsUseCase().call(),
|
|
|
|
|
first_detail=GetFirstDetailUseCase().call(),
|
|
|
|
|
matrix=matrix,
|
|
|
|
|
)
|
2023-07-13 19:55:18 +00:00
|
|
|
|
# Матрица основанная на соприкосновении обьектов
|
|
|
|
|
|
2023-07-05 16:03:51 +03:00
|
|
|
|
def matrixBySurfaces(self):
|
|
|
|
|
matrix = {}
|
2023-07-04 07:19:55 +00:00
|
|
|
|
for part in FreeCadRepository().getAllSolids():
|
2023-07-05 16:03:51 +03:00
|
|
|
|
matrix[part.Label] = []
|
2023-07-04 07:19:55 +00:00
|
|
|
|
for nextPart in FreeCadRepository().getAllSolids():
|
|
|
|
|
if part.Label != nextPart.Label:
|
2023-07-05 16:03:51 +03:00
|
|
|
|
# Вычисление соприконсоновения площади деталей
|
2023-07-04 07:19:55 +00:00
|
|
|
|
collisionResult: int = int(
|
|
|
|
|
part.Shape.distToShape(nextPart.Shape)[0])
|
|
|
|
|
if (collisionResult == 0):
|
2023-07-05 16:03:51 +03:00
|
|
|
|
matrix[part.Label].append(nextPart.Label)
|
2023-07-04 07:19:55 +00:00
|
|
|
|
return AdjacencyMatrix(all_parts=GetAllPartsLabelsUseCase(
|
|
|
|
|
).call(), first_detail=GetFirstDetailUseCase().call(),
|
2023-07-05 16:03:51 +03:00
|
|
|
|
matrix=matrix
|
2023-07-04 07:19:55 +00:00
|
|
|
|
)
|
|
|
|
|
|
2023-07-13 19:55:18 +00:00
|
|
|
|
|
2023-09-12 19:09:33 +00:00
|
|
|
|
def reduce(function, iterable, initializer=None):
|
|
|
|
|
it = iter(iterable)
|
|
|
|
|
if initializer is None:
|
|
|
|
|
value = next(it)
|
|
|
|
|
else:
|
|
|
|
|
value = initializer
|
|
|
|
|
for element in it:
|
|
|
|
|
value = function(value, element)
|
|
|
|
|
return value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def to_ascii_hash(text):
|
|
|
|
|
ascii_values = [ord(character) for character in text]
|
|
|
|
|
return reduce(lambda x, y: x + y, ascii_values)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def matrixGetUniqueContact(matrix):
|
|
|
|
|
|
|
|
|
|
detailsToCheck = []
|
|
|
|
|
detailsHashCheck = {}
|
|
|
|
|
for k, v in matrix.items():
|
|
|
|
|
for el in v:
|
|
|
|
|
if (el != k):
|
|
|
|
|
hash = to_ascii_hash(k + el)
|
|
|
|
|
if (detailsHashCheck.get(hash) == None):
|
|
|
|
|
detailsHashCheck[hash] = hash
|
|
|
|
|
detailsToCheck.append({
|
|
|
|
|
'child': el,
|
|
|
|
|
'parent': k
|
|
|
|
|
})
|
|
|
|
|
return detailsToCheck
|
|
|
|
|
|
|
|
|
|
def intersectionComputed(parts):
|
|
|
|
|
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
|
|
|
|
|
|
2023-07-04 07:19:55 +00:00
|
|
|
|
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)
|
2023-07-13 19:55:18 +00:00
|
|
|
|
|
2023-09-12 19:09:33 +00:00
|
|
|
|
topologyMatrix = CadAdjacencyMatrix().matrixBySurfaces()
|
2023-07-04 07:19:55 +00:00
|
|
|
|
import json
|
2023-07-13 19:55:18 +00:00
|
|
|
|
sequences = json.dumps({"sequences": AllSequences(
|
|
|
|
|
topologyMatrix.matrix).adj_matrix_names}, ensure_ascii=False, indent=4)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
matrix = topologyMatrix.matrix
|
|
|
|
|
contacts = matrixGetUniqueContact(matrix)
|
|
|
|
|
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 = intersectionComputed([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')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FS.writeFile(json.dumps(intersection_geometry, ensure_ascii=False, indent=4), outPath, 'intersection_geometry.json')
|
2023-07-13 19:55:18 +00:00
|
|
|
|
FS.writeFile(sequences, outPath, 'sequences.json')
|
|
|
|
|
FS.writeFile(json.dumps(topologyMatrix.to_dict(),
|
|
|
|
|
ensure_ascii=False, indent=4), outPath, 'adjacency_matrix.json')
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
2023-07-04 07:19:55 +00:00
|
|
|
|
main()
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|