Skip to content

Commit

Permalink
initial PR
Browse files Browse the repository at this point in the history
  • Loading branch information
obucklin committed Oct 24, 2023
1 parent 31654be commit cd685ff
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 128 deletions.
20 changes: 4 additions & 16 deletions src/compas_timber/connections/french_ridge_lap.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import math



from compas_timber.parts import BeamExtensionFeature
from compas_timber.parts import BeamTrimmingFeature

Expand Down Expand Up @@ -122,27 +121,16 @@ def check_geometry(self):

if abs(angle_vectors(normal, self.beam_b.frame.yaxis) - math.pi) < 0.001:
indices.append(3)
elif abs(angle_vectors(normal, self.beam_b.frame.zaxis)- math.pi) < 0.001:
elif abs(angle_vectors(normal, self.beam_b.frame.zaxis) - math.pi) < 0.001:
indices.append(4)
elif abs(angle_vectors(normal, -self.beam_b.frame.yaxis)- math.pi) < 0.001:
elif abs(angle_vectors(normal, -self.beam_b.frame.yaxis) - math.pi) < 0.001:
indices.append(1)
elif abs(angle_vectors(normal, -self.beam_b.frame.zaxis)- math.pi) < 0.001:
elif abs(angle_vectors(normal, -self.beam_b.frame.zaxis) - math.pi) < 0.001:
indices.append(2)
else:
raise ("part not aligned with corner normal, no French Ridge Lap possible")

self.reference_face_indices = {
str(self.beam_a.key): indices[0],
str(self.beam_b.key): indices[1]
}








self.reference_face_indices = {str(self.beam_a.key): indices[0], str(self.beam_b.key): indices[1]}

def add_features(self):
"""Adds the required extension and trimming features to both beams.
Expand Down
120 changes: 69 additions & 51 deletions src/compas_timber/fabrication/btlx.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,26 @@ class BTLx(object):
ANGLE_PRECISION = 3

def __init__(self, assembly):

self.assembly = assembly
self.joints = []
self.parts = {}
self._test = []
self.btlx_joints = []
self._blanks = None
self.history = {
"CompanyName":"Gramazio Kohler Research",
"ProgramName":"COMPAS_Timber",
"ProgramVersion":"Compas: {}".format(compas.__version__),
"ComputerName":"{}".format(os.getenv("computername")),
"UserName":"{}".format(os.getenv("USERNAME")),
"FileName":"",
"Date":"{}".format(date.today()),
"Time":"{}".format(datetime.now().strftime("%H:%M:%S")),
"Comment":"",
}
self.history = {
"CompanyName": "Gramazio Kohler Research",
"ProgramName": "COMPAS_Timber",
"ProgramVersion": "Compas: {}".format(compas.__version__),
"ComputerName": "{}".format(os.getenv("computername")),
"UserName": "{}".format(os.getenv("USERNAME")),
"FileName": "",
"Date": "{}".format(date.today()),
"Time": "{}".format(datetime.now().strftime("%H:%M:%S")),
"Comment": "",
}
self.process_assembly()
self.process_joints()


def __str__(self):
"""returns a pretty xml sting for visualization in GH, Terminal, etc"""
self.ET_element = ET.Element("BTLx", self.file_attributes)
Expand All @@ -76,7 +74,6 @@ def __str__(self):

return MD.parseString(ET.tostring(self.ET_element)).toprettyxml(indent=" ")


def process_assembly(self):
for joint in self.assembly.joints:
btlx_joint = BTLxJoint(joint)
Expand All @@ -103,23 +100,23 @@ def blanks(self):

@property
def file_attributes(self):
return OrderedDict([
("xmlns", "https://www.design2machine.com"),
("Version", "2.0.0"),
("Language", "en"),
("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"),
("xsi:schemaLocation", "https://www.design2machine.com https://www.design2machine.com/btlx/btlx_2_0_0.xsd")
])

return OrderedDict(
[
("xmlns", "https://www.design2machine.com"),
("Version", "2.0.0"),
("Language", "en"),
("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"),
(
"xsi:schemaLocation",
"https://www.design2machine.com https://www.design2machine.com/btlx/btlx_2_0_0.xsd",
),
]
)

@property
def file_history(self):
file_history = ET.Element("FileHistory")
file_history.append(ET.Element(
"InitialExportProgram",
self.history
)
)
file_history.append(ET.Element("InitialExportProgram", self.history))
return file_history


Expand Down Expand Up @@ -148,11 +145,29 @@ def reference_surfaces(self): # TODO: fix Beam.shape definition and update this
if len(self._reference_surfaces) != 6:
self._reference_surfaces = {
"1": Frame(self.blank_frame.point, self.blank_frame.xaxis, self.blank_frame.zaxis),
"2": Frame(self.blank_frame.point + self.blank_frame.yaxis * self.width, self.blank_frame.xaxis, -self.blank_frame.yaxis),
"3": Frame(self.blank_frame.point + self.blank_frame.yaxis * self.width + self.blank_frame.zaxis * self.height, self.blank_frame.xaxis, -self.blank_frame.zaxis),
"4": Frame(self.blank_frame.point + self.blank_frame.zaxis * self.height, self.blank_frame.xaxis, self.blank_frame.yaxis),
"2": Frame(
self.blank_frame.point + self.blank_frame.yaxis * self.width,
self.blank_frame.xaxis,
-self.blank_frame.yaxis,
),
"3": Frame(
self.blank_frame.point + self.blank_frame.yaxis * self.width + self.blank_frame.zaxis * self.height,
self.blank_frame.xaxis,
-self.blank_frame.zaxis,
),
"4": Frame(
self.blank_frame.point + self.blank_frame.zaxis * self.height,
self.blank_frame.xaxis,
self.blank_frame.yaxis,
),
"5": Frame(self.blank_frame.point, self.blank_frame.zaxis, self.blank_frame.yaxis),
"6": Frame(self.blank_frame.point + self.blank_frame.xaxis * self.blank_length + self.blank_frame.yaxis * self.width, self.blank_frame.zaxis, -self.blank_frame.yaxis)
"6": Frame(
self.blank_frame.point
+ self.blank_frame.xaxis * self.blank_length
+ self.blank_frame.yaxis * self.width,
self.blank_frame.zaxis,
-self.blank_frame.yaxis,
),
}
return self._reference_surfaces

Expand Down Expand Up @@ -183,9 +198,9 @@ def attr(self):
"TimberGrade": "",
"QualityGrade": "",
"Count": "1",
"Length": "{:.{prec}f}".format( self.blank_length, prec=BTLx.POINT_PRECISION),
"Height": "{:.{prec}f}".format( self.height, prec=BTLx.POINT_PRECISION),
"Width": "{:.{prec}f}".format( self.width, prec=BTLx.POINT_PRECISION),
"Length": "{:.{prec}f}".format(self.blank_length, prec=BTLx.POINT_PRECISION),
"Height": "{:.{prec}f}".format(self.height, prec=BTLx.POINT_PRECISION),
"Width": "{:.{prec}f}".format(self.width, prec=BTLx.POINT_PRECISION),
"Weight": "0",
"ProcessingQuality": "automatic",
"StoreyType": "",
Expand Down Expand Up @@ -246,7 +261,7 @@ def et_shape(self):
return shape

@property
def shape_strings(self): #TODO: update for different Brep creation environments
def shape_strings(self): # TODO: update for different Brep creation environments
if not self._shape_strings:
brep_vertex_points = []
brep_indices = []
Expand All @@ -264,7 +279,7 @@ def shape_strings(self): #TODO: update for different Brep creation enviro
brep_indices.append(-1)
brep_indices.pop(-1)
except:
pass
pass
brep_indices_string = " "
for index in brep_indices:
brep_indices_string += str(index) + " "
Expand All @@ -273,12 +288,13 @@ def shape_strings(self): #TODO: update for different Brep creation enviro
for point in brep_vertex_points:
xform = Transformation.from_frame_to_frame(self.blank_frame, Frame((0, 0, 0), (1, 0, 0), (0, 1, 0)))
point.transform(xform)
brep_vertices_string += "{:.{prec}f} {:.{prec}f} {:.{prec}f} ".format( point.x, point.y, point.z, prec = BTLx.POINT_PRECISION )
brep_vertices_string += "{:.{prec}f} {:.{prec}f} {:.{prec}f} ".format(
point.x, point.y, point.z, prec=BTLx.POINT_PRECISION
)
self._shape_strings = [brep_indices_string, brep_vertices_string]
return self._shape_strings



class BTLxJoint(object):
REGISTERED_JOINTS = {}

Expand All @@ -289,23 +305,26 @@ def __init__(self, joint):

@property
def ends(self):
if len(self._ends) ==0:
if len(self._ends) == 0:
for index, beam in enumerate(self.joint.beams):
start_distance = min([
beam.centerline.start.distance_to_point(self.joint.beams[index - 1].centerline.start),
beam.centerline.start.distance_to_point(self.joint.beams[index - 1].centerline.end)
])
end_distance = min([
beam.centerline.end.distance_to_point(self.joint.beams[index - 1].centerline.start),
beam.centerline.end.distance_to_point(self.joint.beams[index - 1].centerline.end)
])
start_distance = min(
[
beam.centerline.start.distance_to_point(self.joint.beams[index - 1].centerline.start),
beam.centerline.start.distance_to_point(self.joint.beams[index - 1].centerline.end),
]
)
end_distance = min(
[
beam.centerline.end.distance_to_point(self.joint.beams[index - 1].centerline.start),
beam.centerline.end.distance_to_point(self.joint.beams[index - 1].centerline.end),
]
)
if start_distance < end_distance:
self._ends[str(beam.key)] = "start"
else:
self._ends[str(beam.key)] = "end"
return self._ends


@property
def type(self):
return type(self.joint)
Expand All @@ -323,24 +342,23 @@ def register_joint(cls, joint_type, process_type):
cls.REGISTERED_JOINTS[str(joint_type)] = process_type



class BTLxProcess(object):

"""
Generic class for BTLx Processes.
This should be instantiated and appended to BTLxPart.processes in a specific btlx_process class (eg BTLxJackCut)
"""

def __init__(self, name, attr, params):
self.name = name
self.attr = attr
self.params = params


@property
def et_element(self):
element = ET.Element(self.name, self.attr)
for key, value in self.params.items():
child = ET.Element(key)
child.text = (value)
child.text = value
element.append(child)
return element
45 changes: 21 additions & 24 deletions src/compas_timber/fabrication/btlx_french_ridge_lap.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
from compas_timber.fabrication import BTLx
from compas_timber.fabrication import BTLxJoint
from compas_timber.fabrication import BTLxProcess
#from compas_timber.fabrication import BTLx

# from compas_timber.fabrication import BTLx


class BTLxFrenchRidgeLap(object):
PROCESS_TYPE = "FrenchRidgeLap"
def __init__(self, part, joint, is_top, end):

def __init__(self, part, joint, is_top, end):
self.part = part
for beam in joint.beams:
if beam is part.beam:
Expand Down Expand Up @@ -71,45 +73,43 @@ def drill_hole(self):
else:
return "no"


def process_joints(self):
"""
This property is required for all process types. It returns a dict with the geometric parameters to fabricate the joint. Use OrderedDict to maintain original order
"""
self.get_params()

self.process_parameters = OrderedDict([
("Orientation", str(self.orientation)),
("StartX", "{:.{prec}f}".format(self.startX, prec = BTLx.POINT_PRECISION)),
("Angle", "{:.{prec}f}".format(self.angle, prec = BTLx.POINT_PRECISION)),
("RefPosition", self.ref_edge),
("Drillhole", self.drill_hole),
("DrillholeDiam", "{:.{prec}f}".format(self.drill_hole_diameter, prec = BTLx.POINT_PRECISION)),
])

self.process_parameters = OrderedDict(
[
("Orientation", str(self.orientation)),
("StartX", "{:.{prec}f}".format(self.startX, prec=BTLx.POINT_PRECISION)),
("Angle", "{:.{prec}f}".format(self.angle, prec=BTLx.POINT_PRECISION)),
("RefPosition", self.ref_edge),
("Drillhole", self.drill_hole),
("DrillholeDiam", "{:.{prec}f}".format(self.drill_hole_diameter, prec=BTLx.POINT_PRECISION)),
]
)

def get_params(self):
"""
This is an internal method to generate process parameters
"""



other_vector = self.other_beam.frame.xaxis
if self.btlx_joint.ends[str(self.other_beam.key)] == "end":
other_vector = - other_vector
other_vector = -other_vector

self.angle_rad = angle_vectors_signed(self.ref_face.xaxis, other_vector, self.ref_face.normal)

if self.orientation == "start":
if self.angle_rad < math.pi/2 and self.angle_rad > - math.pi/2:
if self.angle_rad < math.pi / 2 and self.angle_rad > -math.pi / 2:
raise Exception("french ridge lap joint beams must join at 90-180 degrees")
elif self.angle_rad < -math.pi/2:
elif self.angle_rad < -math.pi / 2:
self._ref_edge = False
self.angle_rad = abs(self.angle_rad)

else:
if self.angle_rad < -math.pi/2 or self.angle_rad > math.pi/2:
if self.angle_rad < -math.pi / 2 or self.angle_rad > math.pi / 2:
raise Exception("french ridge lap joint beams must join at 90-180 degrees")
elif self.angle_rad < 0:
self.angle_rad = abs(self.angle_rad)
Expand All @@ -120,17 +120,14 @@ def get_params(self):

if self.orientation == "end":
if self._ref_edge:

self.startX = self.part.blank_length - self.startX
else:
self.startX = self.part.blank_length + self.startX

@classmethod
def apply_processes(cls, part, joint, is_top, end):

frl_process = BTLxFrenchRidgeLap(part, joint, is_top, end)

part.processes.append(BTLxProcess(BTLxFrenchRidgeLap.PROCESS_TYPE, frl_process.header_attributes, frl_process.process_parameters))



part.processes.append(
BTLxProcess(BTLxFrenchRidgeLap.PROCESS_TYPE, frl_process.header_attributes, frl_process.process_parameters)
)
Loading

0 comments on commit cd685ff

Please sign in to comment.