Skip to content

Commit

Permalink
Adaptive_components_work
Browse files Browse the repository at this point in the history
  • Loading branch information
obucklin committed Feb 15, 2024
1 parent c8c2d4b commit 385de90
Show file tree
Hide file tree
Showing 14 changed files with 162 additions and 62 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Added flag `modify_cross` to `L-Butt` joint.
* Added flag `reject_i` to `L-Butt` joint.
* Added new `NullJoint`.
* Added `beam_names` attribute to `JointOptions` class.
* Added `beam_names` attribute to all GH JointOption Components.

### Changed

Expand All @@ -34,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Changed GH Categories for joint rules.
* Made `beam_side_incident` a `staticmethod` of `Joint` and reworked it.
* Extended `DecomposeBeam` component to optionally show beam frame and faces.
* Changed `Direct Joint` and `Category Joint` GH Components to have adaptive inputs that change based on what type of joint is input.

### Removed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ def RunScript(self, Cutoff):
args = {}
if Cutoff:
args["cutoff"] = Cutoff
options = JointOptions(FrenchRidgeLapJoint, **args)
options = JointOptions(FrenchRidgeLapJoint, ['top_beam','bottom_beam'] **args)

return options
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ def RunScript(self, small_beam_butts, modify_cross, reject_i):
if reject_i is not None:
args["reject_i"] = reject_i

options = JointOptions(LButtJoint, **args)
options = JointOptions(LButtJoint, ["main_beam", "cross_beam"], **args)

return options
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ def RunScript(self, flip_lap_side, cut_plane_bias):
if cut_plane_bias:
args["cut_plane_bias"] = cut_plane_bias

options = JointOptions(LHalfLapJoint, **args)
options = JointOptions(LHalfLapJoint, ["top_beam", "bottom_beam"],**args)

return options
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ def RunScript(self, Cutoff):
args = {}
if Cutoff:
args["cutoff"] = Cutoff
options = JointOptions(LMiterJoint, **args)
options = JointOptions(LMiterJoint, ["first_beam", "second_beam"],**args)

return options
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
class NullJointComponent(component):
def RunScript(self):

options = JointOptions(NullJoint, **{})
options = JointOptions(NullJoint, ["first_beam", "second_beam"], **{})
return options
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ def RunScript(self, Gap):
args = {}
if Gap:
args["gap"] = Gap
options = JointOptions(TButtJoint, **args)
options = JointOptions(TButtJoint, ["main_beam", "cross_beam"], **args)

return options
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ def RunScript(self, flip_lap_side, cut_plane_bias):
args["flip_lap_side"] = flip_lap_side
if cut_plane_bias:
args["cut_plane_bias"] = cut_plane_bias
options = JointOptions(THalfLapJoint, **args)
options = JointOptions(THalfLapJoint, ["top_beam", "bottom_beam"],**args)

return options
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ def RunScript(self, flip_lap_side, cut_plane_bias):
args["flip_lap_side"] = flip_lap_side
if cut_plane_bias:
args["cut_plane_bias"] = cut_plane_bias
options = JointOptions(XHalfLapJoint, **args)
options = JointOptions(XHalfLapJoint, ["top_beam", "bottom_beam"], **args)

return options
Original file line number Diff line number Diff line change
@@ -1,9 +1,70 @@
from ghpythonlib.componentbase import executingcomponent as component
from Grasshopper.Kernel.GH_RuntimeMessageLevel import Error
from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning
import Grasshopper

from compas_timber.ghpython import CategoryRule


class CategoryJointRule(component):
def RunScript(self, JointOptions, CatA, CatB):
if JointOptions and CatA and CatB:
return CategoryRule(JointOptions.type, CatA, CatB, **JointOptions.kwargs)
def AddParam(name, IO, list = True):
assert IO in ('Output', 'Input')
params = [param.NickName for param in getattr(ghenv.Component.Params,IO)]
if name not in params:
param = Grasshopper.Kernel.Parameters.Param_GenericObject()
param.NickName = name + " category"
param.Name = name
param.Description = name
param.Access = Grasshopper.Kernel.GH_ParamAccess.item
param.Optional = True
index = getattr(ghenv.Component.Params, IO).Count
registers = dict(Input = 'RegisterInputParam'
,Output = 'RegisterOutputParam'
)
getattr(ghenv.Component.Params,registers[IO])(param, index)
ghenv.Component.Params.OnParametersChanged()
return param

class DirectJointRule(component):
def __init__(self):
self.joint_type = None

def ClearParams(self):
while len(ghenv.Component.Params.Input)>1:
ghenv.Component.Params.UnregisterInputParameter(ghenv.Component.Params.Input[len(ghenv.Component.Params.Input)-1])
ghenv.Component.Params.OnParametersChanged()
ghenv.Component.ExpireSolution(True)


def RunScript(self, JointOptions, *args):
if not JointOptions: #if no JointOptions is input
print("no joint")
self.ClearParams()
self.joint_type = None
return

if JointOptions.type != self.joint_type: # if JointOptions changes
if len(JointOptions.beam_names) != 2:
self.AddRuntimeMessage(Error, "Component currently only supports joint types with 2 beams.")
self.ClearParams()
self.joint_type = JointOptions.type
for name in JointOptions.beam_names:
AddParam(name, "Input")

if len(ghenv.Component.Params.Input) != 3: # something went wrong and the number of input parameters is wrong
self.AddRuntimeMessage(Warning, "Input parameter error.")
return

if len(args) < 2:
self.AddRuntimeMessage(Warning, "Input parameters failed to collect data.")
return
categories = []
create_rule = True
for i in range(len(ghenv.Component.Params.Input)-1):
if not args[i]:
self.AddRuntimeMessage(Warning, "Input parameter {} {} failed to collect data.".format(JointOptions.beam_names[i], 'categories'))
create_rule = False
else:
categories.append(args[i])

if create_rule:
return CategoryRule(JointOptions.type, categories[0], categories[1], **JointOptions.kwargs)
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,6 @@
"description": "Joint Options component.",
"typeHintID": "none",
"scriptParamAccess": 0
},
{
"name": "CatA",
"description": "Categeory of the first Beam.",
"typeHintID": "str",
"scriptParamAccess": 0
},
{
"name": "CatB",
"description": "Category of the sectond Beam.",
"typeHintID": "str",
"scriptParamAccess": 0
}
],
"outputParameters": [
Expand Down
105 changes: 80 additions & 25 deletions src/compas_timber/ghpython/components/CT_Joint_Rule_Direct/code.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,92 @@
from ghpythonlib.componentbase import executingcomponent as component
from Grasshopper.Kernel.GH_RuntimeMessageLevel import Error
from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning
import Grasshopper

from compas_timber.connections import ConnectionSolver
from compas_timber.connections import JointTopology
from compas_timber.ghpython import DirectRule


def AddParam(name, IO, list = True):
assert IO in ('Output', 'Input')
params = [param.NickName for param in getattr(ghenv.Component.Params,IO)]
if name not in params:
param = Grasshopper.Kernel.Parameters.Param_GenericObject()
param.NickName = name
param.Name = name
param.Description = name
param.Access = Grasshopper.Kernel.GH_ParamAccess.list
param.Optional = True
index = getattr(ghenv.Component.Params, IO).Count
registers = dict(Input = 'RegisterInputParam'
,Output = 'RegisterOutputParam'
)
getattr(ghenv.Component.Params,registers[IO])(param, index)
ghenv.Component.Params.OnParametersChanged()
return param




class DirectJointRule(component):
def RunScript(self, JointOptions, MainBeam, SecondaryBeam):
if not MainBeam:
self.AddRuntimeMessage(Warning, "Input parameter MainBeams failed to collect data.")
if not SecondaryBeam:
self.AddRuntimeMessage(Warning, "Input parameter CrossBeams failed to collect data.")
if not (MainBeam and SecondaryBeam):
def __init__(self):
self.joint_type = None

def ClearParams(self):
while len(ghenv.Component.Params.Input)>1:
ghenv.Component.Params.UnregisterInputParameter(ghenv.Component.Params.Input[len(ghenv.Component.Params.Input)-1])
ghenv.Component.Params.OnParametersChanged()


def RunScript(self, JointOptions, *args):
if not JointOptions: #if no JointOptions is input
self.ClearParams()
self.joint_type = None
return
if not isinstance(MainBeam, list):
MainBeam = [MainBeam]
if not isinstance(SecondaryBeam, list):
SecondaryBeam = [SecondaryBeam]
if len(MainBeam) != len(SecondaryBeam):
self.AddRuntimeMessage(Error, "Number of items in MainBeams and CrossBeams must match!")

if JointOptions.type != self.joint_type: # if JointOptions changes
if len(JointOptions.beam_names) != 2:
self.AddRuntimeMessage(Error, "Component currently only supports joint types with 2 beams.")
self.ClearParams()
self.joint_type = JointOptions.type
for name in JointOptions.beam_names:
AddParam(name, "Input")

if len(ghenv.Component.Params.Input) != 3:
self.AddRuntimeMessage(Warning, "Input parameter error.")
return

if len(args) < 2:
self.AddRuntimeMessage(Warning, "Input parameters failed to collect data.")
return
Rules = []
for main, secondary in zip(MainBeam, SecondaryBeam):
topology, _, _ = ConnectionSolver().find_topology(main, secondary)
if topology != JointOptions.type.SUPPORTED_TOPOLOGY:
self.AddRuntimeMessage(
Warning,
"Beams meet with topology: {} which does not agree with joint of type: {}".format(
JointTopology.get_name(topology), JointOptions.type.__name__
),
)
continue
Rules.append(DirectRule(JointOptions.type, [secondary, main], **JointOptions.kwargs))
return Rules

beams = []
create_rule = True
for i in range(len(ghenv.Component.Params.Input)-1):
if not args[i]:
self.AddRuntimeMessage(Warning, "Input parameter {} failed to collect data.".format(JointOptions.beam_names[i]))
create_rule = False
else:
arg_beams= args[i]
if not isinstance(arg_beams, list):
arg_beams = [arg_beams]
beams.append(arg_beams)

if create_rule:
if len(beams[0]) != len(beams[1]):
self.AddRuntimeMessage(Error, "Number of items in {} and {} must match!".format(JointOptions.beam_names[0], JointOptions.beam_names[1]))
return
Rules = []
for main, secondary in zip(beams[0], beams[1]):
topology, _, _ = ConnectionSolver().find_topology(main, secondary)
if topology != JointOptions.type.SUPPORTED_TOPOLOGY:
self.AddRuntimeMessage(
Warning,
"Beams meet with topology: {} which does not agree with joint of type: {}".format(
JointTopology.get_name(topology), JointOptions.type.__name__
),
)
continue
Rules.append(DirectRule(JointOptions.type, [main, secondary], **JointOptions.kwargs))
return Rules
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,6 @@
"description": "Joint Options Component",
"typeHintID": "none",
"scriptParamAccess": 0
},
{
"name": "MainBeam",
"description": "Main Beam.",
"typeHintID": "none",
"scriptParamAccess": 1
},
{
"name": "SecondaryBeam",
"description": "Secondary Beam.",
"typeHintID": "none",
"scriptParamAccess": 1
}
],
"outputParameters": [
Expand Down
7 changes: 6 additions & 1 deletion src/compas_timber/ghpython/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,19 +271,24 @@ class JointOptions(object):
The type of the joint.
kwargs : dict
The keyword arguments to be passed to the joint.
beam_names : list(str)
The names of the beams to be joined.
Attributes
----------
type : cls(:class:`compas_timber.connections.Joint`)
The type of the joint.
kwargs : dict
The keyword arguments to be passed to the joint.
beam_names : list(str)
The names of the beams to be joined.
"""

def __init__(self, type, **kwargs):
def __init__(self, type, beam_names, **kwargs):
self.type = type
self.kwargs = kwargs
self.beam_names = beam_names

def __repr__(self):
return "{}({}{})".format(JointOptions.__name__, self.type, self.kwargs)
Expand Down

0 comments on commit 385de90

Please sign in to comment.