Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -99,6 +100,9 @@ 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.

### Removed


Expand Down
7 changes: 5 additions & 2 deletions src/compas_timber/connections/l_lap.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -64,8 +66,9 @@
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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure that's enough? TOL.absolute is like 1e-9 iirc..

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)

Check warning on line 71 in src/compas_timber/connections/l_lap.py

View check run for this annotation

Codecov / codecov/patch

src/compas_timber/connections/l_lap.py#L69-L71

Added lines #L69 - L71 were not covered by tests

def add_features(self):
"""Adds the required joint features to both beams.
Expand Down
23 changes: 12 additions & 11 deletions src/compas_timber/fabrication/lap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -409,7 +409,7 @@
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]

Expand Down Expand Up @@ -441,11 +441,14 @@
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)
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)

Check warning on line 445 in src/compas_timber/fabrication/lap.py

View check run for this annotation

Codecov / codecov/patch

src/compas_timber/fabrication/lap.py#L445

Added line #L445 was not covered by tests
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
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)
Expand Down Expand Up @@ -739,25 +742,23 @@
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)
end_frame.yaxis = -end_frame.yaxis
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)

Check warning on line 761 in src/compas_timber/fabrication/lap.py

View check run for this annotation

Codecov / codecov/patch

src/compas_timber/fabrication/lap.py#L761

Added line #L761 was not covered by tests

if self.machining_limits["FaceLimitedFront"]:
front_frame = bottom_frame.rotated(math.radians(self.lead_angle), bottom_frame.xaxis, point=bottom_frame.point)
Expand Down
8 changes: 4 additions & 4 deletions src/compas_timber/fabrication/pocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down
28 changes: 0 additions & 28 deletions src/compas_timber/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
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
Expand Down Expand Up @@ -296,32 +295,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):
Copy link
Copy Markdown
Contributor

@chenkasirer chenkasirer Jul 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add to changelog in the Removed section

EDIT: you already did.. sorry!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already did. It should appear to you

"""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 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)
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.

Expand Down Expand Up @@ -432,7 +405,6 @@ def is_point_in_polyline(point, polyline, in_plane=True, tol=TOL):
"intersection_line_beam_param",
"classify_polyline_segments",
"distance_segment_segment",
"angle_vectors_projected",
"is_polyline_clockwise",
"correct_polyline_direction",
"get_polyline_segment_perpendicular_vector",
Expand Down