API with assembly options and constraints; DFS Liaison/Adjacency matrix generation fix; add unit-tests

This commit is contained in:
IDONTSUDO 2024-01-18 10:44:59 +00:00 committed by Igor Brylyov
parent c64bbf4a70
commit d2ab856d64
8 changed files with 693 additions and 148 deletions

View file

@ -1,5 +1,8 @@
{
"cadFilePath": "/Users/idontsudo/Desktop/asp-example/disk_and_axis_n.FCStd",
"outPath": "/Users/idontsudo/Desktop/asp-example/",
"objectIndentation": 0
"cadFilePath": "/Users/idontsudo/Desktop/reductor/test_reductor.FCStd",
"outPath": "/Users/idontsudo/Desktop/reductor/",
"solidBodyPadding": 1,
"firstDetail": "Куб",
"sequencesFixed": [],
"restrictionsOnFasteners": []
}

View file

@ -4,16 +4,255 @@ import os
import json
from typing import List, Dict, Any, TypeVar, Callable, Type, cast
from itertools import repeat
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Any, TypeVar, Type, cast
T = TypeVar("T")
class BackgroundConsoleColors:
HEADER = "\033[95m"
OKBLUE = "\033[94m"
OKCYAN = "\033[96m"
OKGREEN = "\033[92m"
WARNING = "\033[93m"
FAIL = "\033[91m"
ENDC = "\033[0m"
BOLD = "\033[1m"
UNDERLINE = "\033[4m"
def from_float(x: Any) -> float:
assert isinstance(x, (float, int)) and not isinstance(x, bool)
return float(x)
def to_float(x: Any) -> float:
assert isinstance(x, float)
return x
def from_str(x: Any) -> str:
assert isinstance(x, str)
return x
def from_int(x: Any) -> int:
assert isinstance(x, int) and not isinstance(x, bool)
return x
def to_class(c: Type[T], x: Any) -> dict:
assert isinstance(x, c)
return cast(Any, x).to_dict()
@dataclass
class Env:
cadFilePath: str
outPath: str
solidBodyPadding: float
firstDetail: str
sequencesFixed: list[list[str]]
@staticmethod
def from_dict(obj: Any) -> "Env":
assert isinstance(obj, dict)
cadFilePath = from_str(obj.get("cadFilePath"))
outPath = from_str(obj.get("outPath"))
solidBodyPadding = from_float(obj.get("solidBodyPadding"))
firstDetail = from_str(obj.get("firstDetail"))
sequencesFixed = []
sequencesFixedParse = CoreList(obj.get("sequencesFixed"))
for el in sequencesFixedParse:
sequencesFixed.append(el)
restrictionsOnFasteners = CoreList(obj.get("restrictionsOnFasteners"))
for el in restrictionsOnFasteners:
for part in el["parts"]:
sequencesFixed.append([part, el["fastener"]])
return Env(
cadFilePath,
outPath,
solidBodyPadding,
firstDetail,
sequencesFixed,
)
def to_dict(self) -> dict:
result: dict = {}
result["cadFilePath"] = from_str(self.cadFilePath)
result["outPath"] = from_str(self.outPath)
result["solidBodyPadding"] = from_float(self.solidBodyPadding)
result["firstDetail"] = from_str(self.firstDetail)
result["sequencesFixed"] = self.sequencesFixed
return result
class Either(ABC):
@abstractmethod
def isLeft(self):
pass
@abstractmethod
def isRight(self):
pass
@abstractmethod
def getLeft(self):
pass
@abstractmethod
def getRight(self):
pass
@abstractmethod
def mapLeft(self, lf):
pass
@abstractmethod
def mapRight(self, rf):
pass
@abstractmethod
def either(self, leftF, rightF):
pass
class Left(Either):
def __init__(self, lvalue):
self.lvalue = lvalue
def isLeft(self):
return True
def isRight(self):
return False
def getLeft(self):
return self.lvalue
def getRight(self):
raise Error("Cannot get a right value out of Left.")
def mapLeft(self, lf):
return Left(lf(self.lvalue))
def mapRight(self, rf):
return Left(self.lvalue)
def either(self, leftF, rightF):
return leftF(self.lvalue)
class Right(Either):
def __init__(self, rvalue):
self.rvalue = rvalue
def isLeft(self):
return False
def isRight(self):
return True
def getLeft(self):
raise Error("Cannot get a left value out of Right.")
def getRight(self):
return self.rvalue
def mapLeft(self, lf):
return Right(self.rvalue)
def mapRight(self, rf):
return Right(rf(self.rvalue))
def either(self, leftF, rightF):
return rightF(self.rvalue)
class CoreDict(dict):
def isEquivalentByKeys(self, checkDict) -> bool:
print(checkDict)
for key in self:
value = checkDict.get(key)
if value is None:
return False
return True
def isMatchByKeys(self, checkList):
if len(self) != len(checkList):
return False
sorted_dict_keys = sorted(self.keys())
sorted_list_elements = sorted(checkList)
if sorted_dict_keys != sorted_list_elements:
missing_keys = [
key for key in sorted_list_elements if key not in sorted_dict_keys
]
print(f"Отсутствующие ключи в словаре: {missing_keys}")
return False
return True
class CoreList(List):
# the list contains only True
def onlyTrue(self) -> bool:
print(self)
for el in self:
if el is not True:
return False
if el is True:
return True
return False
def onlyUniqueElementAppend(self, el):
if el is None:
return
if self.is_element_in_array(el) is False:
self.append(el)
pass
def is_element_in_array(self, element):
return element in self
def equal(self, array: list) -> bool:
if len(self) != len(array):
return False
return self.sort() == array.sort()
def isConstrainsString(self) -> bool:
for el in self:
if isinstance(el, str):
return True
return False
def indexedPriorities(self, lowerPriority, highPriority) -> bool:
try:
lowerIndex = self.index(lowerPriority)
highPriorityIndex = self.index(highPriority)
return lowerIndex < highPriorityIndex
except:
return False
def getAllString(self) -> list[str]:
return list(filter(lambda x: isinstance(x, str), self))
def onlyUnique(self) -> list:
result = []
[result.append(x) for x in self if x not in self]
return result
def spreadArray(self) -> "CoreList":
unpacked_array = CoreList([])
for el in self:
if isinstance(el, list):
unpacked_array.extend(el)
else:
unpacked_array.append(el)
return unpacked_array
def isInListRange(listIn, index):
@ -30,10 +269,24 @@ class AllSequences:
topologyIds = None
adj_matrix_names = None
def __init__(self, adj_matrix) -> None:
def __init__(self, adj_matrix, restrictions: list[str]) -> None:
self.adj_matrix = adj_matrix
self.all_possible_sequences(self.adj_matrix)
self.matrix_by_name()
if restrictions.__len__() != 0:
self.restrictionsValidate(restrictions)
pass
def restrictionsValidate(self, restrictions: CoreList[str]):
filterMatrix = CoreList()
for el in self.adj_matrix_names:
result = False
for restraint in restrictions:
result = CoreList(el).indexedPriorities(restraint[0], restraint[1])
if result:
filterMatrix.onlyUniqueElementAppend(el)
self.adj_matrix_names = filterMatrix
pass
def matrix_by_name(self):
@ -41,7 +294,7 @@ class AllSequences:
inc = 0
for matrix in self.all_sequences:
for index in range(len(matrix)):
result[inc][index] = list(
result[inc][index] = CoreList(
filter(
lambda el: el.get("number") == matrix[index] + 1,
self.topologyIds,
@ -137,10 +390,29 @@ class VectorModel:
def toFreeCadVector(self):
return App.Vector(self.x, self.y, self.z)
def toString(self):
return str("x:" + str(self.x) + "y:" + str(self.y) + "z:" + str(self.z))
class FreeCadRepository:
_solids = []
def openDocument(self, path: str):
App.open("" + path)
def closeIfOpenDocument(self):
# print('Проверка на документ')
try:
if App.ActiveDocument is not None:
# print(App.ActiveDocument.name + "закрыт")
# App.closeDocument(App.ActiveDocument.name)
App.ActiveDocument.clearDocument()
except Exception as e:
print(e)
def getAllLabelsSolids(self) -> List[str]:
return list(map(lambda el: el.Label, self.getAllSolids()))
def isAllObjectsSolids(self) -> List[str]:
result = []
for part in App.ActiveDocument.Objects:
@ -155,25 +427,28 @@ class FreeCadRepository:
def objectGetPosition(self, solid) -> VectorModel:
return VectorModel(cadVector=solid.Placement.Base)
def isObjectIntersections(self, part) -> bool:
def isObjectIntersections(self, part) -> str:
result = []
for solid in self.getAllSolids():
if solid.Label != part.Label:
if solid.ID != part.ID:
collisionResult: int = int(part.Shape.distToShape(solid.Shape)[0])
if collisionResult == 0:
return True
return False
result.append(solid.Label)
if result.__len__() == 0:
return None
return result
def objectHasTouches(self, part, objectIndentation: float) -> List[str]:
def objectHasTouches(self, part, solidBodyPadding: float) -> List[str]:
try:
positionVector = self.objectGetPosition(part)
result = CoreList()
result.append(self.isObjectIntersections(part=part))
if objectIndentation != 0 and objectIndentation != None:
if solidBodyPadding != 0 and solidBodyPadding != None:
result.append(
self.axis_movement_and_intersections_observer(
positionVector=positionVector,
alongAxis="x",
objectIndentation=objectIndentation,
solidBodyPadding=solidBodyPadding,
part=part,
)
)
@ -181,7 +456,7 @@ class FreeCadRepository:
self.axis_movement_and_intersections_observer(
positionVector=positionVector,
alongAxis="y",
objectIndentation=objectIndentation,
solidBodyPadding=solidBodyPadding,
part=part,
)
)
@ -189,45 +464,61 @@ class FreeCadRepository:
self.axis_movement_and_intersections_observer(
positionVector=positionVector,
alongAxis="z",
objectIndentation=objectIndentation,
solidBodyPadding=solidBodyPadding,
part=part,
)
)
return result.onlyTrue()
spreadArr = result.spreadArray()
if spreadArr.isConstrainsString():
return spreadArr.getAllString()
return None
except Exception as error:
print(error)
return None
def axis_movement_and_intersections_observer(
self,
positionVector: VectorModel,
alongAxis: str,
objectIndentation: float,
solidBodyPadding: float,
part,
) -> bool:
result = CoreList()
# UP
positionVector.__setattr__(
alongAxis, positionVector.__getattribute__(alongAxis) + objectIndentation
alongAxis,
positionVector.__getattribute__(alongAxis) + solidBodyPadding,
)
self.objectSetPosition(part, positionVector.toFreeCadVector())
result = self.isObjectIntersections(part=part)
if result:
return True
# result.onlyUniqueElementAppend(self.isObjectIntersections(part=part))
result.extend(self.isObjectIntersections(part=part))
# RESET UP CHANGES
positionVector.__setattr__(
alongAxis,
positionVector.__getattribute__(alongAxis) - solidBodyPadding,
)
self.objectSetPosition(part, positionVector.toFreeCadVector())
# DOWN
positionVector.__setattr__(
alongAxis, positionVector.__getattribute__(alongAxis) - objectIndentation
)
positionVector.__setattr__(
alongAxis, positionVector.__getattribute__(alongAxis) - objectIndentation
)
result = self.isObjectIntersections(part=part)
if result:
return True
self.isObjectIntersections(part=part)
# ROLLBACK
positionVector.__setattr__(
alongAxis, positionVector.__getattribute__(alongAxis) + objectIndentation
alongAxis,
positionVector.__getattribute__(alongAxis) - solidBodyPadding,
)
self.objectSetPosition(part, positionVector.toFreeCadVector())
return False
# CHECK DOWN INTERSECTIONS
# result.onlyUniqueElementAppend(self.isObjectIntersections(part=part))
result.extend(self.isObjectIntersections(part=part))
# RESET DOWN CHANGES
positionVector.__setattr__(
alongAxis,
positionVector.__getattribute__(alongAxis) + solidBodyPadding,
)
self.objectSetPosition(part, positionVector.toFreeCadVector())
if result.__len__() == 0:
return None
return result.onlyUnique()
def getAllSolids(self):
if self._solids.__len__() == 0:
@ -286,6 +577,8 @@ class AdjacencyMatrix:
first_detail: str
matrix: Dict[str, List[str]]
fileName = "adjacency_matrix.json"
def __init__(
self, all_parts: List[str], first_detail: str, matrix: Dict[str, List[str]]
) -> None:
@ -294,6 +587,38 @@ class AdjacencyMatrix:
self.matrix = matrix
self.validateMatrix()
def matrixToFileSystem(self, path: str):
FileSystemRepository.writeFile(
json.dumps(self.to_dict(), ensure_ascii=False, indent=4),
path,
AdjacencyMatrix.fileName,
)
pass
def sequencesToFileSystem(self, path: str, restrictions: list[str]):
FileSystemRepository.writeFile(
json.dumps(
{"sequences": AllSequences(self.matrix, restrictions).adj_matrix_names},
ensure_ascii=False,
indent=4,
),
path,
"sequences.json",
),
pass
def matrixGetUniqueContact(self):
detailsToCheck = []
detailsHashCheck = {}
for k, v in self.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 whatPlaceLeadingPartIndex(self):
i = 0
for el in self.matrix:
@ -309,6 +634,7 @@ class AdjacencyMatrix:
@staticmethod
def from_dict(obj: Any) -> "AdjacencyMatrix":
assert isinstance(obj, dict)
all_pars = from_list(from_str, obj.get("allParts"))
first_detail = from_str(obj.get("firstDetail"))
matrix = from_dict(lambda x: from_list(from_str, x), obj.get("matrix"))
@ -393,7 +719,7 @@ class MeshGeometryCoordinateModel(object):
App.ActiveDocument.recompute()
class FS:
class FileSystemRepository:
def readJSON(path: str):
return json.loads((open(path)).read())
@ -580,8 +906,7 @@ class CadAdjacencyMatrix:
collisionResult: int = int(
part.Shape.distToShape(nextPart.Shape)[0]
)
print(collisionResult)
print("collisionResult")
if collisionResult == 0:
matrix[part.Label].append(nextPart.Label)
@ -608,19 +933,6 @@ def to_ascii_hash(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
class IntersectionComputedUseCase:
def call(parts):
App.activeDocument().addObject("Part::MultiCommon", "Common")
@ -657,32 +969,55 @@ class ErrorStringModel:
indent=4,
)
def toFileSystem(self, path: str):
return (
FileSystemRepository.writeFile(self.toString(), path, "error.json"),
ExitFreeCadUseCase.call(),
)
class IsAllObjectSolidsCheckUseCase:
def call() -> ErrorStringModel:
def call() -> Either:
result = FreeCadRepository().isAllObjectsSolids()
if result.__len__() == 0:
return None
return Left(None)
return ErrorStringModel(error="Is not solid objects: " + ",".join(result))
return Right(
ErrorStringModel(error="Is not solid objects: " + ",".join(result))
)
class CheckObjectHasTouchesUseCase:
def call(objectIndentation: float) -> ErrorStringModel:
result = []
for part in FreeCadRepository().getAllSolids():
if (
FreeCadRepository().objectHasTouches(
part=part, objectIndentation=objectIndentation
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
)
is False
):
result.append(part.Label)
if result.__len__() == 0:
return None
return ErrorStringModel(
error="Solids bodies have no recounts: " + ",".join(result)
matrix[part.Label].extend(touches)
if errorResult.__len__() == 0:
return Left(
AdjacencyMatrix(
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"))
class CheckCadIntersectionObjects:
@ -697,6 +1032,7 @@ class ExitFreeCadUseCase:
def call():
import FreeCADGui as Gui
App.ActiveDocument.clearDocument()
freecadQTWindow = Gui.getMainWindow()
freecadQTWindow.close()
@ -709,40 +1045,28 @@ class ExitFreeCadUseCase:
# pass
def main():
env = FS.readJSON("env.json")
cadFilePath = str(env["cadFilePath"])
outPath = str(env["outPath"])
objectIndentation = float(env["objectIndentation"])
class EnvReaderUseCase:
def call() -> Either:
try:
return Left(Env.from_dict(FileSystemRepository.readJSON("env.json")))
except:
print("env reader error")
return Right(None)
if cadFilePath == None:
return TypeError("CadFile not found env.json")
App.open("" + cadFilePath)
# isAllObjectSolidsCheckUseCase = IsAllObjectSolidsCheckUseCase.call()
class OpenFreeCadDocumentUseCase:
def call(path: str) -> Either:
try:
FreeCadRepository().closeIfOpenDocument()
FreeCadRepository().openDocument(path)
return Left(None)
except:
print("OpenFreeCadDocumentUseCase error")
return Right(None)
# if isAllObjectSolidsCheckUseCase != None:
# FS.writeFile(isAllObjectSolidsCheckUseCase.toString(), outPath, 'error.json')
# ExitFreeCadUseCase.call()
# return
# checkObjectHasTouchesUseCase = CheckObjectHasTouchesUseCase.call(objectIndentation)
# if checkObjectHasTouchesUseCase != None:
# FS.writeFile(checkObjectHasTouchesUseCase.toString(), outPath, 'error.json')
# ExitFreeCadUseCase.call()
# return
topologyMatrix = CadAdjacencyMatrix().matrixBySurfaces()
import json
sequences = json.dumps(
{"sequences": AllSequences(topologyMatrix.matrix).adj_matrix_names},
ensure_ascii=False,
indent=4,
)
matrix = topologyMatrix.matrix
contacts = matrixGetUniqueContact(matrix)
class IntersectionGeometryUseCase:
def call(contacts, path):
intersection_geometry = {"status": True, "recalculations": None}
for el in contacts:
child = App.ActiveDocument.getObjectsByLabel(el.get("child"))[0]
@ -755,20 +1079,238 @@ def main():
intersection_geometry["recalculations"].append(
{"area": area, "connect": el.get("child") + " " + el.get("parent")}
)
FS.writeFile(
FileSystemRepository.writeFile(
json.dumps(intersection_geometry, ensure_ascii=False, indent=4),
outPath,
path,
"intersection_geometry.json",
)
FS.writeFile(sequences, outPath, "sequences.json")
FS.writeFile(
json.dumps(topologyMatrix.to_dict(), ensure_ascii=False, indent=4),
outPath,
"adjacency_matrix.json",
def main():
try:
EnvReaderUseCase.call().either(
leftF=lambda environment: (
OpenFreeCadDocumentUseCase.call(environment.cadFilePath).either(
leftF=lambda _: (
IsAllObjectSolidsCheckUseCase.call().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,
),
ExitFreeCadUseCase.call(),
),
rightF=lambda error: error.toFileSystem(
environment.outPath
),
),
),
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()
main()
# main()
class ReadFileSystemAndGetInstanceModelUseCase:
def call(self, model, path):
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:
error = str(model) + " " + "from dict error " + "path: " + path
print("ReadFileSystemAndGetInstanceModelUseCase error" + error)
return Right(error)
pass
class FreeCadTest:
testName: str
def testHelper(self, testResult):
if isinstance(testResult, bool) is False:
print(
BackgroundConsoleColors.WARNING,
self.testName
+ " expected a value of type Boolean, returned a value of type below ",
)
print(testResult)
return
if testResult:
print(BackgroundConsoleColors.OKGREEN, self.testName + "is complete!")
else:
print(BackgroundConsoleColors.FAIL, self.testName + " is Error!")
pass
class FreeCadASPGenerationTestController(FreeCadTest):
testName: str
def __init__(self, testName: str) -> None:
self.testName = testName
pass
def test(
self,
assertFn,
documentPath: str,
modelName: str,
model,
execComposition,
outPath=os.path.dirname(__file__) + "/out/",
):
try:
OpenFreeCadDocumentUseCase.call(documentPath).either(
leftF=lambda _: (
execComposition(""),
ReadFileSystemAndGetInstanceModelUseCase()
.call(model=model, path=outPath + modelName)
.either(
leftF=lambda model: (
self.testHelper(
assertFn(model),
)
),
rightF=lambda error: print(error),
),
),
rightF=lambda error: print(error),
)
except Exception as inst:
print("FreeCadASPGenerationTestController error")
print(inst)
pass
def test():
try:
mocksFolder = os.path.dirname(__file__) + "/mocks/"
outFolder = os.path.dirname(__file__) + "/out/"
# FreeCadASPGenerationTestController("test adjaxed matrix simple cube").test(
# assertFn=lambda model: CoreList(model.all_parts).equal(["Куб", "Куб001"]),
# execComposition=lambda _: (
# CheckObjectHasTouchesUseCase()
# .call(0)
# .either(
# leftF=lambda matrix: matrix.matrixToFileSystem(outFolder),
# rightF=lambda error: print(error),
# )
# ),
# documentPath=mocksFolder + "simple_assembly_with_two_cubes.FCStd",
# modelName=AdjacencyMatrix.fileName,
# model=AdjacencyMatrix,
# )
FreeCadASPGenerationTestController(
"test adjaxed matrix vs structure of document"
).test(
assertFn=lambda model: CoreDict(model.matrix).isEquivalentByKeys(
{
"Бутылочный домкрат 4т_Гильза": [
"Бутылочный домкрат 4т_Тяга",
"Бутылочный домкрат 4т_Тяга001",
"Бутылочный домкрат 4т_Шток насоса",
"Бутылочный домкрат 4т_Шток",
"Бутылочный домкрат 4т_Вентиль",
],
"Бутылочный домкрат 4т_Тяга": [
"Бутылочный домкрат 4т_Гильза",
"Бутылочный домкрат 4т_Тяга001",
"Бутылочный домкрат 4т_Коромысло",
],
"Бутылочный домкрат 4т_Тяга001": [
"Бутылочный домкрат 4т_Гильза",
"Бутылочный домкрат 4т_Тяга",
"Бутылочный домкрат 4т_Коромысло",
],
"Бутылочный домкрат 4т_Шток насоса": [
"Бутылочный домкрат 4т_Гильза",
"Бутылочный домкрат 4т_Коромысло",
],
"Бутылочный домкрат 4т_Коромысло": [
"Бутылочный домкрат 4т_Тяга",
"Бутылочный домкрат 4т_Тяга001",
"Бутылочный домкрат 4т_Шток насоса",
],
"Бутылочный домкрат 4т_Шток": [
"Бутылочный домкрат 4т_Гильза",
"Бутылочный домкрат 4т_Винт штока",
],
"Бутылочный домкрат 4т_Винт штока": ["Бутылочный домкрат 4т_Шток"],
"Бутылочный домкрат 4т_Вентиль": ["Бутылочный домкрат 4т_Гильза"],
}
),
execComposition=lambda _: (
CheckObjectHasTouchesUseCase()
.call(0)
.either(
leftF=lambda matrix: matrix.matrixToFileSystem(outFolder),
rightF=lambda error: print(error),
)
),
documentPath=mocksFolder + "bottle_jack.FCStd",
modelName=AdjacencyMatrix.fileName,
model=AdjacencyMatrix,
)
FreeCadASPGenerationTestController(
"test adjacency matrix keys vs allparts"
).test(
assertFn=lambda model: CoreDict(model.matrix).isMatchByKeys(
["Куб", "Куб001"]
),
execComposition=lambda _: (
CheckObjectHasTouchesUseCase()
.call(0)
.either(
leftF=lambda matrix: matrix.matrixToFileSystem(outFolder),
rightF=lambda error: print(error),
)
),
documentPath=mocksFolder + "simple_assembly_with_two_cubes.FCStd",
modelName=AdjacencyMatrix.fileName,
model=AdjacencyMatrix,
)
ExitFreeCadUseCase.call()
except:
print("test error")
ExitFreeCadUseCase.call()
pass
test()
# TODO:
# 1.

Binary file not shown.

Binary file not shown.

BIN
test_models/table_pc.FCStd Normal file

Binary file not shown.

Binary file not shown.