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", "cadFilePath": "/Users/idontsudo/Desktop/reductor/test_reductor.FCStd",
"outPath": "/Users/idontsudo/Desktop/asp-example/", "outPath": "/Users/idontsudo/Desktop/reductor/",
"objectIndentation": 0 "solidBodyPadding": 1,
"firstDetail": "Куб",
"sequencesFixed": [],
"restrictionsOnFasteners": []
} }

View file

@ -4,16 +4,255 @@ import os
import json import json
from typing import List, Dict, Any, TypeVar, Callable, Type, cast from typing import List, Dict, Any, TypeVar, Callable, Type, cast
from itertools import repeat 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): class CoreList(List):
# the list contains only True
def onlyTrue(self) -> bool: def onlyTrue(self) -> bool:
print(self)
for el in self: for el in self:
if el is not True: if el is True:
return False return 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): def isInListRange(listIn, index):
@ -30,10 +269,24 @@ class AllSequences:
topologyIds = None topologyIds = None
adj_matrix_names = 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.adj_matrix = adj_matrix
self.all_possible_sequences(self.adj_matrix) self.all_possible_sequences(self.adj_matrix)
self.matrix_by_name() 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 pass
def matrix_by_name(self): def matrix_by_name(self):
@ -41,7 +294,7 @@ class AllSequences:
inc = 0 inc = 0
for matrix in self.all_sequences: for matrix in self.all_sequences:
for index in range(len(matrix)): for index in range(len(matrix)):
result[inc][index] = list( result[inc][index] = CoreList(
filter( filter(
lambda el: el.get("number") == matrix[index] + 1, lambda el: el.get("number") == matrix[index] + 1,
self.topologyIds, self.topologyIds,
@ -137,10 +390,29 @@ class VectorModel:
def toFreeCadVector(self): def toFreeCadVector(self):
return App.Vector(self.x, self.y, self.z) 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: class FreeCadRepository:
_solids = [] _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]: def isAllObjectsSolids(self) -> List[str]:
result = [] result = []
for part in App.ActiveDocument.Objects: for part in App.ActiveDocument.Objects:
@ -155,79 +427,98 @@ class FreeCadRepository:
def objectGetPosition(self, solid) -> VectorModel: def objectGetPosition(self, solid) -> VectorModel:
return VectorModel(cadVector=solid.Placement.Base) return VectorModel(cadVector=solid.Placement.Base)
def isObjectIntersections(self, part) -> bool: def isObjectIntersections(self, part) -> str:
result = []
for solid in self.getAllSolids(): for solid in self.getAllSolids():
if solid.Label != part.Label: if solid.ID != part.ID:
collisionResult: int = int(part.Shape.distToShape(solid.Shape)[0]) collisionResult: int = int(part.Shape.distToShape(solid.Shape)[0])
if collisionResult == 0: if collisionResult == 0:
return True result.append(solid.Label)
return False if result.__len__() == 0:
return None
return result
def objectHasTouches(self, part, objectIndentation: float) -> List[str]: def objectHasTouches(self, part, solidBodyPadding: float) -> List[str]:
positionVector = self.objectGetPosition(part) try:
result = CoreList() positionVector = self.objectGetPosition(part)
result.append(self.isObjectIntersections(part=part)) result = CoreList()
result.append(self.isObjectIntersections(part=part))
if objectIndentation != 0 and objectIndentation != None: if solidBodyPadding != 0 and solidBodyPadding != None:
result.append( result.append(
self.axis_movement_and_intersections_observer( self.axis_movement_and_intersections_observer(
positionVector=positionVector, positionVector=positionVector,
alongAxis="x", alongAxis="x",
objectIndentation=objectIndentation, solidBodyPadding=solidBodyPadding,
part=part, part=part,
)
) )
) result.append(
result.append( self.axis_movement_and_intersections_observer(
self.axis_movement_and_intersections_observer( positionVector=positionVector,
positionVector=positionVector, alongAxis="y",
alongAxis="y", solidBodyPadding=solidBodyPadding,
objectIndentation=objectIndentation, part=part,
part=part, )
) )
) result.append(
result.append( self.axis_movement_and_intersections_observer(
self.axis_movement_and_intersections_observer( positionVector=positionVector,
positionVector=positionVector, alongAxis="z",
alongAxis="z", solidBodyPadding=solidBodyPadding,
objectIndentation=objectIndentation, part=part,
part=part, )
) )
) spreadArr = result.spreadArray()
if spreadArr.isConstrainsString():
return result.onlyTrue() return spreadArr.getAllString()
return None
except Exception as error:
print(error)
return None
def axis_movement_and_intersections_observer( def axis_movement_and_intersections_observer(
self, self,
positionVector: VectorModel, positionVector: VectorModel,
alongAxis: str, alongAxis: str,
objectIndentation: float, solidBodyPadding: float,
part, part,
) -> bool: ) -> bool:
result = CoreList()
# UP # UP
positionVector.__setattr__( positionVector.__setattr__(
alongAxis, positionVector.__getattribute__(alongAxis) + objectIndentation alongAxis,
positionVector.__getattribute__(alongAxis) + solidBodyPadding,
) )
self.objectSetPosition(part, positionVector.toFreeCadVector()) self.objectSetPosition(part, positionVector.toFreeCadVector())
result = self.isObjectIntersections(part=part) # result.onlyUniqueElementAppend(self.isObjectIntersections(part=part))
if result: result.extend(self.isObjectIntersections(part=part))
return True # RESET UP CHANGES
positionVector.__setattr__(
alongAxis,
positionVector.__getattribute__(alongAxis) - solidBodyPadding,
)
self.objectSetPosition(part, positionVector.toFreeCadVector())
# DOWN # DOWN
positionVector.__setattr__( positionVector.__setattr__(
alongAxis, positionVector.__getattribute__(alongAxis) - objectIndentation alongAxis,
) positionVector.__getattribute__(alongAxis) - solidBodyPadding,
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
) )
self.objectSetPosition(part, positionVector.toFreeCadVector()) 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): def getAllSolids(self):
if self._solids.__len__() == 0: if self._solids.__len__() == 0:
@ -286,6 +577,8 @@ class AdjacencyMatrix:
first_detail: str first_detail: str
matrix: Dict[str, List[str]] matrix: Dict[str, List[str]]
fileName = "adjacency_matrix.json"
def __init__( def __init__(
self, all_parts: List[str], first_detail: str, matrix: Dict[str, List[str]] self, all_parts: List[str], first_detail: str, matrix: Dict[str, List[str]]
) -> None: ) -> None:
@ -294,6 +587,38 @@ class AdjacencyMatrix:
self.matrix = matrix self.matrix = matrix
self.validateMatrix() 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): def whatPlaceLeadingPartIndex(self):
i = 0 i = 0
for el in self.matrix: for el in self.matrix:
@ -309,6 +634,7 @@ class AdjacencyMatrix:
@staticmethod @staticmethod
def from_dict(obj: Any) -> "AdjacencyMatrix": def from_dict(obj: Any) -> "AdjacencyMatrix":
assert isinstance(obj, dict) assert isinstance(obj, dict)
all_pars = from_list(from_str, obj.get("allParts")) all_pars = from_list(from_str, obj.get("allParts"))
first_detail = from_str(obj.get("firstDetail")) first_detail = from_str(obj.get("firstDetail"))
matrix = from_dict(lambda x: from_list(from_str, x), obj.get("matrix")) matrix = from_dict(lambda x: from_list(from_str, x), obj.get("matrix"))
@ -393,7 +719,7 @@ class MeshGeometryCoordinateModel(object):
App.ActiveDocument.recompute() App.ActiveDocument.recompute()
class FS: class FileSystemRepository:
def readJSON(path: str): def readJSON(path: str):
return json.loads((open(path)).read()) return json.loads((open(path)).read())
@ -580,8 +906,7 @@ class CadAdjacencyMatrix:
collisionResult: int = int( collisionResult: int = int(
part.Shape.distToShape(nextPart.Shape)[0] part.Shape.distToShape(nextPart.Shape)[0]
) )
print(collisionResult)
print("collisionResult")
if collisionResult == 0: if collisionResult == 0:
matrix[part.Label].append(nextPart.Label) matrix[part.Label].append(nextPart.Label)
@ -608,19 +933,6 @@ def to_ascii_hash(text):
return reduce(lambda x, y: x + y, ascii_values) 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: class IntersectionComputedUseCase:
def call(parts): def call(parts):
App.activeDocument().addObject("Part::MultiCommon", "Common") App.activeDocument().addObject("Part::MultiCommon", "Common")
@ -657,32 +969,55 @@ class ErrorStringModel:
indent=4, indent=4,
) )
def toFileSystem(self, path: str):
return (
FileSystemRepository.writeFile(self.toString(), path, "error.json"),
ExitFreeCadUseCase.call(),
)
class IsAllObjectSolidsCheckUseCase: class IsAllObjectSolidsCheckUseCase:
def call() -> ErrorStringModel: def call() -> Either:
result = FreeCadRepository().isAllObjectsSolids() result = FreeCadRepository().isAllObjectsSolids()
if result.__len__() == 0: 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: class CheckObjectHasTouchesUseCase:
def call(objectIndentation: float) -> ErrorStringModel: freeCadRepository = FreeCadRepository()
result = []
for part in FreeCadRepository().getAllSolids(): def call(self, solidBodyPadding: float) -> Either:
if ( try:
FreeCadRepository().objectHasTouches( errorResult = []
part=part, objectIndentation=objectIndentation matrix = {}
for part in self.freeCadRepository.getAllSolids():
matrix[part.Label] = []
touches = FreeCadRepository().objectHasTouches(
part=part, solidBodyPadding=solidBodyPadding
) )
is False matrix[part.Label].extend(touches)
): if errorResult.__len__() == 0:
result.append(part.Label) return Left(
if result.__len__() == 0: AdjacencyMatrix(
return None all_parts=self.freeCadRepository.getAllLabelsSolids(),
return ErrorStringModel( first_detail=GetFirstDetailUseCase().call(),
error="Solids bodies have no recounts: " + ",".join(result) 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: class CheckCadIntersectionObjects:
@ -697,6 +1032,7 @@ class ExitFreeCadUseCase:
def call(): def call():
import FreeCADGui as Gui import FreeCADGui as Gui
App.ActiveDocument.clearDocument()
freecadQTWindow = Gui.getMainWindow() freecadQTWindow = Gui.getMainWindow()
freecadQTWindow.close() freecadQTWindow.close()
@ -709,66 +1045,272 @@ class ExitFreeCadUseCase:
# pass # pass
class EnvReaderUseCase:
def call() -> Either:
try:
return Left(Env.from_dict(FileSystemRepository.readJSON("env.json")))
except:
print("env reader error")
return Right(None)
class OpenFreeCadDocumentUseCase:
def call(path: str) -> Either:
try:
FreeCadRepository().closeIfOpenDocument()
FreeCadRepository().openDocument(path)
return Left(None)
except:
print("OpenFreeCadDocumentUseCase error")
return Right(None)
class IntersectionGeometryUseCase:
def call(contacts, path):
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",
)
def main(): def main():
env = FS.readJSON("env.json") try:
cadFilePath = str(env["cadFilePath"]) EnvReaderUseCase.call().either(
outPath = str(env["outPath"]) leftF=lambda environment: (
objectIndentation = float(env["objectIndentation"]) 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),
)
if cadFilePath == None: except Exception as error:
return TypeError("CadFile not found env.json") print(error)
App.open("" + cadFilePath) ExitFreeCadUseCase.call()
# isAllObjectSolidsCheckUseCase = IsAllObjectSolidsCheckUseCase.call()
# if isAllObjectSolidsCheckUseCase != None: # main()
# FS.writeFile(isAllObjectSolidsCheckUseCase.toString(), outPath, 'error.json')
# ExitFreeCadUseCase.call()
# return
# checkObjectHasTouchesUseCase = CheckObjectHasTouchesUseCase.call(objectIndentation)
# if checkObjectHasTouchesUseCase != None: class ReadFileSystemAndGetInstanceModelUseCase:
# FS.writeFile(checkObjectHasTouchesUseCase.toString(), outPath, 'error.json') def call(self, model, path):
# ExitFreeCadUseCase.call() if hasattr(model, "from_dict") is False:
# return return Right(
"ReadFileSystemAndGetInstanceModelUseCase error:"
topologyMatrix = CadAdjacencyMatrix().matrixBySurfaces() + model
import json + "is not have method"
+ "from_dict()"
sequences = json.dumps(
{"sequences": AllSequences(topologyMatrix.matrix).adj_matrix_names},
ensure_ascii=False,
indent=4,
)
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 = 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")}
) )
try:
FS.writeFile( return Left(model.from_dict(FileSystemRepository.readJSON(path)))
json.dumps(intersection_geometry, ensure_ascii=False, indent=4), except:
outPath, error = str(model) + " " + "from dict error " + "path: " + path
"intersection_geometry.json", print("ReadFileSystemAndGetInstanceModelUseCase error" + error)
) return Right(error)
FS.writeFile(sequences, outPath, "sequences.json") pass
FS.writeFile(
json.dumps(topologyMatrix.to_dict(), ensure_ascii=False, indent=4),
outPath,
"adjacency_matrix.json",
)
ExitFreeCadUseCase.call()
main() 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.