From 2287780c047e1feb0556d27a5e51a0dca07f9fa2 Mon Sep 17 00:00:00 2001 From: panos ppchr Date: Tue, 6 May 2025 17:56:51 +0200 Subject: [PATCH 01/12] add tol in extensions --- src/compas_timber/connections/l_lap.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/compas_timber/connections/l_lap.py b/src/compas_timber/connections/l_lap.py index 6f39640e44..266cab2b6a 100644 --- a/src/compas_timber/connections/l_lap.py +++ b/src/compas_timber/connections/l_lap.py @@ -1,3 +1,5 @@ +from compas.tolerance import TOL + from compas_timber.errors import BeamJoiningError from compas_timber.fabrication import JackRafterCut from compas_timber.fabrication import Lap @@ -64,8 +66,9 @@ def add_extensions(self): raise BeamJoiningError(self.elements, self, debug_info=str(ae), debug_geometries=geometries) except Exception as ex: raise BeamJoiningError(self.elements, self, debug_info=str(ex)) - self.main_beam.add_blank_extension(start_main, end_main, self.main_beam_guid) - self.cross_beam.add_blank_extension(start_cross, end_cross, self.cross_beam_guid) + tol = TOL.absolute + self.main_beam.add_blank_extension(start_main + tol, end_main + tol, self.main_beam_guid) + self.cross_beam.add_blank_extension(start_cross + tol, end_cross + tol, self.cross_beam_guid) def add_features(self): """Adds the required joint features to both beams. From c51c008e65c3d7d181c3f82dcd6297906814f325 Mon Sep 17 00:00:00 2001 From: panos ppchr Date: Tue, 6 May 2025 17:57:07 +0200 Subject: [PATCH 02/12] return none if projection fails --- src/compas_timber/utils/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compas_timber/utils/__init__.py b/src/compas_timber/utils/__init__.py index 784cf6e59a..b4be70fd8b 100644 --- a/src/compas_timber/utils/__init__.py +++ b/src/compas_timber/utils/__init__.py @@ -20,6 +20,7 @@ from compas.geometry import intersection_line_plane from compas.geometry import closest_point_on_segment from compas.geometry import intersection_line_line +from compas.tolerance import TOL def intersection_line_line_param(line1, line2, max_distance=1e-6, limit_to_segments=True, tol=1e-6): @@ -307,7 +308,7 @@ def angle_vectors_projected(vector_a, vector_b, normal): Returns ------- float - The angle between the two projected vectors + The angle between the two projected vectors. If any of the projections results in a zero vector, None is returned. """ if isinstance(normal, (Plane, Frame)): normal = normal.normal @@ -315,6 +316,8 @@ def angle_vectors_projected(vector_a, vector_b, normal): projection = Projection.from_plane(Plane(Point(0, 0, 0), normal)) proj_vect_a = vector_a.transformed(projection) proj_vect_b = vector_b.transformed(projection) + if TOL.is_zero(proj_vect_a.length) or TOL.is_zero(proj_vect_b.length): + return None return angle_vectors_signed(proj_vect_a, proj_vect_b, normal, deg=True) From e674f8793419bcdfb495a5ecdbc4e430e3c3cb11 Mon Sep 17 00:00:00 2001 From: panos ppchr Date: Tue, 6 May 2025 17:57:33 +0200 Subject: [PATCH 03/12] fix minor bugs --- src/compas_timber/fabrication/lap.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/compas_timber/fabrication/lap.py b/src/compas_timber/fabrication/lap.py index 3661a0420e..7d54cdb256 100644 --- a/src/compas_timber/fabrication/lap.py +++ b/src/compas_timber/fabrication/lap.py @@ -409,7 +409,7 @@ def from_volume_and_beam(cls, volume, beam, machining_limits=None, ref_side_inde raise ValueError("Volume must have 6 faces.") # get ref_side of the - if not ref_side_index: + if ref_side_index is None: ref_side_index = cls._get_optimal_ref_side_index(beam, volume) ref_side = beam.ref_sides[ref_side_index] @@ -442,6 +442,8 @@ def from_volume_and_beam(cls, volume, beam, machining_limits=None, ref_side_inde # calculate the inclination of the lap inclination = angle_vectors_projected(zzaxis, front_plane.normal, yyaxis) + if not inclination: + inclination = angle_vectors_signed(zzaxis, ref_side.xaxis, ref_side.normal, deg=True) inclination = 180 + inclination if inclination < 0 else inclination # calculate the slope of the lap @@ -736,10 +738,10 @@ def _planes_from_params_and_beam(self, beam): tol = Tolerance() tol.absolute=1e-3 - if self.machining_limits["FaceLimitedStart"]: - start_frame = self._start_frame_from_params_and_beam(beam) - else: - start_frame = beam.ref_sides[4] + start_frame = self._start_frame_from_params_and_beam(beam) + + top_frame = beam.ref_sides[self.ref_side_index] # top should always be unlimited + top_frame.translate(top_frame.normal * TOL.absolute) if self.machining_limits["FaceLimitedEnd"]: end_frame = start_frame.translated(-start_frame.normal * self.length) @@ -747,14 +749,12 @@ def _planes_from_params_and_beam(self, beam): else: end_frame = beam.ref_sides[5] - top_frame = beam.ref_sides[self.ref_side_index] # top should always be unlimited - if self.machining_limits["FaceLimitedBottom"]: bottom_frame = Frame(start_frame.point, start_frame.zaxis, start_frame.yaxis) angle = angle_vectors_signed(top_frame.xaxis, -start_frame.xaxis, top_frame.yaxis) bottom_frame = bottom_frame.translated(bottom_frame.zaxis * (self.depth/math.sin(angle))) else: - bottom_frame = beam.ref_sides[4] + bottom_frame = beam.opp_side(self.ref_side_index) if self.machining_limits["FaceLimitedFront"]: front_frame = bottom_frame.rotated(math.radians(self.lead_angle), bottom_frame.xaxis, point=bottom_frame.point) From e204627c20f1b9d0c0c4dfd428f560d312793712 Mon Sep 17 00:00:00 2001 From: panos ppchr Date: Tue, 6 May 2025 18:14:17 +0200 Subject: [PATCH 04/12] changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18ff2162ca..d4d22546da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed * Fixed `AttributeError` when deserializing a model with Lap joints. +* Fixed a bug in `compas_timber.fabrication.Lap` where `ref_side_index` failed for `0` by checking for `None` instead. +* Fixed a bug in `compas_timber.fabrication.Lap` to handle the case when the vectors used to calculate the `inclination` angle are perpendicular. +* Adjusted `angle_vectors_projected` function so that it returns `None` if any of the projections results in a zero-vector. + ### Removed From ba92f40b80c99d2fedab9601096f1af3dec73b96 Mon Sep 17 00:00:00 2001 From: panos ppchr <145543755+papachap@users.noreply.github.com> Date: Wed, 14 May 2025 01:02:40 +0200 Subject: [PATCH 05/12] Update src/compas_timber/fabrication/lap.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/compas_timber/fabrication/lap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compas_timber/fabrication/lap.py b/src/compas_timber/fabrication/lap.py index 7d54cdb256..f7a9b61640 100644 --- a/src/compas_timber/fabrication/lap.py +++ b/src/compas_timber/fabrication/lap.py @@ -442,7 +442,7 @@ def from_volume_and_beam(cls, volume, beam, machining_limits=None, ref_side_inde # calculate the inclination of the lap inclination = angle_vectors_projected(zzaxis, front_plane.normal, yyaxis) - if not inclination: + if inclination is None: inclination = angle_vectors_signed(zzaxis, ref_side.xaxis, ref_side.normal, deg=True) inclination = 180 + inclination if inclination < 0 else inclination From 049b475bef0eecc854757e5c0af2b2257354dfc9 Mon Sep 17 00:00:00 2001 From: panos ppchr Date: Mon, 2 Jun 2025 14:36:21 +0200 Subject: [PATCH 06/12] replace angle_vectors_projected with core function --- src/compas_timber/fabrication/lap.py | 6 +++--- src/compas_timber/fabrication/pocket.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/compas_timber/fabrication/lap.py b/src/compas_timber/fabrication/lap.py index fd8244d2fb..cefa8e44fc 100644 --- a/src/compas_timber/fabrication/lap.py +++ b/src/compas_timber/fabrication/lap.py @@ -9,6 +9,7 @@ from compas.geometry import Point from compas.geometry import Polyhedron from compas.geometry import Vector +from compas.geometry import angle_vectors_projected from compas.geometry import angle_vectors_signed from compas.geometry import distance_point_plane from compas.geometry import distance_point_point @@ -21,7 +22,6 @@ from compas.tolerance import Tolerance from compas_timber.errors import FeatureApplicationError -from compas_timber.utils import angle_vectors_projected from .btlx import BTLxProcessing from .btlx import BTLxProcessingParams @@ -441,13 +441,13 @@ def from_volume_and_beam(cls, volume, beam, machining_limits=None, ref_side_inde angle = angle_vectors_signed(-yyaxis, ref_side.xaxis, ref_side.normal, deg=True) # calculate the inclination of the lap - inclination = angle_vectors_projected(zzaxis, front_plane.normal, yyaxis) + inclination = angle_vectors_projected(zzaxis, front_plane.normal, yyaxis, deg=True) if inclination is None: inclination = angle_vectors_signed(zzaxis, ref_side.xaxis, ref_side.normal, deg=True) inclination = 180 + inclination if inclination < 0 else inclination # calculate the slope of the lap - slope = angle_vectors_projected(-ref_side.normal, bottom_plane.normal, start_plane.normal) + slope = angle_vectors_projected(-ref_side.normal, bottom_plane.normal, start_plane.normal, deg=True) # calculate length, width and depth length = distance_point_plane(start_plane.point, end_plane) diff --git a/src/compas_timber/fabrication/pocket.py b/src/compas_timber/fabrication/pocket.py index 6a6d33b631..d59e0ed79a 100644 --- a/src/compas_timber/fabrication/pocket.py +++ b/src/compas_timber/fabrication/pocket.py @@ -10,6 +10,7 @@ from compas.geometry import Polyhedron from compas.geometry import Vector from compas.geometry import angle_vectors +from compas.geometry import angle_vectors_projected from compas.geometry import angle_vectors_signed from compas.geometry import dot_vectors from compas.geometry import intersection_plane_plane_plane @@ -19,7 +20,6 @@ from compas.tolerance import Tolerance from compas_timber.errors import FeatureApplicationError -from compas_timber.utils import angle_vectors_projected from .btlx import BTLxProcessing from .btlx import BTLxProcessingParams @@ -354,17 +354,17 @@ def from_volume_and_element(cls, volume, element, machining_limits=None, ref_sid yyaxis = Vector.from_start_end(start_point, back_point) # calculate the angle of the pocket - angle = angle_vectors_projected(ref_side.xaxis, xxaxis, ref_side.normal) + angle = angle_vectors_projected(ref_side.xaxis, xxaxis, ref_side.normal, deg=True) # x'-axis and y'-axis (see BTLx Documentation p.46) xaxis = ref_side.xaxis.rotated(math.radians(angle), ref_side.normal) yaxis = ref_side.yaxis.rotated(math.radians(angle), ref_side.normal) # calculate the inclination of the pocket - inclination = angle_vectors_projected(xaxis, xxaxis, yaxis) + inclination = angle_vectors_projected(xaxis, xxaxis, yaxis, deg=True) # calculate the slope of the pocket - slope = angle_vectors_projected(yaxis, yyaxis, xxaxis) + slope = angle_vectors_projected(yaxis, yyaxis, xxaxis, deg=True) # calculate internal_angle internal_angle = angle_vectors_signed(xxaxis, yyaxis, ref_side.normal, deg=True) From 68fcb2e4c6f6465fabb7eb9a9e4d69cd6cdcfd77 Mon Sep 17 00:00:00 2001 From: panos ppchr Date: Mon, 2 Jun 2025 14:43:09 +0200 Subject: [PATCH 07/12] remove function from utils module --- src/compas_timber/utils/__init__.py | 31 ----------------------------- 1 file changed, 31 deletions(-) diff --git a/src/compas_timber/utils/__init__.py b/src/compas_timber/utils/__init__.py index b4be70fd8b..36621ad9ce 100644 --- a/src/compas_timber/utils/__init__.py +++ b/src/compas_timber/utils/__init__.py @@ -16,11 +16,9 @@ from compas.geometry import subtract_vectors from compas.geometry import Frame from compas.geometry import Transformation -from compas.geometry import Projection from compas.geometry import intersection_line_plane from compas.geometry import closest_point_on_segment from compas.geometry import intersection_line_line -from compas.tolerance import TOL def intersection_line_line_param(line1, line2, max_distance=1e-6, limit_to_segments=True, tol=1e-6): @@ -293,34 +291,6 @@ def distance_segment_segment(segment_a, segment_b): return distance_point_point(pt_seg_a, pt_seg_b) -def angle_vectors_projected(vector_a, vector_b, normal): - """Computes the angle between two vectors projected onto a plane defined by a normal vector. - - Parameters - ---------- - vector_a : :class:`compas.geometry.Vector` - The first vector. - vector_b : :class:`compas.geometry.Vector` - The second vector. - normal : :class:`compas.geometry.Vector` or :class:`compas.geometry.Plane` or :class:`compas.geometry.Frame` - The normal vector of the plane to project the vectors onto. - - Returns - ------- - float - The angle between the two projected vectors. If any of the projections results in a zero vector, None is returned. - """ - if isinstance(normal, (Plane, Frame)): - normal = normal.normal - - projection = Projection.from_plane(Plane(Point(0, 0, 0), normal)) - proj_vect_a = vector_a.transformed(projection) - proj_vect_b = vector_b.transformed(projection) - if TOL.is_zero(proj_vect_a.length) or TOL.is_zero(proj_vect_b.length): - return None - return angle_vectors_signed(proj_vect_a, proj_vect_b, normal, deg=True) - - def is_polyline_clockwise(polyline, normal_vector): """Check if a polyline is clockwise. If the polyline is open, it is closed before the check. @@ -377,7 +347,6 @@ def correct_polyline_direction(polyline, normal_vector, clockwise=False): "intersection_line_beam_param", "classify_polyline_segments", "distance_segment_segment", - "angle_vectors_projected", "is_polyline_clockwise", "correct_polyline_direction", ] From 5335dcc32744b0afc65a5f8cf37d58a57a496bc6 Mon Sep 17 00:00:00 2001 From: panos ppchr Date: Tue, 8 Jul 2025 13:14:49 +0200 Subject: [PATCH 08/12] temporary fix for angle_vectors_projected() --- src/compas_timber/fabrication/lap.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compas_timber/fabrication/lap.py b/src/compas_timber/fabrication/lap.py index 831326eff5..3dcf8ddc26 100644 --- a/src/compas_timber/fabrication/lap.py +++ b/src/compas_timber/fabrication/lap.py @@ -441,9 +441,10 @@ def from_volume_and_beam(cls, volume, beam, machining_limits=None, ref_side_inde angle = angle_vectors_signed(-yyaxis, ref_side.xaxis, ref_side.normal, deg=True) # calculate the inclination of the lap - inclination = angle_vectors_projected(zzaxis, front_plane.normal, yyaxis, deg=True) - if inclination is None: + if TOL.is_zero(abs(yyaxis.dot(zzaxis))) or TOL.is_zero(abs(yyaxis.dot(front_plane.normal))): # TODO: follow changes in compas.geometry and update this acordingly inclination = angle_vectors_signed(zzaxis, ref_side.xaxis, ref_side.normal, deg=True) + else: + inclination = angle_vectors_projected(zzaxis, front_plane.normal, yyaxis, deg=True) inclination = 180 + inclination if inclination < 0 else inclination # calculate the slope of the lap From 03f0e6794edfb4c151ca0e0027aa92c69add9316 Mon Sep 17 00:00:00 2001 From: panos ppchr <145543755+papachap@users.noreply.github.com> Date: Tue, 8 Jul 2025 13:21:49 +0200 Subject: [PATCH 09/12] Update src/compas_timber/fabrication/lap.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/compas_timber/fabrication/lap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compas_timber/fabrication/lap.py b/src/compas_timber/fabrication/lap.py index 3dcf8ddc26..b7d549e936 100644 --- a/src/compas_timber/fabrication/lap.py +++ b/src/compas_timber/fabrication/lap.py @@ -441,7 +441,7 @@ def from_volume_and_beam(cls, volume, beam, machining_limits=None, ref_side_inde angle = angle_vectors_signed(-yyaxis, ref_side.xaxis, ref_side.normal, deg=True) # calculate the inclination of the lap - if TOL.is_zero(abs(yyaxis.dot(zzaxis))) or TOL.is_zero(abs(yyaxis.dot(front_plane.normal))): # TODO: follow changes in compas.geometry and update this acordingly + if TOL.is_zero(abs(yyaxis.dot(zzaxis))) or TOL.is_zero(abs(yyaxis.dot(front_plane.normal))): # TODO: follow changes in compas.geometry and update this accordingly inclination = angle_vectors_signed(zzaxis, ref_side.xaxis, ref_side.normal, deg=True) else: inclination = angle_vectors_projected(zzaxis, front_plane.normal, yyaxis, deg=True) From 9dd732bdd878484927e19e5f44bf2f4f6b2d40cf Mon Sep 17 00:00:00 2001 From: panos ppchr Date: Tue, 8 Jul 2025 13:26:10 +0200 Subject: [PATCH 10/12] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 960f23172f..24e8a4ae2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Removed Grasshopper after-install plugin. Components should be installed via Rhino's Plugin Manager. * Removed `get_face_most_towards_beam` from `Joint` as not used anywhere. * Removed `get_face_most_ortho_to_beam` from `Joint` as not used anywhere. +* Removed `angle_vectors_projected` from `compas_timber.utils` since this has been upstreamed to core. ## [0.16.2] 2025-05-07 From 1b62317e21dceaee2d0235f15b1193a20684243e Mon Sep 17 00:00:00 2001 From: panos ppchr <145543755+papachap@users.noreply.github.com> Date: Tue, 8 Jul 2025 13:34:40 +0200 Subject: [PATCH 11/12] Update CHANGELOG.md Co-authored-by: Chen Kasirer --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24e8a4ae2b..e46cce2a88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -102,7 +102,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Fixed `AttributeError` when deserializing a model with Lap joints. * Fixed a bug in `compas_timber.fabrication.Lap` where `ref_side_index` failed for `0` by checking for `None` instead. * Fixed a bug in `compas_timber.fabrication.Lap` to handle the case when the vectors used to calculate the `inclination` angle are perpendicular. -* Adjusted `angle_vectors_projected` function so that it returns `None` if any of the projections results in a zero-vector. ### Removed From ac25c2d22a559761c7465f8b5c23f67e2cf555ba Mon Sep 17 00:00:00 2001 From: panos ppchr <145543755+papachap@users.noreply.github.com> Date: Tue, 8 Jul 2025 13:36:15 +0200 Subject: [PATCH 12/12] Update src/compas_timber/fabrication/lap.py Co-authored-by: Chen Kasirer --- src/compas_timber/fabrication/lap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compas_timber/fabrication/lap.py b/src/compas_timber/fabrication/lap.py index b7d549e936..207ead53aa 100644 --- a/src/compas_timber/fabrication/lap.py +++ b/src/compas_timber/fabrication/lap.py @@ -441,7 +441,7 @@ def from_volume_and_beam(cls, volume, beam, machining_limits=None, ref_side_inde angle = angle_vectors_signed(-yyaxis, ref_side.xaxis, ref_side.normal, deg=True) # calculate the inclination of the lap - if TOL.is_zero(abs(yyaxis.dot(zzaxis))) or TOL.is_zero(abs(yyaxis.dot(front_plane.normal))): # TODO: follow changes in compas.geometry and update this accordingly + if TOL.is_zero(yyaxis.dot(zzaxis)) or TOL.is_zero(yyaxis.dot(front_plane.normal)): # TODO: follow changes in compas.geometry and update this accordingly inclination = angle_vectors_signed(zzaxis, ref_side.xaxis, ref_side.normal, deg=True) else: inclination = angle_vectors_projected(zzaxis, front_plane.normal, yyaxis, deg=True)