Skip to content

Commit

Permalink
WIP-CAP: solved DFace-brep convertion, adapting exporting new structu…
Browse files Browse the repository at this point in the history
…re now
  • Loading branch information
9and3 committed Apr 10, 2024
1 parent 9b4b8a9 commit 69262c8
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 109 deletions.
190 changes: 86 additions & 104 deletions src/gh/diffCheck/diffCheck/df_geometries.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,38 +59,31 @@ def to_rg_point3d(self):
@dataclass
class DFFace:
"""
This class represents a face, in diffCheck, a face is a collection of vertices
This class represents a face, in diffCheck, a face is a collection of vertices.
"""
outer_loop : typing.List[DFVertex]
inner_loops : typing.List[typing.List[DFVertex]]
# just as breps a first outer loop and then inner loops of DFVertices
all_loops : typing.List[typing.List[DFVertex]]
joint_id : int
def __post_init__(self):
if len(self.outer_loop) < 3:
if len(self.all_loops[0]) < 3:
raise ValueError("A face must have at least 3 vertices")
self.outer_loop = self.outer_loop
self.inner_loops = self.inner_loops or []
self.all_loops = self.all_loops or []

self.joint_id = self.joint_id or None
self.__is_joint = False
self.__id = uuid.uuid4().int

self._hastenonmortise = len(self.inner_loops) > 0

self._brepface : rg.BrepFace = None

def __repr__(self):
return f"Face vertices: {len(self.outer_loop)}, Joint: {self.joint_id}, Inner loops: {len(self.inner_loops)}"
return f"Face id: {len(self.id)}, IsJoint: {self.is_joint} Loops: {len(self.all_loops)}"

def __hash__(self):
outer_loop = tuple(tuple(vertex.__dict__.values()) for vertex in self.outer_loop)
inner_loops = tuple(tuple(tuple(vertex.__dict__.values()) for vertex in loop) for loop in self.inner_loops)
outer_loop = tuple(tuple(vertex.__dict__.values()) for vertex in self.all_loops[0])
inner_loops = tuple(tuple(vertex.__dict__.values()) for loop in self.all_loops[1:] for vertex in loop)
return hash((outer_loop, inner_loops))

def __eq__(self, other):
if isinstance(other, DFFace):
is_outer_loop_equal = self.outer_loop == other.outer_loop
is_inner_loops_equal = self.inner_loops == other.inner_loops
return is_outer_loop_equal and is_inner_loops_equal
return self.all_loops == other.all_loops
return False

@staticmethod
Expand All @@ -115,35 +108,20 @@ def from_brep(cls, brep_face: rg.BrepFace, joint_id: int=None):
:param joint_id: The joint id
:return face: The DFFace object
"""
outer_loop = []

face_loop = brep_face.OuterLoop
face_loop_trims = face_loop.Trims

face_curve_loop = brep_face.OuterLoop.To3dCurve()
face_curve_loop = face_curve_loop.ToNurbsCurve()
face_vertices = face_curve_loop.Points

for f_v in face_vertices:
vertex = DFVertex(f_v.X, f_v.Y, f_v.Z)
outer_loop.append(vertex)

inner_loops = []

if brep_face.Loops.Count > 1:
face_loops = brep_face.Loops
for idx, loop in enumerate(face_loops):
loop_trims = loop.Trims
loop_curve = loop.To3dCurve()
loop_curve = loop_curve.ToNurbsCurve()
loop_vertices = loop_curve.Points
inner_loop = []
for l_v in loop_vertices:
vertex = DFVertex(l_v.X, l_v.Y, l_v.Z)
inner_loop.append(vertex)
inner_loops.append(inner_loop)

df_face = cls(outer_loop, inner_loops, joint_id)
all_loops = []

for idx, loop in enumerate(brep_face.Loops):
loop_trims = loop.Trims
loop_curve = loop.To3dCurve()
loop_curve = loop_curve.ToNurbsCurve()
loop_vertices = loop_curve.Points
loop = []
for l_v in loop_vertices:
vertex = DFVertex(l_v.X, l_v.Y, l_v.Z)
loop.append(vertex)
all_loops.append(loop)

df_face = cls(all_loops, joint_id)
df_face._brepface = brep_face

return df_face
Expand All @@ -154,19 +132,26 @@ def to_brep(self):
:return brep_face: The Rhino Brep planar face
"""
# if the DFace was created from a brep face, return the brep face
if self._brepface is not None:
return self._brepface
brep_curves = []

for loop in self.all_loops:
inner_vertices = [rg.Point3d(vertex.x, vertex.y, vertex.z) for vertex in loop]
inner_polyline = rg.Polyline(inner_vertices)
inner_curve = inner_polyline.ToNurbsCurve()
brep_curves.append(inner_curve)

brep = rg.Brep.CreatePlanarBreps(brep_curves, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance)[0]

return brep

# FIXME: the rebuilding of breps with multiple loops is not working yet
outer_vertices : rg.Point3d = [rg.Point3d(vertex.x, vertex.y, vertex.z) for vertex in self.outer_loop]
outer_polyline = rg.Polyline(outer_vertices)
outer_curve = outer_polyline.ToNurbsCurve()
outer_curve = rg.Curve.CreateControlPointCurve(outer_vertices, 1)
trim_loops.append(outer_curve)
outer_brep = rg.Brep.CreatePlanarBreps(outer_curve, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance)[0]
def to_mesh(self):
"""
Convert the face to a Rhino Mesh
return outer_brep
:return mesh: The Rhino Mesh object
"""
mesh = self.to_brep().GetMesh(rg.MeshType.Default)
return mesh

@property
def is_joint(self):
Expand All @@ -180,11 +165,6 @@ def is_joint(self):
def id(self):
return self.__id

@property
def has_tenonmortise(self):
self._hastenonmortise = len(self.inner_loops) > 0
return self._hastenonmortise


@dataclass
class DFBeam:
Expand Down Expand Up @@ -251,43 +231,43 @@ def add_beam(self, beam: DFBeam):
def remove_beam(self, beam_id: int):
self.beams = [beam for beam in self.beams if beam.id != beam_id]

@classmethod
def from_xml(cls, file_path: str):
"""
Create an assembly from an XML file
:param file_path: The path to the XML file
:return assembly: The assembly object
"""
# parse the XML file
tree = ET.parse(file_path)
root = tree.getroot()
beams : typing.List[DFBeam] = []
# @classmethod
# def from_xml(cls, file_path: str):
# """
# Create an assembly from an XML file

# :param file_path: The path to the XML file
# :return assembly: The assembly object
# """
# # parse the XML file
# tree = ET.parse(file_path)
# root = tree.getroot()
# beams : typing.List[DFBeam] = []

name = root.get("name")
for beam_elem in root.findall("Beam"):
beam = DFBeam(beam_elem.get("name"), [])
beam._DFBeam__id = int(beam_elem.get("id"))
for face_elem in beam_elem.findall("Face"):
outer_loop = []
for vertex_elem in face_elem.findall("Vertex"):
vertex = DFVertex(
float(vertex_elem.get("x")),
float(vertex_elem.get("y")),
float(vertex_elem.get("z"))
)
outer_loop.append(vertex)
face = DFFace(outer_loop)
face._DFFace__id = int(face_elem.get("id"))
face._DFFace__is_joint = bool(face_elem.get("is_joint"))
face_joint : str = face_elem.get("joint_id")
if face_joint != "None":
face.joint_id = int(face_joint)
else:
face.joint_id = None
beam.faces.append(face)
beams.append(beam)
return cls(beams, name)
# name = root.get("name")
# for beam_elem in root.findall("Beam"):
# beam = DFBeam(beam_elem.get("name"), [])
# beam._DFBeam__id = int(beam_elem.get("id"))
# for face_elem in beam_elem.findall("Face"):
# outer_loop = []
# for vertex_elem in face_elem.findall("Vertex"):
# vertex = DFVertex(
# float(vertex_elem.get("x")),
# float(vertex_elem.get("y")),
# float(vertex_elem.get("z"))
# )
# outer_loop.append(vertex)
# face = DFFace(outer_loop)
# face._DFFace__id = int(face_elem.get("id"))
# face._DFFace__is_joint = bool(face_elem.get("is_joint"))
# face_joint : str = face_elem.get("joint_id")
# if face_joint != "None":
# face.joint_id = int(face_joint)
# else:
# face.joint_id = None
# beam.faces.append(face)
# beams.append(beam)
# return cls(beams, name)

# FIXME: to be reworked
def to_xml(self):
Expand All @@ -296,11 +276,11 @@ def to_xml(self):
:return xml_string: The pretty XML string
"""
root = ET.Element("Assembly")
root = ET.Element("DFAssembly")
root.set("name", self.name)
# dfbeams
for beam in self.beams:
beam_elem = ET.SubElement(root, "Beam")
beam_elem = ET.SubElement(root, "DFBeam")
beam_elem.set("name", beam.name)
beam_elem.set("id", str(beam.id))
# dffaces
Expand All @@ -310,11 +290,13 @@ def to_xml(self):
face_elem.set("is_joint", str(face.is_joint))
face_elem.set("joint_id", str(face.joint_id))
# dfvertices
for vertex in face.outer_loop:
vertex_elem = ET.SubElement(face_elem, "Vertex")
vertex_elem.set("x", str(vertex.x))
vertex_elem.set("y", str(vertex.y))
vertex_elem.set("z", str(vertex.z))
for loop in face.all_loops:
for vertex in loop:
vertex_elem = ET.SubElement(face_elem, "DFVertex")
vertex_elem.set("x", str(vertex.x))
vertex_elem.set("y", str(vertex.y))
vertex_elem.set("z", str(vertex.z))

tree = ET.ElementTree(root)
xml_string = ET.tostring(root, encoding='unicode')
dom = parseString(xml_string)
Expand Down
8 changes: 3 additions & 5 deletions src/gh/diffCheck/diffCheck/diffCheck_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import Rhino
import Rhino.Geometry as rg
import scriptcontext as sc

import os
import typing
Expand Down Expand Up @@ -39,8 +38,7 @@
o_xml = xml

# show the joint/side faces
joints_faces_breps = [jf.to_brep() for jf in assembly1.all_joint_faces]
sides_faces_breps = [sf.to_brep() for sf in assembly1.all_side_faces]
o_joints = [jf.to_brep() for jf in assembly1.all_joint_faces]
o_sides = [sf.to_brep() for sf in assembly1.all_side_faces]

o_joints = joints_faces_breps
o_sides = sides_faces_breps
o_test1 = beams[0].faces[7].to_brep()
9 changes: 9 additions & 0 deletions src/gh/diffCheck/diffCheck/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#! python3

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

tol=sc.doc.ModelAbsoluteTolerance
breps = Rhino.Geometry.Brep.CreatePlanarBreps(i_crvs, tol)
o_brep = breps[0]

0 comments on commit 69262c8

Please sign in to comment.