Skip to content

Commit

Permalink
fixed topo beam order
Browse files Browse the repository at this point in the history
  • Loading branch information
obucklin committed Nov 4, 2024
1 parent efb12c1 commit 1fc2ad1
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 16 deletions.
20 changes: 11 additions & 9 deletions src/compas_timber/connections/solver.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import itertools
import math
import stat

from compas.geometry import Point
from compas.geometry import add_vectors
Expand Down Expand Up @@ -109,7 +110,8 @@ def find_intersecting_pairs(cls, beams, rtree=False, max_distance=0.0):
"""
return find_neighboring_beams(beams, inflate_by=max_distance) if rtree else itertools.combinations(beams, 2)

def find_topology(self, beam_a, beam_b, tol=TOLERANCE, max_distance=None):
@staticmethod
def find_topology(beam_a, beam_b, tol=TOLERANCE, max_distance=None):
"""If `beam_a` and `beam_b` intersect within the given `max_distance`, return the topology type of the intersection.
If the topology is role-sensitive, the method outputs the beams in a consistent specific order
Expand All @@ -133,7 +135,7 @@ def find_topology(self, beam_a, beam_b, tol=TOLERANCE, max_distance=None):
"""

tol = self.TOLERANCE # TODO: change to a unit-sensitive value
tol = ConnectionSolver.TOLERANCE # TODO: change to a unit-sensitive value
angtol = 1e-3

a1, a2 = beam_a.centerline
Expand All @@ -151,12 +153,12 @@ def find_topology(self, beam_a, beam_b, tol=TOLERANCE, max_distance=None):
if parallel:
pa = a1
pb = closest_point_on_line(a1, [b1, b2])
if self._exceed_max_distance(pa, pb, max_distance, tol):
if ConnectionSolver._exceed_max_distance(pa, pb, max_distance, tol):
return JointTopology.TOPO_UNKNOWN, None, None

# check if any ends meet
comb = [[0, 0], [0, 1], [1, 0], [1, 1]]
meet = [not self._exceed_max_distance([a1, a2][ia], [b1, b2][ib], max_distance, tol) for ia, ib in comb]
meet = [not ConnectionSolver._exceed_max_distance([a1, a2][ia], [b1, b2][ib], max_distance, tol) for ia, ib in comb]
if sum(meet) != 1:
return JointTopology.TOPO_UNKNOWN, None, None

Expand All @@ -181,9 +183,9 @@ def find_topology(self, beam_a, beam_b, tol=TOLERANCE, max_distance=None):
vna = cross_vectors(va, vn)
vnb = cross_vectors(vb, vn)

ta = self._calc_t([a1, a2], [b1, vnb])
ta = ConnectionSolver._calc_t([a1, a2], [b1, vnb])
pa = Point(*add_vectors(a1, scale_vector(va, ta)))
tb = self._calc_t([b1, b2], [a1, vna])
tb = ConnectionSolver._calc_t([b1, b2], [a1, vna])
pb = Point(*add_vectors(b1, scale_vector(vb, tb)))

# for max_distance calculations, limit intersection point to line segment
Expand All @@ -196,12 +198,12 @@ def find_topology(self, beam_a, beam_b, tol=TOLERANCE, max_distance=None):
if tb > 1:
pb = b2

if self._exceed_max_distance(pa, pb, max_distance, tol):
if ConnectionSolver._exceed_max_distance(pa, pb, max_distance, tol):
return JointTopology.TOPO_UNKNOWN, None, None

# topologies:
xa = self._is_near_end(ta, beam_a.centerline.length, max_distance or 0, tol)
xb = self._is_near_end(tb, beam_b.centerline.length, max_distance or 0, tol)
xa = ConnectionSolver._is_near_end(ta, beam_a.centerline.length, max_distance or 0, tol)
xb = ConnectionSolver._is_near_end(tb, beam_b.centerline.length, max_distance or 0, tol)

# L-joint (both meeting at ends)
if xa and xb:
Expand Down
11 changes: 4 additions & 7 deletions src/compas_timber/design/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ def get_topology_rules(rules, use_defaults=False):
JointTopology.TOPO_T: TopologyRule(JointTopology.TOPO_T, TButtJoint),
JointTopology.TOPO_X: TopologyRule(JointTopology.TOPO_X, XHalfLapJoint),
}
# else:
# topo_rules = {JointTopology.TOPO_L: TopologyRule(JointTopology.TOPO_L, None),
# JointTopology.TOPO_T: TopologyRule(JointTopology.TOPO_T, None),
# JointTopology.TOPO_X: TopologyRule(JointTopology.TOPO_X, None)}
for rule in rules: # separate category and topo and direct joint rules
if rule.__class__.__name__ == "TopologyRule":
topo_rules[rule.topology_type] = TopologyRule(
Expand Down Expand Up @@ -110,7 +106,8 @@ def joints_from_beams_and_rules(beams, rules, max_distance=1e-6):

if not match_found:
for rule in JointRule.get_topology_rules(rules): # see if pair is used in a topology rule
if rule.comply(pair):
comply, pair = rule.comply(pair)
if comply:
match_found = True
joint_defs.append(JointDefinition(rule.joint_type, pair, **rule.kwargs))
break
Expand Down Expand Up @@ -235,8 +232,8 @@ def __repr__(self):
def comply(self, beams, max_distance=1e-3):
try:
beams = list(beams)
solver = ConnectionSolver()
return self.topology_type == solver.find_topology(beams[0], beams[1], max_distance=max_distance)[0]
topo_results = ConnectionSolver.find_topology(beams[0], beams[1], max_distance=max_distance)
return (self.topology_type == topo_results[0], [topo_results[1], topo_results[2]]) # comply, if topologies match, reverse if the beam order should be switched
except KeyError:
return False

Expand Down

0 comments on commit 1fc2ad1

Please sign in to comment.