2023-07-05 14:14:36 +00:00
|
|
|
|
# Алгоритм генерации графа с помощью оценки стабильности подсборок в физическом движке PyBullet
|
2023-09-12 19:09:33 +00:00
|
|
|
|
from typing import Any, TypeVar, Type, cast
|
2023-07-04 07:19:55 +00:00
|
|
|
|
import FreeCAD as App
|
|
|
|
|
import json
|
2023-09-12 19:09:33 +00:00
|
|
|
|
import importOBJ
|
|
|
|
|
import Draft
|
|
|
|
|
import os
|
|
|
|
|
import Part
|
|
|
|
|
import numpy as np
|
|
|
|
|
from typing import TypeAlias
|
|
|
|
|
import FreeCADGui as Gui
|
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
ISequencesUnion: TypeAlias = dict[str : dict[str : list[str]]]
|
2023-07-04 07:19:55 +00:00
|
|
|
|
|
2023-07-05 16:03:51 +03:00
|
|
|
|
|
2023-09-12 19:09:33 +00:00
|
|
|
|
def importObjAtPath(path: str, inc: int):
|
2023-12-17 13:58:43 +00:00
|
|
|
|
try:
|
|
|
|
|
importOBJ.insert("" + path, App.ActiveDocument.Label)
|
|
|
|
|
|
|
|
|
|
mesh = App.ActiveDocument.Objects[inc]
|
|
|
|
|
shape = Part.Shape()
|
|
|
|
|
shape.makeShapeFromMesh(mesh.Mesh.Topology, 0.05)
|
|
|
|
|
solid = Part.makeSolid(shape)
|
|
|
|
|
|
|
|
|
|
Part.show(solid)
|
2023-07-04 07:19:55 +00:00
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
App.ActiveDocument.Objects[inc + 1].Label = App.ActiveDocument.Objects[inc].Name
|
|
|
|
|
App.ActiveDocument.removeObject(App.ActiveDocument.Objects[inc].Name)
|
|
|
|
|
return App.ActiveDocument.Objects[inc]
|
|
|
|
|
except:
|
|
|
|
|
print("path")
|
|
|
|
|
print(path)
|
|
|
|
|
print("inc")
|
|
|
|
|
print(inc)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
T = TypeVar("T")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 to_class(c: Type[T], x: Any) -> dict:
|
|
|
|
|
assert isinstance(x, c)
|
|
|
|
|
return cast(Any, x).to_dict()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def euler_to_quaternion(yaw, pitch, roll):
|
2023-12-17 13:58:43 +00:00
|
|
|
|
qx = np.sin(roll / 2) * np.cos(pitch / 2) * np.cos(yaw / 2) - np.cos(
|
|
|
|
|
roll / 2
|
|
|
|
|
) * np.sin(pitch / 2) * np.sin(yaw / 2)
|
|
|
|
|
qy = np.cos(roll / 2) * np.sin(pitch / 2) * np.cos(yaw / 2) + np.sin(
|
|
|
|
|
roll / 2
|
|
|
|
|
) * np.cos(pitch / 2) * np.sin(yaw / 2)
|
|
|
|
|
qz = np.cos(roll / 2) * np.cos(pitch / 2) * np.sin(yaw / 2) - np.sin(
|
|
|
|
|
roll / 2
|
|
|
|
|
) * np.sin(pitch / 2) * np.cos(yaw / 2)
|
|
|
|
|
qw = np.cos(roll / 2) * np.cos(pitch / 2) * np.cos(yaw / 2) + np.sin(
|
|
|
|
|
roll / 2
|
|
|
|
|
) * np.sin(pitch / 2) * np.sin(yaw / 2)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
|
|
|
|
return [qx, qy, qz, qw]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Coords:
|
|
|
|
|
x: float
|
|
|
|
|
y: float
|
|
|
|
|
z: float
|
|
|
|
|
|
|
|
|
|
def __init__(self, x: float, y: float, z: float) -> None:
|
|
|
|
|
self.x = x
|
|
|
|
|
self.y = y
|
|
|
|
|
self.z = z
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
2023-12-17 13:58:43 +00:00
|
|
|
|
def from_dict(obj: Any) -> "Coords":
|
2023-09-12 19:09:33 +00:00
|
|
|
|
assert isinstance(obj, dict)
|
|
|
|
|
x = from_float(obj.get("x"))
|
|
|
|
|
y = from_float(obj.get("y"))
|
|
|
|
|
z = from_float(obj.get("z"))
|
|
|
|
|
return Coords(x, y, z)
|
|
|
|
|
|
|
|
|
|
def to_dict(self) -> dict:
|
|
|
|
|
result: dict = {}
|
|
|
|
|
result["x"] = to_float(self.x)
|
|
|
|
|
result["y"] = to_float(self.y)
|
|
|
|
|
result["z"] = to_float(self.z)
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
def vector(self):
|
|
|
|
|
return App.Vector(self.x, self.y, self.z)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MotionResultModel:
|
|
|
|
|
id: str
|
2023-12-17 13:58:43 +00:00
|
|
|
|
quaternion: Coords
|
2023-09-12 19:09:33 +00:00
|
|
|
|
position: Coords
|
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
def __init__(self, id: str, quaternion: Coords, position: Coords) -> None:
|
2023-09-12 19:09:33 +00:00
|
|
|
|
self.id = id
|
2023-12-17 13:58:43 +00:00
|
|
|
|
self.quaternion = quaternion
|
2023-09-12 19:09:33 +00:00
|
|
|
|
self.position = position
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
2023-12-17 13:58:43 +00:00
|
|
|
|
def from_dict(obj: Any) -> "MotionResultModel":
|
2023-09-12 19:09:33 +00:00
|
|
|
|
id = from_str(obj.get("id"))
|
2023-12-17 13:58:43 +00:00
|
|
|
|
quaternion = Coords.from_dict(obj.get("quaternion"))
|
2023-09-12 19:09:33 +00:00
|
|
|
|
position = Coords.from_dict(obj.get("position"))
|
2023-12-17 13:58:43 +00:00
|
|
|
|
return MotionResultModel(id, quaternion, position)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
|
|
|
|
def to_dict(self) -> dict:
|
|
|
|
|
result: dict = {}
|
|
|
|
|
result["id"] = from_str(self.id)
|
2023-12-17 13:58:43 +00:00
|
|
|
|
result["quaternion"] = to_class(Coords, self.quaternion)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
result["position"] = to_class(Coords, self.position)
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SequencesEvaluation:
|
|
|
|
|
sequences: ISequencesUnion
|
|
|
|
|
assemblyDir: str
|
|
|
|
|
result: dict = {}
|
|
|
|
|
|
|
|
|
|
def __init__(self, sequences, assemblyDir) -> None:
|
|
|
|
|
self.sequences = sequences
|
|
|
|
|
self.assemblyDir = assemblyDir
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def assemblyComputed(self):
|
2023-12-17 13:58:43 +00:00
|
|
|
|
isOk = True
|
2023-09-12 19:09:33 +00:00
|
|
|
|
for sequenceNumber, v in self.sequences.items():
|
|
|
|
|
for assemblyNumber, assemblySequenced in v.items():
|
2023-12-17 13:58:43 +00:00
|
|
|
|
if isOk:
|
|
|
|
|
# sequenceNumber += 1
|
|
|
|
|
isOk = False
|
2023-09-12 19:09:33 +00:00
|
|
|
|
self.comptedAssembly(
|
2023-12-17 13:58:43 +00:00
|
|
|
|
assemblySequenced, sequenceNumber, assemblyNumber
|
|
|
|
|
)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
def comptedAssembly(
|
|
|
|
|
self, assembly: list[str], sequenceNumber: int, assemblyNumber: int
|
|
|
|
|
):
|
2023-09-12 19:09:33 +00:00
|
|
|
|
assemblyParts = []
|
|
|
|
|
for counter in range(len(assembly)):
|
|
|
|
|
importObjAtPath(
|
2023-12-17 13:58:43 +00:00
|
|
|
|
self.assemblyDir + "generation/meshes/" + assembly[counter] + ".obj",
|
|
|
|
|
counter,
|
|
|
|
|
)
|
|
|
|
|
assemblyParts.append(
|
|
|
|
|
{"part": App.ActiveDocument.Objects[counter], "name": assembly[counter]}
|
2023-09-12 19:09:33 +00:00
|
|
|
|
)
|
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
motionResult = json.loads(
|
|
|
|
|
(
|
|
|
|
|
open(
|
|
|
|
|
self.assemblyDir
|
|
|
|
|
+ "stability"
|
|
|
|
|
+ "/"
|
|
|
|
|
+ str(sequenceNumber + 1)
|
|
|
|
|
+ "/"
|
|
|
|
|
+ str(assemblyNumber)
|
|
|
|
|
+ "/"
|
|
|
|
|
+ "motion_result.json"
|
|
|
|
|
)
|
|
|
|
|
).read()
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
simulatorMotionResults: list["MotionResultModel"] = []
|
2023-09-12 19:09:33 +00:00
|
|
|
|
for _k, v in motionResult.items():
|
2023-12-17 13:58:43 +00:00
|
|
|
|
print(v)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
simulatorMotionResults.append(MotionResultModel.from_dict(v))
|
|
|
|
|
|
|
|
|
|
for el in simulatorMotionResults:
|
|
|
|
|
for e in assemblyParts:
|
|
|
|
|
# сопоставляем детали
|
2023-12-17 13:58:43 +00:00
|
|
|
|
if el.id == e.get("name"):
|
2023-09-12 19:09:33 +00:00
|
|
|
|
# вычисляем центр детали для перемещения
|
2023-12-17 13:58:43 +00:00
|
|
|
|
center = e.get("part").Shape.CenterOfMass
|
2023-09-12 19:09:33 +00:00
|
|
|
|
# получаем центр деталей из симуляции
|
|
|
|
|
new_center = App.Vector(el.position.vector())
|
|
|
|
|
|
|
|
|
|
# вычисляем вектор смещения
|
|
|
|
|
offset = new_center - center
|
|
|
|
|
# перемещаем деталь на вектор смещения
|
2023-12-17 13:58:43 +00:00
|
|
|
|
e.get("part").Placement.Base += offset
|
|
|
|
|
|
|
|
|
|
# # импортируем меш связанный с зоной обьекта
|
|
|
|
|
zonePart = importObjAtPath(
|
|
|
|
|
self.assemblyDir
|
|
|
|
|
+ "stability/zones/meshes/zone_sub_assembly"
|
|
|
|
|
+ str(assembly.__len__() - 1)
|
|
|
|
|
+ ".obj",
|
|
|
|
|
len(App.ActiveDocument.Objects),
|
|
|
|
|
)
|
|
|
|
|
# # получаем координаты зоны относительно детали за которой закреплена зона
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
|
|
|
|
coords = json.loads(
|
2023-12-17 13:58:43 +00:00
|
|
|
|
(
|
|
|
|
|
open(
|
|
|
|
|
self.assemblyDir
|
|
|
|
|
+ "stability/zones/sub_assembly_coords_"
|
|
|
|
|
+ str(assemblyNumber - 1)
|
|
|
|
|
+ ".json"
|
|
|
|
|
)
|
|
|
|
|
).read()
|
|
|
|
|
)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
assemblyCounter = len(assemblyParts)
|
2023-12-17 13:58:43 +00:00
|
|
|
|
detailWhichZoneBindings = assemblyParts[assemblyCounter - 2].get("part")
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
detailStabilityComputed = assemblyParts[assemblyCounter - 1].get("part")
|
|
|
|
|
relativeCoordinates = coords.get("relativeCoordinates")
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
relativeEuler = coords.get("relativeEuler")
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
|
|
|
|
specificEuler = {
|
2023-12-17 13:58:43 +00:00
|
|
|
|
"yaw": detailWhichZoneBindings.Placement.Rotation.toEuler()[0]
|
|
|
|
|
- relativeEuler.get("yaw"),
|
|
|
|
|
"pitch": detailWhichZoneBindings.Placement.Rotation.toEuler()[1]
|
|
|
|
|
- relativeEuler.get("pitch"),
|
|
|
|
|
"roll": detailWhichZoneBindings.Placement.Rotation.toEuler()[2]
|
|
|
|
|
- relativeEuler.get("roll"),
|
2023-09-12 19:09:33 +00:00
|
|
|
|
}
|
2023-12-17 13:58:43 +00:00
|
|
|
|
quaternion = euler_to_quaternion(
|
|
|
|
|
specificEuler.get("yaw"),
|
|
|
|
|
specificEuler.get("pitch"),
|
|
|
|
|
specificEuler.get("roll"),
|
|
|
|
|
)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
rotation = App.Rotation(
|
2023-12-17 13:58:43 +00:00
|
|
|
|
quaternion[0], quaternion[1], quaternion[2], quaternion[3]
|
|
|
|
|
)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
|
|
|
|
detailStabilityComputed.Placement.Rotation = rotation
|
|
|
|
|
centerVector = detailWhichZoneBindings.Shape.CenterOfMass
|
2023-12-17 13:58:43 +00:00
|
|
|
|
vector = App.Vector(
|
|
|
|
|
relativeCoordinates.get("x"),
|
|
|
|
|
relativeCoordinates.get("y"),
|
|
|
|
|
relativeCoordinates.get("z"),
|
|
|
|
|
)
|
|
|
|
|
print(vector)
|
|
|
|
|
# TODO
|
|
|
|
|
current_center = zonePart.Shape.CenterOfMass
|
|
|
|
|
move_vector = App.Vector(centerVector + vector) - current_center
|
|
|
|
|
zonePart.Placement.move(move_vector)
|
|
|
|
|
|
|
|
|
|
computedStabilityResult = computedStability(zonePart, detailStabilityComputed)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
|
|
|
|
if sequenceNumber not in self.result.keys():
|
|
|
|
|
self.result[sequenceNumber] = []
|
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
self.result[sequenceNumber].append(
|
|
|
|
|
{str(assemblyNumber): assembly, "result": computedStabilityResult}
|
|
|
|
|
)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
# for part in App.ActiveDocument.Objects:
|
|
|
|
|
# App.ActiveDocument.removeObject(part.Name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_part_center(part):
|
|
|
|
|
shape = None
|
2023-12-17 13:58:43 +00:00
|
|
|
|
if not hasattr(part, "Shape"):
|
2023-09-12 19:09:33 +00:00
|
|
|
|
shape = part.Mesh
|
2023-12-17 13:58:43 +00:00
|
|
|
|
if hasattr(part, "Shape"):
|
2023-09-12 19:09:33 +00:00
|
|
|
|
shape = part.Shape
|
|
|
|
|
|
|
|
|
|
center = shape.BoundBox.Center
|
2023-12-17 13:58:43 +00:00
|
|
|
|
return App.Vector(center[0], center[1], center[2])
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def move_second_part_to_match_center(first_part, second_part):
|
|
|
|
|
first_center = get_part_center(first_part)
|
|
|
|
|
second_center = get_part_center(second_part)
|
|
|
|
|
offset = first_center - second_center
|
|
|
|
|
second_part.Placement.move(offset)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create(part):
|
|
|
|
|
clone = Draft.make_clone([part], forcedraft=True)
|
|
|
|
|
|
|
|
|
|
clone.Scale = App.Vector(1.30, 1.30, 1.30)
|
2023-12-17 13:58:43 +00:00
|
|
|
|
clone_corr = (
|
|
|
|
|
App.Vector(0.4476673941774023, -2.109332894191716, -0.5918687740295264)
|
|
|
|
|
- clone.Placement.Base
|
|
|
|
|
).scale(*App.Vector(-0.25, -0.25, -0.25))
|
2023-09-12 19:09:33 +00:00
|
|
|
|
clone.Placement.move(clone_corr)
|
|
|
|
|
App.ActiveDocument.recompute()
|
|
|
|
|
|
|
|
|
|
return clone
|
2023-07-04 07:19:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getFullPathObj(assemblyFolder: str, name: str):
|
2023-12-17 13:58:43 +00:00
|
|
|
|
return assemblyFolder + "sdf/meshes/" + name + ".obj"
|
2023-07-04 07:19:55 +00:00
|
|
|
|
|
|
|
|
|
|
2023-07-05 16:03:51 +03:00
|
|
|
|
def computedStability(refElement, childElement):
|
2023-07-05 13:33:45 +00:00
|
|
|
|
rootElement = childElement.Shape.BoundBox
|
|
|
|
|
# Создание обьекта на котором делается операция пересечения
|
2023-07-04 07:19:55 +00:00
|
|
|
|
App.activeDocument().addObject("Part::MultiCommon", "Common")
|
2023-12-17 13:58:43 +00:00
|
|
|
|
App.activeDocument().Common.Shapes = [
|
|
|
|
|
refElement,
|
|
|
|
|
childElement,
|
|
|
|
|
]
|
|
|
|
|
App.ActiveDocument.getObject("Common").ViewObject.ShapeColor = getattr(
|
|
|
|
|
App.ActiveDocument.getObject(refElement.Name).getLinkedObject(True).ViewObject,
|
|
|
|
|
"ShapeColor",
|
|
|
|
|
App.ActiveDocument.getObject("Common").ViewObject.ShapeColor,
|
|
|
|
|
)
|
|
|
|
|
App.ActiveDocument.getObject("Common").ViewObject.DisplayMode = getattr(
|
|
|
|
|
App.ActiveDocument.getObject(childElement.Name)
|
|
|
|
|
.getLinkedObject(True)
|
|
|
|
|
.ViewObject,
|
|
|
|
|
"DisplayMode",
|
|
|
|
|
App.ActiveDocument.getObject("Common").ViewObject.DisplayMode,
|
|
|
|
|
)
|
2023-07-04 07:19:55 +00:00
|
|
|
|
App.ActiveDocument.recompute()
|
2023-12-17 13:58:43 +00:00
|
|
|
|
obj = App.ActiveDocument.getObjectsByLabel("Common")[0]
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
2023-07-04 07:19:55 +00:00
|
|
|
|
shp = obj.Shape
|
|
|
|
|
bbox = shp.BoundBox
|
2023-09-12 19:09:33 +00:00
|
|
|
|
# Если после операции пересечения зона обьекта совпадает с зоной тестируемого обьекта то тест прошел успешно
|
2023-12-17 13:58:43 +00:00
|
|
|
|
if (
|
|
|
|
|
bbox.XLength == rootElement.XLength
|
|
|
|
|
and bbox.YLength == rootElement.YLength
|
|
|
|
|
and rootElement.ZLength == bbox.ZLength
|
|
|
|
|
):
|
2023-07-04 07:19:55 +00:00
|
|
|
|
return True
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
2023-09-12 19:09:33 +00:00
|
|
|
|
def autoStabilityZoneComputed(stepFilesPaths: list[str], directoryStableZonesPath: str):
|
|
|
|
|
cadObjects = []
|
|
|
|
|
for count in range(len(stepFilesPaths)):
|
|
|
|
|
importObjAtPath(stepFilesPaths[count], count)
|
|
|
|
|
cadObjects.append(App.ActiveDocument.Objects[count])
|
|
|
|
|
|
|
|
|
|
assemblesBindings = []
|
|
|
|
|
|
|
|
|
|
for increment in range(len(cadObjects)):
|
2023-12-17 13:58:43 +00:00
|
|
|
|
if increment != 0:
|
2023-09-12 19:09:33 +00:00
|
|
|
|
detailForEvaluationZ = cadObjects[increment]
|
2023-12-17 13:58:43 +00:00
|
|
|
|
zoneBindingDetailZ = cadObjects[increment - 1]
|
2023-09-12 19:09:33 +00:00
|
|
|
|
assemblesBindings.append(
|
2023-12-17 13:58:43 +00:00
|
|
|
|
{
|
|
|
|
|
"zoneBindingDetail": detailForEvaluationZ,
|
|
|
|
|
"detailForEvaluation": zoneBindingDetailZ,
|
|
|
|
|
"relativeCoordinates": None,
|
|
|
|
|
"zonePart": None,
|
|
|
|
|
}
|
|
|
|
|
)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
for increment in range(len(assemblesBindings)):
|
|
|
|
|
el = assemblesBindings[increment]
|
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
zoneBindingDetail = el.get("zoneBindingDetail")
|
2023-09-12 19:09:33 +00:00
|
|
|
|
zoneBindingDetailCenterVector = zoneBindingDetail.Shape.CenterOfMass
|
2023-12-17 13:58:43 +00:00
|
|
|
|
zoneDetail = create(el.get("detailForEvaluation"))
|
|
|
|
|
move_second_part_to_match_center(el.get("zoneBindingDetail"), zoneDetail)
|
|
|
|
|
zoneDetail.Label = "zone_sub_assembly" + str(increment + 1)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
|
|
|
|
zoneDetail.ViewObject.ShapeColor = (0.40, 0.74, 0.71)
|
|
|
|
|
zoneDetail.ViewObject.Transparency = 50
|
2023-12-17 13:58:43 +00:00
|
|
|
|
zoneDetailCenterVector = el.get("detailForEvaluation").Shape.CenterOfMass
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
el["relativeCoordinates"] = {
|
|
|
|
|
"x": zoneBindingDetailCenterVector.x - zoneDetailCenterVector.x,
|
|
|
|
|
"y": zoneBindingDetailCenterVector.y - zoneDetailCenterVector.y,
|
|
|
|
|
"z": zoneBindingDetailCenterVector.z - zoneDetailCenterVector.z,
|
2023-09-12 19:09:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
el["relativeEuler"] = {
|
|
|
|
|
"yaw": zoneBindingDetail.Placement.Rotation.toEuler()[0]
|
|
|
|
|
- el.get("detailForEvaluation").Placement.Rotation.toEuler()[0],
|
|
|
|
|
"pitch": zoneBindingDetail.Placement.Rotation.toEuler()[1]
|
|
|
|
|
- el.get("detailForEvaluation").Placement.Rotation.toEuler()[1],
|
|
|
|
|
"roll": zoneBindingDetail.Placement.Rotation.toEuler()[2]
|
|
|
|
|
- el.get("detailForEvaluation").Placement.Rotation.toEuler()[2],
|
2023-09-12 19:09:33 +00:00
|
|
|
|
}
|
2023-12-17 13:58:43 +00:00
|
|
|
|
el["zonePart"] = zoneDetail
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
meshesPath = directoryStableZonesPath + "meshes/"
|
2023-09-12 19:09:33 +00:00
|
|
|
|
if not os.path.exists(directoryStableZonesPath):
|
|
|
|
|
os.makedirs(directoryStableZonesPath)
|
|
|
|
|
if not os.path.exists(meshesPath):
|
|
|
|
|
os.makedirs(meshesPath)
|
|
|
|
|
zonesSaved = {}
|
|
|
|
|
for counter in range(len(assemblesBindings)):
|
|
|
|
|
zoneComputed = assemblesBindings[counter]
|
2023-12-17 13:58:43 +00:00
|
|
|
|
mesh = zoneComputed.get("zonePart")
|
|
|
|
|
zonesSavePath = meshesPath + mesh.Label + ".obj"
|
2023-09-12 19:09:33 +00:00
|
|
|
|
importOBJ.export([mesh], zonesSavePath)
|
2023-12-17 13:58:43 +00:00
|
|
|
|
zonesSaved[mesh.Label] = "meshes/" + mesh.Label + ".obj"
|
2023-09-12 19:09:33 +00:00
|
|
|
|
for counter in range(len(assemblesBindings)):
|
|
|
|
|
el = assemblesBindings[counter]
|
2023-12-17 13:58:43 +00:00
|
|
|
|
savePath = zonesSaved[el.get("zonePart").Label]
|
|
|
|
|
el["zonePart"] = savePath
|
|
|
|
|
el["detailForEvaluation"] = el["detailForEvaluation"].Label
|
|
|
|
|
el["zoneBindingDetail"] = el["zoneBindingDetail"].Label
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
|
|
|
|
json_result = json.dumps(el)
|
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
file_to_open = (
|
|
|
|
|
directoryStableZonesPath + "sub_assembly_coords_" + str(counter) + ".json"
|
|
|
|
|
)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
f = open(
|
|
|
|
|
file_to_open,
|
|
|
|
|
"w",
|
|
|
|
|
)
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
|
|
|
|
f.write(json_result)
|
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
|
|
|
2023-07-04 07:19:55 +00:00
|
|
|
|
def main():
|
|
|
|
|
App.newDocument()
|
2023-12-17 13:58:43 +00:00
|
|
|
|
env = json.loads((open("./env.json")).read())
|
2023-07-05 16:03:51 +03:00
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
assemblyDir = env.get("aspPath")
|
|
|
|
|
sequencesJSON = json.loads((open(assemblyDir + "sequences.json")).read())
|
|
|
|
|
directoryStableZones = assemblyDir + "stability/zones/"
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
2023-12-17 13:58:43 +00:00
|
|
|
|
sequences = sequencesJSON.get("sequences")
|
|
|
|
|
stepStructure = json.loads((open(assemblyDir + "step-structure.json")).read())
|
2023-09-12 19:09:33 +00:00
|
|
|
|
|
|
|
|
|
stepFilesPaths = []
|
|
|
|
|
for step in stepStructure:
|
2023-12-17 13:58:43 +00:00
|
|
|
|
stepFilesPaths.append(assemblyDir + "generation/meshes/" + step + ".obj")
|
2023-09-12 19:09:33 +00:00
|
|
|
|
if not os.path.exists(directoryStableZones):
|
2023-12-17 13:58:43 +00:00
|
|
|
|
print("Zones not found automatic calculation started")
|
2023-09-12 19:09:33 +00:00
|
|
|
|
autoStabilityZoneComputed(stepFilesPaths, directoryStableZones)
|
|
|
|
|
|
|
|
|
|
sequencesJoin = {}
|
|
|
|
|
|
|
|
|
|
for arrayCounter in range(len(sequences)):
|
|
|
|
|
for indexCounter in range(len(sequences[arrayCounter])):
|
2023-12-17 13:58:43 +00:00
|
|
|
|
if indexCounter != 0:
|
|
|
|
|
if sequencesJoin.get(arrayCounter) == None:
|
2023-09-12 19:09:33 +00:00
|
|
|
|
sequencesJoin[arrayCounter] = {
|
2023-12-17 13:58:43 +00:00
|
|
|
|
indexCounter: sequences[arrayCounter][0 : indexCounter + 1]
|
2023-09-12 19:09:33 +00:00
|
|
|
|
}
|
|
|
|
|
else:
|
2023-12-17 13:58:43 +00:00
|
|
|
|
sequencesJoin[arrayCounter][indexCounter] = sequences[arrayCounter][
|
|
|
|
|
0 : indexCounter + 1
|
|
|
|
|
]
|
|
|
|
|
|
2023-09-12 19:09:33 +00:00
|
|
|
|
seqEvaluation = SequencesEvaluation(sequencesJoin, assemblyDir)
|
|
|
|
|
seqEvaluation.assemblyComputed()
|
2023-07-04 07:19:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
main()
|