adding cad adjaxed matrix predicate
This commit is contained in:
parent
9fa936cfba
commit
dde3bde235
3 changed files with 363 additions and 0 deletions
1
geometric_feasibility_predicate/README.MD
Normal file
1
geometric_feasibility_predicate/README.MD
Normal file
|
@ -0,0 +1 @@
|
|||
freecadcmd main.py
|
4
geometric_feasibility_predicate/env.json
Normal file
4
geometric_feasibility_predicate/env.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"cadFilePath":"",
|
||||
"outPath":""
|
||||
}
|
358
geometric_feasibility_predicate/main.py
Normal file
358
geometric_feasibility_predicate/main.py
Normal file
|
@ -0,0 +1,358 @@
|
|||
import FreeCAD as App
|
||||
import uuid
|
||||
import os
|
||||
import json
|
||||
from typing import List, Dict, Any, TypeVar, Callable, Type, cast
|
||||
|
||||
|
||||
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()
|
||||
|
||||
|
||||
class AdjacencyMatrix:
|
||||
matrixError: Dict[str,str] = {}
|
||||
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
|
||||
def validateMatrix(self):
|
||||
for el in self.all_parts:
|
||||
if(self.matrix.get(el) == None):
|
||||
self.matrixError[el] = 'Not found adjacency ' + el
|
||||
@staticmethod
|
||||
def from_dict(obj: Any) -> 'AdjacencyMatrix':
|
||||
assert isinstance(obj, dict)
|
||||
all_pars = from_list(from_str, obj.get("allPars"))
|
||||
first_detail = from_str(obj.get("firstDetail"))
|
||||
matrix = from_dict(lambda x: from_list(from_str, x), obj.get("matrix"))
|
||||
|
||||
return AdjacencyMatrix(all_pars, first_detail, matrix)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
result: dict = {}
|
||||
result["allPars"] = from_list(from_str, self.all_parts)
|
||||
result["firstDetail"] = from_str(self.first_detail)
|
||||
result["matrix"] = from_dict(
|
||||
lambda x: from_list(from_str, x), self.matrix)
|
||||
if(self.matrixError.values().__len__() == 0):
|
||||
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)
|
||||
|
||||
|
||||
class FreeCadMetaModel(object):
|
||||
|
||||
def __init__(self, label, vertex) -> None:
|
||||
self.label = label
|
||||
self.vertex = vertex
|
||||
|
||||
|
||||
collision_squares_labels = []
|
||||
|
||||
|
||||
class MeshGeometryCoordinateModel(object):
|
||||
|
||||
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:
|
||||
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):
|
||||
|
||||
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:
|
||||
def call(self):
|
||||
return FreeCadRepository().getAllSolids()[0].Label
|
||||
|
||||
|
||||
class GetPartPrimitiveCoordinatesUseCase(object):
|
||||
|
||||
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():
|
||||
|
||||
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):
|
||||
|
||||
def call(self, meshModels: list[MeshGeometryCoordinateModel], detailSquares) -> None:
|
||||
for mesh in meshModels:
|
||||
mesh.initializePrimitivesByCoordinate(detailSquares)
|
||||
|
||||
|
||||
class ClearWorkSpaceDocumentUseCase(object):
|
||||
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):
|
||||
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:
|
||||
def primitiveMatrix(self):
|
||||
matrix = RenderPrimitivesScenario(
|
||||
InitPartsParseUseCase(),
|
||||
GetPartPrimitiveCoordinatesUseCase(),
|
||||
RenderPrimitiveUseCase(),
|
||||
GetCollisionAtPrimitiveUseCase(),
|
||||
ClearWorkSpaceDocumentUseCase(),
|
||||
).call()
|
||||
|
||||
return AdjacencyMatrix(
|
||||
all_parts=GetAllPartsLabelsUseCase().call(),
|
||||
first_detail=GetFirstDetailUseCase().call(),
|
||||
matrix=matrix,
|
||||
)
|
||||
|
||||
def matrixBySurfaces(self,):
|
||||
adjaxed = {}
|
||||
for part in FreeCadRepository().getAllSolids():
|
||||
adjaxed[part.Label] = []
|
||||
for nextPart in FreeCadRepository().getAllSolids():
|
||||
if part.Label != nextPart.Label:
|
||||
collisionResult: int = int(
|
||||
part.Shape.distToShape(nextPart.Shape)[0])
|
||||
if (collisionResult == 0):
|
||||
adjaxed[part.Label].append(nextPart.Label)
|
||||
|
||||
return AdjacencyMatrix(all_parts=GetAllPartsLabelsUseCase(
|
||||
).call(), first_detail=GetFirstDetailUseCase().call(),
|
||||
matrix=adjaxed
|
||||
)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
matrixOut = CadAdjacencyMatrix().primitiveMatrix().to_dict()
|
||||
import json
|
||||
FS.writeFile(json.dumps(matrixOut, ensure_ascii=False, indent=4), outPath,'out.json')
|
||||
|
||||
|
||||
main()
|
Loading…
Add table
Add a link
Reference in a new issue