Skip to content

Commit

Permalink
added TOPO filter to CategoryRule
Browse files Browse the repository at this point in the history
  • Loading branch information
obucklin committed Mar 11, 2024
1 parent 4975957 commit 2565367
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 16 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Added new `NullJoint`.
* Added new `L_TopologyJointRule`, `T_TopologyJointRule`, `X_TopologyJointRule` GH components
* Added GH component param support functions in `compas_timber.ghpython.ghcomponent_helpers.py`
* Added `topos` attribute to `CategoryRule` to filter when joints get applied

### Changed

Expand All @@ -37,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Made `beam_side_incident` a `staticmethod` of `Joint` and reworked it.
* Extended `DecomposeBeam` component to optionally show beam frame and faces.
* Changed `CategoryJointRule` and `DirectJointRule` to a dynamic interface where joint type is selected with right click menu
* Changed `Assembly` GH component to apply category joints if the detected topology is in `CategoryRule.topos`

### Removed

Expand Down
9 changes: 9 additions & 0 deletions src/compas_timber/ghpython/components/CT_Assembly/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ def get_joints_from_rules(self, beams, rules, topologies):
),
)
continue
if rule.topos and detected_topo not in rule.topos:
msg = "Conflict detected! Beams: {}, {} meet with topology: {} but rule allows: {}"
self.AddRuntimeMessage(
Warning,
msg.format(
beam_a.key, beam_b.key, JointTopology.get_name(detected_topo), [JointTopology.get_name(topo) for topo in rule.topos]
),
)
continue
# sort by category to allow beam role by order (main beam first, cross beam second)
beam_a, beam_b = rule.reorder([beam_a, beam_b])
joints.append(JointDefinition(rule.joint_type, [beam_a, beam_b], **rule.kwargs))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from ghpythonlib.componentbase import executingcomponent as component
from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning
import clr
import System
import inspect
from System.Windows.Forms import ToolStripSeparator
from System.Windows.Forms import ToolStripMenuItem
from collections import OrderedDict

from compas_timber.connections import Joint
from compas_timber.ghpython.ghcomponent_helpers import manage_dynamic_params
Expand All @@ -9,17 +14,30 @@
from compas_timber.ghpython import CategoryRule



class CategoryJointRule(component):
def __init__(self):
super(CategoryJointRule, self).__init__()
self.classes = {}
self.topo_bools = OrderedDict([
("Unknown", False),
("I", False),
("L" , False),
("T" , False),
("X" , False)
])

self.classes = {}
for cls in get_leaf_subclasses(Joint):
self.classes[cls.__name__] = cls

if ghenv.Component.Params.Output[0].NickName == "Rule":
if ghenv.Component.Params.Output[0].NickName == 'Rule':
self.joint_type = None
else:
self.joint_type = self.classes.get(ghenv.Component.Params.Output[0].NickName, None)
parsed_output = ghenv.Component.Params.Output[0].NickName.split("_")
self.joint_type = self.classes.get(parsed_output[0])
for key in parsed_output[1:]:
self.topo_bools[key] = True


def RunScript(self, *args):
if not self.joint_type:
Expand All @@ -34,35 +52,59 @@ def RunScript(self, *args):
kwargs = {}
for i, val in enumerate(args[2:]):
if val:
kwargs[self.arg_names()[i + 2]] = val
kwargs[self.arg_names()[i+2]] = val
print(kwargs)
if not cat_a:
self.AddRuntimeMessage(
Warning, "Input parameter {} failed to collect data.".format(self.arg_names()[0])
)
self.AddRuntimeMessage(Warning, "Input parameter {} failed to collect data.".format(self.arg_names()[0]))
if not cat_b:
self.AddRuntimeMessage(
Warning, "Input parameter {} failed to collect data.".format(self.arg_names()[1])
)
self.AddRuntimeMessage(Warning, "Input parameter {} failed to collect data.".format(self.arg_names()[1]))
if not (cat_a and cat_b):
return

return CategoryRule(self.joint_type, cat_a, cat_b, **kwargs)
topos = []
for i, bool in enumerate(self.topo_bools.values()):
if bool:
topos.append(i)

return CategoryRule(self.joint_type, cat_a, cat_b, topos, **kwargs)


def arg_names(self):
names = inspect.getargspec(self.joint_type.__init__)[0][1:]
for i in range(2):
names[i] += " category"
return [name for name in names if (name != "key") and (name != "frame")]
return [name for name in names if (name != 'key') and (name != 'frame')]


def AppendAdditionalMenuItems(self, menu):
for name in self.classes.keys():
item = menu.Items.Add(name, None, self.on_item_click)
if self.joint_type and name == self.joint_type.__name__:
item.Checked = True
item.Checked = True

menu.Items.Add(ToolStripSeparator())
topo_menu = ToolStripMenuItem("Apply to Topology")
menu.Items.Add(topo_menu)
for name, bool in self.topo_bools.items():
item = ToolStripMenuItem(name, None, self.on_topo_click)
item.Checked = bool
topo_menu.DropDownItems.Add(item)

def output_name(self):
name = self.joint_type.__name__
for key, bool in self.topo_bools.items():
if bool:
name += "_{}".format(key)
return name

def on_topo_click(self, sender, event_info):
self.topo_bools[str(sender)] = not self.topo_bools[str(sender)]
rename_GH_output(self.output_name(), 0, ghenv)
ghenv.Component.ExpireSolution(True)


def on_item_click(self, sender, event_info):
self.joint_type = self.classes[str(sender)]
rename_GH_output(self.joint_type.__name__, 0, ghenv)
manage_dynamic_params(self.arg_names(), ghenv, rename_count=2, permanent_param_count=0)
rename_GH_output(self.output_name(), 0, ghenv)
manage_dynamic_params(self.arg_names(), ghenv, rename_count = 2, permanent_param_count = 0)
ghenv.Component.ExpireSolution(True)
3 changes: 2 additions & 1 deletion src/compas_timber/ghpython/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,11 @@ def comply(self, beams):
class CategoryRule(JointRule):
"""Based on the category attribute attached to the beams, this rule assigns"""

def __init__(self, joint_type, category_a, category_b, **kwargs):
def __init__(self, joint_type, category_a, category_b, topos = [], **kwargs):
self.joint_type = joint_type
self.category_a = category_a
self.category_b = category_b
self.topos = topos
self.kwargs = kwargs

def ToString(self):
Expand Down

0 comments on commit 2565367

Please sign in to comment.