From 53209936476580c95d1779d07a3d493160dab6cb Mon Sep 17 00:00:00 2001 From: papachap Date: Wed, 7 Aug 2024 17:08:51 +0200 Subject: [PATCH] gh test --- .../_fabrication/step_joint_notch.py | 11 +- .../gh_tests/test_step_joint_notch.ghx | 4616 +++++++++++++++++ 2 files changed, 4624 insertions(+), 3 deletions(-) create mode 100644 tests/compas_timber/gh_tests/test_step_joint_notch.ghx diff --git a/src/compas_timber/_fabrication/step_joint_notch.py b/src/compas_timber/_fabrication/step_joint_notch.py index 7942073d6..1a8628c9e 100644 --- a/src/compas_timber/_fabrication/step_joint_notch.py +++ b/src/compas_timber/_fabrication/step_joint_notch.py @@ -817,14 +817,19 @@ def mortise_volume_from_params_and_beam(self, beam): vector_angle = math.radians(180 - self.strut_inclination) else: vector_angle = math.radians(self.strut_inclination) + extr_vector = extr_vector * -1 rot_vect = Rotation.from_axis_and_angle(rot_axis, vector_angle) extr_vector.transform(rot_vect) + + + mortise_polyline_extrusion = mortise_polyline.translated(extr_vector) # extrude the polyline to create the mortise volume as a Brep - mortise_volume = Brep.from_extrusion(mortise_polyline, extr_vector, cap_ends=True) + # mortise_volume = Brep.from_extrusion(mortise_polyline, extr_vector, cap_ends=True) # trim brep with step cutting planes - mortise_volume.trim(step_cutting_plane) # !: check if the trimming works correctly // add checks + # mortise_volume.trim(step_cutting_plane) # !: check if the trimming works correctly // add checks - return mortise_volume + # return mortise_volume + return mortise_polyline, mortise_polyline_extrusion class StepJointNotchParams(BTLxProcessParams): diff --git a/tests/compas_timber/gh_tests/test_step_joint_notch.ghx b/tests/compas_timber/gh_tests/test_step_joint_notch.ghx new file mode 100644 index 000000000..9d8ba94d0 --- /dev/null +++ b/tests/compas_timber/gh_tests/test_step_joint_notch.ghx @@ -0,0 +1,4616 @@ + + + + + + + + 0 + 2 + 2 + + + + + + + 1 + 0 + 7 + + + + + + fa5d732c-b31a-4064-bc30-fdd75169872b + Shaded + 1 + + 100;150;0;0 + + + 100;0;150;0 + + + + + + 638584536051543966 + + test_step_joint_notch.ghx + + + + + 0 + + + + + + -21 + 17 + + 0.246093154 + + + + + 0 + + + + + + + 0 + + + + + 2 + + + + + GhPython, Version=7.34.23267.11001, Culture=neutral, PublicKeyToken=null + 7.34.23267.11001 + + 00000000-0000-0000-0000-000000000000 + + + + + + + Human, Version=1.7.3.0, Culture=neutral, PublicKeyToken=null + 1.7.3.0 + + 5f86fa9f-c62b-50e8-157b-b454ef3e00fa + Human + 1.2.0 + + + + + + + 45 + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + GhPython Script + + + + + from compas_rhino.conversions import surface_to_rhino +from compas_timber._fabrication import StepJointNotch +from compas_timber._fabrication import StepJointNotchParams + +from compas_timber.model import TimberModel +from compas_timber.fabrication import BTLx + +from compas_rhino import unload_modules +from compas.scene import SceneObject + +from compas_rhino.conversions import frame_to_rhino, plane_to_rhino, surface_to_rhino, polyline_to_rhino + +import Rhino.Geometry as rg +unload_modules("compas_timber") + +#define beam and cutting plane +beam = cross_beam +plane = main_beam.ref_sides[index] + +#create step_joint_notch +step_joint_notch = StepJointNotch.from_surface_and_beam(plane, beam, notch_limited=False, step_depth=step, heel_depth=heel, strut_height=100.0, tapered_heel=tapered, ref_side_index=ref_side_index) +cutting_planes = step_joint_notch.planes_from_params_and_beam(beam) + +print("Orientation: ", step_joint_notch.orientation) +print("StartX: ", step_joint_notch.start_x) +print("StrutInclination: ", step_joint_notch.strut_inclination) + + +#add mortise +if mortise_height > 0: + step_joint_notch.add_mortise(beam.width/4, mortise_height, beam) + mortise_polylines = step_joint_notch.mortise_volume_from_params_and_beam(beam) + +##apply geometric features +#step_joint_notch.apply(brep, beam) + +#get btlx params +step_joint_notch_params = StepJointNotchParams(step_joint_notch).as_dict() +btlx_params = [] +for key, value in step_joint_notch_params.items(): + btlx_params.append("{0}: {1}".format(key, value)) + + +#vizualize in rhino +rg_ref_side = frame_to_rhino(beam.ref_sides[ref_side_index]) +rg_cutting_plane = frame_to_rhino(plane) +rg_planes = (plane_to_rhino(plane) for plane in cutting_planes) + +rg_mortise_polylines = [polyline_to_rhino(polyline) for polyline in mortise_polylines] + + + + GhPython provides a Python script component + + 154 + 194 + + + 1232 + 796 + + true + true + false + false + ca34b946-50be-42d7-8e6d-080419aa1aba + false + true + GhPython Script + Python + + + + + + 1987 + 695 + 222 + 164 + + + 2083 + 777 + + + + + + 8 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 7 + 3ede854e-c753-40eb-84cb-b48008f14fd4 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + Script variable Python + 050b78a7-8649-45a7-8e2b-9f2c8fe617b8 + cross_beam + cross_beam + true + 0 + true + c38af54d-dfec-411f-ab38-22c657830b82 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1989 + 697 + 79 + 20 + + + 2030 + 707 + + + + + + + + true + Script input main_beam. + 85e336ca-36fd-4257-ae26-80a079e9d946 + main_beam + main_beam + true + 0 + true + 19ba4d57-8c61-4bac-90d7-412dfcb8ac0b + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1989 + 717 + 79 + 20 + + + 2030 + 727 + + + + + + + + true + Script input index. + 63012ab7-70b5-4b48-adbc-da1744ff7b8e + index + index + true + 0 + true + c18f9e62-d6f5-42c4-a426-10688f24ca61 + 1 + 48d01794-d3d8-4aef-990e-127168822244 + + + + + + 1989 + 737 + 79 + 20 + + + 2030 + 747 + + + + + + + + true + Script input ref_side_index. + a5edb702-630e-4672-9612-89a6f43ae14c + ref_side_index + ref_side_index + true + 0 + true + fd67193c-c124-4e9b-bf38-3d6a6e085438 + 1 + 48d01794-d3d8-4aef-990e-127168822244 + + + + + + 1989 + 757 + 79 + 20 + + + 2030 + 767 + + + + + + + + true + Script input step. + 7d77a23a-b3b1-4179-80e8-6045dbf22259 + step + step + true + 0 + true + d5f970b8-28fa-4f28-b038-8f3eed5c682d + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1989 + 777 + 79 + 20 + + + 2030 + 787 + + + + + + + + true + Script input heel. + 62418504-ee4a-4be5-84d5-25d7f04b2671 + heel + heel + true + 0 + true + c1e88145-a742-40e8-9b8b-a549422a646d + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1989 + 797 + 79 + 20 + + + 2030 + 807 + + + + + + + + true + Script input tapered. + 1ff95643-005d-47e6-a338-fca927af62e5 + tapered + tapered + true + 0 + true + c925fa54-d90e-456f-863a-2f4f0a2857ba + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1989 + 817 + 79 + 20 + + + 2030 + 827 + + + + + + + + true + Script input mortise_height. + 9355bd0c-5761-49ff-8c36-c610f66d7569 + mortise_height + mortise_height + true + 0 + true + 654077fb-9447-42ca-a4ed-d6a4dd8d1874 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1989 + 837 + 79 + 20 + + + 2030 + 847 + + + + + + + + The execution information, as output and error streams + 40308c84-a0ba-4c41-b158-38a3341beb2c + out + out + false + 0 + + + + + + 2098 + 697 + 109 + 22 + + + 2152.5 + 708.4286 + + + + + + + + Script output surface. + 43d74bb6-8d1a-4853-8757-d522804215d3 + surface + surface + false + 0 + + + + + + 2098 + 719 + 109 + 23 + + + 2152.5 + 731.2857 + + + + + + + + Script output rg_cutting_plane. + 602ccbf4-1274-4cd9-8349-ba4c5ba030fe + rg_cutting_plane + rg_cutting_plane + false + 0 + + + + + + 2098 + 742 + 109 + 23 + + + 2152.5 + 754.1429 + + + + + + + + Script output rg_planes. + 16bc55f9-a035-4099-834e-e9dc0931b695 + rg_planes + rg_planes + false + 0 + + + + + + 2098 + 765 + 109 + 23 + + + 2152.5 + 777 + + + + + + + + Script output rg_ref_side. + ddc1d959-4491-4f72-b7d5-a74d74b99385 + rg_ref_side + rg_ref_side + false + 0 + + + + + + 2098 + 788 + 109 + 23 + + + 2152.5 + 799.8572 + + + + + + + + Script output rg_mortise_polylines. + 1a4781d4-bfe8-4573-86bb-90d0f0ffc197 + rg_mortise_polylines + rg_mortise_polylines + false + 0 + + + + + + 2098 + 811 + 109 + 23 + + + 2152.5 + 822.7143 + + + + + + + + Script output btlx_params. + d525eccb-5bff-4563-b75e-472cbbdc5901 + step_joint_notch_params + btlx_params + false + 0 + + + + + + 2098 + 834 + 109 + 22 + + + 2152.5 + 845.5714 + + + + + + + + + + + + + + d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 + Curve + + + + + Contains a collection of generic curves + true + 6bbc142b-2536-41bf-a215-ea52704d32b6 + Curve + Crv + false + 0 + + + + + + 521 + 459 + 50 + 24 + + + 546.5278 + 471.428 + + + + + + 1 + + + + + 1 + {0} + + + + + -1 + + Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyNzYbxpcrDPvOXz8/18+rHjlAYmi2O741CCH48eNlj7zvu9wBCoe0mqltvDcBAcmBgTY2xy1xs52sgPIJY3vmdz+1zM1wOS4GQYTAAA= + + 00000000-0000-0000-0000-000000000000 + + + + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + CT: Beam + + + + + """Creates a Beam from a LineCurve.""" + +import rhinoscriptsyntax as rs +from compas.scene import Scene +from compas_rhino.conversions import line_to_compas +from compas_rhino.conversions import vector_to_compas +from ghpythonlib.componentbase import executingcomponent as component +from Grasshopper.Kernel.GH_RuntimeMessageLevel import Error +from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning +from Rhino.RhinoDoc import ActiveDoc + +from compas_timber.elements import Beam as CTBeam +from compas_timber.ghpython.rhino_object_name_attributes import update_rhobj_attributes_name + + +class Beam_fromCurve(component): + def RunScript(self, centerline, z_vector, width, height, category, updateRefObj): + # minimum inputs required + if not centerline: + self.AddRuntimeMessage(Warning, "Input parameter 'Centerline' failed to collect data") + if not width: + self.AddRuntimeMessage(Warning, "Input parameter 'Width' failed to collect data") + if not height: + self.AddRuntimeMessage(Warning, "Input parameter 'Height' failed to collect data") + + # reformat unset parameters for consistency + if not z_vector: + z_vector = [None] + if not category: + category = [None] + + beams = [] + blanks = [] + scene = Scene() + + if centerline and height and width: + # check list lengths for consistency + N = len(centerline) + if len(z_vector) not in (0, 1, N): + self.AddRuntimeMessage( + Error, " In 'ZVector' I need either none, one or the same number of inputs as the Crv parameter." + ) + if len(width) not in (1, N): + self.AddRuntimeMessage( + Error, " In 'W' I need either one or the same number of inputs as the Crv parameter." + ) + if len(height) not in (1, N): + self.AddRuntimeMessage( + Error, " In 'H' I need either one or the same number of inputs as the Crv parameter." + ) + if len(category) not in (0, 1, N): + self.AddRuntimeMessage( + Error, " In 'Category' I need either none, one or the same number of inputs as the Crv parameter." + ) + + # duplicate data if None or single value + if len(z_vector) != N: + z_vector = [z_vector[0] for _ in range(N)] + if len(width) != N: + width = [width[0] for _ in range(N)] + if len(height) != N: + height = [height[0] for _ in range(N)] + if len(category) != N: + category = [category[0] for _ in range(N)] + + for line, z, w, h, c in zip(centerline, z_vector, width, height, category): + guid, geometry = self._get_guid_and_geometry(line) + rhino_line = rs.coerceline(geometry) + line = line_to_compas(rhino_line) + + z = vector_to_compas(z) if z else None + beam = CTBeam.from_centerline(centerline=line, width=w, height=h, z_vector=z) + beam.attributes["rhino_guid"] = str(guid) if guid else None + beam.attributes["category"] = c + print(guid) + if updateRefObj and guid: + update_rhobj_attributes_name(guid, "width", str(w)) + update_rhobj_attributes_name(guid, "height", str(h)) + update_rhobj_attributes_name(guid, "zvector", str(list(beam.frame.zaxis))) + update_rhobj_attributes_name(guid, "category", c) + + beams.append(beam) + scene.add(beam.blank) + + blanks = scene.draw() + + return beams, blanks + + def _get_guid_and_geometry(self, line): + # internalized curves and GH geometry will not have persistent GUIDs, referenced Rhino objects will + # type hint on the input has to be 'ghdoc' for this to work + guid = None + geometry = line + rhino_obj = ActiveDoc.Objects.FindId(line) + if rhino_obj: + guid = line + geometry = rhino_obj.Geometry + return guid, geometry + + Creates a Beam from a LineCurve. + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDwAACw8BkvkDpQAAAhRJREFUSEulVLtKA0EUzSfkD3zlrUKMIcHGB6ghIj5QxEoDiiA2gtqGYBEfRRQiSRc7iXU6IWKZwh8Q/AI/wEcRr/cMmWUZ7ya7Whw2uXvvOTNnzqyPiP6Nob7+Q0bBQJ0xLQ64BRP4R6OxZ37Swf4+nRwdKyxmFyg4MEhcvxYH3YCH4+GhwHsqMd6+r9ep1WrRY7OpyGcmp2hvZxcCBXG4F3gQligykIIcIulkknJb26qGnXgW4AF/NBi6AzkIQAxcnl+AjAr5vFXzLMDN8ZFI9JXxfVMuW0RYMZ8D3dZqVs2zADeuRALBD3jbaDQUAZ74D2ib/iQwHI5UudHyFsNYLVaN5JjEGj0F+KUVQXisB+EzyO01CV0F+IUYwY21dZUUXXMCemGdKMBFMYIYgIDktx2wD0FAILBQO7FjBGGJveYE2Id5Jn8AH3g1uRhBHCLI7TUJ2BVCAHLuP9eLVgJc3GS/vyZSaboqldQWq5UKZeczyhYdSyfouCLGzLViJ9cCT1A2sbq03NNv7Ay7joXCLzzTb5JbAqa/mdm5XzfTRCeG1Dk35bcEUQAJchLArpAmkDMOJVI7PAkgrrgbuCM8F5cITbgWQFyHI9F2x29HS0y4EkBcuU/5LZF0Q1cB+I3fHMFP7stJBL3gKHBWLOoIvnGPK78lKAEQQkQjOZZQlnS+pq79lgABfNxw2UycSgPeQL4fsKzVEEQlKEcAAAAASUVORK5CYII= + + false + 61e455d1-1197-42f2-9b19-c9255984e680 + true + true + CT: Beam + Beam + + + + + + 1076 + 480 + 145 + 124 + + + 1167 + 542 + + + + + + 6 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 2 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + 1 + true + Referenced curve or line, Guid of curve or line in the active Rhino document. + af8ecabe-1f50-44f9-9732-a28f0101da66 + Centerline + Centerline + true + 1 + true + 82ddb61d-d21e-49ce-a61c-851130becb9a + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1078 + 482 + 74 + 20 + + + 1116.5 + 492 + + + + + + + + 1 + true + Vector defining the orientation of the cross-section (corresponds to the height dimension). If None, a default will be taken. + e24b6965-6eb8-44c9-a93f-921178776153 + ZVector + ZVector + true + 1 + true + 0 + 15a50725-e3d3-4075-9f7c-142ba5f40747 + + + + + + 1078 + 502 + 74 + 20 + + + 1116.5 + 512 + + + + + + + + 1 + true + Width of the cross-section (usually the smaller dimension). + 3141853d-6310-4d57-8fcb-4485e2106585 + Width + Width + true + 1 + true + 5cc940ad-f898-479c-8389-be3142764477 + 1 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 1078 + 522 + 74 + 20 + + + 1116.5 + 532 + + + + + + + + 1 + true + Height of the cross-section (usually the larger dimension). + 649d67fb-cb07-4166-b6a6-1412ba66780a + Height + Height + true + 1 + true + 5d71a959-57a2-4f08-b6ec-584164b09c95 + 1 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 1078 + 542 + 74 + 20 + + + 1116.5 + 552 + + + + + + + + 1 + true + Category of a beam. + e7afb315-d6b9-4da4-8b6f-5c05aa8b1895 + Category + Category + true + 1 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 1078 + 562 + 74 + 20 + + + 1116.5 + 572 + + + + + + + + true + (optional) If True, the attributes in the referenced object will be updated/overwritten with the new values given here. + b9a3c1d6-5e9a-407b-8be2-e4e66ceda80e + updateRefObj + updateRefObj + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1078 + 582 + 74 + 20 + + + 1116.5 + 592 + + + + + + + + Beam object(s). + 19ba4d57-8c61-4bac-90d7-412dfcb8ac0b + Beam + Beam + false + 0 + + + + + + 1182 + 482 + 37 + 60 + + + 1200.5 + 512 + + + + + + + + Shape of the beam's blank. + 7ccf81c5-136d-420f-b550-4a331abbcb49 + Blank + Blank + false + 0 + + + + + + 1182 + 542 + 37 + 60 + + + 1200.5 + 572 + + + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 5d71a959-57a2-4f08-b6ec-584164b09c95 + Number Slider + + false + 0 + + + + + + 853 + 550 + 166 + 20 + + + 853.4926 + 550.1252 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 100 + + + + + + + + + d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 + Curve + + + + + Contains a collection of generic curves + true + 2f78b16d-80d1-4502-954e-49040fe761a3 + Curve + Crv + false + 0 + + + + + + 472 + 684 + 50 + 24 + + + 497.5087 + 696.4502 + + + + + + 1 + + + + + 1 + {0} + + + + + -1 + + Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyFyF5Ln1s/nvOXz8/18+rHjlAYmi2O741CCHCRvP7T9b98DhM5o4EwMaKFjuAHKJ94LooP/1TA0wYW50dQMKAA== + + 00000000-0000-0000-0000-000000000000 + + + + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + CT: Beam + + + + + """Creates a Beam from a LineCurve.""" + +import rhinoscriptsyntax as rs +from compas.scene import Scene +from compas_rhino.conversions import line_to_compas +from compas_rhino.conversions import vector_to_compas +from ghpythonlib.componentbase import executingcomponent as component +from Grasshopper.Kernel.GH_RuntimeMessageLevel import Error +from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning +from Rhino.RhinoDoc import ActiveDoc + +from compas_timber.elements import Beam as CTBeam +from compas_timber.ghpython.rhino_object_name_attributes import update_rhobj_attributes_name + + +class Beam_fromCurve(component): + def RunScript(self, centerline, z_vector, width, height, category, updateRefObj): + # minimum inputs required + if not centerline: + self.AddRuntimeMessage(Warning, "Input parameter 'Centerline' failed to collect data") + if not width: + self.AddRuntimeMessage(Warning, "Input parameter 'Width' failed to collect data") + if not height: + self.AddRuntimeMessage(Warning, "Input parameter 'Height' failed to collect data") + + # reformat unset parameters for consistency + if not z_vector: + z_vector = [None] + if not category: + category = [None] + + beams = [] + blanks = [] + scene = Scene() + + if centerline and height and width: + # check list lengths for consistency + N = len(centerline) + if len(z_vector) not in (0, 1, N): + self.AddRuntimeMessage( + Error, " In 'ZVector' I need either none, one or the same number of inputs as the Crv parameter." + ) + if len(width) not in (1, N): + self.AddRuntimeMessage( + Error, " In 'W' I need either one or the same number of inputs as the Crv parameter." + ) + if len(height) not in (1, N): + self.AddRuntimeMessage( + Error, " In 'H' I need either one or the same number of inputs as the Crv parameter." + ) + if len(category) not in (0, 1, N): + self.AddRuntimeMessage( + Error, " In 'Category' I need either none, one or the same number of inputs as the Crv parameter." + ) + + # duplicate data if None or single value + if len(z_vector) != N: + z_vector = [z_vector[0] for _ in range(N)] + if len(width) != N: + width = [width[0] for _ in range(N)] + if len(height) != N: + height = [height[0] for _ in range(N)] + if len(category) != N: + category = [category[0] for _ in range(N)] + + for line, z, w, h, c in zip(centerline, z_vector, width, height, category): + guid, geometry = self._get_guid_and_geometry(line) + rhino_line = rs.coerceline(geometry) + line = line_to_compas(rhino_line) + + z = vector_to_compas(z) if z else None + beam = CTBeam.from_centerline(centerline=line, width=w, height=h, z_vector=z) + beam.attributes["rhino_guid"] = str(guid) if guid else None + beam.attributes["category"] = c + print(guid) + if updateRefObj and guid: + update_rhobj_attributes_name(guid, "width", str(w)) + update_rhobj_attributes_name(guid, "height", str(h)) + update_rhobj_attributes_name(guid, "zvector", str(list(beam.frame.zaxis))) + update_rhobj_attributes_name(guid, "category", c) + + beams.append(beam) + scene.add(beam.blank) + + blanks = scene.draw() + + return beams, blanks + + def _get_guid_and_geometry(self, line): + # internalized curves and GH geometry will not have persistent GUIDs, referenced Rhino objects will + # type hint on the input has to be 'ghdoc' for this to work + guid = None + geometry = line + rhino_obj = ActiveDoc.Objects.FindId(line) + if rhino_obj: + guid = line + geometry = rhino_obj.Geometry + return guid, geometry + + Creates a Beam from a LineCurve. + true + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDgAACw4BQL7hQQAAAhRJREFUSEulVLtKA0EUzSfkD3zlrUKMIcHGB6ghIj5QxEoDiiA2gtqGYBEfRRQiSRc7iXU6IWKZwh8Q/AI/wEcRr/cMmWUZ7ya7Whw2uXvvOTNnzqyPiP6Nob7+Q0bBQJ0xLQ64BRP4R6OxZ37Swf4+nRwdKyxmFyg4MEhcvxYH3YCH4+GhwHsqMd6+r9ep1WrRY7OpyGcmp2hvZxcCBXG4F3gQligykIIcIulkknJb26qGnXgW4AF/NBi6AzkIQAxcnl+AjAr5vFXzLMDN8ZFI9JXxfVMuW0RYMZ8D3dZqVs2zADeuRALBD3jbaDQUAZ74D2ib/iQwHI5UudHyFsNYLVaN5JjEGj0F+KUVQXisB+EzyO01CV0F+IUYwY21dZUUXXMCemGdKMBFMYIYgIDktx2wD0FAILBQO7FjBGGJveYE2Id5Jn8AH3g1uRhBHCLI7TUJ2BVCAHLuP9eLVgJc3GS/vyZSaboqldQWq5UKZeczyhYdSyfouCLGzLViJ9cCT1A2sbq03NNv7Ay7joXCLzzTb5JbAqa/mdm5XzfTRCeG1Dk35bcEUQAJchLArpAmkDMOJVI7PAkgrrgbuCM8F5cITbgWQFyHI9F2x29HS0y4EkBcuU/5LZF0Q1cB+I3fHMFP7stJBL3gKHBWLOoIvnGPK78lKAEQQkQjOZZQlnS+pq79lgABfNxw2UycSgPeQL4fsKzVEEQlKEcAAAAASUVORK5CYII= + + false + efe8bffe-0848-4d32-993f-7f43d93bbf01 + true + true + CT: Beam + Beam + + + + + + 1074 + 688 + 145 + 124 + + + 1165 + 750 + + + + + + 6 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 2 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + 1 + true + Referenced curve or line, Guid of curve or line in the active Rhino document. + 8ca4719b-64bb-4a1e-bd21-47829a6da8fb + Centerline + Centerline + true + 1 + true + 919e0b0e-50c5-4983-bf15-4bb7b9f39c0a + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1076 + 690 + 74 + 20 + + + 1114.5 + 700 + + + + + + + + 1 + true + Vector defining the orientation of the cross-section (corresponds to the height dimension). If None, a default will be taken. + e4854a14-8e9a-421e-a9c2-b070f3e54f84 + ZVector + ZVector + true + 1 + true + 0 + 15a50725-e3d3-4075-9f7c-142ba5f40747 + + + + + + 1076 + 710 + 74 + 20 + + + 1114.5 + 720 + + + + + + + + 1 + true + Width of the cross-section (usually the smaller dimension). + 4941e70a-0c52-4f0e-829c-88c706d76cab + Width + Width + true + 1 + true + f40578da-c08b-4e1d-b010-8b988d3269a2 + 1 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 1076 + 730 + 74 + 20 + + + 1114.5 + 740 + + + + + + + + 1 + true + Height of the cross-section (usually the larger dimension). + 86c7e8a6-883d-41bb-8889-46964d8e84b3 + Height + Height + true + 1 + true + f40578da-c08b-4e1d-b010-8b988d3269a2 + 1 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 1076 + 750 + 74 + 20 + + + 1114.5 + 760 + + + + + + + + 1 + true + Category of a beam. + f30f6c3e-93b2-40b0-aa59-ae87fdde3fe1 + Category + Category + true + 1 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 1076 + 770 + 74 + 20 + + + 1114.5 + 780 + + + + + + + + true + (optional) If True, the attributes in the referenced object will be updated/overwritten with the new values given here. + 63f2f6d5-c8f8-446e-af8e-245bc6bd3b84 + updateRefObj + updateRefObj + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1076 + 790 + 74 + 20 + + + 1114.5 + 800 + + + + + + + + Beam object(s). + c38af54d-dfec-411f-ab38-22c657830b82 + Beam + Beam + false + 0 + + + + + + 1180 + 690 + 37 + 60 + + + 1198.5 + 720 + + + + + + + + Shape of the beam's blank. + 489d49f6-b379-49e3-8aed-197b4a1468a4 + Blank + Blank + false + 0 + + + + + + 1180 + 750 + 37 + 60 + + + 1198.5 + 780 + + + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + f40578da-c08b-4e1d-b010-8b988d3269a2 + Number Slider + + false + 0 + + + + + + 888 + 745 + 166 + 20 + + + 888.4611 + 745.2539 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 100 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 5cc940ad-f898-479c-8389-be3142764477 + Number Slider + + false + 0 + + + + + + 853 + 526 + 166 + 20 + + + 853.5906 + 526.7526 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 80 + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + CT: DecomposeBeam + + + + + # flake8: noqa +from compas.geometry import Line +from compas_rhino.conversions import frame_to_rhino_plane +from compas_rhino.conversions import line_to_rhino +from compas_rhino.conversions import point_to_rhino +from compas_rhino.conversions import box_to_rhino +from ghpythonlib.componentbase import executingcomponent as component +from System.Drawing import Color + + +class BeamDecompose(component): + RED = Color.FromArgb(255, 255, 100, 100) + GREEN = Color.FromArgb(200, 50, 220, 100) + BLUE = Color.FromArgb(200, 50, 150, 255) + WHITE = Color.FromArgb(255, 255, 255, 255) + YELLOW = Color.FromArgb(255, 255, 255, 0) + SCREEN_SIZE = 10 + RELATIVE_SIZE = 0 + + def RunScript(self, beam, show_frame, show_faces): + self.show_faces = show_faces if show_faces is not None else False + self.show_frame = show_frame if show_frame is not None else False + self.frames = [] + self.rhino_frames = [] + self.scales = [] + self.faces = [] + self.width = [] + self.height = [] + self.centerline = [] + self.shapes = [] + + for b in beam: + self.frames.append(b.frame) + self.rhino_frames.append(frame_to_rhino_plane(b.frame)) + self.scales.append(b.width + b.height) + self.centerline.append(line_to_rhino(b.centerline)) + self.shapes.append(box_to_rhino(b.shape)) + self.width.append(b.width) + self.height.append(b.height) + self.faces.append(b.faces) + + return self.rhino_frames, self.centerline, self.shapes, self.width, self.height + + def DrawViewportWires(self, arg): + if self.Locked: + return + + for f, s, faces in zip(self.frames, self.scales, self.faces): + if self.show_frame: + self._draw_frame(arg.Display, f, s) + if self.show_faces: + self._draw_faces(arg.Display, faces, s) + + def _draw_frame(self, display, frame, scale): + x = Line.from_point_and_vector(frame.point, frame.xaxis * scale) + y = Line.from_point_and_vector(frame.point, frame.yaxis * scale) + z = Line.from_point_and_vector(frame.point, frame.zaxis * scale) + display.DrawArrow(line_to_rhino(x), self.RED, self.SCREEN_SIZE, self.RELATIVE_SIZE) + display.DrawArrow(line_to_rhino(y), self.GREEN, self.SCREEN_SIZE, self.RELATIVE_SIZE) + display.DrawArrow(line_to_rhino(z), self.BLUE, self.SCREEN_SIZE, self.RELATIVE_SIZE) + + x_loc = x.end + x.vector * scale * 1.1 + y_loc = y.end + y.vector * scale * 1.1 + z_loc = z.end + z.vector * scale * 1.1 + display.Draw2dText("X", self.RED, point_to_rhino(x_loc), True, 16, "Verdana") + display.Draw2dText("Y", self.GREEN, point_to_rhino(y_loc), True, 16, "Verdana") + display.Draw2dText("Z", self.BLUE, point_to_rhino(z_loc), True, 16, "Verdana") + + def _draw_faces(self, display, faces, scale): + for index, face in enumerate(faces): + normal = Line.from_point_and_vector(face.point, face.normal * scale) + text = str(index) + display.Draw2dText(text, self.WHITE, point_to_rhino(face.point), True, 16, "Verdana") + display.DrawArrow(line_to_rhino(normal), self.YELLOW, self.SCREEN_SIZE, self.RELATIVE_SIZE) + + GhPython provides a Python script component + true + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDwAACw8BkvkDpQAAAohJREFUSEuVlj9rFEEYxvMR7gMEdvFy/6NZDGijuQ3aKCKLiqVuIUKwOdBYWIQtkxQWJhAQvFgdEeyuUrggIniFhWAlCPoJ1MoESRyfZ5z3nN2b+7PFj7nbmX2emXfe972bUUoNMfv43RsQuOayFD0/AokDn/NDL0A4Boom2TkbCBRqpXIHo4pv3dbwc3WudIgxNiSplyBaAD+NAYnseQEv+vPV2hfwZ3trS+2224qf+QxzgRi7DBJLnHwDBXsNXoqwy4Plpabqdrtq9f4DvXOIv8bo1cuVz41q7ZjzKQMI+ZawTSJrGpXqDsUYDorfvH5Di4MWCCvFuV/h+aWjF3t7YjxkEIKWEf5ovgdYWDhZq3+AwdHm+oaiwJnTi8cUpLAx0Ib7vZ7q9/vDBpYRRWmgL5kCFKIghWnAEDAUmPMk3hSksDCVARakdiaZYkLl00Qu2hafysB71PlOsWRtTcebl2alYOqis+JjDby7G3do4K+2dfplUxB3sU5jnkbi7cIkQNoAD+JS8+pvGlx8+lZ2oRYa8y8xeiYV9alcooSmVy5dltNGIjyoynsrK3pRJgUDnoAn4Ylcws9evVfN7Z46ey2W7NKtRldl+UTxkxEbIIsA433IeI8LycMnu1I3anZzv4PxXy+CwDnAXWbx7MKyxQZC42HLSWjAzpfavYEF5Ix3RmgU/w2yRXIhXP4hBqNiznCZ1D3AughiUj/kORiEKLcBK5oXfqre+Io1+jKNAX9HQn4XchuwVfA5exPGVKd1kcuAKcxnvHyXmIupDDJ1EbuERjHRgFnEy7SLJw8TDYhpzTor8qIN2DtoIiwuBEw9bWBayMTLHAUNKJT9y0F80HK9ND1q5i+sgg6R/W1M2wAAAABJRU5ErkJggg== + + false + eb9d5147-e225-45a5-a44b-61953c4955eb + true + true + CT: DecomposeBeam + DecomposeBeam + + + + + + 1382 + 621 + 156 + 104 + + + 1462 + 673 + + + + + + 3 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 5 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + 1 + true + Beam + 8e04df08-7ba8-497d-81a4-3df28baa4429 + Beam + Beam + true + 1 + true + 19ba4d57-8c61-4bac-90d7-412dfcb8ac0b + c38af54d-dfec-411f-ab38-22c657830b82 + 2 + 35915213-5534-4277-81b8-1bdc9e7383d2 + + + + + + 1384 + 623 + 63 + 33 + + + 1417 + 639.6667 + + + + + + + + true + Script input ShowFrame. + 55d797db-e8b9-4a25-83f9-fb3ce5e97dda + ShowFrame + ShowFrame + true + 0 + true + 4589d281-06a1-48a8-ab9c-fa318fb66883 + 1 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1384 + 656 + 63 + 33 + + + 1417 + 673 + + + + + + + + true + Script input ShowFaces. + 38380630-dd0c-4f25-ba4d-8be79af14f88 + ShowFaces + ShowFaces + true + 0 + true + 4589d281-06a1-48a8-ab9c-fa318fb66883 + 1 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1384 + 689 + 63 + 34 + + + 1417 + 706.3334 + + + + + + + + Script output Frame. + eaa8a578-60ae-4948-8427-7ef3e9061069 + Frame + Frame + false + 0 + + + + + + 1477 + 623 + 59 + 20 + + + 1506.5 + 633 + + + + + + + + Script output Centerline. + d5904a7c-0c03-4764-8d8c-d828062b20dd + Centerline + Centerline + false + 0 + + + + + + 1477 + 643 + 59 + 20 + + + 1506.5 + 653 + + + + + + + + Script output Box. + e778515e-1975-4634-93fa-0a12d895cfb0 + Box + Box + false + 0 + + + + + + 1477 + 663 + 59 + 20 + + + 1506.5 + 673 + + + + + + + + Script output Width. + d3ee9e41-73c8-4e9b-8793-3de14a036ce6 + Width + Width + false + 0 + + + + + + 1477 + 683 + 59 + 20 + + + 1506.5 + 693 + + + + + + + + Script output Height. + 712b50a9-aa16-4a06-850a-5ccaa6c1e4a1 + Height + Height + false + 0 + + + + + + 1477 + 703 + 59 + 20 + + + 1506.5 + 713 + + + + + + + + + + + + + + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle + + + + + Boolean (true/false) toggle + 4589d281-06a1-48a8-ab9c-fa318fb66883 + Boolean Toggle + Toggle + false + 0 + true + + + + + + 1257 + 679 + 104 + 22 + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + c18f9e62-d6f5-42c4-a426-10688f24ca61 + Number Slider + + false + 0 + + + + + + 1762 + 694 + 159 + 20 + + + 1762.14 + 694.5345 + + + + + + 3 + 1 + 1 + 15 + 0 + 0 + 0 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + fd67193c-c124-4e9b-bf38-3d6a6e085438 + Number Slider + + false + 0 + + + + + + 1722 + 718 + 201 + 20 + + + 1722.123 + 718.8546 + + + + + + 3 + 1 + 1 + 5 + 0 + 0 + 2 + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + cfb4b1f8-a02e-44ce-9c95-80b1164d7fca + Panel + BTLx Params + false + 0 + d525eccb-5bff-4563-b75e-472cbbdc5901 + 1 + Double click to edit panel content… + + + + + + 2400 + 926 + 212 + 333 + + 0 + 0 + 0 + + 2400.01 + 926.6734 + + + + + + + 255;255;255;255 + + true + true + true + false + false + true + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + d5f970b8-28fa-4f28-b038-8f3eed5c682d + Number Slider + + false + 0 + + + + + + 1727 + 786 + 160 + 20 + + + 1727.211 + 786.5431 + + + + + + 3 + 1 + 1 + 200 + 0 + 0 + 30 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + c1e88145-a742-40e8-9b8b-a549422a646d + Number Slider + + false + 0 + + + + + + 1727 + 809 + 160 + 20 + + + 1727.21 + 809.6162 + + + + + + 3 + 1 + 1 + 200 + 0 + 0 + 15 + + + + + + + + + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle + + + + + Boolean (true/false) toggle + c925fa54-d90e-456f-863a-2f4f0a2857ba + Boolean Toggle + tapered_heel + false + 0 + false + + + + + + 1752 + 831 + 133 + 22 + + + + + + + + + + f31d8d7a-7536-4ac8-9c96-fde6ecda4d0a + Cluster + + + + + + 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 + + Contains a cluster of Grasshopper components + true + a5869824-14fc-400f-a69e-f5050392632f + Cluster + Cluster + false + + + + + 5 + 3f3af581-d64e-4909-91e4-3576cf2e9e86 + 4c2588f5-9e63-4ce5-a5e7-50f44fb19cb9 + d28e1b27-74ad-41ab-b017-540fa9111876 + ebd18bdb-78c3-4d40-8a69-e1af30a53c27 + fd03a9d4-272c-4590-9595-4d3107dc0fdc + 3c631e1e-b12f-4297-9535-87b4fdc7b45e + 5d665740-a9cc-4f15-8a38-0dc75e214ae2 + 5d32325d-62cf-40bd-93fe-74af56a2c91e + b360d350-2b53-401b-9420-d9402019cb30 + 796ac502-faba-4bb6-a612-7e3dfb448d98 + + + + + + 2381 + 756 + 72 + 84 + + + 2420 + 798 + + + + + + 4 + 919e146f-30ae-4aae-be34-4d72f555e7da + 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 + 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 + d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 + 1 + 919e146f-30ae-4aae-be34-4d72f555e7da + + + + + Brep to split + ebd18bdb-78c3-4d40-8a69-e1af30a53c27 + Brep + B + true + 489d49f6-b379-49e3-8aed-197b4a1468a4 + 1 + + + + + + 2383 + 758 + 22 + 20 + + + 2395.5 + 768 + + + + + + + + Contains a collection of three-dimensional axis-systems + d28e1b27-74ad-41ab-b017-540fa9111876 + Plane + Pln + true + 16bc55f9-a035-4099-834e-e9dc0931b695 + 1 + + + + + + 2383 + 778 + 22 + 20 + + + 2395.5 + 788 + + + + + + + + Contains a collection of three-dimensional axis-systems + fd03a9d4-272c-4590-9595-4d3107dc0fdc + Plane + Pln + true + ddc1d959-4491-4f72-b7d5-a74d74b99385 + 1 + + + + + + 2383 + 798 + 22 + 20 + + + 2395.5 + 808 + + + + + + + + 1 + Section curves + 3f3af581-d64e-4909-91e4-3576cf2e9e86 + Curves + C + true + 1a4781d4-bfe8-4573-86bb-90d0f0ffc197 + 1 + + + + + + 2383 + 818 + 22 + 20 + + + 2395.5 + 828 + + + + + + + + 1 + Joined Breps + 4c2588f5-9e63-4ce5-a5e7-50f44fb19cb9 + Breps + B + false + 0 + + + + + + 2435 + 758 + 16 + 80 + + + 2443 + 798 + + + + + + + + + + + + + + 537b0419-bbc2-4ff4-bf08-afe526367b2c + Custom Preview + + + + + Allows for customized geometry previews + true + true + 9e4f0b21-759b-4c9a-8dfb-6654484027c5 + Custom Preview + Preview + + + + + + + 2569 + 841 + 48 + 44 + + + 2603 + 863 + + + + + + Geometry to preview + true + bc0fc1fe-a18e-40ca-ab8a-8ba765dde1f9 + Geometry + G + false + 4c2588f5-9e63-4ce5-a5e7-50f44fb19cb9 + 1 + + + + + + 2571 + 843 + 17 + 20 + + + 2581 + 853 + + + + + + + + The material override + 8cbb31fa-4051-471d-87be-5ce455d7f325 + Material + M + false + 0 + + + + + + 2571 + 863 + 17 + 20 + + + 2581 + 873 + + + + + + 1 + + + + + 1 + {0} + + + + + + 255;221;160;221 + + + 255;66;48;66 + + 0.5 + + 255;255;255;255 + + 0 + + + + + + + + + + + + + + + 0148a65d-6f42-414a-9db7-9a9b2eb78437 + Brep Edges + + + + + Extract the edge curves of a brep. + true + be8a15e2-8773-4720-9d61-dfdc10761646 + Brep Edges + Edges + + + + + + 2469 + 766 + 72 + 64 + + + 2499 + 798 + + + + + + Base Brep + 0056a757-f1c7-4722-83e9-e00c5e697cfc + Brep + B + false + 4c2588f5-9e63-4ce5-a5e7-50f44fb19cb9 + 1 + + + + + + 2471 + 768 + 13 + 60 + + + 2479 + 798 + + + + + + + + 1 + Naked edge curves + 2fc3daa1-27be-494a-9118-8afa0df8edc7 + Naked + En + false + 0 + + + + + + 2514 + 768 + 25 + 20 + + + 2526.5 + 778 + + + + + + + + 1 + Interior edge curves + 7db965ba-79d8-42a1-926c-cc7c5ea6a716 + Interior + Ei + false + 0 + + + + + + 2514 + 788 + 25 + 20 + + + 2526.5 + 798 + + + + + + + + 1 + Non-Manifold edge curves + dfe49992-1aa8-4a4e-bf86-f66139ca06c5 + Non-Manifold + Em + false + 0 + + + + + + 2514 + 808 + 25 + 20 + + + 2526.5 + 818 + + + + + + + + + + + + 22990b1f-9be6-477c-ad89-f775cd347105 + Flip Curve + + + + + Flip a curve using an optional guide curve. + true + 0c07a9ce-439d-466f-98d1-fcc3dcd14023 + Flip Curve + Flip + + + + + + 876 + 695 + 66 + 44 + + + 908 + 717 + + + + + + Curve to flip + 082a270f-f37d-4c27-8266-d4348e1e059b + Curve + C + false + 2f78b16d-80d1-4502-954e-49040fe761a3 + 1 + + + + + + 878 + 697 + 15 + 20 + + + 887 + 707 + + + + + + + + Optional guide curve + 94c738fb-f46a-4531-af70-ea11c88263f2 + Guide + G + true + 0 + + + + + + 878 + 717 + 15 + 20 + + + 887 + 727 + + + + + + + + Flipped curve + c284b03b-3c25-4136-b35d-211207e5e246 + Curve + C + false + 0 + + + + + + 923 + 697 + 17 + 20 + + + 931.5 + 707 + + + + + + + + Flip action + a48ad8ba-3072-486f-9f31-f1cbfcaa31e2 + Flag + F + false + 0 + + + + + + 923 + 717 + 17 + 20 + + + 931.5 + 727 + + + + + + + + + + + + 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 + Plane + + + + + Contains a collection of three-dimensional axis-systems + true + 482410b9-724c-46d6-be3a-3d63785bc853 + Plane + Pln + false + 16bc55f9-a035-4099-834e-e9dc0931b695 + 1 + + + + + + 2566 + 703 + 50 + 24 + + + 2591.305 + 715.5306 + + + + + + + + + + 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 + Plane + + + + + Contains a collection of three-dimensional axis-systems + true + 9c473eb6-ff8f-4c7f-bd69-56527d0257f6 + Plane + Pln + false + ddc1d959-4491-4f72-b7d5-a74d74b99385 + 1 + + + + + + 2565 + 632 + 50 + 24 + + + 2590.664 + 644.5862 + + + + + + + + + + 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 + Plane + + + + + Contains a collection of three-dimensional axis-systems + true + 88b4a335-192d-48a1-81d5-163278eaecbe + Plane + Pln + false + 602ccbf4-1274-4cd9-8349-ba4c5ba030fe + 1 + + + + + + 2565 + 564 + 50 + 24 + + + 2590.097 + 576.5297 + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + 84325f58-aa64-43ef-9c59-6631e3ff4da9 + Panel + + false + 1 + 40308c84-a0ba-4c41-b158-38a3341beb2c + 1 + Double click to edit panel content… + + + + + + 1988 + 610 + 221 + 85 + + 0 + 0 + 0 + + 1988.603 + 610.7073 + + + + + + + 255;255;250;90 + + true + true + true + false + false + true + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 88b4a335-192d-48a1-81d5-163278eaecbe + 1 + 234eec62-a3cc-4178-9760-678a11912fb0 + Group + CUTTING PLANE + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 9c473eb6-ff8f-4c7f-bd69-56527d0257f6 + 1 + 86bc7ac3-bdd8-443c-ae9b-e22ea6ec103a + Group + REF_SIDE + + + + + + + + + + a77d0879-94c2-4101-be44-e4a616ffeb0c + 5f86fa9f-c62b-50e8-157b-b454ef3e00fa + Custom Preview Lineweights + + + + + Custom Preview with Lineweights + 56020ec2-ccb1-4ae9-a538-84dcb2857db9 + Custom Preview Lineweights + PreviewLW + + + + + + + 2570 + 747 + 46 + 84 + + + 2602 + 789 + + + + + + Geometry to preview + true + 11bd5cdd-8b99-4483-950a-c0cb8f29576c + Geometry + G + false + 7db965ba-79d8-42a1-926c-cc7c5ea6a716 + 1 + + + + + + 2572 + 749 + 15 + 20 + + + 2581 + 759 + + + + + + + + The preview shader override + 7eb996a5-eb09-476d-8a9f-c49f7a1c895e + Shader + S + false + 0 + + + + + + 2572 + 769 + 15 + 20 + + + 2581 + 779 + + + + + + 1 + + + + + 1 + {0} + + + + + + 255;255;105;180 + + + 255;76;32;54 + + 0.5 + + 255;255;255;255 + + 0 + + + + + + + + + + + The thickness of the wire display + c3053791-290f-494e-8384-81e8464e4dc4 + Thickness + T + true + 0 + + + + + + 2572 + 789 + 15 + 20 + + + 2581 + 799 + + + + + + + + Set to true to try to render curves with an absolute dimension. + 073aa3ff-0ed7-42b6-bdd5-c5b25159731c + Absolute + A + false + 0 + + + + + + 2572 + 809 + 15 + 20 + + + 2581 + 819 + + + + + + 1 + + + + + 1 + {0} + + + + + false + + + + + + + + + + + + + + + 11bbd48b-bb0a-4f1b-8167-fa297590390d + End Points + + + + + Extract the end points of a curve. + true + 715464ea-9048-4ae7-9c5c-942cc0fa2486 + End Points + End + + + + + + 727 + 448 + 64 + 44 + + + 758 + 470 + + + + + + Curve to evaluate + ba457b2a-de34-4922-929d-926d8adedc5a + Curve + C + false + 6bbc142b-2536-41bf-a215-ea52704d32b6 + 1 + + + + + + 729 + 450 + 14 + 40 + + + 737.5 + 470 + + + + + + + + Curve start point + 77f5802b-abc0-49e5-91cc-3376ae99a75c + Start + S + false + 0 + + + + + + 773 + 450 + 16 + 20 + + + 781 + 460 + + + + + + + + Curve end point + 5a7d2dd5-1871-45dd-b9c0-e6289501fd3a + End + E + false + 0 + + + + + + 773 + 470 + 16 + 20 + + + 781 + 480 + + + + + + + + + + + + e9eb1dcf-92f6-4d4d-84ae-96222d60f56b + Move + + + + + Translate (move) an object along a vector. + true + 22d84b32-205f-41d5-8663-8af45f94307c + Move + Move + + + + + + 833 + 468 + 83 + 44 + + + 881 + 490 + + + + + + Base geometry + 4f7e8528-a89b-42ec-8171-f6004589fdcb + Geometry + G + true + 5a7d2dd5-1871-45dd-b9c0-e6289501fd3a + 1 + + + + + + 835 + 470 + 31 + 20 + + + 860 + 480 + + + + + + + + Translation vector + 21c38b75-b524-4c4f-93e3-89a660e1a69b + -x + Motion + T + false + 1e474aea-db61-424d-be9a-804e3fd04359 + 1 + + + + + + 835 + 490 + 31 + 20 + + + 860 + 500 + + + + + + 1 + + + + + 1 + {0} + + + + + + 0 + 0 + 10 + + + + + + + + + + + + Translated geometry + 9348c98e-479b-416c-9b0b-54c72c33be75 + Geometry + G + false + 0 + + + + + + 896 + 470 + 18 + 20 + + + 905 + 480 + + + + + + + + Transformation data + 35ee0f80-11b3-44ca-8fde-aa3bba3f7c43 + Transform + X + false + 0 + + + + + + 896 + 490 + 18 + 20 + + + 905 + 500 + + + + + + + + + + + + 79f9fbb3-8f1d-4d9a-88a9-f7961b1012cd + Unit X + + + + + Unit vector parallel to the world {x} axis. + true + 73ddbf47-b58a-451f-8f84-85c767ffb835 + Unit X + X + + + + + + 513 + 491 + 63 + 28 + + + 542 + 505 + + + + + + Unit multiplication + 4b128ece-c9a7-4204-9394-3fda75fa3d6f + Factor + F + false + 912e5dfb-d2a2-463b-a0eb-2610982bf536 + 1 + + + + + + 515 + 493 + 12 + 24 + + + 522.5 + 505 + + + + + + 1 + + + + + 1 + {0} + + + + + 1 + + + + + + + + + + + World {x} vector + 323481aa-7502-4bf4-8393-f5ea30a2e8ed + Unit vector + V + false + 0 + + + + + + 557 + 493 + 17 + 24 + + + 565.5 + 505 + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 912e5dfb-d2a2-463b-a0eb-2610982bf536 + Number Slider + + false + 0 + + + + + + 323 + 497 + 163 + 20 + + + 323.5465 + 497.3116 + + + + + + 3 + 1 + 1 + 2000 + 0 + 0 + 0 + + + + + + + + + 4c4e56eb-2f04-43f9-95a3-cc46a14f495a + Line + + + + + Create a line between two points. + true + 25e3b03c-eedc-4418-babd-0df09c1d6284 + Line + Ln + + + + + + 943 + 448 + 63 + 44 + + + 974 + 470 + + + + + + Line start point + 99feaba8-239b-40e1-ae13-db12fa1af53e + Start Point + A + false + 77f5802b-abc0-49e5-91cc-3376ae99a75c + 1 + + + + + + 945 + 450 + 14 + 20 + + + 953.5 + 460 + + + + + + + + Line end point + 5d3fa723-a735-4608-9a27-c304c4c3aa44 + End Point + B + false + 9348c98e-479b-416c-9b0b-54c72c33be75 + 1 + + + + + + 945 + 470 + 14 + 20 + + + 953.5 + 480 + + + + + + + + Line segment + 82ddb61d-d21e-49ce-a61c-851130becb9a + Line + L + false + 0 + + + + + + 989 + 450 + 15 + 40 + + + 996.5 + 470 + + + + + + + + + + + + 9103c240-a6a9-4223-9b42-dbd19bf38e2b + Unit Z + + + + + Unit vector parallel to the world {z} axis. + true + eaf786cc-99fc-4d46-b6b3-cf6b5314011a + Unit Z + Z + + + + + + 515 + 525 + 63 + 28 + + + 544 + 539 + + + + + + Unit multiplication + 88ec5468-52fb-4929-b59a-79cb5d549828 + Factor + F + false + 68472b2f-1682-4c03-a570-0bd3dafb7255 + 1 + + + + + + 517 + 527 + 12 + 24 + + + 524.5 + 539 + + + + + + 1 + + + + + 1 + {0} + + + + + 1 + + + + + + + + + + + World {z} vector + f08f6ccf-8731-4561-b2d4-cf43dcb5070e + Unit vector + V + false + 0 + + + + + + 559 + 527 + 17 + 24 + + + 567.5 + 539 + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 68472b2f-1682-4c03-a570-0bd3dafb7255 + Number Slider + + false + 0 + + + + + + 329 + 529 + 163 + 20 + + + 329.7557 + 529.9963 + + + + + + 3 + 1 + 1 + 2000 + 0 + 0 + 0 + + + + + + + + + a0d62394-a118-422d-abb3-6af115c75b25 + Addition + + + + + Mathematical addition + true + 362a8c85-9ff1-4541-8448-a78e3c79ff60 + Addition + A+B + + + + + + 728 + 493 + 65 + 44 + + + 759 + 515 + + + + + + 2 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + First item for addition + 0b1b606a-bd74-4af5-928f-2813c43db4f7 + A + A + true + 323481aa-7502-4bf4-8393-f5ea30a2e8ed + 1 + + + + + + 730 + 495 + 14 + 20 + + + 738.5 + 505 + + + + + + + + Second item for addition + 29d1f2a4-5fa6-44f6-af85-bc0232c7f3ed + B + B + true + f08f6ccf-8731-4561-b2d4-cf43dcb5070e + 1 + + + + + + 730 + 515 + 14 + 20 + + + 738.5 + 525 + + + + + + + + Result of addition + 1e474aea-db61-424d-be9a-804e3fd04359 + Result + R + false + 0 + + + + + + 774 + 495 + 17 + 40 + + + 782.5 + 515 + + + + + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 482410b9-724c-46d6-be3a-3d63785bc853 + 1 + 541e5f17-7a28-48ff-8820-37e3076647dd + Group + notch_planes + + + + + + + + + + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle + + + + + Boolean (true/false) toggle + 1f1c2959-2344-4152-a5d6-0e718f54669a + Boolean Toggle + FlipCurve + false + 0 + true + + + + + + 462 + 647 + 115 + 22 + + + + + + + + + + eeafc956-268e-461d-8e73-ee05c6f72c01 + Stream Filter + + + + + Filters a collection of input streams + true + 46298eb6-2834-4153-b072-4cc235a21b8d + Stream Filter + Filter + + + + + + 957 + 655 + 77 + 64 + + + 989 + 687 + + + + + + 3 + 2e3ab970-8545-46bb-836c-1c11e5610bce + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + Index of Gate stream + 376909ae-471f-4338-bd76-0550fd56a4cb + Gate + G + false + 1f1c2959-2344-4152-a5d6-0e718f54669a + 1 + + + + + + 959 + 657 + 15 + 20 + + + 968 + 667 + + + + + + 1 + + + + + 1 + {0} + + + + + 0 + + + + + + + + + + + 2 + Input stream at index 0 + acea90f0-616d-4203-908a-45991c3b043f + false + Stream 0 + 0 + true + 2f78b16d-80d1-4502-954e-49040fe761a3 + 1 + + + + + + 959 + 677 + 15 + 20 + + + 968 + 687 + + + + + + + + 2 + Input stream at index 1 + 282b385d-4abd-455c-848a-9a06b88edbbc + false + Stream 1 + 1 + true + c284b03b-3c25-4136-b35d-211207e5e246 + 1 + + + + + + 959 + 697 + 15 + 20 + + + 968 + 707 + + + + + + + + 2 + Filtered stream + 919e0b0e-50c5-4983-bf15-4bb7b9f39c0a + false + Stream + S(1) + false + 0 + + + + + + 1004 + 657 + 28 + 60 + + + 1018 + 687 + + + + + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 2f78b16d-80d1-4502-954e-49040fe761a3 + 1f1c2959-2344-4152-a5d6-0e718f54669a + 2 + 507139ff-df02-4319-9176-8b2ce4935cf5 + Group + cross_centerline + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 6bbc142b-2536-41bf-a215-ea52704d32b6 + 73ddbf47-b58a-451f-8f84-85c767ffb835 + 912e5dfb-d2a2-463b-a0eb-2610982bf536 + eaf786cc-99fc-4d46-b6b3-cf6b5314011a + 68472b2f-1682-4c03-a570-0bd3dafb7255 + 5 + 917db72d-186f-4f9b-9bae-68106080e5ea + Group + main_centerline + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 654077fb-9447-42ca-a4ed-d6a4dd8d1874 + Number Slider + + false + 0 + + + + + + 1721 + 902 + 205 + 20 + + + 1721.597 + 902.3441 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 40 + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + c18f9e62-d6f5-42c4-a426-10688f24ca61 + fd67193c-c124-4e9b-bf38-3d6a6e085438 + 2 + b916d0a2-94ed-4de0-9991-6f37b3e59ce4 + Group + Ref_Side + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + d5f970b8-28fa-4f28-b038-8f3eed5c682d + c1e88145-a742-40e8-9b8b-a549422a646d + c925fa54-d90e-456f-863a-2f4f0a2857ba + 3 + 280e3dc8-45ed-4759-8d99-df91689dd4d8 + Group + StepShape + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 654077fb-9447-42ca-a4ed-d6a4dd8d1874 + 1 + 98458446-0073-4c25-ac14-bdda3bc5b7ad + Group + Mortise + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;56;56 + + A group of Grasshopper objects + cfb4b1f8-a02e-44ce-9c95-80b1164d7fca + 1 + d22d460d-f45b-4227-b1b7-0d4f280ddbcc + Group + + + + + + + + + + + + + + + + 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 + + + + + \ No newline at end of file