From 6c80b1a8d98c87f119527362942262bff3fb3dc2 Mon Sep 17 00:00:00 2001 From: papachap Date: Wed, 30 Oct 2024 15:18:27 +0100 Subject: [PATCH] minor adjustments --- .../Grasshopper/tests/test_dovetail_joint.ghx | 7290 ++++++++ .../Grasshopper/tests}/test_step_joint.ghx | 4774 +++-- .../_fabrication/btlx_process.py | 18 +- .../_fabrication/dovetail_mortise.py | 21 +- .../_fabrication/dovetail_tenon.py | 33 +- src/compas_timber/_fabrication/step_joint.py | 1 + .../_fabrication/step_joint_notch.py | 1 + tests/compas_timber/gh/test_dovetail.ghx | 15023 ---------------- 8 files changed, 9630 insertions(+), 17531 deletions(-) create mode 100644 examples/Grasshopper/tests/test_dovetail_joint.ghx rename {tests/compas_timber/gh => examples/Grasshopper/tests}/test_step_joint.ghx (84%) delete mode 100644 tests/compas_timber/gh/test_dovetail.ghx diff --git a/examples/Grasshopper/tests/test_dovetail_joint.ghx b/examples/Grasshopper/tests/test_dovetail_joint.ghx new file mode 100644 index 000000000..c1e9c4d87 --- /dev/null +++ b/examples/Grasshopper/tests/test_dovetail_joint.ghx @@ -0,0 +1,7290 @@ + + + + + + + + 0 + 2 + 2 + + + + + + + 1 + 0 + 7 + + + + + + fa5d732c-b31a-4064-bc30-fdd75169872b + Shaded + Selection + 1 + + 100;150;0;0 + + + 100;0;150;0 + + + + + + 638584536051543966 + + test_dovetail_joint.ghx + + + + + 0 + + + + + + 574 + 754 + + 0.3474256 + + + + + 0 + + + + + + + 0 + + + + + 1 + + + + + GhPython, Version=7.34.23267.11001, Culture=neutral, PublicKeyToken=null + 7.34.23267.11001 + + 00000000-0000-0000-0000-000000000000 + + + + + + + + + 81 + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + c67c3391-fbfa-4fd4-bd01-edf5270cbdc6 + c3c1dc6d-7ceb-4d7f-add6-fa924b4cc936 + ab977350-6a8d-472b-9276-52a400da755b + 1f382d1c-8a89-4e8a-8102-597801cd81a3 + 071ab375-9118-4d58-aba2-a9de6de2f088 + f1db2a34-33d7-489c-af3c-6723cd9cafed + 244dd1d8-93d4-4afc-851d-064a07e08680 + 2b407bc7-5cf8-4769-888d-66de2e16c241 + 17656a19-e22f-448a-b26f-e7d025b96e6f + 405d1b89-3c83-4839-aa6a-7e9ca46c1aad + 6b6d7ea8-7a08-4879-939c-5f96604c4678 + 89a39aa2-89d0-4ad6-9043-6ef61b51023c + 61d94f4d-5239-4d5e-a848-ab890c2a7194 + a5781cd0-b305-4ed7-99aa-69c993f66d09 + 8bd29712-ff83-438b-b8f1-1d5f93dba350 + fce549a7-0108-4a88-b977-d6d4b63e84a0 + 21efd848-0a03-4347-82a3-6a077b2c51d5 + 17 + be21a29f-1f53-48d4-a960-d1abfdce7212 + Group + + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 68447cb4-778f-4e2c-a7ca-627a868c84e1 + dcc01bf8-eaab-475a-9a3d-34524bf3dfa7 + 0cae4f91-95c7-4cfa-8d10-c084807de87e + fb924a22-fb82-45ca-81fd-fb8a3ef8536a + fe8fa9fd-21f2-43ef-b49f-767b0753a1ae + a3e72ece-c329-479f-b17f-94062e976ee8 + 48898955-f881-4e56-b6e5-3c7ee5cdc4a2 + 0d673e88-5ab0-4910-98ed-aa50c52a5acc + dfa57b10-b759-4c01-8ef6-e8f27c2261c0 + fb2bee0a-2791-40d8-ba2d-3facd193d280 + ee37f1a7-f247-4dd1-9926-3498f06eec02 + 09833aa5-1994-4337-85d5-341624343d48 + 19c8f5b9-f818-4553-9fec-96ae2df55628 + 10946ab9-030f-41c8-8192-8fc73ecb49e4 + 697f731c-faf2-45c5-a9c4-a947431b741b + 74f12b35-8c0f-4016-92da-4457ad7215e5 + 04a8d391-5de1-43a3-bc1e-9148489eba13 + 6b5f5a99-98ff-4322-b2f6-76ed37c15310 + fe63683a-84ba-462b-b688-9e3f081f52fb + c9c46265-63bf-4a08-a740-f490552e886d + 20 + f933758c-1ec0-48d2-a445-83d28dc99239 + Group + + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 1631fe30-c80f-49ec-9128-96481121ad52 + a8a91d2c-6d94-4451-b47e-a81520b31d82 + ae229730-bb17-41d8-826e-9f750d58d128 + 54426880-0968-40ad-8b1e-e50de0a67289 + 46feaa45-4a40-458f-a4fd-9de5989af911 + 1dc4a321-0021-4a13-90df-e852c7e4e773 + f05fce76-e87f-48e1-a86d-07f6d4084049 + 3606e2e7-dfd8-4977-a4d6-75b937b9b9f1 + 2a5a867a-a76c-4f02-bce5-209e79f61aac + f29282aa-9bfd-49b7-a1a0-1f7fc87af0e9 + 31a8ef0b-5079-4e66-9612-dff6a751c5a8 + 11 + 0b9fb065-5070-4c3f-96bb-831d0aa1aedf + Group + MainBeam + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 37c9fe3d-b5bb-4362-ba0f-d5053fcb2141 + 7e4bcb53-01cc-446e-8792-764d02b1451e + c3c1dc6d-7ceb-4d7f-add6-fa924b4cc936 + ab977350-6a8d-472b-9276-52a400da755b + dec5089d-c452-417b-a948-4034d6df42ce + 1f382d1c-8a89-4e8a-8102-597801cd81a3 + ba1c263a-665b-4a0d-a1a6-e771de90f422 + 62e63fca-99eb-4ff3-8b10-df2b88807b8d + d6206efa-67b1-4c9e-b762-42a2cf302219 + 244dd1d8-93d4-4afc-851d-064a07e08680 + 6b6d7ea8-7a08-4879-939c-5f96604c4678 + 89a39aa2-89d0-4ad6-9043-6ef61b51023c + 12 + c67c3391-fbfa-4fd4-bd01-edf5270cbdc6 + Group + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + c3c1dc6d-7ceb-4d7f-add6-fa924b4cc936 + Number Slider + + false + 0 + + + + + + 1463 + 257 + 188 + 20 + + + 1463.824 + 257.7544 + + + + + + 2 + 1 + 0 + 200 + 0 + 0 + 10 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + ab977350-6a8d-472b-9276-52a400da755b + Number Slider + width + false + 0 + + + + + + 1463 + 278 + 188 + 20 + + + 1463.755 + 278.8987 + + + + + + 3 + 1 + 1 + 200 + 0 + 0 + 25 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 1f382d1c-8a89-4e8a-8102-597801cd81a3 + Number Slider + cone_angle + false + 0 + + + + + + 1463 + 322 + 188 + 20 + + + 1463.902 + 322.6094 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 10 + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 37c9fe3d-b5bb-4362-ba0f-d5053fcb2141 + 7e4bcb53-01cc-446e-8792-764d02b1451e + 2 + ba1c263a-665b-4a0d-a1a6-e771de90f422 + Group + Ref_Side + + + + + + + + + + d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 + Curve + + + + + Contains a collection of generic curves + true + 1631fe30-c80f-49ec-9128-96481121ad52 + Curve + Crv + false + 0 + + + + + + -193 + 533 + 50 + 24 + + + -167.8206 + 545.0109 + + + + + + 1 + + + + + 1 + {0} + + + + + -1 + + Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyNy4bxpcrDPvOXz4/18+rHjlAagcQwpU3KHb70cS13q4OBMDAuxtjlpjZzvZAeSS6oIuv//1TA0wOW6GwQQA + + 00000000-0000-0000-0000-000000000000 + + + + + + + + + + + + + d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 + Curve + + + + + Contains a collection of generic curves + true + 18d2fa4a-de1b-4cfd-bf80-4b8d5fa0182f + Curve + Crv + false + 0 + + + + + + 90 + 227 + 50 + 24 + + + 115.7182 + 239.6854 + + + + + + 1 + + + + + 1 + {0} + + + + + -1 + + Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyFyF5Ln1s/nvOXz8/18+rHjlAagcw4SN5/afrXvg8BlNnIkBDRQsdwC55PeJbev/1zM1wIS50dUNKAAA + + 00000000-0000-0000-0000-000000000000 + + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 478fc3b1-c4f8-4087-8fe6-c2905e21be9a + Number Slider + + false + 0 + + + + + + 825 + 596 + 166 + 20 + + + 825.0048 + 596.0939 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 100 + + + + + + + + + 22990b1f-9be6-477c-ad89-f775cd347105 + Flip Curve + + + + + Flip a curve using an optional guide curve. + true + 2098ce01-e0b3-4e52-b0ed-3c62bb419a62 + Flip Curve + Flip + + + + + + 391 + 615 + 66 + 44 + + + 423 + 637 + + + + + + Curve to flip + 417fea5c-f458-4cb9-81ea-3c456faf67b1 + Curve + C + false + 2ace07a8-3cff-4c52-b37f-cd3e591aeddd + 1 + + + + + + 393 + 617 + 15 + 20 + + + 402 + 627 + + + + + + + + Optional guide curve + 0cee7869-6730-4b7d-832a-4aa6b5d4749a + Guide + G + true + 0 + + + + + + 393 + 637 + 15 + 20 + + + 402 + 647 + + + + + + + + Flipped curve + 0b2eef87-f147-4a36-b443-85031493ef71 + Curve + C + false + 0 + + + + + + 438 + 617 + 17 + 20 + + + 446.5 + 627 + + + + + + + + Flip action + d77f6082-7255-4694-8fae-7a31bce87565 + Flag + F + false + 0 + + + + + + 438 + 637 + 17 + 20 + + + 446.5 + 647 + + + + + + + + + + + + 11bbd48b-bb0a-4f1b-8167-fa297590390d + End Points + + + + + Extract the end points of a curve. + true + 3606e2e7-dfd8-4977-a4d6-75b937b9b9f1 + End Points + End + + + + + + -91 + 559 + 64 + 44 + + + -60 + 581 + + + + + + Curve to evaluate + c35e0949-31c0-4148-833b-aeed3fc97aa3 + Curve + C + false + 1631fe30-c80f-49ec-9128-96481121ad52 + 1 + + + + + + -89 + 561 + 14 + 40 + + + -80.5 + 581 + + + + + + + + Curve start point + 349dd0c5-02cc-4111-abf4-8728c5a86c2c + Start + S + false + 0 + + + + + + -45 + 561 + 16 + 20 + + + -37 + 571 + + + + + + + + Curve end point + 08d2450a-ba8f-45b3-a29d-274a84997a85 + End + E + false + 0 + + + + + + -45 + 581 + 16 + 20 + + + -37 + 591 + + + + + + + + + + + + e9eb1dcf-92f6-4d4d-84ae-96222d60f56b + Move + + + + + Translate (move) an object along a vector. + true + 2a5a867a-a76c-4f02-bce5-209e79f61aac + Move + Move + + + + + + -5 + 606 + 83 + 44 + + + 43 + 628 + + + + + + Base geometry + a0edbf9a-3853-4ab0-b53f-aef5027fa137 + Geometry + G + true + 08d2450a-ba8f-45b3-a29d-274a84997a85 + 1 + + + + + + -3 + 608 + 31 + 20 + + + 22 + 618 + + + + + + + + Translation vector + 8acddbb8-4abe-4d9b-81aa-f36b38b9dda4 + -x + Motion + T + false + 3441a608-3853-45f3-92c7-1d1941125460 + 1 + + + + + + -3 + 628 + 31 + 20 + + + 22 + 638 + + + + + + 1 + + + + + 1 + {0} + + + + + + 0 + 0 + 10 + + + + + + + + + + + + Translated geometry + 3b2b25a6-3d8c-4a41-b0a2-3ea3be957972 + Geometry + G + false + 0 + + + + + + 58 + 608 + 18 + 20 + + + 67 + 618 + + + + + + + + Transformation data + d8dfb3a4-eb51-4258-aa5c-b6584682d0ef + Transform + X + false + 0 + + + + + + 58 + 628 + 18 + 20 + + + 67 + 638 + + + + + + + + + + + + 79f9fbb3-8f1d-4d9a-88a9-f7961b1012cd + Unit X + + + + + Unit vector parallel to the world {x} axis. + true + a8a91d2c-6d94-4451-b47e-a81520b31d82 + Unit X + X + + + + + + -193 + 604 + 79 + 28 + + + -148 + 618 + + + + + + Unit multiplication + 0640aeed-9882-4ebf-a1b1-5080f3b20bb9 + -x + Factor + F + false + ae229730-bb17-41d8-826e-9f750d58d128 + 1 + + + + + + -191 + 606 + 28 + 24 + + + -167.5 + 618 + + + + + + 1 + + + + + 1 + {0} + + + + + 1 + + + + + + + + + + + World {x} vector + 20ce5606-82c9-43d0-b182-e8db425945b5 + Unit vector + V + false + 0 + + + + + + -133 + 606 + 17 + 24 + + + -124.5 + 618 + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + ae229730-bb17-41d8-826e-9f750d58d128 + Number Slider + + false + 0 + + + + + + -367 + 609 + 163 + 20 + + + -366.041 + 609.4734 + + + + + + 3 + 1 + 1 + 4000 + 0 + 0 + 500 + + + + + + + + + 4c4e56eb-2f04-43f9-95a3-cc46a14f495a + Line + + + + + Create a line between two points. + true + f29282aa-9bfd-49b7-a1a0-1f7fc87af0e9 + Line + Ln + + + + + + 103 + 586 + 63 + 44 + + + 134 + 608 + + + + + + Line start point + cb99cc28-9c59-4191-95b9-3cae3e6f1e9c + Start Point + A + false + 349dd0c5-02cc-4111-abf4-8728c5a86c2c + 1 + + + + + + 105 + 588 + 14 + 20 + + + 113.5 + 598 + + + + + + + + Line end point + fb12ca80-6fc6-404b-8d93-4fdb6c2c6520 + End Point + B + false + 3b2b25a6-3d8c-4a41-b0a2-3ea3be957972 + 1 + + + + + + 105 + 608 + 14 + 20 + + + 113.5 + 618 + + + + + + + + Line segment + b37fb167-edb3-4a28-b8fd-a498a7811210 + Line + L + false + 0 + + + + + + 149 + 588 + 15 + 40 + + + 156.5 + 608 + + + + + + + + + + + + 9103c240-a6a9-4223-9b42-dbd19bf38e2b + Unit Z + + + + + Unit vector parallel to the world {z} axis. + true + 54426880-0968-40ad-8b1e-e50de0a67289 + Unit Z + Z + + + + + + -175 + 638 + 63 + 28 + + + -146 + 652 + + + + + + Unit multiplication + 45ecdc35-f4be-4e29-97b3-ae200336ed76 + Factor + F + false + 46feaa45-4a40-458f-a4fd-9de5989af911 + 1 + + + + + + -173 + 640 + 12 + 24 + + + -165.5 + 652 + + + + + + 1 + + + + + 1 + {0} + + + + + 1 + + + + + + + + + + + World {z} vector + 31dfa7fb-7b92-4e78-8a6c-51149c8b2402 + Unit vector + V + false + 0 + + + + + + -131 + 640 + 17 + 24 + + + -122.5 + 652 + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 46feaa45-4a40-458f-a4fd-9de5989af911 + Number Slider + + false + 0 + + + + + + -367 + 643 + 163 + 20 + + + -366.3402 + 643.5607 + + + + + + 3 + 1 + 1 + 2000 + 0 + 0 + 500 + + + + + + + + + a0d62394-a118-422d-abb3-6af115c75b25 + Addition + + + + + Mathematical addition + true + 31a8ef0b-5079-4e66-9612-dff6a751c5a8 + Addition + A+B + + + + + + -89 + 606 + 65 + 64 + + + -58 + 638 + + + + + + 3 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + First item for addition + d9d3d34d-5080-4bb5-aa7b-9e02635fbae5 + A + A + true + 20ce5606-82c9-43d0-b182-e8db425945b5 + 1 + + + + + + -87 + 608 + 14 + 20 + + + -78.5 + 618 + + + + + + + + Second item for addition + 3898220f-37d7-48fc-b80c-31e2b32274f5 + B + B + true + 31dfa7fb-7b92-4e78-8a6c-51149c8b2402 + 1 + + + + + + -87 + 628 + 14 + 20 + + + -78.5 + 638 + + + + + + + + Third item for addition + 13ca1130-de29-4026-94fc-c1ca22604c07 + C + C + true + 7a214201-5ed9-46c9-afe6-bf48e768f870 + 1 + + + + + + -87 + 648 + 14 + 20 + + + -78.5 + 658 + + + + + + + + Result of addition + 3441a608-3853-45f3-92c7-1d1941125460 + Result + R + false + 0 + + + + + + -43 + 608 + 17 + 60 + + + -34.5 + 638 + + + + + + + + + + + + + + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle + + + + + Boolean (true/false) toggle + ca0ea429-34fb-4ce1-a30e-2c14ddc1552e + Boolean Toggle + FlipCurve + false + 0 + true + + + + + + 258 + 569 + 115 + 22 + + + + + + + + + + eeafc956-268e-461d-8e73-ee05c6f72c01 + Stream Filter + + + + + Filters a collection of input streams + true + 9c98408b-5774-4f45-bb43-c16e5d4c92b4 + Stream Filter + Filter + + + + + + 469 + 575 + 77 + 64 + + + 501 + 607 + + + + + + 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 + be384cd0-c014-4922-86ee-f8be45625fad + Gate + G + false + ca0ea429-34fb-4ce1-a30e-2c14ddc1552e + 1 + + + + + + 471 + 577 + 15 + 20 + + + 480 + 587 + + + + + + 1 + + + + + 1 + {0} + + + + + 0 + + + + + + + + + + + 2 + Input stream at index 0 + b069b652-f7a4-47dc-a04c-9b3003b0e168 + false + Stream 0 + 0 + true + 2ace07a8-3cff-4c52-b37f-cd3e591aeddd + 1 + + + + + + 471 + 597 + 15 + 20 + + + 480 + 607 + + + + + + + + 2 + Input stream at index 1 + 4bbd6850-b99a-47c4-a371-8adee5564955 + false + Stream 1 + 1 + true + 0b2eef87-f147-4a36-b443-85031493ef71 + 1 + + + + + + 471 + 617 + 15 + 20 + + + 480 + 627 + + + + + + + + 2 + Filtered stream + 09fe95fb-9551-4690-abf6-4a0665002914 + false + Stream + S(1) + false + 0 + + + + + + 516 + 577 + 28 + 60 + + + 530 + 607 + + + + + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + a8a91d2c-6d94-4451-b47e-a81520b31d82 + ae229730-bb17-41d8-826e-9f750d58d128 + 54426880-0968-40ad-8b1e-e50de0a67289 + 46feaa45-4a40-458f-a4fd-9de5989af911 + 780dd7ff-1451-4d20-b77b-f1c386f8a9ed + 27b7a426-ec72-4334-8c70-78c50fb834e2 + 6 + f05fce76-e87f-48e1-a86d-07f6d4084049 + Group + + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 18d2fa4a-de1b-4cfd-bf80-4b8d5fa0182f + 1 + e22e52d8-5a24-494f-8bd6-2f5c368cced0 + Group + CrossBeam + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + a31a3c97-3e91-47a8-add8-793f530b94e1 + Panel + + false + 0.88918887078762054 + ec68082b-6816-42e0-b242-ac0746b13092 + 1 + G:\Shared drives\2024_MAS\T2\03_finalization\Fabrication - Joints\BTLx\step_joint_joint_test.btlx + + + + + + 2555 + 841 + 455 + 420 + + 0 + 0 + 0 + + 2555.197 + 841.1592 + + + + + + + 255;255;250;90 + + true + true + true + false + true + D:\Papachap\Desktop\BTLx\dovetail_joint.btlx + true + + + + + + + + + 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 DovetailTenon +from compas_timber._fabrication import DovetailTenonParams +from compas_timber._fabrication import DovetailMortise +from compas_timber._fabrication import DovetailMortiseParams + +from compas_timber.connections import Joint +from compas_timber.connections.utilities import beam_ref_side_incidence, beam_ref_side_incidence_with_vector + +from compas_timber.model import TimberModel +from compas_timber.fabrication import BTLx + +from compas.geometry import Point, intersection_line_line, angle_vectors, angle_vectors_signed + +from compas_rhino import unload_modules +from compas.scene import SceneObject + +import math + +from compas_rhino.conversions import frame_to_rhino, plane_to_rhino, vector_to_rhino, surface_to_rhino, polyline_to_rhino, brep_to_rhino, point_to_rhino, surface_to_rhino + +import Rhino.Geometry as rg +unload_modules("compas_timber") + +geo_tenon = main_beam.compute_geometry(False) +geo_mortise = cross_beam.compute_geometry(False) + +#define ref_sides +cross_ref_side_dict = beam_ref_side_incidence(main_beam, cross_beam, ignore_ends=True) +cross_ref_side_index = min(cross_ref_side_dict, key=cross_ref_side_dict.get) +print(cross_ref_side_index, "cross") +cross_ref_side_normal = cross_beam.ref_sides[cross_ref_side_index].normal +main_ref_side_dict = beam_ref_side_incidence_with_vector(main_beam, cross_ref_side_normal, ignore_ends=True) +main_ref_side_index = min(main_ref_side_dict, key=main_ref_side_dict.get) +print(main_ref_side_index, "main") + +ref_side_main = frame_to_rhino(main_beam.ref_sides[main_ref_side_index]) +ref_side_cross = frame_to_rhino(cross_beam.ref_sides[cross_ref_side_index]) + +#create dovetail_tenon +DovetailTenon.define_dovetail_tool(15.0, 60.034, 28.0) +dovetail_tenon = DovetailTenon.from_plane_and_beam( + cross_beam.ref_sides[cross_ref_side_index], + main_beam, + start_y=start_y, + rotation=rotation, + start_depth=start_depth, + width=width, + length=length, + cone_angle=cone_angle, + ref_side_index=main_ref_side_index, + ) + +#cutting_frame +cutting_plane_tenon= dovetail_tenon.frame_from_params_and_beam(main_beam) +#tenon cutting planes +dovetail_tenon_planes = dovetail_tenon.dovetail_cutting_frames_from_params_and_beam(main_beam) +#tenon volume +tenon_volume = dovetail_tenon.dovetail_volume_from_params_and_beam(main_beam) + + +dovetail_mortise = DovetailMortise.from_frame_and_beam( + frame=cutting_plane_tenon, + beam=cross_beam, + start_depth=0.0, + angle=rotation, + length=dovetail_tenon.length, + width=dovetail_tenon.width, + depth=dovetail_tenon.height, + cone_angle=dovetail_tenon.cone_angle, + flank_angle=dovetail_tenon.flank_angle, + shape=dovetail_tenon.shape, + shape_radius=dovetail_tenon.shape_radius, + ref_side_index=cross_ref_side_index, + ) +#cutting frame +cutting_plane_mortise = dovetail_mortise.frame_from_params_and_beam(cross_beam) +#mortise cutting planes +dovetail_mortise_planes = dovetail_mortise.dovetail_cutting_frames_from_params_and_beam(cross_beam) +#mortise volue +mortise_volume = dovetail_mortise.dovetail_volume_from_params_and_beam(cross_beam) + +#get btlx params +dovetail_mortise_params = DovetailMortiseParams(dovetail_mortise).as_dict() +mortise_btlx_params = [] +for key, value in dovetail_mortise_params.items(): + mortise_btlx_params.append("{0}: {1}".format(key, value)) + +#get btlx params +dovetail_tenon_params = DovetailTenonParams(dovetail_tenon).as_dict() +tenon_btlx_params = [] +for key, value in dovetail_tenon_params.items(): + tenon_btlx_params.append("{0}: {1}".format(key, value)) + + +#vizualize in rhino + +cutting_plane_tenon = frame_to_rhino(cutting_plane_tenon) +cutting_plane_mortise = frame_to_rhino(cutting_plane_mortise) + +tenon_planes = [frame_to_rhino(plane) for plane in dovetail_tenon_planes] +mortise_planes = [frame_to_rhino(plane) for plane in dovetail_mortise_planes] + +geo_tenon = brep_to_rhino(dovetail_tenon.apply(geo_tenon, main_beam)) +geo_mortise = brep_to_rhino(dovetail_mortise.apply(geo_mortise, cross_beam)) + + + GhPython provides a Python script component + + 178 + 222 + + + 1586 + 781 + + true + false + false + 071ab375-9118-4d58-aba2-a9de6de2f088 + false + true + GhPython Script + Python + + + + + + 1693 + 206 + 214 + 184 + + + 1774 + 298 + + + + + + 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 + 9 + 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 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + Script variable Python + e17658fc-3064-4e83-9c8d-2ca7d71257bd + cross_beam + cross_beam + true + 0 + true + 421f6dc4-6e2e-4f36-9475-969e527e32cb + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1695 + 208 + 64 + 22 + + + 1728.5 + 219.25 + + + + + + + + true + Script input main_beam. + c5907a16-b1b8-4c71-bdc0-ccca293ad70f + main_beam + main_beam + true + 0 + true + 710e74b1-2ede-4081-931a-087d503d6a24 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1695 + 230 + 64 + 23 + + + 1728.5 + 241.75 + + + + + + + + true + Script input start_depth. + 004aac7d-efce-4814-98f9-6d6581b11a4a + start_depth + start_depth + true + 0 + true + c3c1dc6d-7ceb-4d7f-add6-fa924b4cc936 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1695 + 253 + 64 + 22 + + + 1728.5 + 264.25 + + + + + + + + true + Script input width. + b76082c7-47ee-49e6-90a5-7fed960a32bb + width + width + true + 0 + true + ab977350-6a8d-472b-9276-52a400da755b + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1695 + 275 + 64 + 23 + + + 1728.5 + 286.75 + + + + + + + + true + Script input length. + 3e9be09b-b9b1-46ae-88bd-2a68cff46e13 + length + length + true + 0 + true + 244dd1d8-93d4-4afc-851d-064a07e08680 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1695 + 298 + 64 + 22 + + + 1728.5 + 309.25 + + + + + + + + true + Script input cone_angle. + 77eebdf9-6c87-4e51-b360-dd5f773e8cd2 + cone_angle + cone_angle + true + 0 + true + 1f382d1c-8a89-4e8a-8102-597801cd81a3 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1695 + 320 + 64 + 23 + + + 1728.5 + 331.75 + + + + + + + + true + Script input start_y. + 05be9a7a-6224-49b3-bcf0-791c623f7f77 + start_y + start_y + true + 0 + true + 89a39aa2-89d0-4ad6-9043-6ef61b51023c + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1695 + 343 + 64 + 22 + + + 1728.5 + 354.25 + + + + + + + + true + Script input rotation. + 09a29b2e-a2b5-4147-81d7-21fa818dc6cc + rotation + rotation + true + 0 + true + 6b6d7ea8-7a08-4879-939c-5f96604c4678 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1695 + 365 + 64 + 23 + + + 1728.5 + 376.75 + + + + + + + + The execution information, as output and error streams + fb966008-8d47-4262-8c09-ce71985833b0 + out + out + false + 0 + + + + + + 1789 + 208 + 116 + 20 + + + 1847 + 218 + + + + + + + + Script output cutting_plane_tenon. + 213adbf5-0592-48ab-b06a-06543b55b8da + cutting_plane_tenon + cutting_plane_tenon + false + 0 + + + + + + 1789 + 228 + 116 + 20 + + + 1847 + 238 + + + + + + + + Script output cutting_plane_mortise. + cc5eda18-08de-4b0d-91bd-9eefbfcc5dc7 + cutting_plane_mortise + cutting_plane_mortise + false + 0 + + + + + + 1789 + 248 + 116 + 20 + + + 1847 + 258 + + + + + + + + Script output ref_side_main. + d7c2e387-1413-47f3-96a4-1fd6a08f1e62 + ref_side_main + ref_side_main + false + 0 + + + + + + 1789 + 268 + 116 + 20 + + + 1847 + 278 + + + + + + + + Script output ref_side_cross. + a8110476-8bb3-4892-9423-09704614c7a3 + ref_side_cross + ref_side_cross + false + 0 + + + + + + 1789 + 288 + 116 + 20 + + + 1847 + 298 + + + + + + + + Script output mortise_btlx_params. + 83bdcfa8-afbb-420d-9faa-98a158aee68d + mortise_btlx_params + mortise_btlx_params + false + 0 + + + + + + 1789 + 308 + 116 + 20 + + + 1847 + 318 + + + + + + + + Script output tenon_btlx_params. + 6d4fe408-c656-48f6-88c9-67f2fbcdb1df + tenon_btlx_params + tenon_btlx_params + false + 0 + + + + + + 1789 + 328 + 116 + 20 + + + 1847 + 338 + + + + + + + + Script output geo_tenon. + be1a6a99-5e4d-460c-a8f0-e8312a661132 + geo_tenon + geo_tenon + false + 0 + + + + + + 1789 + 348 + 116 + 20 + + + 1847 + 358 + + + + + + + + Script output geo_mortise. + 389410e6-fbd0-4b13-ad00-528c4c2075fd + geo_mortise + geo_mortise + false + 0 + + + + + + 1789 + 368 + 116 + 20 + + + 1847 + 378 + + + + + + + + + + + + + + 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 + Plane + + + + + Contains a collection of three-dimensional axis-systems + f1db2a34-33d7-489c-af3c-6723cd9cafed + Plane + Pln + false + d7c2e387-1413-47f3-96a4-1fd6a08f1e62 + 1 + + + + + + 1941 + 263 + 50 + 24 + + + 1966.171 + 275.4026 + + + + + + + + + + d3d195ea-2d59-4ffa-90b1-8b7ff3369f69 + Unit Y + + + + + Unit vector parallel to the world {y} axis. + true + 780dd7ff-1451-4d20-b77b-f1c386f8a9ed + Unit Y + Y + + + + + + -174 + 672 + 63 + 28 + + + -145 + 686 + + + + + + Unit multiplication + f46970bc-a15b-434c-931c-2ba17d942c80 + Factor + F + false + 27b7a426-ec72-4334-8c70-78c50fb834e2 + 1 + + + + + + -172 + 674 + 12 + 24 + + + -164.5 + 686 + + + + + + 1 + + + + + 1 + {0} + + + + + 1 + + + + + + + + + + + World {y} vector + 7a214201-5ed9-46c9-afe6-bf48e768f870 + Unit vector + V + false + 0 + + + + + + -130 + 674 + 17 + 24 + + + -121.5 + 686 + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 27b7a426-ec72-4334-8c70-78c50fb834e2 + Number Slider + + false + 0 + + + + + + -362 + 677 + 163 + 20 + + + -361.9075 + 677.7514 + + + + + + 3 + 1 + 1 + 4000 + 0 + 0 + 0 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 244dd1d8-93d4-4afc-851d-064a07e08680 + Number Slider + length + false + 0 + + + + + + 1463 + 300 + 188 + 20 + + + 1463.828 + 300.8458 + + + + + + 3 + 1 + 1 + 200 + 0 + 0 + 60 + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + 2b407bc7-5cf8-4769-888d-66de2e16c241 + Panel + + false + 1 + fb966008-8d47-4262-8c09-ce71985833b0 + 1 + Double click to edit panel content… + + + + + + 1695 + 147 + 213 + 58 + + 0 + 0 + 0 + + 1695.757 + 147.8631 + + + + + + + 255;255;250;90 + + true + true + true + false + false + true + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + f2af4f17-9955-4d61-93cd-76e0d692f241 + Panel + BTLx Params + false + 0 + 83bdcfa8-afbb-420d-9faa-98a158aee68d + 1 + Double click to edit panel content… + + + + + + 2298 + -120 + 206 + 333 + + 0 + 0 + 0 + + 2298.547 + -119.9866 + + + + + + + 255;255;255;255 + + true + true + true + false + false + true + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;56;56 + + A group of Grasshopper objects + f2af4f17-9955-4d61-93cd-76e0d692f241 + 1 + 02293eca-caf6-4507-8376-6b1f1bbf6472 + Group + + + + + + + + + + + 919e146f-30ae-4aae-be34-4d72f555e7da + Brep + + + + + Contains a collection of Breps (Boundary REPresentations) + 17656a19-e22f-448a-b26f-e7d025b96e6f + Brep + Brep + false + be1a6a99-5e4d-460c-a8f0-e8312a661132 + 1 + + + + + + 1941 + 336 + 50 + 24 + + + 1966.803 + 348.2994 + + + + + + + + + + d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 + Curve + + + + + Contains a collection of generic curves + true + 2ace07a8-3cff-4c52-b37f-cd3e591aeddd + Curve + Crv + false + b37fb167-edb3-4a28-b8fd-a498a7811210 + 1 + + + + + + 320 + 595 + 50 + 24 + + + 345.5917 + 607.4064 + + + + + + 1 + + + + + 1 + {0} + + + + + -1 + + Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyNy4bxpcrDPvOXz4/18+rHjlAagcQwpU3KHb70cS13q4OBMDAuxtjlpjZzvZAeSS6oIuv//1TA0wOW6GwQQA + + 00000000-0000-0000-0000-000000000000 + + + + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 2ace07a8-3cff-4c52-b37f-cd3e591aeddd + ca0ea429-34fb-4ce1-a30e-2c14ddc1552e + 2 + e0450338-f168-4770-aeb4-8e3b1b320b54 + Group + + + + + + + + + + + 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 + Plane + + + + + Contains a collection of three-dimensional axis-systems + 405d1b89-3c83-4839-aa6a-7e9ca46c1aad + Plane + Pln + false + 213adbf5-0592-48ab-b06a-06543b55b8da + 1 + + + + + + 1943 + 209 + 50 + 24 + + + 1968.076 + 221.0302 + + + + + + 1 + + + + + 1 + {0;0} + + + + + + 31287.423274001 + -3231.69101859564 + 48.2812000254933 + -0.259942858411819 + -0.929978182927627 + 0.259942858411848 + 0.963085199245858 + -0.269196766313353 + -1.7074539712177E-15 + + + + + + + + + + + + + + 2a5cfb31-028a-4b34-b4e1-9b20ae15312e + Cross Product + + + + + Compute vector cross product. + true + 4dfed18b-2ae2-4401-932a-d35c5687b48f + Cross Product + XProd + + + + + + 742 + 546 + 66 + 64 + + + 774 + 578 + + + + + + First vector + 20c07560-21cb-462a-913e-33c8dfba4f1a + Vector A + A + false + 36c4deda-ceed-4920-a3f3-2d18ca613b35 + 1 + + + + + + 744 + 548 + 15 + 20 + + + 753 + 558 + + + + + + + + Second vector + d792952b-8d14-4258-93a8-f657e9d4e328 + Vector B + B + false + d2d51328-18f6-4ef3-8dd6-1df6b6af922e + 1 + + + + + + 744 + 568 + 15 + 20 + + + 753 + 578 + + + + + + + + Unitize output + ec1aee98-3178-4b5f-8943-45ff0468d2ad + Unitize + U + false + 0 + + + + + + 744 + 588 + 15 + 20 + + + 753 + 598 + + + + + + 1 + + + + + 1 + {0} + + + + + false + + + + + + + + + + + Cross product vector + 4c90d06e-9810-41a6-baa8-91b753ccec55 + Vector + V + false + 0 + + + + + + 789 + 548 + 17 + 30 + + + 797.5 + 563 + + + + + + + + Vector length + 6cfe60aa-eede-4d54-9b2b-e48c3287be06 + Length + L + false + 0 + + + + + + 789 + 578 + 17 + 30 + + + 797.5 + 593 + + + + + + + + + + + + 9103c240-a6a9-4223-9b42-dbd19bf38e2b + Unit Z + + + + + Unit vector parallel to the world {z} axis. + true + e98b3a90-fae4-407f-a38e-3f9d806bc67d + Unit Z + Z + + + + + + 483 + 537 + 63 + 28 + + + 512 + 551 + + + + + + Unit multiplication + 99a90f24-1411-4423-854c-1d9440888867 + Factor + F + false + 0 + + + + + + 485 + 539 + 12 + 24 + + + 492.5 + 551 + + + + + + 1 + + + + + 1 + {0} + + + + + 1 + + + + + + + + + + + World {z} vector + 3fa223fc-b370-43ff-9286-d236dfc1155a + Unit vector + V + false + 0 + + + + + + 527 + 539 + 17 + 24 + + + 535.5 + 551 + + + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + be283d6e-d4d9-46e1-9a9d-f0f142489cc4 + Panel + Tenon BTLx Params + false + 0 + 6d4fe408-c656-48f6-88c9-67f2fbcdb1df + 1 + Double click to edit panel content… + + + + + + 2298 + 243 + 206 + 333 + + 0 + 0 + 0 + + 2298.139 + 243.8269 + + + + + + + 255;255;255;255 + + true + true + true + false + false + true + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;56;56 + + A group of Grasshopper objects + be283d6e-d4d9-46e1-9a9d-f0f142489cc4 + 1 + 87fa8c87-c926-4271-b108-197a068dafee + Group + + + + + + + + + + + f31d8d7a-7536-4ac8-9c96-fde6ecda4d0a + Cluster + + + + + + 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 + + Contains a cluster of Grasshopper components + true + 9c0f68ef-d76a-47b0-8e49-544cf9321db9 + Cluster + Cluster + false + + + + + 6 + 889b2da6-e09d-4486-879f-2ca5073fe873 + 91116c7c-c6f6-4b91-b30e-651548dbb2cd + 957b3f47-111f-4a0f-9dfa-3dede52b857e + c08a55b9-8d03-46e8-9856-18fdb41e1daf + cf4db125-1c5e-46b5-899e-ec4fbe113fdd + d2d51328-18f6-4ef3-8dd6-1df6b6af922e + 205b16a3-be6e-4cf4-b6c8-545e13207a7a + 757d1752-e8de-4612-b5a0-3d53b66f04ea + c638130d-be5b-464c-b2f4-8c28d38362a7 + 4441038b-e8f1-4972-be88-7e8e0e9b491e + 9103c1fa-d594-44f2-a4ce-2d6b8016e92c + 6e96ab7a-377b-47d1-b788-514f4644a658 + + + + + + 573 + 575 + 99 + 84 + + + 621 + 617 + + + + + + 4 + 16ef3e75-e315-4899-b531-d3166b42dac9 + d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 + cb95db89-6165-43b6-9c41-5702bc5bf137 + 3e8ca6be-fda8-4aaf-b5c0-3c54c8bb7312 + 2 + d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 + 3e8ca6be-fda8-4aaf-b5c0-3c54c8bb7312 + + + + + Contains a collection of three-dimensional vectors + cf4db125-1c5e-46b5-899e-ec4fbe113fdd + Vector + Vec + true + 3fa223fc-b370-43ff-9286-d236dfc1155a + 1 + + + + + + 575 + 577 + 31 + 20 + + + 592 + 587 + + + + + + + + Contains a collection of generic curves + 957b3f47-111f-4a0f-9dfa-3dede52b857e + Curve + Crv + true + 09fe95fb-9551-4690-abf6-4a0665002914 + 1 + + + + + + 575 + 597 + 31 + 20 + + + 592 + 607 + + + + + + + + Contains a collection of boolean values + 889b2da6-e09d-4486-879f-2ca5073fe873 + Boolean + Bool + true + ca0ea429-34fb-4ce1-a30e-2c14ddc1552e + 1 + + + + + + 575 + 617 + 31 + 20 + + + 592 + 627 + + + + + + + + Contains a collection of floating point numbers + c08a55b9-8d03-46e8-9856-18fdb41e1daf + Number + Num + true + c0dd7c3a-81ff-41c2-b62c-72cfdce3816b + 1 + + + + + + 575 + 637 + 31 + 20 + + + 592 + 647 + + + + + + + + Contains a collection of generic curves + d2d51328-18f6-4ef3-8dd6-1df6b6af922e + Curve + Crv + false + 0 + + + + + + 636 + 577 + 34 + 40 + + + 653 + 597 + + + + + + + + Contains a collection of floating point numbers + 91116c7c-c6f6-4b91-b30e-651548dbb2cd + Number + Num + false + 0 + + + + + + 636 + 617 + 34 + 40 + + + 653 + 637 + + + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + c0dd7c3a-81ff-41c2-b62c-72cfdce3816b + Number Slider + + false + 0 + + + + + + 371 + 665 + 173 + 20 + + + 371.0457 + 665.6685 + + + + + + 1 + 1 + 0 + 20 + 0 + 0 + 2 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 6b6d7ea8-7a08-4879-939c-5f96604c4678 + Number Slider + + false + 0 + + + + + + 1466 + 367 + 186 + 20 + + + 1466.286 + 367.0535 + + + + + + 2 + 1 + 0 + 200 + 0 + 0 + 20 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 89a39aa2-89d0-4ad6-9043-6ef61b51023c + Number Slider + + false + 0 + + + + + + 1464 + 344 + 188 + 20 + + + 1464.205 + 344.2856 + + + + + + 3 + 1 + 1 + 50 + 0 + 0 + 10 + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + CT: T Topological Joint Rules + + + + + import inspect + +from ghpythonlib.componentbase import executingcomponent as component +from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning + +from compas_timber.connections import Joint +from compas_timber.connections import JointTopology +from compas_timber.connections import TButtJoint +from compas_timber.design import TopologyRule +from compas_timber.ghpython.ghcomponent_helpers import get_leaf_subclasses +from compas_timber.ghpython.ghcomponent_helpers import manage_dynamic_params +from compas_timber.ghpython.ghcomponent_helpers import rename_gh_output + + +class T_TopologyJointRule(component): + def __init__(self): + super(T_TopologyJointRule, self).__init__() + self.classes = {} + for cls in get_leaf_subclasses(Joint): + if cls.SUPPORTED_TOPOLOGY == JointTopology.TOPO_T: + self.classes[cls.__name__] = cls + if ghenv.Component.Params.Output[0].NickName == "Rule": + self.joint_type = TButtJoint + self.clicked = False + else: + self.joint_type = self.classes.get(ghenv.Component.Params.Output[0].NickName, None) + self.clicked = True + + def RunScript(self, *args): + if not self.clicked: + ghenv.Component.Message = "Default: TButtJoint" + self.AddRuntimeMessage(Warning, "TButtJoint is default, change in context menu (right click)") + return TopologyRule(JointTopology.TOPO_T, TButtJoint) + else: + ghenv.Component.Message = self.joint_type.__name__ + kwargs = {} + for i, val in enumerate(args): + if val is not None: + kwargs[self.arg_names()[i]] = val + if self.joint_type.SUPPORTED_TOPOLOGY != JointTopology.TOPO_T: + self.AddRuntimeMessage(Warning, "Joint type does not match topology. Joint may not be generated.") + return TopologyRule(JointTopology.TOPO_T, self.joint_type, **kwargs) + + def arg_names(self): + names = inspect.getargspec(self.joint_type.__init__)[0][3:] + 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 + + def on_item_click(self, sender, event_info): + self.clicked = True + 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=0, permanent_param_count=0) + ghenv.Component.ExpireSolution(True) + + GhPython provides a Python script component + + 96 + 96 + + + 741 + 702 + + true + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDAAACwwBP0AiyAAAAN5JREFUSEvtk7ENwkAMRTNC6JGIxAIZhREYgY6WCRAjpKbKCCkoKRiBEdjAfJ/uImPMXS6EAinFsy4++3/JvhRE9FPM5HpVdYA8J6tmKP0BQhUowcELS3ayKQcXILBRgp+4g1qLxHDBN1qCFq0WieECmuTMmQbwuHhsN58LdFokhgtoapVIGQpwrtXdKAO92MkNeCRShL95PJONSO8gxqglD32mD5D/TBluBNZImG2oWx4vC0AJzqG+N5BAUO7k5S9G8/cGOUDs6kX31v1bIpfZIMlskOT/DVKYyemg4glf8MWtha38JQAAAABJRU5ErkJggg== + + false + 68447cb4-778f-4e2c-a7ca-627a868c84e1 + true + true + CT: T Topological Joint Rules + T_Topo_Joint + + + + + + 1634 + 876 + 192 + 204 + + + 1730 + 978 + + + + + + 10 + 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 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + start_y + 534626fc-7966-4736-9188-176756493fcc + start_y + start_y + true + a3e72ece-c329-479f-b17f-94062e976ee8 + 1 + + + + + + 1636 + 878 + 79 + 20 + + + 1677 + 888 + + + + + + + + Script input start_depth. + 7597de76-5e70-4808-9b8e-e81cbcc37925 + start_depth + start_depth + true + fe8fa9fd-21f2-43ef-b49f-767b0753a1ae + 1 + + + + + + 1636 + 898 + 79 + 20 + + + 1677 + 908 + + + + + + + + Script input rotation. + 151edfa6-82d1-4b59-96ef-2d94ed57e39e + rotation + rotation + true + 48898955-f881-4e56-b6e5-3c7ee5cdc4a2 + 1 + + + + + + 1636 + 918 + 79 + 20 + + + 1677 + 928 + + + + + + + + Script input length. + d502ab54-077d-4a58-8129-a281e626ea22 + length + length + true + fb924a22-fb82-45ca-81fd-fb8a3ef8536a + 1 + + + + + + 1636 + 938 + 79 + 20 + + + 1677 + 948 + + + + + + + + Script input width. + cf534226-abf9-4421-af45-780bfb2a9218 + width + width + true + dcc01bf8-eaab-475a-9a3d-34524bf3dfa7 + 1 + + + + + + 1636 + 958 + 79 + 20 + + + 1677 + 968 + + + + + + + + Script input cone_angle. + d99cde1f-d7fd-4021-b596-b00c93659492 + cone_angle + cone_angle + true + 0cae4f91-95c7-4cfa-8d10-c084807de87e + 1 + + + + + + 1636 + 978 + 79 + 20 + + + 1677 + 988 + + + + + + + + Script input dovetail_shape. + 347275da-3171-4d50-89da-fb719a724122 + dovetail_shape + dovetail_shape + true + dfa57b10-b759-4c01-8ef6-e8f27c2261c0 + 1 + + + + + + 1636 + 998 + 79 + 20 + + + 1677 + 1008 + + + + + + + + Script input tool_angle. + 3f15676d-0938-42ad-a0d7-8090bcb46e4f + tool_angle + tool_angle + true + 19c8f5b9-f818-4553-9fec-96ae2df55628 + 1 + + + + + + 1636 + 1018 + 79 + 20 + + + 1677 + 1028 + + + + + + + + Script input tool_diameter. + aef3de77-ddf0-4ec7-ab3f-93300c6c15ae + tool_diameter + tool_diameter + true + 10946ab9-030f-41c8-8192-8fc73ecb49e4 + 1 + + + + + + 1636 + 1038 + 79 + 20 + + + 1677 + 1048 + + + + + + + + Script input tool_height. + 883bd64a-9859-44a6-b61e-8c025315b39c + tool_height + tool_height + true + 697f731c-faf2-45c5-a9c4-a947431b741b + 1 + + + + + + 1636 + 1058 + 79 + 20 + + + 1677 + 1068 + + + + + + + + Script output TDovetailJoint. + 9ef43da6-ada7-4c17-a8ec-f321d9379183 + TDovetailJoint + TDovetailJoint + false + 0 + + + + + + 1745 + 878 + 79 + 200 + + + 1784.5 + 978 + + + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + dcc01bf8-eaab-475a-9a3d-34524bf3dfa7 + true + Number Slider + width + false + 0 + + + + + + 1350 + 941 + 191 + 20 + + + 1350.879 + 941.2886 + + + + + + 3 + 1 + 1 + 200 + 0 + 0 + 25 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 0cae4f91-95c7-4cfa-8d10-c084807de87e + true + Number Slider + cone_angle + false + 0 + + + + + + 1350 + 966 + 192 + 20 + + + 1350.184 + 966.6056 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 10 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + fb924a22-fb82-45ca-81fd-fb8a3ef8536a + true + Number Slider + length + false + 0 + + + + + + 1350 + 915 + 190 + 20 + + + 1350.76 + 915.5276 + + + + + + 3 + 1 + 1 + 200 + 0 + 0 + 60 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + fe8fa9fd-21f2-43ef-b49f-767b0753a1ae + true + Number Slider + + false + 0 + + + + + + 1349 + 865 + 192 + 20 + + + 1349.766 + 865.6586 + + + + + + 2 + 1 + 0 + 100 + 0 + 0 + 10 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + a3e72ece-c329-479f-b17f-94062e976ee8 + true + Number Slider + + false + 0 + + + + + + 1350 + 842 + 192 + 20 + + + 1350.21 + 842.0546 + + + + + + 2 + 1 + 0 + 100 + 0 + 0 + 10 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 48898955-f881-4e56-b6e5-3c7ee5cdc4a2 + true + Number Slider + rotation + false + 0 + + + + + + 1350 + 890 + 192 + 20 + + + 1350.024 + 890.0675 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 20 + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + dcc01bf8-eaab-475a-9a3d-34524bf3dfa7 + 0cae4f91-95c7-4cfa-8d10-c084807de87e + fb924a22-fb82-45ca-81fd-fb8a3ef8536a + fe8fa9fd-21f2-43ef-b49f-767b0753a1ae + a3e72ece-c329-479f-b17f-94062e976ee8 + 48898955-f881-4e56-b6e5-3c7ee5cdc4a2 + dfa57b10-b759-4c01-8ef6-e8f27c2261c0 + 7 + 0d673e88-5ab0-4910-98ed-aa50c52a5acc + Group + + + + + + + + + + + 00027467-0d24-4fa7-b178-8dc0ac5f42ec + Value List + + + + + Provides a list of preset values to choose from + true + dfa57b10-b759-4c01-8ef6-e8f27c2261c0 + 5 + 1 + true + Value List + List + false + 0 + + + + + 0 + Automatic + false + + + + + 1 + Square + false + + + + + 2 + Round + false + + + + + 3 + Rounded + false + + + + + 4 + Radius + true + + + + + + 1349 + 991 + 113 + 22 + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + CT: Model + + + + + from compas.scene import Scene +from compas.tolerance import TOL +from ghpythonlib.componentbase import executingcomponent as component +from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning + +from compas_timber.connections import BeamJoinningError +from compas_timber.connections import ConnectionSolver +from compas_timber.connections import JointTopology +from compas_timber.connections import LMiterJoint +from compas_timber.connections import TButtJoint +from compas_timber.connections import XHalfLapJoint +from compas_timber.design import CategoryRule +from compas_timber.design import DebugInfomation +from compas_timber.design import DirectRule +from compas_timber.design import JointDefinition +from compas_timber.design import TopologyRule +from compas_timber.model import TimberModel + +JOINT_DEFAULTS = { + JointTopology.TOPO_X: XHalfLapJoint, + JointTopology.TOPO_T: TButtJoint, + JointTopology.TOPO_L: LMiterJoint, +} + + +# workaround for https://github.com/gramaziokohler/compas_timber/issues/280 +TOL.absolute = 1e-6 + + +class ModelComponent(component): + def get_joints_from_rules(self, beams, rules, topologies): + if not isinstance(rules, list): + rules = [rules] + rules = [r for r in rules if r is not None] + + joints = [] + # rules have to be resolved into joint definitions + topo_rules = {} + cat_rules = [] + direct_rules = [] + + # TODO: refactor this into some kind of a rule reloving class/function + for r in rules: # separate category and topo and direct joint rules + if isinstance(r, TopologyRule): + if topo_rules.get(r.topology_type, None): # if rule for this Topo exists + if (r.joint_type != JOINT_DEFAULTS[r.topology_type]) or ( + len(r.kwargs) != 0 + ): # if this rule is NOT default + topo_rules[r.topology_type] = r + else: + topo_rules[r.topology_type] = r + elif isinstance(r, CategoryRule): + cat_rules.append(r) + if isinstance(r, DirectRule): + direct_rules.append(r) + + for topo in topologies: + beam_a = topo["beam_a"] + beam_b = topo["beam_b"] + detected_topo = topo["detected_topo"] + pair = beam_a, beam_b + pair_joined = False + + if detected_topo == JointTopology.TOPO_UNKNOWN: + continue + + for rule in direct_rules: # apply direct rules first + if rule.comply(pair): + joints.append(JointDefinition(rule.joint_type, rule.beams, **rule.kwargs)) + pair_joined = True + break + + if not pair_joined: # if no direct rule applies, apply category rules next + for rule in cat_rules: + if not rule.comply(pair): + continue + if rule.joint_type.SUPPORTED_TOPOLOGY != detected_topo: + msg = "Conflict detected! Beams: {}, {} meet with topology: {} but rule assigns: {}" + self.AddRuntimeMessage( + Warning, + msg.format( + beam_a.guid, + beam_b.guid, + JointTopology.get_name(detected_topo), + rule.joint_type.__name__, + ), + ) + 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.guid, + beam_b.guid, + 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)) + break # first matching rule + + else: # no category rule applies, apply topology rules + if detected_topo not in topo_rules: + continue + else: + joints.append( + JointDefinition( + topo_rules[detected_topo].joint_type, + [beam_a, beam_b], + **topo_rules[detected_topo].kwargs + ) + ) + return joints + + def RunScript(self, Elements, JointRules, Features, MaxDistance, CreateGeometry): + if not Elements: + self.AddRuntimeMessage(Warning, "Input parameter Beams failed to collect data") + if not JointRules: + self.AddRuntimeMessage(Warning, "Input parameter JointRules failed to collect data") + if not (Elements): # shows beams even if no joints are found + return + if MaxDistance is None: + MaxDistance = TOL.ABSOLUTE # compared to calculted distance, so shouldn't be just 0.0 + + Model = TimberModel() + debug_info = DebugInfomation() + for element in Elements: + # prepare elements for downstream processing + if element is None: + continue + element.remove_features() + if hasattr(element, "remove_blank_extension"): + element.remove_blank_extension() + element.debug_info = [] + Model.add_element(element) + + topologies = [] + solver = ConnectionSolver() + found_pairs = solver.find_intersecting_pairs(list(Model.beams), rtree=True, max_distance=MaxDistance) + for pair in found_pairs: + beam_a, beam_b = pair + detected_topo, beam_a, beam_b = solver.find_topology(beam_a, beam_b, max_distance=MaxDistance) + if not detected_topo == JointTopology.TOPO_UNKNOWN: + topologies.append({"detected_topo": detected_topo, "beam_a": beam_a, "beam_b": beam_b}) + Model.set_topologies(topologies) + + joints = self.get_joints_from_rules(Model.beams, JointRules, topologies) + + if joints: + handled_beams = [] + joints = [j for j in joints if j is not None] + # apply reversed. later joints in orginal list override ealier ones + for joint in joints[::-1]: + beams_to_pair = joint.beams + beam_pair_ids = set([id(beam) for beam in beams_to_pair]) + if beam_pair_ids in handled_beams: + continue + try: + joint.joint_type.create(Model, *beams_to_pair, **joint.kwargs) + except BeamJoinningError as bje: + debug_info.add_joint_error(bje) + else: + handled_beams.append(beam_pair_ids) + + # applies extensions and features resulting from joints + Model.process_joinery() + + if Features: + features = [f for f in Features if f is not None] + for f_def in features: + for element in f_def.elements: + element.add_features(f_def.feature) + + Geometry = None + scene = Scene() + for element in Model.elements(): + if CreateGeometry: + scene.add(element.geometry) + if element.debug_info: + debug_info.add_feature_error(element.debug_info) + else: + scene.add(element.blank) + + if debug_info.has_errors: + self.AddRuntimeMessage(Warning, "Error found during joint creation. See DebugInfo output for details.") + + Geometry = scene.draw() + return Model, Geometry, debug_info + + GhPython provides a Python script component + + 160 + 160 + + + 741 + 702 + + true + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDAAACwwBP0AiyAAAAa1JREFUSEu1lc1NA0EMRqeElJASUkJK4MgxJaSElEAJKSFHjikhBw4cERUgcUNI4XsTe+Td8S4bJCw9MePPP7uezFKu1+tiZA+QaVOkzgzZQbCAQxaTkTojspU4WeFXgzW+VZYTSZ2ObC0ugg1vEMGHts5yndQJsq34MOrcZbW4rTkP17cxN5I7S9kJFm9iE/ytge03ghg2O/dHekcpR0s4i8GMZYMG5uOMiGVzjFrV2+IW6PPuAi2maxA0fzBqtAdz8ddXBdlkAyBXsGijxeJhtXlnyGYbADWE16N2m99/QO3yJL4FM+SnGcHHTH3/aPgebSqPmtSur83MeKXBpTHtHH0RNGJGPi4ntahJ/q2IOU6j4L804BNCrarh8Aa8GhHtVsruaiBrNcSwQUi4hIR7G3AmsVbXgPmx2Nt+cQPZXrCo5yjrG5jAnkPiZi9qIIglJ77NZAMP5ie2tAGx9aESrS8i8yv/bH/n8JjBJ0Y23SAEvIt40cagETOVP9uAAixexpqDZjHdPxzZoAHzwzHmU3yNfBE0YjKtHrqoT8oig28KNzPTAI2YTBNl+wPOvtI8NDHinQAAAABJRU5ErkJggg== + + false + fb2bee0a-2791-40d8-ba2d-3facd193d280 + true + true + CT: Model + Model + + + + + + 2081 + 946 + 198 + 104 + + + 2200 + 998 + + + + + + 5 + 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 + 3 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + 1 + true + Collection of Beams + 75b9cd26-8234-4296-a759-24e24b94d514 + 1 + Elements + Elements + true + 1 + true + 421f6dc4-6e2e-4f36-9475-969e527e32cb + 710e74b1-2ede-4081-931a-087d503d6a24 + 2 + 35915213-5534-4277-81b8-1bdc9e7383d2 + + + + + + 2083 + 948 + 102 + 20 + + + 2143.5 + 958 + + + + + + + + 1 + true + Script input JointRules. + 962ac6c9-86fb-4b6f-bb76-9baafd776740 + 1 + JointRules + JointRules + true + 1 + true + 9ef43da6-ada7-4c17-a8ec-f321d9379183 + 1 + 35915213-5534-4277-81b8-1bdc9e7383d2 + + + + + + 2083 + 968 + 102 + 20 + + + 2143.5 + 978 + + + + + + + + 1 + true + Script input Features. + b9026523-5f20-46e2-9ab8-e0dc7abcdd97 + Features + Features + true + 1 + true + 0 + 35915213-5534-4277-81b8-1bdc9e7383d2 + + + + + + 2083 + 988 + 102 + 20 + + + 2143.5 + 998 + + + + + + + + true + Script input MaxDistance. + f9095c56-0432-4f5d-9a51-f28ccd44fe4c + MaxDistance + MaxDistance + true + 0 + true + 09833aa5-1994-4337-85d5-341624343d48 + 1 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 2083 + 1008 + 102 + 20 + + + 2143.5 + 1018 + + + + + + + + true + Script input CreateGeometry. + 72e58a16-32c5-47b7-8f31-dd3b2de0d42a + CreateGeometry + CreateGeometry + true + 0 + true + ee37f1a7-f247-4dd1-9926-3498f06eec02 + 1 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 2083 + 1028 + 102 + 20 + + + 2143.5 + 1038 + + + + + + + + Script output Model. + 420b8f1c-7df1-405b-a1f3-387f3716017a + Model + Model + false + 0 + + + + + + 2215 + 948 + 62 + 33 + + + 2246 + 964.6667 + + + + + + + + Script output Geometry. + 486668a9-de54-49fb-b662-03694889d429 + Geometry + Geometry + false + 0 + + + + + + 2215 + 981 + 62 + 33 + + + 2246 + 998 + + + + + + + + Script output DebugInfo. + 6c5ffdba-503c-435e-9b82-201c7ce03292 + DebugInfo + DebugInfo + false + 0 + + + + + + 2215 + 1014 + 62 + 34 + + + 2246 + 1031.333 + + + + + + + + + + + + + + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle + + + + + Boolean (true/false) toggle + ee37f1a7-f247-4dd1-9926-3498f06eec02 + Boolean Toggle + Toggle + false + 0 + true + + + + + + 1959 + 1033 + 104 + 22 + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 09833aa5-1994-4337-85d5-341624343d48 + Number Slider + + false + 0 + + + + + + 1869 + 1008 + 195 + 20 + + + 1869.391 + 1008.999 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 40 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 19c8f5b9-f818-4553-9fec-96ae2df55628 + true + Number Slider + + false + 0 + + + + + + 1350 + 1041 + 199 + 20 + + + 1350.004 + 1041.691 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 15 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 10946ab9-030f-41c8-8192-8fc73ecb49e4 + true + Number Slider + + false + 0 + + + + + + 1349 + 1065 + 200 + 20 + + + 1349.941 + 1065.884 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 60 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 697f731c-faf2-45c5-a9c4-a947431b741b + true + Number Slider + + false + 0 + + + + + + 1350 + 1089 + 201 + 20 + + + 1350.058 + 1089.077 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 28 + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 19c8f5b9-f818-4553-9fec-96ae2df55628 + 10946ab9-030f-41c8-8192-8fc73ecb49e4 + 697f731c-faf2-45c5-a9c4-a947431b741b + 3 + 74f12b35-8c0f-4016-92da-4457ad7215e5 + Group + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 13835904-23ad-43b2-a586-0ae141339040 + Number Slider + + false + 0 + + + + + + 828 + 452 + 166 + 20 + + + 828.7086 + 452.7064 + + + + + + 3 + 1 + 1 + 1000 + 0 + 0 + 120 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + b0579e2b-7024-4c03-8e13-7ddcca5e08a6 + Number Slider + + false + 0 + + + + + + 827 + 396 + 162 + 20 + + + 827.0381 + 396.3297 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 60 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 81d19eff-02b1-4406-a0c3-47dd897a152f + Number Slider + + false + 0 + + + + + + 825 + 570 + 162 + 20 + + + 825.3678 + 570.3737 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 80 + + + + + + + + + 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 + Plane + + + + + Contains a collection of three-dimensional axis-systems + 61d94f4d-5239-4d5e-a848-ab890c2a7194 + Plane + Pln + false + cc5eda18-08de-4b0d-91bd-9eefbfcc5dc7 + 1 + + + + + + 1941 + 235 + 50 + 24 + + + 1966.556 + 247.558 + + + + + + + + + + 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 + Plane + + + + + Contains a collection of three-dimensional axis-systems + a5781cd0-b305-4ed7-99aa-69c993f66d09 + Plane + Pln + false + a8110476-8bb3-4892-9423-09704614c7a3 + 1 + + + + + + 1940 + 289 + 50 + 24 + + + 1965.816 + 301.6699 + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + CT: WriteBTLx + + + + + import Rhino +from ghpythonlib.componentbase import executingcomponent as component +from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning + +from compas_timber.fabrication import BTLx + + +class WriteBTLx(component): + def RunScript(self, model, path, write): + if not model: + self.AddRuntimeMessage(Warning, "Input parameter Model failed to collect data") + return + + btlx = BTLx(model) + btlx.history["FileName"] = Rhino.RhinoDoc.ActiveDoc.Name + + if write: + if not path: + self.AddRuntimeMessage(Warning, "Input parameter Path failed to collect data") + return + if path[-5:] != ".btlx": + path += ".btlx" + with open(path, "w") as f: + f.write(btlx.btlx_string()) + return btlx.btlx_string() + + GhPython provides a Python script component + true + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDAAACwwBP0AiyAAAAShJREFUSEu1lFERwjAQRCsBAYhAQiUgAQlIQAGDBCQggQ8EVAIScBB2MxyzCZvwQbiZB/S6d9smF6aU0l+xyZHY5EhsciQ26UAcAne/hU06EPzI1Pd6TOvj7QxW7qbyi0ECyzeTXw3IHWyciNQGiBnEvuxeOf4ueqgBeYBZBW/hpwGbRe5aaS4gr0htEOQnUqQYl/m6Z0DytLUMyImCQItf126J3hrwAKuewRLN62LNK4id6sC+ZXA2xVrYG4ZFdAdnYE8q4qqFDQ2XLTRZVxt8bG6A4GRoMZ/0BPIegC24A9XMYcDxbL42yeKyWOHb6VSRS65DY57ibvMAwSfldGgjUhsU5+Dr/5DCQkAjNuQSsTm/Y2yLg1oU/wObHIlNjsQmR2KT40jTExovdFkNMNc1AAAAAElFTkSuQmCC + + false + 04a8d391-5de1-43a3-bc1e-9148489eba13 + true + true + CT: WriteBTLx + WriteBTLx + + + + + + 2389 + 1019 + 104 + 64 + + + 2444 + 1051 + + + + + + 3 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + Model object. + a3efc012-177d-446f-8246-57f6fdc66a3e + Model + Model + true + 0 + true + 420b8f1c-7df1-405b-a1f3-387f3716017a + 1 + 35915213-5534-4277-81b8-1bdc9e7383d2 + + + + + + 2391 + 1021 + 38 + 20 + + + 2411.5 + 1031 + + + + + + + + true + Script input Path. + 9ec97830-a244-4a9a-9eaa-7025e1ca2aad + Path + Path + true + 0 + true + 6b5f5a99-98ff-4322-b2f6-76ed37c15310 + 1 + 35915213-5534-4277-81b8-1bdc9e7383d2 + + + + + + 2391 + 1041 + 38 + 20 + + + 2411.5 + 1051 + + + + + + + + true + Script input Write. + 15ed91b8-1bee-4f81-b07a-68f57f0c7c24 + Write + Write + true + 0 + true + fe63683a-84ba-462b-b688-9e3f081f52fb + 1 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 2391 + 1061 + 38 + 20 + + + 2411.5 + 1071 + + + + + + + + Script output BTLx. + ec68082b-6816-42e0-b242-ac0746b13092 + BTLx + BTLx + false + 0 + + + + + + 2459 + 1021 + 32 + 60 + + + 2475 + 1051 + + + + + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + 6b5f5a99-98ff-4322-b2f6-76ed37c15310 + Panel + + false + 0 + 0 + D:\Papachap\Desktop\BTLx\TDovetailJoint.btlx + + + + + + 2130 + 1061 + 147 + 100 + + 0 + 0 + 0 + + 2130.444 + 1061.198 + + + + + + + 255;255;250;90 + + true + true + true + false + false + true + + + + + + + + + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle + + + + + Boolean (true/false) toggle + fe63683a-84ba-462b-b688-9e3f081f52fb + Boolean Toggle + Toggle + false + 0 + false + + + + + + 2174 + 1170 + 104 + 22 + + + + + + + + + + 22990b1f-9be6-477c-ad89-f775cd347105 + Flip Curve + + + + + Flip a curve using an optional guide curve. + true + 906af723-08ba-430d-ad6e-ce07b5200482 + Flip Curve + Flip + + + + + + 306 + 247 + 66 + 44 + + + 338 + 269 + + + + + + Curve to flip + bd1ba6e6-2103-43e7-879b-abc57ddb7e9b + Curve + C + false + e2fec716-2636-48c7-b126-85ba3955f210 + 1 + + + + + + 308 + 249 + 15 + 20 + + + 317 + 259 + + + + + + + + Optional guide curve + 5008ee96-d5d7-4eb5-9a37-ea1e8e51e171 + Guide + G + true + 0 + + + + + + 308 + 269 + 15 + 20 + + + 317 + 279 + + + + + + + + Flipped curve + acefae73-90c1-40be-b9e0-9dacb241a229 + Curve + C + false + 0 + + + + + + 353 + 249 + 17 + 20 + + + 361.5 + 259 + + + + + + + + Flip action + cf03ee7a-3fab-46f1-ad0d-ca67432e84fe + Flag + F + false + 0 + + + + + + 353 + 269 + 17 + 20 + + + 361.5 + 279 + + + + + + + + + + + + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle + + + + + Boolean (true/false) toggle + f0df0e81-ffad-41f2-a721-b13a2d9713ac + Boolean Toggle + FlipCurve + false + 0 + false + + + + + + 173 + 201 + 115 + 22 + + + + + + + + + + eeafc956-268e-461d-8e73-ee05c6f72c01 + Stream Filter + + + + + Filters a collection of input streams + true + c8935f57-0127-4738-af16-55bef27daede + Stream Filter + Filter + + + + + + 384 + 207 + 77 + 64 + + + 416 + 239 + + + + + + 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 + 2150f2e4-0536-4061-bcc7-82a78f2ce165 + Gate + G + false + f0df0e81-ffad-41f2-a721-b13a2d9713ac + 1 + + + + + + 386 + 209 + 15 + 20 + + + 395 + 219 + + + + + + 1 + + + + + 1 + {0} + + + + + 0 + + + + + + + + + + + 2 + Input stream at index 0 + 52165d88-897d-4411-b229-40c33d6dcacf + false + Stream 0 + 0 + true + e2fec716-2636-48c7-b126-85ba3955f210 + 1 + + + + + + 386 + 229 + 15 + 20 + + + 395 + 239 + + + + + + + + 2 + Input stream at index 1 + ef6ce42a-3047-4a1a-9ecd-2c6bcc799ad5 + false + Stream 1 + 1 + true + acefae73-90c1-40be-b9e0-9dacb241a229 + 1 + + + + + + 386 + 249 + 15 + 20 + + + 395 + 259 + + + + + + + + 2 + Filtered stream + 36c4deda-ceed-4920-a3f3-2d18ca613b35 + false + Stream + S(0) + false + 0 + + + + + + 431 + 209 + 28 + 60 + + + 445 + 239 + + + + + + + + + + + + + + d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 + Curve + + + + + Contains a collection of generic curves + true + e2fec716-2636-48c7-b126-85ba3955f210 + Curve + Crv + false + 18d2fa4a-de1b-4cfd-bf80-4b8d5fa0182f + 1 + + + + + + 236 + 227 + 50 + 24 + + + 261.4741 + 239.9949 + + + + + + 1 + + + + + 1 + {0} + + + + + -1 + + Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyNy4bxpcrDPvOXz4/18+rHjlAagcQwpU3KHb70cS13q4OBMDAuxtjlpjZzvZAeSS6oIuv//1TA0wOW6GwQQA + + 00000000-0000-0000-0000-000000000000 + + + + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + e2fec716-2636-48c7-b126-85ba3955f210 + f0df0e81-ffad-41f2-a721-b13a2d9713ac + 2 + c4bae22a-eb6f-4c74-a53a-12421686e963 + Group + + + + + + + + + + + 919e146f-30ae-4aae-be34-4d72f555e7da + Brep + + + + + Contains a collection of Breps (Boundary REPresentations) + 8bd29712-ff83-438b-b8f1-1d5f93dba350 + Brep + Brep + false + 389410e6-fbd0-4b13-ad00-528c4c2075fd + 1 + + + + + + 1942 + 363 + 50 + 24 + + + 1967.152 + 375.9135 + + + + + + + + + + 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe + Scribble + + + + + true + + 1696.031 + 783.7492 + + + 2171.469 + 783.7492 + + + 2171.469 + 836.0783 + + + 1696.031 + 836.0783 + + A quick note + Microsoft Sans Serif + f6a0d135-56d7-4997-a402-533d18b0461f + false + Scribble + Scribble + 70 + TDovetailJoint + + + + + + 1691.031 + 778.7492 + 485.4388 + 62.3291 + + + 1696.031 + 783.7492 + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + f6a0d135-56d7-4997-a402-533d18b0461f + 1 + c9c46265-63bf-4a08-a740-f490552e886d + Group + + + + + + + + + + + 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: + length = self._get_centerline_length(centerline) + width = [length / 20] + if not height: + length = self._get_centerline_length(centerline) + height = [length / 10] + + # 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 + + def _get_centerline_length(self, centerline): + centerline_length = [] + for i in centerline: + centerline_length.append(rs.CurveLength(i)) + if centerline_length: + length_average = sum(centerline_length) / len(centerline_length) + else: + length_average = 1 + return length_average + + Creates a Beam from a LineCurve. + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAGPSURBVEhLpZQxagJBGIX3BHoAiy0tBeuInaVWkkYQrGyEYGNhYZlLBDzCHsHcYC8QsEy5XZpAJn4Lk8z+89adkAef4j/7P/DN08w592/2+/3jcDj8yLLMhazXa73wFzabzUuv1/uy5ufz2V2vV72UwvF4zGez2Zs1zvPclWXpLpeL6/f7ermLtkim06mrqsqdTqffuTK4x2q1KkJTD6aYLxaL5pkyURDJZDJ5byzfIIaiKOpYiMeeSzMLkQwGg0+7PBqN6ovkQuu8zXmNMgxZLpevapEKEkldRXH+gzIFIhmPx5Va8hXkG6jzBsp8t9s9qW5HFTTnEmveFomsYAre+HA4PKhuQ2sFO+BXXptvt9tnFUlnBVugcTQP72w+n5fqoaQKCigGBfHJ8NKqzgoauL/b2k/sgKIHAam5gniJ2ZuGoGgBkJpbKAYF8YYWFC0BUvMQ/q7DvBUoWgSk5h4q6E3ugaJlQGoeVjAFFJkAsjNbwRRQZAQo/KwqmAJqGHkQ7/cqmAJqGHtQVwW7cdk3bAt2B1ocf6oAAAAASUVORK5CYII= + + false + b43641b3-59fc-4a04-8859-73f5db110ba0 + true + true + CT: Beam + Beam + + + + + + 1035 + 534 + 145 + 124 + + + 1126 + 596 + + + + + + 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. + 0c31c4f0-a254-4604-b376-642bd1af9371 + Centerline + Centerline + true + 1 + true + d2d51328-18f6-4ef3-8dd6-1df6b6af922e + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1037 + 536 + 74 + 20 + + + 1075.5 + 546 + + + + + + + + 1 + true + Vector defining the orientation of the cross-section (corresponds to the height dimension). If None, a default will be taken. + 23adc6a8-71cc-4920-9b6e-e30c6327093d + ZVector + ZVector + true + 1 + true + 4c90d06e-9810-41a6-baa8-91b753ccec55 + 1 + 15a50725-e3d3-4075-9f7c-142ba5f40747 + + + + + + 1037 + 556 + 74 + 20 + + + 1075.5 + 566 + + + + + + + + 1 + true + Width of the cross-section (usually the smaller dimension). + 7c03fea9-8999-4500-9207-08a0b25bfa46 + Width + Width + true + 1 + true + 81d19eff-02b1-4406-a0c3-47dd897a152f + 1 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 1037 + 576 + 74 + 20 + + + 1075.5 + 586 + + + + + + + + 1 + true + Height of the cross-section (usually the larger dimension). + 09b1bb68-2931-46ec-a825-5a6be2013132 + Height + Height + true + 1 + true + 478fc3b1-c4f8-4087-8fe6-c2905e21be9a + 1 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 1037 + 596 + 74 + 20 + + + 1075.5 + 606 + + + + + + + + 1 + true + Category of a beam. + 88089a84-ec0c-4a12-a5bd-a824eb74ec5d + Category + Category + true + 1 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 1037 + 616 + 74 + 20 + + + 1075.5 + 626 + + + + + + + + true + (optional) If True, the attributes in the referenced object will be updated/overwritten with the new values given here. + 451f3bf0-167d-454b-a823-6c248e312cef + updateRefObj + updateRefObj + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1037 + 636 + 74 + 20 + + + 1075.5 + 646 + + + + + + + + Beam object(s). + 710e74b1-2ede-4081-931a-087d503d6a24 + Beam + Beam + false + 0 + + + + + + 1141 + 536 + 37 + 60 + + + 1159.5 + 566 + + + + + + + + Shape of the beam's blank. + 5f7af910-8712-4b6b-bbee-b94a8160189d + Blank + Blank + false + 0 + + + + + + 1141 + 596 + 37 + 60 + + + 1159.5 + 626 + + + + + + + + + + + + + + 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: + length = self._get_centerline_length(centerline) + width = [length / 20] + if not height: + length = self._get_centerline_length(centerline) + height = [length / 10] + + # 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 + + def _get_centerline_length(self, centerline): + centerline_length = [] + for i in centerline: + centerline_length.append(rs.CurveLength(i)) + if centerline_length: + length_average = sum(centerline_length) / len(centerline_length) + else: + length_average = 1 + return length_average + + Creates a Beam from a LineCurve. + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAGPSURBVEhLpZQxagJBGIX3BHoAiy0tBeuInaVWkkYQrGyEYGNhYZlLBDzCHsHcYC8QsEy5XZpAJn4Lk8z+89adkAef4j/7P/DN08w592/2+/3jcDj8yLLMhazXa73wFzabzUuv1/uy5ufz2V2vV72UwvF4zGez2Zs1zvPclWXpLpeL6/f7ermLtkim06mrqsqdTqffuTK4x2q1KkJTD6aYLxaL5pkyURDJZDJ5byzfIIaiKOpYiMeeSzMLkQwGg0+7PBqN6ovkQuu8zXmNMgxZLpevapEKEkldRXH+gzIFIhmPx5Va8hXkG6jzBsp8t9s9qW5HFTTnEmveFomsYAre+HA4PKhuQ2sFO+BXXptvt9tnFUlnBVugcTQP72w+n5fqoaQKCigGBfHJ8NKqzgoauL/b2k/sgKIHAam5gniJ2ZuGoGgBkJpbKAYF8YYWFC0BUvMQ/q7DvBUoWgSk5h4q6E3ugaJlQGoeVjAFFJkAsjNbwRRQZAQo/KwqmAJqGHkQ7/cqmAJqGHtQVwW7cdk3bAt2B1ocf6oAAAAASUVORK5CYII= + + false + 9145c582-3948-46d8-8753-5d7cc1f15158 + true + true + CT: Beam + Beam + + + + + + 1034 + 373 + 145 + 124 + + + 1125 + 435 + + + + + + 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. + 52b22954-cc28-42d2-bc18-cba3067d9f03 + Centerline + Centerline + true + 1 + true + 36c4deda-ceed-4920-a3f3-2d18ca613b35 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1036 + 375 + 74 + 20 + + + 1074.5 + 385 + + + + + + + + 1 + true + Vector defining the orientation of the cross-section (corresponds to the height dimension). If None, a default will be taken. + 5e466a25-a69c-46d7-84fd-08acfd12b82c + ZVector + ZVector + true + 1 + true + 0 + 15a50725-e3d3-4075-9f7c-142ba5f40747 + + + + + + 1036 + 395 + 74 + 20 + + + 1074.5 + 405 + + + + + + + + 1 + true + Width of the cross-section (usually the smaller dimension). + 9a5643fd-cf0c-4be8-a900-66c3c892e934 + Width + Width + true + 1 + true + b0579e2b-7024-4c03-8e13-7ddcca5e08a6 + 1 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 1036 + 415 + 74 + 20 + + + 1074.5 + 425 + + + + + + + + 1 + true + Height of the cross-section (usually the larger dimension). + a77d8232-534e-4b10-baf6-be9abb9fe65e + Height + Height + true + 1 + true + 13835904-23ad-43b2-a586-0ae141339040 + 1 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 1036 + 435 + 74 + 20 + + + 1074.5 + 445 + + + + + + + + 1 + true + Category of a beam. + aa19701d-fdf0-432e-bfd2-57c5046e5e8d + Category + Category + true + 1 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 1036 + 455 + 74 + 20 + + + 1074.5 + 465 + + + + + + + + true + (optional) If True, the attributes in the referenced object will be updated/overwritten with the new values given here. + 3353d407-b7cb-444d-90c6-c24e5679cd16 + updateRefObj + updateRefObj + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1036 + 475 + 74 + 20 + + + 1074.5 + 485 + + + + + + + + Beam object(s). + 421f6dc4-6e2e-4f36-9475-969e527e32cb + Beam + Beam + false + 0 + + + + + + 1140 + 375 + 37 + 60 + + + 1158.5 + 405 + + + + + + + + Shape of the beam's blank. + f3c71f66-299e-40db-ac17-8744d915dcf0 + Blank + Blank + false + 0 + + + + + + 1140 + 435 + 37 + 60 + + + 1158.5 + 465 + + + + + + + + + + + + + + 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe + Scribble + + + + + true + + 1416.977 + 68.75895 + + + 2160.452 + 68.75895 + + + 2160.452 + 121.0881 + + + 1416.977 + 121.0881 + + A quick note + Microsoft Sans Serif + fce549a7-0108-4a88-b977-d6d4b63e84a0 + false + Scribble + Scribble + 70 + DovetailTenon/Mortise + + + + + + 1411.977 + 63.75895 + 753.4749 + 62.32911 + + + 1416.977 + 68.75895 + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + fce549a7-0108-4a88-b977-d6d4b63e84a0 + 1 + 21efd848-0a03-4347-82a3-6a077b2c51d5 + Group + + + + + + + + + + + + + + + + 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 + + + + + \ No newline at end of file diff --git a/tests/compas_timber/gh/test_step_joint.ghx b/examples/Grasshopper/tests/test_step_joint.ghx similarity index 84% rename from tests/compas_timber/gh/test_step_joint.ghx rename to examples/Grasshopper/tests/test_step_joint.ghx index 2714dd7cb..f1ab951f9 100644 --- a/tests/compas_timber/gh/test_step_joint.ghx +++ b/examples/Grasshopper/tests/test_step_joint.ghx @@ -48,10 +48,10 @@ - 95 - 68 + -1889 + -641 - 0.151132211 + 0.921188235 @@ -95,9 +95,9 @@ - 81 + 74 - + c552a431-af5b-46a9-a8a4-0fcbc27ef596 @@ -343,7 +343,7 @@ rg_planes = (plane_to_rhino(plane) for plane in cutting_planes) true 0 true - 3984d0df-294e-462f-b103-b87bb94e3021 + d2365ef0-f85c-4709-9361-522790ff3ed5 1 87f87f55-5b71-41f4-8aea-21d494016f81 @@ -375,7 +375,7 @@ rg_planes = (plane_to_rhino(plane) for plane in cutting_planes) true 0 true - 90fae02f-7750-462d-828f-cf5f2a0d39ae + 287d3ad7-dfd0-4415-b5a0-ff41819a7aba 1 87f87f55-5b71-41f4-8aea-21d494016f81 @@ -1696,7 +1696,7 @@ rg_planes = (plane_to_rhino(plane) for plane in cutting_planes) true 0 true - 3984d0df-294e-462f-b103-b87bb94e3021 + d2365ef0-f85c-4709-9361-522790ff3ed5 1 87f87f55-5b71-41f4-8aea-21d494016f81 @@ -1728,7 +1728,7 @@ rg_planes = (plane_to_rhino(plane) for plane in cutting_planes) true 0 true - 90fae02f-7750-462d-828f-cf5f2a0d39ae + 287d3ad7-dfd0-4415-b5a0-ff41819a7aba 1 87f87f55-5b71-41f4-8aea-21d494016f81 @@ -3262,392 +3262,99 @@ rg_planes = (plane_to_rhino(plane) for plane in cutting_planes) - - 410755b1-224a-4c1e-a407-bf32fb45ea7e - 00000000-0000-0000-0000-000000000000 - CT: Beam + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider - - """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. + + Numeric slider for single values + d9d51b18-d5af-4f8f-822f-9fbd0f30d642 + Number Slider + + false + 0 + + + + + + 795 + 1340 + 166 + 20 + + + 795.5547 + 1340.486 + + + + + + 3 + 1 + 1 + 120 + 0 + 0 + 120 + + + + + + + + + d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 + Curve + + + + + Contains a collection of generic curves true - true - true - - iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDAAACwwBP0AiyAAAAhRJREFUSEulVLtKA0EUzSfkD3zlrUKMIcHGB6ghIj5QxEoDiiA2gtqGYBEfRRQiSRc7iXU6IWKZwh8Q/AI/wEcRr/cMmWUZ7ya7Whw2uXvvOTNnzqyPiP6Nob7+Q0bBQJ0xLQ64BRP4R6OxZ37Swf4+nRwdKyxmFyg4MEhcvxYH3YCH4+GhwHsqMd6+r9ep1WrRY7OpyGcmp2hvZxcCBXG4F3gQligykIIcIulkknJb26qGnXgW4AF/NBi6AzkIQAxcnl+AjAr5vFXzLMDN8ZFI9JXxfVMuW0RYMZ8D3dZqVs2zADeuRALBD3jbaDQUAZ74D2ib/iQwHI5UudHyFsNYLVaN5JjEGj0F+KUVQXisB+EzyO01CV0F+IUYwY21dZUUXXMCemGdKMBFMYIYgIDktx2wD0FAILBQO7FjBGGJveYE2Id5Jn8AH3g1uRhBHCLI7TUJ2BVCAHLuP9eLVgJc3GS/vyZSaboqldQWq5UKZeczyhYdSyfouCLGzLViJ9cCT1A2sbq03NNv7Ay7joXCLzzTb5JbAqa/mdm5XzfTRCeG1Dk35bcEUQAJchLArpAmkDMOJVI7PAkgrrgbuCM8F5cITbgWQFyHI9F2x29HS0y4EkBcuU/5LZF0Q1cB+I3fHMFP7stJBL3gKHBWLOoIvnGPK78lKAEQQkQjOZZQlnS+pq79lgABfNxw2UycSgPeQL4fsKzVEEQlKEcAAAAASUVORK5CYII= - - false - e28e26d5-b791-48bc-902c-a1929ace9685 - true - true - CT: Beam - Beam + 18d2fa4a-de1b-4cfd-bf80-4b8d5fa0182f + Curve + Crv + false + 0 - 1018 - 1273 - 145 - 124 + 437 + 1274 + 50 + 24 - 1109 - 1335 + 462.4865 + 1286.721 - - - 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 - - - - 1 - true - Referenced curve or line, Guid of curve or line in the active Rhino document. - 1bee6a78-7b3a-4d65-9fa6-ee03a6a467d7 - Centerline - Centerline - true - 1 - true - 18d2fa4a-de1b-4cfd-bf80-4b8d5fa0182f - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 1020 - 1275 - 74 - 20 - - - 1058.5 - 1285 - - - - - - - - 1 - true - Vector defining the orientation of the cross-section (corresponds to the height dimension). If None, a default will be taken. - 9cde7a1d-c80f-42e0-9a2a-232ea2038830 - ZVector - ZVector - true - 1 - true - 0 - 15a50725-e3d3-4075-9f7c-142ba5f40747 + + + + 1 + {0} - - - - 1020 - 1295 - 74 - 20 - - - 1058.5 - 1305 - - - - - - - - 1 - true - Width of the cross-section (usually the smaller dimension). - 640d61a5-30a2-4d6d-9d06-693c7998daa3 - Width - Width - true - 1 - true - c64fa590-0923-4f6c-bc02-60bf9bf5e33c - 1 - 39fbc626-7a01-46ab-a18e-ec1c0c41685b - - - - - - 1020 - 1315 - 74 - 20 - - - 1058.5 - 1325 - - - - - - - - 1 - true - Height of the cross-section (usually the larger dimension). - c55fd807-c67f-4bc9-8acb-00f1fb7639c8 - Height - Height - true - 1 - true - d9d51b18-d5af-4f8f-822f-9fbd0f30d642 - 1 - 39fbc626-7a01-46ab-a18e-ec1c0c41685b - - - - - - 1020 - 1335 - 74 - 20 - - - 1058.5 - 1345 - - - - - - - - 1 - true - Category of a beam. - 3cabcb03-288e-45d6-a8c0-e9ddc8b859ce - Category - Category - true - 1 - true - 0 - 37261734-eec7-4f50-b6a8-b8d1f3c4396b - - - - - - 1020 - 1355 - 74 - 20 - - - 1058.5 - 1365 - - - - - - - - true - (optional) If True, the attributes in the referenced object will be updated/overwritten with the new values given here. - bb55e50a-3bee-410d-8466-5dfca9d565d1 - updateRefObj - updateRefObj - true - 0 - true - 0 - d60527f5-b5af-4ef6-8970-5f96fe412559 - - - - - - 1020 - 1375 - 74 - 20 - - - 1058.5 - 1385 - - - - - - - - Beam object(s). - 3984d0df-294e-462f-b103-b87bb94e3021 - Beam - Beam - false - 0 - - - - - - 1124 - 1275 - 37 - 60 - - - 1142.5 - 1305 - - - - - - - - Shape of the beam's blank. - b0a6568e-06d8-4c68-b393-d8274f661640 - Blank - Blank - false - 0 - - - - - - 1124 - 1335 - 37 - 60 - - - 1142.5 - 1365 + + + -1 + + Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyFyF5Ln1s/nvOXz8/18+rHjlAYmi2O741CCHCRvP7T9b98DhM5o4EwMaKFjuAHKJ94LooP/1TA0wYW50dQMKAA== + 00000000-0000-0000-0000-000000000000 @@ -3658,7 +3365,7 @@ class Beam_fromCurve(component): - + 57da07bd-ecab-415d-9d86-af36d7073abc Number Slider @@ -3667,7 +3374,7 @@ class Beam_fromCurve(component): Numeric slider for single values - d9d51b18-d5af-4f8f-822f-9fbd0f30d642 + 478fc3b1-c4f8-4087-8fe6-c2905e21be9a Number Slider false @@ -3677,14 +3384,14 @@ class Beam_fromCurve(component): - 795 - 1340 + 824 + 1523 166 20 - 795.5547 - 1340.486 + 824.523 + 1523.767 @@ -3693,29 +3400,28 @@ class Beam_fromCurve(component): 3 1 1 - 120 + 100 0 0 - 120 + 60 - + - d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 - Curve + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider - - Contains a collection of generic curves - true - 18d2fa4a-de1b-4cfd-bf80-4b8d5fa0182f - Curve - Crv + + Numeric slider for single values + da50cc8d-94c7-4348-b6e9-2f46272647d3 + Number Slider + false 0 @@ -3723,536 +3429,36 @@ class Beam_fromCurve(component): - 350 - 1274 - 50 - 24 + 824 + 1548 + 166 + 20 - 375.6421 - 1286.721 + 824.3324 + 1548.025 - - - 1 + + + 3 + 1 + 1 + 100 + 0 + 0 + 80 - - - - 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/xhBQAAAAlwSFlzAAALDAAACwwBP0AiyAAAAhRJREFUSEulVLtKA0EUzSfkD3zlrUKMIcHGB6ghIj5QxEoDiiA2gtqGYBEfRRQiSRc7iXU6IWKZwh8Q/AI/wEcRr/cMmWUZ7ya7Whw2uXvvOTNnzqyPiP6Nob7+Q0bBQJ0xLQ64BRP4R6OxZ37Swf4+nRwdKyxmFyg4MEhcvxYH3YCH4+GhwHsqMd6+r9ep1WrRY7OpyGcmp2hvZxcCBXG4F3gQligykIIcIulkknJb26qGnXgW4AF/NBi6AzkIQAxcnl+AjAr5vFXzLMDN8ZFI9JXxfVMuW0RYMZ8D3dZqVs2zADeuRALBD3jbaDQUAZ74D2ib/iQwHI5UudHyFsNYLVaN5JjEGj0F+KUVQXisB+EzyO01CV0F+IUYwY21dZUUXXMCemGdKMBFMYIYgIDktx2wD0FAILBQO7FjBGGJveYE2Id5Jn8AH3g1uRhBHCLI7TUJ2BVCAHLuP9eLVgJc3GS/vyZSaboqldQWq5UKZeczyhYdSyfouCLGzLViJ9cCT1A2sbq03NNv7Ay7joXCLzzTb5JbAqa/mdm5XzfTRCeG1Dk35bcEUQAJchLArpAmkDMOJVI7PAkgrrgbuCM8F5cITbgWQFyHI9F2x29HS0y4EkBcuU/5LZF0Q1cB+I3fHMFP7stJBL3gKHBWLOoIvnGPK78lKAEQQkQjOZZQlnS+pq79lgABfNxw2UycSgPeQL4fsKzVEEQlKEcAAAAASUVORK5CYII= - - false - ea292354-f0cd-4b58-ba78-57c730de54ad - true - true - CT: Beam - Beam - - - - - - 1016 - 1481 - 145 - 124 - - - 1107 - 1543 - - - - - - 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. - 53757008-8b2d-49b8-ada7-e0c81d24586f - Centerline - Centerline - true - 1 - true - 1c09c813-ee95-4356-93ff-668de076cf9e - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 1018 - 1483 - 74 - 20 - - - 1056.5 - 1493 - - - - - - - - 1 - true - Vector defining the orientation of the cross-section (corresponds to the height dimension). If None, a default will be taken. - db7b0ca0-f838-405d-ae51-0e61596dd253 - ZVector - ZVector - true - 1 - true - 0 - 15a50725-e3d3-4075-9f7c-142ba5f40747 - - - - - - 1018 - 1503 - 74 - 20 - - - 1056.5 - 1513 - - - - - - - - 1 - true - Width of the cross-section (usually the smaller dimension). - 4b9bf139-421a-4a01-b027-ec23d68ace87 - Width - Width - true - 1 - true - 478fc3b1-c4f8-4087-8fe6-c2905e21be9a - 1 - 39fbc626-7a01-46ab-a18e-ec1c0c41685b - - - - - - 1018 - 1523 - 74 - 20 - - - 1056.5 - 1533 - - - - - - - - 1 - true - Height of the cross-section (usually the larger dimension). - 4ae02a01-6e0a-4998-bca5-654916c862fc - Height - Height - true - 1 - true - da50cc8d-94c7-4348-b6e9-2f46272647d3 - 1 - 39fbc626-7a01-46ab-a18e-ec1c0c41685b - - - - - - 1018 - 1543 - 74 - 20 - - - 1056.5 - 1553 - - - - - - - - 1 - true - Category of a beam. - 98e31428-399a-4dde-a0e3-585981226918 - Category - Category - true - 1 - true - 0 - 37261734-eec7-4f50-b6a8-b8d1f3c4396b - - - - - - 1018 - 1563 - 74 - 20 - - - 1056.5 - 1573 - - - - - - - - true - (optional) If True, the attributes in the referenced object will be updated/overwritten with the new values given here. - 32189ead-4252-4352-bf45-514c147d7b57 - updateRefObj - updateRefObj - true - 0 - true - 0 - d60527f5-b5af-4ef6-8970-5f96fe412559 - - - - - - 1018 - 1583 - 74 - 20 - - - 1056.5 - 1593 - - - - - - - - Beam object(s). - 90fae02f-7750-462d-828f-cf5f2a0d39ae - Beam - Beam - false - 0 - - - - - - 1122 - 1483 - 37 - 60 - - - 1140.5 - 1513 - - - - - - - - Shape of the beam's blank. - 55c66290-a177-4518-824a-6a531a1e8086 - Blank - Blank - false - 0 - - - - - - 1122 - 1543 - 37 - 60 - - - 1140.5 - 1573 - - - - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 478fc3b1-c4f8-4087-8fe6-c2905e21be9a - Number Slider - - false - 0 - - - - - - 824 - 1523 - 166 - 20 - - - 824.523 - 1523.767 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 60 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - da50cc8d-94c7-4348-b6e9-2f46272647d3 - Number Slider - - false - 0 - - - - - - 824 - 1548 - 166 - 20 - - - 824.3324 - 1548.025 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 80 - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group @@ -4278,7 +3484,7 @@ class Beam_fromCurve(component): - + 9c53bac0-ba66-40bd-8154-ce9829b9db1a Colour Swatch @@ -4316,7 +3522,7 @@ class Beam_fromCurve(component): - + 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe Scribble @@ -4357,7 +3563,7 @@ class Beam_fromCurve(component): 2400.003 213.149 367.5195 - 57.33887 + 57.33885 2405.003 @@ -4369,7 +3575,7 @@ class Beam_fromCurve(component): - + c552a431-af5b-46a9-a8a4-0fcbc27ef596 Group @@ -4394,7 +3600,7 @@ class Beam_fromCurve(component): - + 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe Scribble @@ -4413,11 +3619,11 @@ class Beam_fromCurve(component): 2691.895 - 1906.505 + 1906.506 2470.777 - 1906.505 + 1906.506 A quick note Microsoft Sans Serif @@ -4447,7 +3653,7 @@ class Beam_fromCurve(component): - + c552a431-af5b-46a9-a8a4-0fcbc27ef596 Group @@ -4472,7 +3678,7 @@ class Beam_fromCurve(component): - + c552a431-af5b-46a9-a8a4-0fcbc27ef596 Group @@ -4497,7 +3703,7 @@ class Beam_fromCurve(component): - + 919e146f-30ae-4aae-be34-4d72f555e7da Brep @@ -4534,7 +3740,7 @@ class Beam_fromCurve(component): - + 9c53bac0-ba66-40bd-8154-ce9829b9db1a Colour Swatch @@ -4572,7 +3778,7 @@ class Beam_fromCurve(component): - + 919e146f-30ae-4aae-be34-4d72f555e7da Brep @@ -4609,7 +3815,7 @@ class Beam_fromCurve(component): - + c552a431-af5b-46a9-a8a4-0fcbc27ef596 Group @@ -4638,7 +3844,7 @@ class Beam_fromCurve(component): - + c552a431-af5b-46a9-a8a4-0fcbc27ef596 Group @@ -4667,379 +3873,443 @@ class Beam_fromCurve(component): + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + a31a3c97-3e91-47a8-add8-793f530b94e1 + Panel + + false + 0 + 122c32e0-f3e7-4c87-98a7-196c6459af3c + 1 + G:\Shared drives\2024_MAS\T2\03_finalization\Fabrication - Joints\BTLx\step_joint_joint_test.btlx + + + + + + 3205 + 1303 + 446 + 420 + + 0 + 0 + 0 + + 3205.497 + 1303.073 + + + + + + + 255;255;250;90 + + true + true + true + false + true + D:\Papachap\Desktop\btlx\TStepJoint.btlx + true + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + + A group of Grasshopper objects + 20be8b4b-0eba-41a5-8f13-25defa3e633d + d0efa1ab-d893-4335-8af7-dd6d94484ea7 + 9f3e0877-7fa6-4696-83ae-f6281f1d75f8 + 3c27b464-0da3-49d8-922b-780384eb4127 + ba663821-ec0e-4ff9-9124-fe98533cab66 + 97e9efc3-9035-45ee-bac9-e1c0876defe3 + 47c9ac3d-5335-4e4b-8cf3-b22cd1284a8e + e9fbb74f-6b87-4a1e-a684-8202331f1480 + f11ad7e4-429f-4eac-92db-ff79b89a4fa3 + f02972d5-c58c-4216-b53b-7f078d1f7fdc + 5b8e4ee4-cb19-450a-ba61-866a3686f2b2 + c6f9d24c-2b1e-4276-8e76-0fd2049e3d3a + fc245c73-88f5-4db4-a914-d3a9d191bd54 + e4da7b43-f08d-4e84-a53a-6d4d965dca71 + 05345419-f1d5-4f4d-aea7-b888275c43f0 + 574904c9-0f6a-4dc7-9431-055e7aa620aa + 9dd669ed-8fea-466e-8b3f-c6555794d56a + da35a5d7-1b20-42d0-acad-65c4ca451910 + fb0906ff-54ac-46a1-bccb-48fc75b26004 + edac9d60-3f4b-4c1d-8f27-c9820e97a97a + 483b91a1-a27f-4416-b350-a0d9e0d1e613 + 21 + c6445b86-caf6-4180-b0be-5dcfc6eaea9a + Group + + + + + + + + - - 410755b1-224a-4c1e-a407-bf32fb45ea7e - 00000000-0000-0000-0000-000000000000 - GhPython Script + + 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe + Scribble - from compas_timber.connections import TStepJoint - -from compas_timber.model import TimberModel -from compas_timber.fabrication import BTLx - -from compas_rhino.conversions import brep_to_rhino - -from compas_rhino import unload_modules - -unload_modules("compas_timber") - -# Instantiate TimberModel & Add Beams -timber_model = TimberModel() -beams = [cross_beam, main_beam] -for beam in beams: - beam.remove_features() - timber_model.add_element(beam) - -# Create TStepJoint joint -step_joint_joint = TStepJoint.create( - timber_model, - main_beam, - cross_beam, - step_shape=step_shape, - step_depth=step_depth, - heel_depth=heel_depth, - tapered_heel=tapered_heel, - tenon_mortise_height=tenon_mortise_height - ) - -# Process Joinery -timber_model.process_joinery() - -# Generate Geometry -geometry = [brep_to_rhino(beam.compute_geometry()) for beam in timber_model.beams] - -# Write BTLx -btlx = BTLx(timber_model) -BTLx = btlx.btlx_string() - GhPython provides a Python script component - - 924 - 209 + true + + 2387.48 + 1271.054 - - 901 - 818 + + 2642.241 + 1271.054 + + + 2642.241 + 1318.393 + + + 2387.48 + 1318.393 + + A quick note + Microsoft Sans Serif + 9f3e0877-7fa6-4696-83ae-f6281f1d75f8 + false + Scribble + Scribble + 50 + TStepJoint + + + + + + 2382.48 + 1266.054 + 264.7607 + 57.33887 + + + 2387.48 + 1271.054 + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;255;255;255 + A group of Grasshopper objects + 9f3e0877-7fa6-4696-83ae-f6281f1d75f8 + 1 + 3c27b464-0da3-49d8-922b-780384eb4127 + Group + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + fc245c73-88f5-4db4-a914-d3a9d191bd54 + true + Number Slider + + false + 0 + + + + + + 2094 + 1456 + 187 + 20 + + + 2094.823 + 1456.34 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 10 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + e4da7b43-f08d-4e84-a53a-6d4d965dca71 + true + Number Slider + + false + 0 + + + + + + 2094 + 1506 + 238 + 20 + + + 2094.913 + 1506.836 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 20 + + + + + + + + + 59daf374-bc21-4a5e-8282-5504fb7ae9ae + List Item + + + + + 0 + Retrieve a specific item from a list. true - true - false - false - 20be8b4b-0eba-41a5-8f13-25defa3e633d - false - true - GhPython Script - Python + 645777e9-3e35-4980-b9de-1af150e02dd0 + List Item + Item - 2239 - 1399 - 203 - 144 + 604 + 1461 + 64 + 64 - 2368 - 1471 + 638 + 1493 - - 7 - 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 - 3 - 3ede854e-c753-40eb-84cb-b48008f14fd4 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 + + 3 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 2e3ab970-8545-46bb-836c-1c11e5610bce + cb95db89-6165-43b6-9c41-5702bc5bf137 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 - + - - true - Script input cross_beam. - 36ebe6e6-4cdb-4b9d-8c4a-65feaf8cee5a - cross_beam - cross_beam - true - 0 - true - 3984d0df-294e-462f-b103-b87bb94e3021 + + 1 + Base list + 43423b3e-64ff-4e92-a077-9e59debece3d + List + L + false + c285f14a-7ead-4d46-9545-12950096c0b4 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - 2241 - 1401 - 112 + 606 + 1463 + 17 20 - 2298.5 - 1411 + 616 + 1473 - - true - Script input main_beam. - 407e65c9-4ebe-4581-9401-a364b25f96c2 - main_beam - main_beam - true - 0 - true - 90fae02f-7750-462d-828f-cf5f2a0d39ae - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 2241 - 1421 - 112 - 20 - - - 2298.5 - 1431 - - - - - - - - true - Script input step_shape. - 58ad3fdc-3692-40b4-bbbc-8848ec077c68 - step_shape - step_shape - true - 0 - true - da35a5d7-1b20-42d0-acad-65c4ca451910 - 1 - 48d01794-d3d8-4aef-990e-127168822244 - - - - - - 2241 - 1441 - 112 - 20 - - - 2298.5 - 1451 - - - - - - - - true - Script input step_depth. - fbd107db-8f8a-4baa-876f-623012dd3bb0 - step_depth - step_depth - true - 0 - true - 574904c9-0f6a-4dc7-9431-055e7aa620aa - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 2241 - 1461 - 112 - 20 - - - 2298.5 - 1471 - - - - - - - - true - Script input heel_depth. - dab8fd89-b668-48ad-91eb-c695241b0e94 - heel_depth - heel_depth - true - 0 - true - fc245c73-88f5-4db4-a914-d3a9d191bd54 - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 2241 - 1481 - 112 - 20 - - - 2298.5 - 1491 - - - - - - - - true - Script input tapered_heel. - f4ca3577-e0dc-42fa-8923-d574fb19c330 - tapered_heel - tapered_heel - true - 0 - true - 05345419-f1d5-4f4d-aea7-b888275c43f0 - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 2241 - 1501 - 112 - 20 - - - 2298.5 - 1511 - - - - - - - - true - Script input tenon_mortise_height. - e6b1d326-8808-4533-930e-154d3cd939d3 - tenon_mortise_height - tenon_mortise_height - true - 0 - true - e4da7b43-f08d-4e84-a53a-6d4d965dca71 + + Item index + 1f84b569-7192-4e9c-9c72-eac0579e6fb5 + Index + i + false + 0427415b-7064-4ecf-875e-ad8efb142eee 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - + - 2241 - 1521 - 112 + 606 + 1483 + 17 20 - 2298.5 - 1531 + 616 + 1493 - - - - - The execution information, as output and error streams - fb496e59-6b43-4266-9c61-c466f3a89f8e - out - out - false - 0 - - - - - - 2383 - 1401 - 57 - 46 - - - 2411.5 - 1424.333 - + + + 1 + + + + 1 + {0} + + + + + 0 + + + + + - + - Script output geometry. - 188326e4-b130-4230-9b7f-f89e9a5dca84 - geometry - geometry + Wrap index to list bounds + 8659d981-c16a-4820-bae2-1011ae70ffb5 + Wrap + W false 0 - + - 2383 - 1447 - 57 - 47 + 606 + 1503 + 17 + 20 - 2411.5 - 1471 + 616 + 1513 + + + 1 + + + + + 1 + {0} + + + + + true + + + + + + - - - Script output BTLx. - 8674ed0a-6d18-41d1-9209-ae7aed0e558d - BTLx - BTLx + + + Item at {i'} + 1c09c813-ee95-4356-93ff-668de076cf9e + false + Item + i false 0 @@ -5047,14 +4317,14 @@ BTLx = btlx.btlx_string() - 2383 - 1494 - 57 - 47 + 653 + 1463 + 13 + 60 - 2411.5 - 1517.667 + 659.5 + 1493 @@ -5066,140 +4336,273 @@ BTLx = btlx.btlx_string() - + - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider - - A panel for custom notes and text values - a31a3c97-3e91-47a8-add8-793f530b94e1 - Panel + + Numeric slider for single values + 0427415b-7064-4ecf-875e-ad8efb142eee + Number Slider false - 0 - 8674ed0a-6d18-41d1-9209-ae7aed0e558d - 1 - G:\Shared drives\2024_MAS\T2\03_finalization\Fabrication - Joints\BTLx\step_joint_joint_test.btlx + 0 - + - 2885 - 1294 - 446 - 420 + 426 + 1485 + 160 + 20 - 0 - 0 - 0 - 2885.897 - 1294.745 + 426.4622 + 1485.098 - - - - 255;255;250;90 + + + 3 + 1 + 1 + 2 + 0 + 0 + 0 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + c64fa590-0923-4f6c-bc02-60bf9bf5e33c + Number Slider + + false + 0 + + + + + + 796 + 1305 + 166 + 20 + + + 796.2646 + 1305.699 - true - true - true - false - true - D:\Papachap\Desktop\btlx\TStepJoint.btlx - true + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 80 - + - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle - - A panel for custom notes and text values - d0efa1ab-d893-4335-8af7-dd6d94484ea7 - Panel + + Boolean (true/false) toggle + 05345419-f1d5-4f4d-aea7-b888275c43f0 + true + Boolean Toggle + Toggle + false + 0 + false + + + + + + 2094 + 1480 + 104 + 22 + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 574904c9-0f6a-4dc7-9431-055e7aa620aa + true + Number Slider false - 1 - fb496e59-6b43-4266-9c61-c466f3a89f8e - 1 - Double click to edit panel content… + 0 - + - 2238 - 1357 - 204 - 41 + 2095 + 1432 + 187 + 20 - 0 - 0 - 0 - 2238.467 - 1357.654 + 2095.225 + 1432.386 - + - - 255;255;250;90 + 3 + 1 + 1 + 100 + 0 + 0 + 20 + + + + + + + + + d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 + Curve + + + + + Contains a collection of generic curves + true + c285f14a-7ead-4d46-9545-12950096c0b4 + Curve + Crv + false + 0 + + + + + + 440 + 1454 + 50 + 24 - true - true - true - false - false - true + + 465.2531 + 1466.838 + + + + + + 1 + + + + 3 + {0;0} + + + + + -1 + + Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyNzYbxpcrDPvOXz8/18+rHjlAYmi2O741CCH48eNlj7zvu9wBCoe0mqltvDcBAcmBgTY2xy1xs52sgPIJY3vmdz+1zM1wOS4GQYTAAA= + + 00000000-0000-0000-0000-000000000000 + + + + + -1 + + Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyNwtT5J42GPuO3z6/18+rHjlAYmi2O741CCH8Hxuq3ly9x0+OEg8DTDeABdnYkCAe5WXLGqv9ziAXPIxM3nP/3qmBpgcN8NgAgA= + + 00000000-0000-0000-0000-000000000000 + + + + + -1 + + Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyFzH6U87Q4MfOAQe/SM0wXLRAYmi2O741CCH+Q80Tt0XfODw6f9/+bDilXBxkJ6WVzwmEs97DkDNaQC5hEeQUfN/PVMDVIyBm2EwAQA= + + 00000000-0000-0000-0000-000000000000 + + + + + - + c552a431-af5b-46a9-a8a4-0fcbc27ef596 Group - + 1 150;255;255;255 A group of Grasshopper objects - 20be8b4b-0eba-41a5-8f13-25defa3e633d - d0efa1ab-d893-4335-8af7-dd6d94484ea7 - 9f3e0877-7fa6-4696-83ae-f6281f1d75f8 - 3c27b464-0da3-49d8-922b-780384eb4127 - ba663821-ec0e-4ff9-9124-fe98533cab66 - 97e9efc3-9035-45ee-bac9-e1c0876defe3 - 47c9ac3d-5335-4e4b-8cf3-b22cd1284a8e - e9fbb74f-6b87-4a1e-a684-8202331f1480 - f11ad7e4-429f-4eac-92db-ff79b89a4fa3 - f02972d5-c58c-4216-b53b-7f078d1f7fdc - 5b8e4ee4-cb19-450a-ba61-866a3686f2b2 - c6f9d24c-2b1e-4276-8e76-0fd2049e3d3a - 12 - c6445b86-caf6-4180-b0be-5dcfc6eaea9a + 539aeba5-2090-4272-bf3d-8d4bacf470d5 + fc245c73-88f5-4db4-a914-d3a9d191bd54 + e4da7b43-f08d-4e84-a53a-6d4d965dca71 + 05345419-f1d5-4f4d-aea7-b888275c43f0 + 574904c9-0f6a-4dc7-9431-055e7aa620aa + 86a2746f-76cf-4e10-a542-88ffc1de0b83 + da35a5d7-1b20-42d0-acad-65c4ca451910 + 7 + 9dd669ed-8fea-466e-8b3f-c6555794d56a Group @@ -5209,52 +4612,53 @@ BTLx = btlx.btlx_string() - + - 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe - Scribble + 00027467-0d24-4fa7-b178-8dc0ac5f42ec + Value List - - true - - 2387.48 - 1271.054 - - - 2642.241 - 1271.054 - - - 2642.241 - 1318.393 - - - 2387.48 - 1318.393 - - A quick note - Microsoft Sans Serif - 9f3e0877-7fa6-4696-83ae-f6281f1d75f8 - false - Scribble - Scribble - 50 - TStepJoint + + Provides a list of preset values to choose from + da35a5d7-1b20-42d0-acad-65c4ca451910 + 3 + 1 + true + Value List + List + false + 0 - + + + + 0 + step + true + + + + + 1 + heel + false + + + + + 2 + double + false + + - + - 2382.48 - 1266.054 - 264.7607 - 57.33875 - - - 2387.48 - 1271.054 + 2094 + 1404 + 89 + 22 @@ -5262,285 +4666,408 @@ BTLx = btlx.btlx_string() - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - 9f3e0877-7fa6-4696-83ae-f6281f1d75f8 - 1 - 3c27b464-0da3-49d8-922b-780384eb4127 - Group - - - - - - - - - - - 537b0419-bbc2-4ff4-bf08-afe526367b2c - Custom Preview + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + CT: Beam - - Allows for customized geometry previews - false - ba663821-ec0e-4ff9-9124-fe98533cab66 - Custom Preview - Preview - + + """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: + length = self._get_centerline_length(centerline) + width = [length / 20] + if not height: + length = self._get_centerline_length(centerline) + height = [length / 10] + + # 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 + + def _get_centerline_length(self, centerline): + centerline_length = [] + for i in centerline: + centerline_length.append(rs.CurveLength(i)) + if centerline_length: + length_average = sum(centerline_length) / len(centerline_length) + else: + length_average = 1 + return length_average + + Creates a Beam from a LineCurve. + true + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAGPSURBVEhLpZQxagJBGIX3BHoAiy0tBeuInaVWkkYQrGyEYGNhYZlLBDzCHsHcYC8QsEy5XZpAJn4Lk8z+89adkAef4j/7P/DN08w592/2+/3jcDj8yLLMhazXa73wFzabzUuv1/uy5ufz2V2vV72UwvF4zGez2Zs1zvPclWXpLpeL6/f7ermLtkim06mrqsqdTqffuTK4x2q1KkJTD6aYLxaL5pkyURDJZDJ5byzfIIaiKOpYiMeeSzMLkQwGg0+7PBqN6ovkQuu8zXmNMgxZLpevapEKEkldRXH+gzIFIhmPx5Va8hXkG6jzBsp8t9s9qW5HFTTnEmveFomsYAre+HA4PKhuQ2sFO+BXXptvt9tnFUlnBVugcTQP72w+n5fqoaQKCigGBfHJ8NKqzgoauL/b2k/sgKIHAam5gniJ2ZuGoGgBkJpbKAYF8YYWFC0BUvMQ/q7DvBUoWgSk5h4q6E3ugaJlQGoeVjAFFJkAsjNbwRRQZAQo/KwqmAJqGHkQ7/cqmAJqGHtQVwW7cdk3bAt2B1ocf6oAAAAASUVORK5CYII= + + false + bf722eeb-fc58-4d41-9636-a4abe4ff1b05 + true + true + CT: Beam + Beam - + - 2731 - 1508 - 64 - 44 + 1008 + 1268 + 145 + 124 - 2781 - 1530 + 1099 + 1330 - - - Geometry to preview - true - c34e1843-bfd6-4a82-b983-7194c9f9c18c - Geometry - G - false - e9fbb74f-6b87-4a1e-a684-8202331f1480 - 1 + + + 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 - - - - - 2733 - 1510 - 33 - 20 - - - 2759 - 1520 - + + + + 1 + true + Referenced curve or line, Guid of curve or line in the active Rhino document. + a1e698be-e5cc-4007-ad45-7ad242daacb1 + Centerline + Centerline + true + 1 + true + 18d2fa4a-de1b-4cfd-bf80-4b8d5fa0182f + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + 1010 + 1270 + 74 + 20 + + + 1048.5 + 1280 + + + + - - - - - The material override - 710c97a8-7564-4390-af09-089f9958717d - 1 - Material - M - false - d5779e9d-d95c-4279-bd0c-9036111f46eb - 1 - - - - - - 2733 - 1530 - 33 - 20 - - - 2759 - 1540 - + + + 1 + true + Vector defining the orientation of the cross-section (corresponds to the height dimension). If None, a default will be taken. + ea847ed7-5489-459a-97d1-5c8d044128c3 + ZVector + ZVector + true + 1 + true + 0 + 15a50725-e3d3-4075-9f7c-142ba5f40747 + + + + + 1010 + 1290 + 74 + 20 + + + 1048.5 + 1300 + + + + - - - 1 + + + 1 + true + Width of the cross-section (usually the smaller dimension). + 019cea01-9ec7-4a75-b6f2-0c67c3be7aef + Width + Width + true + 1 + true + c64fa590-0923-4f6c-bc02-60bf9bf5e33c + 1 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b - + - 1 - {0} + + 1010 + 1310 + 74 + 20 + + + 1048.5 + 1320 + - - - - - 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 - 97e9efc3-9035-45ee-bac9-e1c0876defe3 - Brep Edges - Edges - - - - - - 2625 - 1438 - 72 - 64 - - - 2655 - 1470 - - - - - - Base Brep - d76deb57-3846-4215-a6d3-b4cc65f5f623 - Brep - B - false - e9fbb74f-6b87-4a1e-a684-8202331f1480 - 1 - - - - - - 2627 - 1440 - 13 - 60 - - - 2635 - 1470 - + + + 1 + true + Height of the cross-section (usually the larger dimension). + 24087a33-ea83-440f-83af-61b49d8d317c + Height + Height + true + 1 + true + d9d51b18-d5af-4f8f-822f-9fbd0f30d642 + 1 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + 1010 + 1330 + 74 + 20 + + + 1048.5 + 1340 + + + + + + + + 1 + true + Category of a beam. + 0c93adef-0bc0-421a-9c08-5af17ce6be3c + Category + Category + true + 1 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 1010 + 1350 + 74 + 20 + + + 1048.5 + 1360 + + + + - - - - - 1 - Naked edge curves - d6302059-08b9-4456-a7f4-fc4b73a03458 - Naked - En - false - 0 - - - - - - 2670 - 1440 - 25 - 20 - - - 2682.5 - 1450 - + + + true + (optional) If True, the attributes in the referenced object will be updated/overwritten with the new values given here. + 8203ee9f-c2d2-42b4-b17c-51f97c6eddd2 + updateRefObj + updateRefObj + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + 1010 + 1370 + 74 + 20 + + + 1048.5 + 1380 + + + + - - - - - 1 - Interior edge curves - 8db6122b-9378-4026-a86e-58c5dd430f2a - Interior - Ei - false - 0 - - - - - - 2670 - 1460 - 25 - 20 - - - 2682.5 - 1470 - + + + Beam object(s). + d2365ef0-f85c-4709-9361-522790ff3ed5 + Beam + Beam + false + 0 + + + + + 1114 + 1270 + 37 + 60 + + + 1132.5 + 1300 + + + + - - - - - 1 - Non-Manifold edge curves - 0c2574f5-76b7-475f-80aa-c87143496df3 - Non-Manifold - Em - false - 0 - - - - - - 2670 - 1480 - 25 - 20 - - - 2682.5 - 1490 - + + + Shape of the beam's blank. + b8e540ec-b143-467b-a0d4-9b8c96f0c6ee + Blank + Blank + false + 0 + + + + + 1114 + 1330 + 37 + 60 + + + 1132.5 + 1360 + + + + @@ -5548,189 +5075,406 @@ BTLx = btlx.btlx_string() - + - a77d0879-94c2-4101-be44-e4a616ffeb0c - 5f86fa9f-c62b-50e8-157b-b454ef3e00fa - Custom Preview Lineweights + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + CT: Beam - - Custom Preview with Lineweights - 47c9ac3d-5335-4e4b-8cf3-b22cd1284a8e - Custom Preview Lineweights - PreviewLW - + + """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: + length = self._get_centerline_length(centerline) + width = [length / 20] + if not height: + length = self._get_centerline_length(centerline) + height = [length / 10] + + # 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 + + def _get_centerline_length(self, centerline): + centerline_length = [] + for i in centerline: + centerline_length.append(rs.CurveLength(i)) + if centerline_length: + length_average = sum(centerline_length) / len(centerline_length) + else: + length_average = 1 + return length_average + + Creates a Beam from a LineCurve. + true + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAGPSURBVEhLpZQxagJBGIX3BHoAiy0tBeuInaVWkkYQrGyEYGNhYZlLBDzCHsHcYC8QsEy5XZpAJn4Lk8z+89adkAef4j/7P/DN08w592/2+/3jcDj8yLLMhazXa73wFzabzUuv1/uy5ufz2V2vV72UwvF4zGez2Zs1zvPclWXpLpeL6/f7ermLtkim06mrqsqdTqffuTK4x2q1KkJTD6aYLxaL5pkyURDJZDJ5byzfIIaiKOpYiMeeSzMLkQwGg0+7PBqN6ovkQuu8zXmNMgxZLpevapEKEkldRXH+gzIFIhmPx5Va8hXkG6jzBsp8t9s9qW5HFTTnEmveFomsYAre+HA4PKhuQ2sFO+BXXptvt9tnFUlnBVugcTQP72w+n5fqoaQKCigGBfHJ8NKqzgoauL/b2k/sgKIHAam5gniJ2ZuGoGgBkJpbKAYF8YYWFC0BUvMQ/q7DvBUoWgSk5h4q6E3ugaJlQGoeVjAFFJkAsjNbwRRQZAQo/KwqmAJqGHkQ7/cqmAJqGHtQVwW7cdk3bAt2B1ocf6oAAAAASUVORK5CYII= + + false + da647de1-dd10-4e78-b1d6-8bd3064b4856 + true + true + CT: Beam + Beam - + - 2731 - 1418 - 62 - 84 + 1008 + 1481 + 145 + 124 - 2779 - 1460 + 1099 + 1543 - - - Geometry to preview - true - b386acb8-8321-49bf-ac12-f062d85c969d - Geometry - G - false - 8db6122b-9378-4026-a86e-58c5dd430f2a - 1 + + + 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 - - - - - 2733 - 1420 - 31 - 20 - - - 2758 - 1430 - + + + + 1 + true + Referenced curve or line, Guid of curve or line in the active Rhino document. + 8fbbdfc0-ddf1-497d-bab5-127859a8497d + Centerline + Centerline + true + 1 + true + 1c09c813-ee95-4356-93ff-668de076cf9e + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + 1010 + 1483 + 74 + 20 + + + 1048.5 + 1493 + + + + - - - - - The preview shader override - 11af4056-9698-4b92-b067-fae857f62252 - 2 - Shader - S - false - d5779e9d-d95c-4279-bd0c-9036111f46eb - 1 - - - - - - 2733 - 1440 - 31 - 20 - - - 2758 - 1450 - + + + 1 + true + Vector defining the orientation of the cross-section (corresponds to the height dimension). If None, a default will be taken. + 30b9a2e1-c92a-4d4f-bfb7-b4e28b54225b + ZVector + ZVector + true + 1 + true + 0 + 15a50725-e3d3-4075-9f7c-142ba5f40747 + + + + + 1010 + 1503 + 74 + 20 + + + 1048.5 + 1513 + + + + - - - 1 + + + 1 + true + Width of the cross-section (usually the smaller dimension). + 99f9429c-66da-4746-9d35-3608cee70f2a + Width + Width + true + 1 + true + 478fc3b1-c4f8-4087-8fe6-c2905e21be9a + 1 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b - + - 1 - {0} + + 1010 + 1523 + 74 + 20 + + + 1048.5 + 1533 + - - - - - 255;255;105;180 - - - 255;76;32;54 - - 0.5 - - 255;255;255;255 - - 0 - - - - - - - - The thickness of the wire display - f4113c88-a8ac-49cd-a656-a1e84f635519 - Thickness - T - true - 0 - - - - - - 2733 - 1460 - 31 - 20 - - - 2758 - 1470 - + + + 1 + true + Height of the cross-section (usually the larger dimension). + c72cc71d-f13e-4d93-a0f9-0ae82b991a79 + Height + Height + true + 1 + true + da50cc8d-94c7-4348-b6e9-2f46272647d3 + 1 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + 1010 + 1543 + 74 + 20 + + + 1048.5 + 1553 + + + + - - - - - Set to true to try to render curves with an absolute dimension. - 56fb3908-c9cb-478b-be37-49785e21754d - Absolute - A - false - 0 - - - - - - 2733 - 1480 - 31 - 20 - - - 2758 - 1490 - + + + 1 + true + Category of a beam. + 87270c6b-2d61-415d-a9e6-2b8997847e24 + Category + Category + true + 1 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 1010 + 1563 + 74 + 20 + + + 1048.5 + 1573 + + + + + + + + true + (optional) If True, the attributes in the referenced object will be updated/overwritten with the new values given here. + 24a45657-2e86-4574-b96b-fdfc1e768096 + updateRefObj + updateRefObj + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1010 + 1583 + 74 + 20 + + + 1048.5 + 1593 + + + + + + + + Beam object(s). + 287d3ad7-dfd0-4415-b5a0-ff41819a7aba + Beam + Beam + false + 0 + + + + + 1114 + 1483 + 37 + 60 + + + 1132.5 + 1513 + + + + - - - 1 + + + Shape of the beam's blank. + 1c9b9019-ed24-499d-a988-36f7f95ea194 + Blank + Blank + false + 0 - + - 1 - {0} + + 1114 + 1543 + 37 + 60 + + + 1132.5 + 1573 + - - - - false - - - @@ -5740,239 +5484,245 @@ BTLx = btlx.btlx_string() - - - 919e146f-30ae-4aae-be34-4d72f555e7da - Brep - - - - - Contains a collection of Breps (Boundary REPresentations) - true - e9fbb74f-6b87-4a1e-a684-8202331f1480 - Brep - Brep - false - 188326e4-b130-4230-9b7f-f89e9a5dca84 - 1 - - - - - - 2538 - 1461 - 50 - 24 - - - 2563.602 - 1473.006 - - - - - - - - - - 9c53bac0-ba66-40bd-8154-ce9829b9db1a - Colour Swatch - - - - - Colour (palette) swatch - f11ad7e4-429f-4eac-92db-ff79b89a4fa3 - Colour Swatch - Swatch - false - 0 - - 29;0;102;255 - - - - - - - 2521 - 1509 - 88 - 20 - - - 2521.967 - 1509.452 - - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - ba663821-ec0e-4ff9-9124-fe98533cab66 - 97e9efc3-9035-45ee-bac9-e1c0876defe3 - 47c9ac3d-5335-4e4b-8cf3-b22cd1284a8e - e9fbb74f-6b87-4a1e-a684-8202331f1480 - f11ad7e4-429f-4eac-92db-ff79b89a4fa3 - 5b8e4ee4-cb19-450a-ba61-866a3686f2b2 - c6f9d24c-2b1e-4276-8e76-0fd2049e3d3a - 7 - f02972d5-c58c-4216-b53b-7f078d1f7fdc - Group - GEOMETRY - - - - - - - - - - 9c53bac0-ba66-40bd-8154-ce9829b9db1a - Colour Swatch + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + CT: T Topological Joint Rules - - Colour (palette) swatch - 5b8e4ee4-cb19-450a-ba61-866a3686f2b2 - Colour Swatch - Swatch - false - 0 - - 34;240;180;137 + + import inspect + +from ghpythonlib.componentbase import executingcomponent as component +from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning + +from compas_timber.connections import Joint +from compas_timber.connections import JointTopology +from compas_timber.connections import TButtJoint +from compas_timber.design import TopologyRule +from compas_timber.ghpython.ghcomponent_helpers import get_leaf_subclasses +from compas_timber.ghpython.ghcomponent_helpers import manage_dynamic_params +from compas_timber.ghpython.ghcomponent_helpers import rename_gh_output + + +class T_TopologyJointRule(component): + def __init__(self): + super(T_TopologyJointRule, self).__init__() + self.classes = {} + for cls in get_leaf_subclasses(Joint): + if cls.SUPPORTED_TOPOLOGY == JointTopology.TOPO_T: + self.classes[cls.__name__] = cls + if ghenv.Component.Params.Output[0].NickName == "Rule": + self.joint_type = TButtJoint + self.clicked = False + else: + self.joint_type = self.classes.get(ghenv.Component.Params.Output[0].NickName, None) + self.clicked = True + + def RunScript(self, *args): + if not self.clicked: + ghenv.Component.Message = "Default: TButtJoint" + self.AddRuntimeMessage(Warning, "TButtJoint is default, change in context menu (right click)") + return TopologyRule(JointTopology.TOPO_T, TButtJoint) + else: + ghenv.Component.Message = self.joint_type.__name__ + kwargs = {} + for i, val in enumerate(args): + if val is not None: + kwargs[self.arg_names()[i]] = val + if self.joint_type.SUPPORTED_TOPOLOGY != JointTopology.TOPO_T: + self.AddRuntimeMessage(Warning, "Joint type does not match topology. Joint may not be generated.") + return TopologyRule(JointTopology.TOPO_T, self.joint_type, **kwargs) + + def arg_names(self): + names = inspect.getargspec(self.joint_type.__init__)[0][3:] + 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 + + def on_item_click(self, sender, event_info): + self.clicked = True + 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=0, permanent_param_count=0) + ghenv.Component.ExpireSolution(True) + + GhPython provides a Python script component + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxEAAAsRAX9kX5EAAADeSURBVEhL7ZOxDcJADEUzQuiRiMQCGYURGIGOlgkQI6SmyggpKCkYgRHYwHyf7iJjzF0uhAIpxbMuPvt/yb4URPRTzOR6VXWAPCerZij9AUIVKMHBC0t2sikHFyCwUYKfuINai8RwwTdaghatFonhAprkzJkG8Lh4bDefC3RaJIYLaGqVSBkKcK7V3SgDvdjJDXgkUoS/eTyTjUjvIMaoJQ99pg+Q/0wZbgTWSJhtqFseLwtACc6hvjeQQFDu5OUvRvP3BjlA7OpF99b9WyKX2SDJbJDk/w1SmMnpoOIJX/DFrYWt/CUAAAAASUVORK5CYII= - - - - - - 2521 - 1533 - 88 - 20 - - - 2521.729 - 1533.101 - - - - - - - - - - c9785b8e-2f30-4f90-8ee3-cca710f82402 - Entwine - - - - - Flatten and combine a collection of data streams - true - true - c6f9d24c-2b1e-4276-8e76-0fd2049e3d3a - Entwine - Entwine + false + fb0906ff-54ac-46a1-bccb-48fc75b26004 + true + true + CT: T Topological Joint Rules + T_Topo_Joint - 2624 - 1505 - 79 - 44 + 2374 + 1413 + 207 + 104 - 2669 - 1527 + 2503 + 1465 - - 2 + + 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 8ec86459-bf01-4409-baee-174d0d2b13d0 - + - - 2 - Data to entwine - f1b60494-3bf8-4181-99bd-69acd3c3059a - false - Branch {0;0} - {0;0} + + step_shape + 90447357-41c5-4510-9403-87c7477a793b + step_shape + step_shape + true + da35a5d7-1b20-42d0-acad-65c4ca451910 + 1 + + + + + + 2376 + 1415 + 112 + 20 + + + 2433.5 + 1425 + + + + + + + + step_depth + 8416ec1a-d869-42b5-8910-8ab9f07a7376 + step_depth + step_depth + true + 574904c9-0f6a-4dc7-9431-055e7aa620aa + 1 + + + + + + 2376 + 1435 + 112 + 20 + + + 2433.5 + 1445 + + + + + + + + heel_depth + d2de0203-b4b1-4d15-b554-86c1671523b8 + heel_depth + heel_depth + true + fc245c73-88f5-4db4-a914-d3a9d191bd54 + 1 + + + + + + 2376 + 1455 + 112 + 20 + + + 2433.5 + 1465 + + + + + + + + tapered_heel + 0aabafa9-5d5b-4f5f-9021-06d2a4b460a6 + tapered_heel + tapered_heel true - f11ad7e4-429f-4eac-92db-ff79b89a4fa3 + 05345419-f1d5-4f4d-aea7-b888275c43f0 1 - 2626 - 1507 - 28 + 2376 + 1475 + 112 20 - 2641.5 - 1517 + 2433.5 + 1485 - - - 2 - Data to entwine - 56b1c6dd-1a2e-4764-8c90-316095f2007a - false - Branch {0;1} - {0;1} + + + tenon_mortise_height + f85fe123-b5c2-43fe-a5a0-9feb291030ba + tenon_mortise_height + tenon_mortise_height true - 5b8e4ee4-cb19-450a-ba61-866a3686f2b2 + e4da7b43-f08d-4e84-a53a-6d4d965dca71 1 - 2626 - 1527 - 28 + 2376 + 1495 + 112 20 - 2641.5 - 1537 + 2433.5 + 1505 @@ -5980,10 +5730,10 @@ BTLx = btlx.btlx_string() - Entwined result - d5779e9d-d95c-4279-bd0c-9036111f46eb - Result - R + TStepJoint + de845bcb-afd3-404f-8a02-5b3b2b21611c + TStepJoint + TStepJoint false 0 @@ -5991,14 +5741,14 @@ BTLx = btlx.btlx_string() - 2684 - 1507 - 17 - 40 + 2518 + 1415 + 61 + 100 - 2692.5 - 1527 + 2548.5 + 1465 @@ -6010,527 +5760,483 @@ BTLx = btlx.btlx_string() - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - fc245c73-88f5-4db4-a914-d3a9d191bd54 - true - Number Slider - - false - 0 - - - - - - 1961 - 1494 - 187 - 20 - - - 1961.03 - 1494.398 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 10 - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - e4da7b43-f08d-4e84-a53a-6d4d965dca71 - true - Number Slider - - false - 0 - - - - - - 1961 - 1544 - 238 - 20 - - - 1961.12 - 1544.358 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 0 - - - - - - - - - 59daf374-bc21-4a5e-8282-5504fb7ae9ae - List Item + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + CT: Model - - 0 - Retrieve a specific item from a list. - true - 645777e9-3e35-4980-b9de-1af150e02dd0 - List Item - Item + + from compas.scene import Scene +from compas.tolerance import TOL +from ghpythonlib.componentbase import executingcomponent as component +from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning + +from compas_timber.connections import BeamJoinningError +from compas_timber.connections import ConnectionSolver +from compas_timber.connections import JointTopology +from compas_timber.connections import LMiterJoint +from compas_timber.connections import TButtJoint +from compas_timber.connections import XHalfLapJoint +from compas_timber.design import CategoryRule +from compas_timber.design import DebugInfomation +from compas_timber.design import DirectRule +from compas_timber.design import JointDefinition +from compas_timber.design import TopologyRule +from compas_timber.model import TimberModel + +JOINT_DEFAULTS = { + JointTopology.TOPO_X: XHalfLapJoint, + JointTopology.TOPO_T: TButtJoint, + JointTopology.TOPO_L: LMiterJoint, +} + + +# workaround for https://github.com/gramaziokohler/compas_timber/issues/280 +TOL.absolute = 1e-6 + + +class ModelComponent(component): + def get_joints_from_rules(self, beams, rules, topologies): + if not isinstance(rules, list): + rules = [rules] + rules = [r for r in rules if r is not None] + + joints = [] + # rules have to be resolved into joint definitions + topo_rules = {} + cat_rules = [] + direct_rules = [] + + # TODO: refactor this into some kind of a rule reloving class/function + for r in rules: # separate category and topo and direct joint rules + if isinstance(r, TopologyRule): + if topo_rules.get(r.topology_type, None): # if rule for this Topo exists + if (r.joint_type != JOINT_DEFAULTS[r.topology_type]) or ( + len(r.kwargs) != 0 + ): # if this rule is NOT default + topo_rules[r.topology_type] = r + else: + topo_rules[r.topology_type] = r + elif isinstance(r, CategoryRule): + cat_rules.append(r) + if isinstance(r, DirectRule): + direct_rules.append(r) + + for topo in topologies: + beam_a = topo["beam_a"] + beam_b = topo["beam_b"] + detected_topo = topo["detected_topo"] + pair = beam_a, beam_b + pair_joined = False + + if detected_topo == JointTopology.TOPO_UNKNOWN: + continue + + for rule in direct_rules: # apply direct rules first + if rule.comply(pair): + joints.append(JointDefinition(rule.joint_type, rule.beams, **rule.kwargs)) + pair_joined = True + break + + if not pair_joined: # if no direct rule applies, apply category rules next + for rule in cat_rules: + if not rule.comply(pair): + continue + if rule.joint_type.SUPPORTED_TOPOLOGY != detected_topo: + msg = "Conflict detected! Beams: {}, {} meet with topology: {} but rule assigns: {}" + self.AddRuntimeMessage( + Warning, + msg.format( + beam_a.guid, + beam_b.guid, + JointTopology.get_name(detected_topo), + rule.joint_type.__name__, + ), + ) + 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.guid, + beam_b.guid, + 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)) + break # first matching rule + + else: # no category rule applies, apply topology rules + if detected_topo not in topo_rules: + continue + else: + joints.append( + JointDefinition( + topo_rules[detected_topo].joint_type, + [beam_a, beam_b], + **topo_rules[detected_topo].kwargs + ) + ) + return joints + + def RunScript(self, Elements, JointRules, Features, MaxDistance, CreateGeometry): + if not Elements: + self.AddRuntimeMessage(Warning, "Input parameter Beams failed to collect data") + if not JointRules: + self.AddRuntimeMessage(Warning, "Input parameter JointRules failed to collect data") + if not (Elements): # shows beams even if no joints are found + return + if MaxDistance is None: + MaxDistance = TOL.ABSOLUTE # compared to calculted distance, so shouldn't be just 0.0 + + Model = TimberModel() + debug_info = DebugInfomation() + for element in Elements: + # prepare elements for downstream processing + if element is None: + continue + element.remove_features() + if hasattr(element, "remove_blank_extension"): + element.remove_blank_extension() + element.debug_info = [] + Model.add_element(element) + + topologies = [] + solver = ConnectionSolver() + found_pairs = solver.find_intersecting_pairs(list(Model.beams), rtree=True, max_distance=MaxDistance) + for pair in found_pairs: + beam_a, beam_b = pair + detected_topo, beam_a, beam_b = solver.find_topology(beam_a, beam_b, max_distance=MaxDistance) + if not detected_topo == JointTopology.TOPO_UNKNOWN: + topologies.append({"detected_topo": detected_topo, "beam_a": beam_a, "beam_b": beam_b}) + Model.set_topologies(topologies) + + joints = self.get_joints_from_rules(Model.beams, JointRules, topologies) + + if joints: + handled_beams = [] + joints = [j for j in joints if j is not None] + # apply reversed. later joints in orginal list override ealier ones + for joint in joints[::-1]: + beams_to_pair = joint.beams + beam_pair_ids = set([id(beam) for beam in beams_to_pair]) + if beam_pair_ids in handled_beams: + continue + try: + joint.joint_type.create(Model, *beams_to_pair, **joint.kwargs) + except BeamJoinningError as bje: + debug_info.add_joint_error(bje) + else: + handled_beams.append(beam_pair_ids) + + # applies extensions and features resulting from joints + Model.process_joinery() + + if Features: + features = [f for f in Features if f is not None] + for f_def in features: + for element in f_def.elements: + element.add_features(f_def.feature) + + Geometry = None + scene = Scene() + for element in Model.elements(): + if CreateGeometry: + scene.add(element.geometry) + if element.debug_info: + debug_info.add_feature_error(element.debug_info) + else: + scene.add(element.blank) + + if debug_info.has_errors: + self.AddRuntimeMessage(Warning, "Error found during joint creation. See DebugInfo output for details.") + + Geometry = scene.draw() + return Model, Geometry, debug_info + + GhPython provides a Python script component + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAGtSURBVEhLtZXNTQNBDEanhJSQElJCSuDIMSWkhJRACSkhR44pIQcOHBEVIHFDSOF7E3vk3fEuGyQsPTHjzz+7nsxSrtfrYmQPkGlTpM4M2UGwgEMWk5E6I7KVOFnhV4M1vlWWE0mdjmwtLoINbxDBh7bOcp3UCbKt+DDq3GW1uK05D9e3MTeSO0vZCRZvYhP8rYHtN4IYNjv3R3pHKUdLOIvBjGWDBubjjIhlc4xa1dviFujz7gItpmsQNH8warQHc/HXVwXZZAMgV7Boo8XiYbV5Z8hmGwA1hNejdpvff0Dt8iS+BTPkpxnBx0x9/2j4Hm0qj5rUrq/NzHilwaUx7Rx9ETRiRj4uJ7WoSf6tiDlOo+C/NOATQq2q4fAGvBoR7VbK7mogazXEsEFIuISEextwJrFW14D5sdjbfnED2V6wqOco6xuYwJ5D4mYvaiCIJSe+zWQDD+YntrQBsfWhEq0vIvMr/2x/5/CYwSdGNt0gBLyLeNHGoBEzlT/bgAIsXsaag2Yx3T8c2aAB88Mx5lN8jXwRNGIyrR66qE/KIoNvCjcz0wCNmEwTZfsDzr7SPDQx4p0AAAAASUVORK5CYII= + + false + edac9d60-3f4b-4c1d-8f27-c9820e97a97a + true + true + CT: Model + Model - 518 - 1461 - 64 - 64 + 2657 + 1473 + 198 + 104 - 552 - 1493 + 2776 + 1525 - - 3 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 2e3ab970-8545-46bb-836c-1c11e5610bce - cb95db89-6165-43b6-9c41-5702bc5bf137 - 1 + + 5 + 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 + 3 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 - + - + 1 - Base list - 43423b3e-64ff-4e92-a077-9e59debece3d - List - L - false - c285f14a-7ead-4d46-9545-12950096c0b4 - 1 + true + Collection of Beams + 52ba0d86-c970-4006-bcf5-cc815097d784 + 1 + Elements + Elements + true + 1 + true + d2365ef0-f85c-4709-9361-522790ff3ed5 + 287d3ad7-dfd0-4415-b5a0-ff41819a7aba + 2 + 35915213-5534-4277-81b8-1bdc9e7383d2 - 520 - 1463 - 17 + 2659 + 1475 + 102 20 - 530 - 1473 + 2719.5 + 1485 - - Item index - 1f84b569-7192-4e9c-9c72-eac0579e6fb5 - Index - i - false - 0427415b-7064-4ecf-875e-ad8efb142eee + + 1 + true + Script input JointRules. + 356db849-23a7-40e2-b5c2-a3a27bc348fd + 1 + JointRules + JointRules + true + 1 + true + de845bcb-afd3-404f-8a02-5b3b2b21611c 1 + 35915213-5534-4277-81b8-1bdc9e7383d2 - + - 520 - 1483 - 17 + 2659 + 1495 + 102 20 - 530 - 1493 + 2719.5 + 1505 - - - 1 + + + + + 1 + true + Script input Features. + 497f4ffb-547e-4cda-a694-9e983e95289b + Features + Features + true + 1 + true + 0 + 35915213-5534-4277-81b8-1bdc9e7383d2 + + + + + + 2659 + 1515 + 102 + 20 + + + 2719.5 + 1525 + - - - - 1 - {0} - - - - - 0 - - - - - - - - Wrap index to list bounds - 8659d981-c16a-4820-bae2-1011ae70ffb5 - Wrap - W - false + + + true + Script input MaxDistance. + d44b52e9-24ca-45ca-ab14-43319e3b018c + MaxDistance + MaxDistance + true + 0 + true 0 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b - + - 520 - 1503 - 17 + 2659 + 1535 + 102 20 - 530 - 1513 + 2719.5 + 1545 - - - 1 - - - - - 1 - {0} - - - - - true - - - - - - - - - Item at {i'} - 1c09c813-ee95-4356-93ff-668de076cf9e - false - Item - i - false - 0 + + + true + Script input CreateGeometry. + f745ec38-d707-4e5f-8326-2f067588fd31 + CreateGeometry + CreateGeometry + true + 0 + true + 483b91a1-a27f-4416-b350-a0d9e0d1e613 + 1 + d60527f5-b5af-4ef6-8970-5f96fe412559 - 567 - 1463 - 13 - 60 + 2659 + 1555 + 102 + 20 - 573.5 - 1493 + 2719.5 + 1565 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 0427415b-7064-4ecf-875e-ad8efb142eee - Number Slider - - false - 0 - - - - - - 339 - 1485 - 159 - 20 - - - 339.6179 - 1485.098 - - - - - - 3 - 1 - 1 - 2 - 0 - 0 - 0 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - c64fa590-0923-4f6c-bc02-60bf9bf5e33c - Number Slider - - false - 0 - - - - - - 796 - 1305 - 166 - 20 - - - 796.2646 - 1305.699 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 80 - - - - - - - - - 2e78987b-9dfb-42a2-8b76-3923ac8bd91a - Boolean Toggle - - - - - Boolean (true/false) toggle - 05345419-f1d5-4f4d-aea7-b888275c43f0 - true - Boolean Toggle - Toggle - false - 0 - false - - - - - - 1959 - 1515 - 104 - 22 - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 574904c9-0f6a-4dc7-9431-055e7aa620aa - true - Number Slider - - false - 0 - - - - - - 1960 - 1469 - 187 - 20 - - - 1960.432 - 1469.712 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 20 - - - - - - - - - d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 - Curve - - - - - Contains a collection of generic curves - true - c285f14a-7ead-4d46-9545-12950096c0b4 - Curve - Crv - false - 0 - - - - - - 446 - 1454 - 50 - 24 - - - 471.742 - 1466.838 - - - - - - 1 - - - - - 3 - {0;0} + + + Script output Model. + ef1e3166-9d32-4e5c-a29d-ce521ae68b72 + Model + Model + false + 0 - - - - -1 - - Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyNzYbxpcrDPvOXz8/18+rHjlAYmi2O741CCH48eNlj7zvu9wBCoe0mqltvDcBAcmBgTY2xy1xs52sgPIJY3vmdz+1zM1wOS4GQYTAAA= + + + + + 2791 + 1475 + 62 + 33 + + + 2822 + 1491.667 - 00000000-0000-0000-0000-000000000000 - - - -1 - - Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyNwtT5J42GPuO3z6/18+rHjlAYmi2O741CCH8Hxuq3ly9x0+OEg8DTDeABdnYkCAe5WXLGqv9ziAXPIxM3nP/3qmBpgcN8NgAgA= + + + + + Script output Geometry. + d0a19f59-f1dd-4a7b-b921-f13ebcc0535b + Geometry + Geometry + false + 0 + + + + + + 2791 + 1508 + 62 + 33 + + + 2822 + 1525 - 00000000-0000-0000-0000-000000000000 - - - -1 - - Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyFzH6U87Q4MfOAQe/SM0wXLRAYmi2O741CCH+Q80Tt0XfODw6f9/+bDilXBxkJ6WVzwmEs97DkDNaQC5hEeQUfN/PVMDVIyBm2EwAQA= + + + + + Script output DebugInfo. + 7a9f8ba2-a6bb-4d30-a84a-2c6206ba4b63 + DebugInfo + DebugInfo + false + 0 + + + + + + 2791 + 1541 + 62 + 34 + + + 2822 + 1558.333 - 00000000-0000-0000-0000-000000000000 @@ -6541,80 +6247,29 @@ BTLx = btlx.btlx_string() - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - 539aeba5-2090-4272-bf3d-8d4bacf470d5 - fc245c73-88f5-4db4-a914-d3a9d191bd54 - e4da7b43-f08d-4e84-a53a-6d4d965dca71 - 05345419-f1d5-4f4d-aea7-b888275c43f0 - 574904c9-0f6a-4dc7-9431-055e7aa620aa - 5 - 9dd669ed-8fea-466e-8b3f-c6555794d56a - Group - - - - - - - - - + - 00027467-0d24-4fa7-b178-8dc0ac5f42ec - Value List + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle - - Provides a list of preset values to choose from - da35a5d7-1b20-42d0-acad-65c4ca451910 - 3 - 1 - Value List - List + + Boolean (true/false) toggle + 483b91a1-a27f-4416-b350-a0d9e0d1e613 + Boolean Toggle + Toggle false 0 + true - - - - 0 - step - true - - - - - 1 - heel - false - - - - - 2 - double - false - - + - 1974 - 1400 - 79 + 2528 + 1554 + 104 22 @@ -6623,27 +6278,198 @@ BTLx = btlx.btlx_string() - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + CT: WriteBTLx - - 5 - - 150;255;255;255 + + import Rhino +from ghpythonlib.componentbase import executingcomponent as component +from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning + +from compas_timber.fabrication import BTLx + + +class WriteBTLx(component): + def RunScript(self, model, path, write): + if not model: + self.AddRuntimeMessage(Warning, "Input parameter Model failed to collect data") + return + + btlx = BTLx(model) + btlx.history["FileName"] = Rhino.RhinoDoc.ActiveDoc.Name + + if write: + if not path: + self.AddRuntimeMessage(Warning, "Input parameter Path failed to collect data") + return + if path[-5:] != ".btlx": + path += ".btlx" + with open(path, "w") as f: + f.write(btlx.btlx_string()) + return btlx.btlx_string() + + GhPython provides a Python script component + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAEoSURBVEhLtZRREcIwEEQrAQGIQEIlIAEJSEABgwQkIIEPBFQCEnAQdjMcswmb8EG4mQf0unfbJhemlNJfscmR2ORIbHIkNulAHAJ3v4VNOhD8yNT3ekzr4+0MVu6m8otBAss3k18NyB1snIjUBogZxL7sXjn+LnqoAXmAWQVv4acBm0XuWmkuIK9IbRDkJ1KkGJf5umdA8rS1DMiJgkCLX9duid4a8ACrnsESzetizSuInerAvmVwNsVa2BuGRXQHZ2BPKuKqhQ0Nly00WVcbfGxugOBkaDGf9ATyHoAtuAPVzGHA8Wy+Nsnisljh2+lUkUuuQ2Oe4m7zAMEn5XRoI1IbFOfg6/+QwkJAIzbkErE5v2Nsi4NaFP8DmxyJTY7EJkdik+NI0xMaL3RZDTDXNQAAAABJRU5ErkJggg== - A group of Grasshopper objects - da35a5d7-1b20-42d0-acad-65c4ca451910 - 1 - 86a2746f-76cf-4e10-a542-88ffc1de0b83 - Group - + false + 25a5d208-cdaf-45eb-a05d-78ab9fe9ce8c + true + true + CT: WriteBTLx + WriteBTLx - - + + + + + 3083 + 1480 + 104 + 64 + + + 3138 + 1512 + + + + + + 3 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + Model object. + b3fcc3eb-1221-4b6c-8a2f-abd50e4ab4f9 + Model + Model + true + 0 + true + ef1e3166-9d32-4e5c-a29d-ce521ae68b72 + 1 + 35915213-5534-4277-81b8-1bdc9e7383d2 + + + + + + 3085 + 1482 + 38 + 20 + + + 3105.5 + 1492 + + + + + + + + true + Script input Path. + 71cdff33-2411-49d0-ab46-86368a774a4d + Path + Path + true + 0 + true + 0 + 35915213-5534-4277-81b8-1bdc9e7383d2 + + + + + + 3085 + 1502 + 38 + 20 + + + 3105.5 + 1512 + + + + + + + + true + Script input Write. + b9232719-c3fe-4957-b7e3-373d20cac74e + Write + Write + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 3085 + 1522 + 38 + 20 + + + 3105.5 + 1532 + + + + + + + + Script output BTLx. + 122c32e0-f3e7-4c87-98a7-196c6459af3c + BTLx + BTLx + false + 0 + + + + + + 3153 + 1482 + 32 + 60 + + + 3169 + 1512 + + + + + + + @@ -6655,7 +6481,7 @@ BTLx = btlx.btlx_string() - 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 diff --git a/src/compas_timber/_fabrication/btlx_process.py b/src/compas_timber/_fabrication/btlx_process.py index f84b6d0a6..b77653cd7 100644 --- a/src/compas_timber/_fabrication/btlx_process.py +++ b/src/compas_timber/_fabrication/btlx_process.py @@ -113,14 +113,16 @@ class TenonShapeType(object): Attributes ---------- - STEP : literal("step") - A step shape. - HEEL : literal("heel") - A heel shape. - TAPERED_HEEL : literal("taperedheel") - A tapered heel shape. - DOUBLE : literal("double") - A double shape. + AUTOMATIC : literal("automatic") + Automatic tenon shape. + SQUARE : literal("square") + Square tenon shape. + ROUND : literal("round") + Round tenon shape. + ROUNDED : literal("rounded") + Rounded tenon shape. + RADIUS : literal("radius") + Radius tenon shape. """ AUTOMATIC = "automatic" diff --git a/src/compas_timber/_fabrication/dovetail_mortise.py b/src/compas_timber/_fabrication/dovetail_mortise.py index 2af846122..8cd5b29f4 100644 --- a/src/compas_timber/_fabrication/dovetail_mortise.py +++ b/src/compas_timber/_fabrication/dovetail_mortise.py @@ -64,7 +64,7 @@ class DovetailMortise(BTLxProcess): PROCESS_NAME = "DovetailMortise" # type: ignore # Class-level attribute - _dovetail_tool_params = {} + _DOVETAIL_TOOL_PARAMS = {} @property def __data__(self): @@ -87,6 +87,7 @@ def __data__(self): data["shape_radius"] = self.shape_radius return data + # fmt: off def __init__( self, start_x=0.0, @@ -449,7 +450,7 @@ def _calculate_start_x(ref_side, ref_edge, cutting_frame): ######################################################################## @classmethod - def define_dovetail_tool(self, tool_angle, tool_diameter, tool_height): + def define_dovetail_tool(cls, tool_angle, tool_diameter, tool_height): """Define the parameters for the dovetail feature based on a defined dovetail cutting tool. Parameters @@ -463,7 +464,7 @@ def define_dovetail_tool(self, tool_angle, tool_diameter, tool_height): """ # type: (float, float, float) -> None - self._dovetail_tool_params = { + cls._DOVETAIL_TOOL_PARAMS = { "tool_angle": tool_angle, "tool_diameter": tool_diameter, "tool_height": tool_height, @@ -509,10 +510,10 @@ def apply(self, geometry, beam): if ( self.shape != TenonShapeType.SQUARE and not self.length_limited_bottom ): # TODO: Change negation to affirmation once Brep.fillet is implemented - edge_ideces = [4, 7] if self.length_limited_bottom else [5, 8] + edge_idexes = [4, 7] if self.length_limited_bottom else [5, 8] try: dovetail_volume.fillet( - self.shape_radius, [dovetail_volume.edges[edge_ideces[0]], dovetail_volume.edges[edge_ideces[1]]] + self.shape_radius, [dovetail_volume.edges[edge_idexes[0]], dovetail_volume.edges[edge_idexes[1]]] ) # TODO: NotImplementedError except Exception as e: raise FeatureApplicationError( @@ -562,8 +563,8 @@ def frame_from_params_and_beam(self, beam): return cutting_frame - def dovetail_cutting_planes_from_params_and_beam(self, beam): - """Calculates the cutting planes for the dovetail mortise from the machining parameters in this instance and the given beam. + def dovetail_cutting_frames_from_params_and_beam(self, beam): + """Calculates the cutting frames for the dovetail mortise from the machining parameters in this instance and the given beam. Parameters ---------- @@ -573,7 +574,7 @@ def dovetail_cutting_planes_from_params_and_beam(self, beam): Returns ------- list of :class:`compas.geometry.Frame` - The cutting planes for the dovetail mortise. + The cutting frames for the dovetail mortise. """ assert self.angle is not None assert self.depth is not None @@ -667,8 +668,8 @@ def dovetail_volume_from_params_and_beam(self, beam): ) ) - # get the cutting planes for the dovetail tenon - trimming_frames = self.dovetail_cutting_planes_from_params_and_beam(beam) + # get the cutting frames for the dovetail tenon + trimming_frames = self.dovetail_cutting_frames_from_params_and_beam(beam) # trim the box to create the dovetail volume for frame in trimming_frames: diff --git a/src/compas_timber/_fabrication/dovetail_tenon.py b/src/compas_timber/_fabrication/dovetail_tenon.py index eaafd7a65..a30aba256 100644 --- a/src/compas_timber/_fabrication/dovetail_tenon.py +++ b/src/compas_timber/_fabrication/dovetail_tenon.py @@ -67,7 +67,7 @@ class DovetailTenon(BTLxProcess): PROCESS_NAME = "DovetailTenon" # type: ignore # Class-level attribute - _dovetail_tool_params = {} + _DOVETAIL_TOOL_PARAMS = {} @property def __data__(self): @@ -91,6 +91,7 @@ def __data__(self): data["shape_radius"] = self.shape_radius return data + # fmt: off def __init__( self, orientation, @@ -392,11 +393,11 @@ def from_plane_and_beam( """ # type: (Plane|Frame, Beam, float, float, bool, int) -> DovetailTenon - if cls._dovetail_tool_params: + if cls._DOVETAIL_TOOL_PARAMS: # get the tool parameters - tool_angle = cls._dovetail_tool_params["tool_angle"] - tool_diameter = cls._dovetail_tool_params["tool_diameter"] - tool_height = cls._dovetail_tool_params["tool_height"] + tool_angle = cls._DOVETAIL_TOOL_PARAMS["tool_angle"] + tool_diameter = cls._DOVETAIL_TOOL_PARAMS["tool_diameter"] + tool_height = cls._DOVETAIL_TOOL_PARAMS["tool_height"] tool_top_radius = tool_diameter / 2 - tool_height * (math.tan(math.radians(tool_angle))) # update parameters related to the tool if a tool is defined height = min(height, tool_height) @@ -569,7 +570,7 @@ def _bound_start_depth(start_depth, inclination, height): ######################################################################## @classmethod - def define_dovetail_tool(self, tool_angle, tool_diameter, tool_height): + def define_dovetail_tool(cls, tool_angle, tool_diameter, tool_height): """Define the parameters for the dovetail feature based on a defined dovetail cutting tool. Parameters @@ -583,7 +584,7 @@ def define_dovetail_tool(self, tool_angle, tool_diameter, tool_height): """ # type: (float, float, float) -> None - self._dovetail_tool_params = { + cls._DOVETAIL_TOOL_PARAMS = { "tool_angle": tool_angle, "tool_diameter": tool_diameter, "tool_height": tool_height, @@ -607,7 +608,7 @@ def apply(self, geometry, beam): Raises ------ :class:`~compas_timber.elements.FeatureApplicationError` - If the cutting planes do not create a volume that itersects with beam geometry or any step fails. + If the cutting frames do not create a volume that itersects with beam geometry or any step fails. Returns ------- @@ -622,7 +623,7 @@ def apply(self, geometry, beam): cutting_plane = Plane.from_frame(self.frame_from_params_and_beam(beam)) except ValueError as e: raise FeatureApplicationError( - None, geometry, "Failed to generate cutting plane from parameters and beam: {}".format(str(e)) + None, geometry, "Failed to generate cutting frame from parameters and beam: {}".format(str(e)) ) # get dovetail volume from params and beam @@ -637,10 +638,10 @@ def apply(self, geometry, beam): if ( self.shape != TenonShapeType.SQUARE and not self.length_limited_bottom ): # TODO: Change negation to affirmation once Brep.fillet is implemented - edge_ideces = [4, 7] if self.length_limited_top else [5, 8] + edge_idexes = [4, 7] if self.length_limited_top else [5, 8] try: dovetail_volume.fillet( - self.shape_radius, [dovetail_volume.edges[edge_ideces[0]], dovetail_volume.edges[edge_ideces[1]]] + self.shape_radius, [dovetail_volume.edges[edge_idexes[0]], dovetail_volume.edges[edge_idexes[1]]] ) # TODO: NotImplementedError except Exception as e: raise FeatureApplicationError( @@ -723,8 +724,8 @@ def frame_from_params_and_beam(self, beam): return cutting_frame - def dovetail_cutting_planes_from_params_and_beam(self, beam): - """Calculates the cutting planes for the dovetail tenon from the machining parameters in this instance and the given beam.""" + def dovetail_cutting_frames_from_params_and_beam(self, beam): + """Calculates the cutting frames for the dovetail tenon from the machining parameters in this instance and the given beam.""" # get the cutting frame cutting_frame = self.frame_from_params_and_beam(beam) @@ -814,8 +815,8 @@ def dovetail_volume_from_params_and_beam(self, beam): ) ) - # get the cutting planes for the dovetail tenon - trimming_frames = self.dovetail_cutting_planes_from_params_and_beam(beam) + # get the cutting frames for the dovetail tenon + trimming_frames = self.dovetail_cutting_frames_from_params_and_beam(beam) # trim the box to create the dovetail volume for frame in trimming_frames: @@ -823,7 +824,7 @@ def dovetail_volume_from_params_and_beam(self, beam): dovetail_volume.trim(frame) except Exception as e: raise FeatureApplicationError( - frame, dovetail_volume, "Failed to trim tenon volume with cutting plane: {}".format(str(e)) + frame, dovetail_volume, "Failed to trim tenon volume with cutting frame: {}".format(str(e)) ) return dovetail_volume diff --git a/src/compas_timber/_fabrication/step_joint.py b/src/compas_timber/_fabrication/step_joint.py index 36aa08f07..02255e242 100644 --- a/src/compas_timber/_fabrication/step_joint.py +++ b/src/compas_timber/_fabrication/step_joint.py @@ -64,6 +64,7 @@ def __data__(self): data["tenon_height"] = self.tenon_height return data + # fmt: off def __init__( self, orientation, diff --git a/src/compas_timber/_fabrication/step_joint_notch.py b/src/compas_timber/_fabrication/step_joint_notch.py index b9e3219c7..abd3113f2 100644 --- a/src/compas_timber/_fabrication/step_joint_notch.py +++ b/src/compas_timber/_fabrication/step_joint_notch.py @@ -76,6 +76,7 @@ def __data__(self): data["mortise_height"] = self.mortise_height return data + # fmt: off def __init__( self, orientation, diff --git a/tests/compas_timber/gh/test_dovetail.ghx b/tests/compas_timber/gh/test_dovetail.ghx deleted file mode 100644 index d7f946809..000000000 --- a/tests/compas_timber/gh/test_dovetail.ghx +++ /dev/null @@ -1,15023 +0,0 @@ - - - - - - - - 0 - 2 - 2 - - - - - - - 1 - 0 - 7 - - - - - - fa5d732c-b31a-4064-bc30-fdd75169872b - Shaded - Selection - 1 - - 100;150;0;0 - - - 100;0;150;0 - - - - - - 638584536051543966 - - test_dovetail.ghx - - - - - 0 - - - - - - -1967 - 229 - - 1.47058821 - - - - - 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 - - - - - - - 150 - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - 1631fe30-c80f-49ec-9128-96481121ad52 - a8a91d2c-6d94-4451-b47e-a81520b31d82 - ae229730-bb17-41d8-826e-9f750d58d128 - 54426880-0968-40ad-8b1e-e50de0a67289 - 46feaa45-4a40-458f-a4fd-9de5989af911 - 1dc4a321-0021-4a13-90df-e852c7e4e773 - f05fce76-e87f-48e1-a86d-07f6d4084049 - 3606e2e7-dfd8-4977-a4d6-75b937b9b9f1 - 2a5a867a-a76c-4f02-bce5-209e79f61aac - f29282aa-9bfd-49b7-a1a0-1f7fc87af0e9 - 31a8ef0b-5079-4e66-9612-dff6a751c5a8 - 11 - 0b9fb065-5070-4c3f-96bb-831d0aa1aedf - Group - - - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - 37c9fe3d-b5bb-4362-ba0f-d5053fcb2141 - 7e4bcb53-01cc-446e-8792-764d02b1451e - c3c1dc6d-7ceb-4d7f-add6-fa924b4cc936 - ab977350-6a8d-472b-9276-52a400da755b - dec5089d-c452-417b-a948-4034d6df42ce - 1f382d1c-8a89-4e8a-8102-597801cd81a3 - ba1c263a-665b-4a0d-a1a6-e771de90f422 - 62e63fca-99eb-4ff3-8b10-df2b88807b8d - d6206efa-67b1-4c9e-b762-42a2cf302219 - 244dd1d8-93d4-4afc-851d-064a07e08680 - 6b6d7ea8-7a08-4879-939c-5f96604c4678 - 89a39aa2-89d0-4ad6-9043-6ef61b51023c - 12 - c67c3391-fbfa-4fd4-bd01-edf5270cbdc6 - Group - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - c3c1dc6d-7ceb-4d7f-add6-fa924b4cc936 - Number Slider - - false - 0 - - - - - - 1405 - 137 - 188 - 20 - - - 1405.227 - 137.5545 - - - - - - 2 - 1 - 0 - 200 - 0 - 0 - 10 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - ab977350-6a8d-472b-9276-52a400da755b - Number Slider - width - false - 0 - - - - - - 1405 - 158 - 188 - 20 - - - 1405.158 - 158.6988 - - - - - - 3 - 1 - 1 - 200 - 0 - 0 - 25 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 1f382d1c-8a89-4e8a-8102-597801cd81a3 - Number Slider - cone_angle - false - 0 - - - - - - 1405 - 202 - 188 - 20 - - - 1405.305 - 202.4095 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 10 - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - 37c9fe3d-b5bb-4362-ba0f-d5053fcb2141 - 7e4bcb53-01cc-446e-8792-764d02b1451e - 2 - ba1c263a-665b-4a0d-a1a6-e771de90f422 - Group - Ref_Side - - - - - - - - - - d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 - Curve - - - - - Contains a collection of generic curves - true - 1631fe30-c80f-49ec-9128-96481121ad52 - Curve - Crv - false - 0 - - - - - - -222 - 535 - 50 - 24 - - - -196.0559 - 547.3639 - - - - - - 1 - - - - - 1 - {0} - - - - - -1 - - Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyNy4bxpcrDPvOXz4/18+rHjlAagcQwpU3KHb70cS13q4OBMDAuxtjlpjZzvZAeSS6oIuv//1TA0wOW6GwQQA - - 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. - - 192 - 192 - - - 974 - 699 - - true - true - true - - iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDAAACwwBP0AiyAAAAhRJREFUSEulVLtKA0EUzSfkD3zlrUKMIcHGB6ghIj5QxEoDiiA2gtqGYBEfRRQiSRc7iXU6IWKZwh8Q/AI/wEcRr/cMmWUZ7ya7Whw2uXvvOTNnzqyPiP6Nob7+Q0bBQJ0xLQ64BRP4R6OxZ37Swf4+nRwdKyxmFyg4MEhcvxYH3YCH4+GhwHsqMd6+r9ep1WrRY7OpyGcmp2hvZxcCBXG4F3gQligykIIcIulkknJb26qGnXgW4AF/NBi6AzkIQAxcnl+AjAr5vFXzLMDN8ZFI9JXxfVMuW0RYMZ8D3dZqVs2zADeuRALBD3jbaDQUAZ74D2ib/iQwHI5UudHyFsNYLVaN5JjEGj0F+KUVQXisB+EzyO01CV0F+IUYwY21dZUUXXMCemGdKMBFMYIYgIDktx2wD0FAILBQO7FjBGGJveYE2Id5Jn8AH3g1uRhBHCLI7TUJ2BVCAHLuP9eLVgJc3GS/vyZSaboqldQWq5UKZeczyhYdSyfouCLGzLViJ9cCT1A2sbq03NNv7Ay7joXCLzzTb5JbAqa/mdm5XzfTRCeG1Dk35bcEUQAJchLArpAmkDMOJVI7PAkgrrgbuCM8F5cITbgWQFyHI9F2x29HS0y4EkBcuU/5LZF0Q1cB+I3fHMFP7stJBL3gKHBWLOoIvnGPK78lKAEQQkQjOZZQlnS+pq79lgABfNxw2UycSgPeQL4fsKzVEEQlKEcAAAAASUVORK5CYII= - - false - e28e26d5-b791-48bc-902c-a1929ace9685 - true - true - CT: Beam - Beam - - - - - - 1016 - 377 - 145 - 124 - - - 1107 - 439 - - - - - - 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. - 1bee6a78-7b3a-4d65-9fa6-ee03a6a467d7 - Centerline - Centerline - true - 1 - true - 36c4deda-ceed-4920-a3f3-2d18ca613b35 - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 1018 - 379 - 74 - 20 - - - 1056.5 - 389 - - - - - - - - 1 - true - Vector defining the orientation of the cross-section (corresponds to the height dimension). If None, a default will be taken. - 9cde7a1d-c80f-42e0-9a2a-232ea2038830 - ZVector - ZVector - true - 1 - true - 0 - 15a50725-e3d3-4075-9f7c-142ba5f40747 - - - - - - 1018 - 399 - 74 - 20 - - - 1056.5 - 409 - - - - - - - - 1 - true - Width of the cross-section (usually the smaller dimension). - 640d61a5-30a2-4d6d-9d06-693c7998daa3 - Width - Width - true - 1 - true - b0579e2b-7024-4c03-8e13-7ddcca5e08a6 - 1 - 39fbc626-7a01-46ab-a18e-ec1c0c41685b - - - - - - 1018 - 419 - 74 - 20 - - - 1056.5 - 429 - - - - - - - - 1 - true - Height of the cross-section (usually the larger dimension). - c55fd807-c67f-4bc9-8acb-00f1fb7639c8 - Height - Height - true - 1 - true - 13835904-23ad-43b2-a586-0ae141339040 - 1 - 39fbc626-7a01-46ab-a18e-ec1c0c41685b - - - - - - 1018 - 439 - 74 - 20 - - - 1056.5 - 449 - - - - - - - - 1 - true - Category of a beam. - 3cabcb03-288e-45d6-a8c0-e9ddc8b859ce - Category - Category - true - 1 - true - 0 - 37261734-eec7-4f50-b6a8-b8d1f3c4396b - - - - - - 1018 - 459 - 74 - 20 - - - 1056.5 - 469 - - - - - - - - true - (optional) If True, the attributes in the referenced object will be updated/overwritten with the new values given here. - bb55e50a-3bee-410d-8466-5dfca9d565d1 - updateRefObj - updateRefObj - true - 0 - true - 0 - d60527f5-b5af-4ef6-8970-5f96fe412559 - - - - - - 1018 - 479 - 74 - 20 - - - 1056.5 - 489 - - - - - - - - Beam object(s). - 3984d0df-294e-462f-b103-b87bb94e3021 - Beam - Beam - false - 0 - - - - - - 1122 - 379 - 37 - 60 - - - 1140.5 - 409 - - - - - - - - Shape of the beam's blank. - b0a6568e-06d8-4c68-b393-d8274f661640 - Blank - Blank - false - 0 - - - - - - 1122 - 439 - 37 - 60 - - - 1140.5 - 469 - - - - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - d9d51b18-d5af-4f8f-822f-9fbd0f30d642 - Number Slider - - false - 0 - - - - - - 827 - 422 - 166 - 20 - - - 827.5709 - 422.7206 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 100 - - - - - - - - - d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 - Curve - - - - - Contains a collection of generic curves - true - 18d2fa4a-de1b-4cfd-bf80-4b8d5fa0182f - Curve - Crv - false - 0 - - - - - - 317 - 369 - 50 - 24 - - - 342.1181 - 381.6854 - - - - - - 1 - - - - - 1 - {0} - - - - - -1 - - Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyFyF5Ln1s/nvOXz8/18+rHjlAagcw4SN5/afrXvg8BlNnIkBDRQsdwC55PeJbev/1zM1wIS50dUNKAAA - - 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. - - 96 - 96 - - - 741 - 702 - - true - true - true - - iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDAAACwwBP0AiyAAAAhRJREFUSEulVLtKA0EUzSfkD3zlrUKMIcHGB6ghIj5QxEoDiiA2gtqGYBEfRRQiSRc7iXU6IWKZwh8Q/AI/wEcRr/cMmWUZ7ya7Whw2uXvvOTNnzqyPiP6Nob7+Q0bBQJ0xLQ64BRP4R6OxZ37Swf4+nRwdKyxmFyg4MEhcvxYH3YCH4+GhwHsqMd6+r9ep1WrRY7OpyGcmp2hvZxcCBXG4F3gQligykIIcIulkknJb26qGnXgW4AF/NBi6AzkIQAxcnl+AjAr5vFXzLMDN8ZFI9JXxfVMuW0RYMZ8D3dZqVs2zADeuRALBD3jbaDQUAZ74D2ib/iQwHI5UudHyFsNYLVaN5JjEGj0F+KUVQXisB+EzyO01CV0F+IUYwY21dZUUXXMCemGdKMBFMYIYgIDktx2wD0FAILBQO7FjBGGJveYE2Id5Jn8AH3g1uRhBHCLI7TUJ2BVCAHLuP9eLVgJc3GS/vyZSaboqldQWq5UKZeczyhYdSyfouCLGzLViJ9cCT1A2sbq03NNv7Ay7joXCLzzTb5JbAqa/mdm5XzfTRCeG1Dk35bcEUQAJchLArpAmkDMOJVI7PAkgrrgbuCM8F5cITbgWQFyHI9F2x29HS0y4EkBcuU/5LZF0Q1cB+I3fHMFP7stJBL3gKHBWLOoIvnGPK78lKAEQQkQjOZZQlnS+pq79lgABfNxw2UycSgPeQL4fsKzVEEQlKEcAAAAASUVORK5CYII= - - false - ea292354-f0cd-4b58-ba78-57c730de54ad - true - true - CT: Beam - Beam - - - - - - 1032 - 531 - 145 - 124 - - - 1123 - 593 - - - - - - 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. - 53757008-8b2d-49b8-ada7-e0c81d24586f - Centerline - Centerline - true - 1 - true - d2d51328-18f6-4ef3-8dd6-1df6b6af922e - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 1034 - 533 - 74 - 20 - - - 1072.5 - 543 - - - - - - - - 1 - true - Vector defining the orientation of the cross-section (corresponds to the height dimension). If None, a default will be taken. - db7b0ca0-f838-405d-ae51-0e61596dd253 - ZVector - ZVector - true - 1 - true - 4c90d06e-9810-41a6-baa8-91b753ccec55 - 1 - 15a50725-e3d3-4075-9f7c-142ba5f40747 - - - - - - 1034 - 553 - 74 - 20 - - - 1072.5 - 563 - - - - - - - - 1 - true - Width of the cross-section (usually the smaller dimension). - 4b9bf139-421a-4a01-b027-ec23d68ace87 - Width - Width - true - 1 - true - 81d19eff-02b1-4406-a0c3-47dd897a152f - 1 - 39fbc626-7a01-46ab-a18e-ec1c0c41685b - - - - - - 1034 - 573 - 74 - 20 - - - 1072.5 - 583 - - - - - - - - 1 - true - Height of the cross-section (usually the larger dimension). - 4ae02a01-6e0a-4998-bca5-654916c862fc - Height - Height - true - 1 - true - 478fc3b1-c4f8-4087-8fe6-c2905e21be9a - 1 - 39fbc626-7a01-46ab-a18e-ec1c0c41685b - - - - - - 1034 - 593 - 74 - 20 - - - 1072.5 - 603 - - - - - - - - 1 - true - Category of a beam. - 98e31428-399a-4dde-a0e3-585981226918 - Category - Category - true - 1 - true - 0 - 37261734-eec7-4f50-b6a8-b8d1f3c4396b - - - - - - 1034 - 613 - 74 - 20 - - - 1072.5 - 623 - - - - - - - - true - (optional) If True, the attributes in the referenced object will be updated/overwritten with the new values given here. - 32189ead-4252-4352-bf45-514c147d7b57 - updateRefObj - updateRefObj - true - 0 - true - 0 - d60527f5-b5af-4ef6-8970-5f96fe412559 - - - - - - 1034 - 633 - 74 - 20 - - - 1072.5 - 643 - - - - - - - - Beam object(s). - 90fae02f-7750-462d-828f-cf5f2a0d39ae - Beam - Beam - false - 0 - - - - - - 1138 - 533 - 37 - 60 - - - 1156.5 - 563 - - - - - - - - Shape of the beam's blank. - 55c66290-a177-4518-824a-6a531a1e8086 - Blank - Blank - false - 0 - - - - - - 1138 - 593 - 37 - 60 - - - 1156.5 - 623 - - - - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 478fc3b1-c4f8-4087-8fe6-c2905e21be9a - Number Slider - - false - 0 - - - - - - 825 - 596 - 166 - 20 - - - 825.0048 - 596.0939 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 100 - - - - - - - - - 22990b1f-9be6-477c-ad89-f775cd347105 - Flip Curve - - - - - Flip a curve using an optional guide curve. - true - 2098ce01-e0b3-4e52-b0ed-3c62bb419a62 - Flip Curve - Flip - - - - - - 391 - 615 - 66 - 44 - - - 423 - 637 - - - - - - Curve to flip - 417fea5c-f458-4cb9-81ea-3c456faf67b1 - Curve - C - false - 2ace07a8-3cff-4c52-b37f-cd3e591aeddd - 1 - - - - - - 393 - 617 - 15 - 20 - - - 402 - 627 - - - - - - - - Optional guide curve - 0cee7869-6730-4b7d-832a-4aa6b5d4749a - Guide - G - true - 0 - - - - - - 393 - 637 - 15 - 20 - - - 402 - 647 - - - - - - - - Flipped curve - 0b2eef87-f147-4a36-b443-85031493ef71 - Curve - C - false - 0 - - - - - - 438 - 617 - 17 - 20 - - - 446.5 - 627 - - - - - - - - Flip action - d77f6082-7255-4694-8fae-7a31bce87565 - Flag - F - false - 0 - - - - - - 438 - 637 - 17 - 20 - - - 446.5 - 647 - - - - - - - - - - - - 11bbd48b-bb0a-4f1b-8167-fa297590390d - End Points - - - - - Extract the end points of a curve. - true - 3606e2e7-dfd8-4977-a4d6-75b937b9b9f1 - End Points - End - - - - - - -119 - 562 - 64 - 44 - - - -88 - 584 - - - - - - Curve to evaluate - c35e0949-31c0-4148-833b-aeed3fc97aa3 - Curve - C - false - 1631fe30-c80f-49ec-9128-96481121ad52 - 1 - - - - - - -117 - 564 - 14 - 40 - - - -108.5 - 584 - - - - - - - - Curve start point - 349dd0c5-02cc-4111-abf4-8728c5a86c2c - Start - S - false - 0 - - - - - - -73 - 564 - 16 - 20 - - - -65 - 574 - - - - - - - - Curve end point - 08d2450a-ba8f-45b3-a29d-274a84997a85 - End - E - false - 0 - - - - - - -73 - 584 - 16 - 20 - - - -65 - 594 - - - - - - - - - - - - e9eb1dcf-92f6-4d4d-84ae-96222d60f56b - Move - - - - - Translate (move) an object along a vector. - true - 2a5a867a-a76c-4f02-bce5-209e79f61aac - Move - Move - - - - - - -33 - 609 - 83 - 44 - - - 15 - 631 - - - - - - Base geometry - a0edbf9a-3853-4ab0-b53f-aef5027fa137 - Geometry - G - true - 08d2450a-ba8f-45b3-a29d-274a84997a85 - 1 - - - - - - -31 - 611 - 31 - 20 - - - -6 - 621 - - - - - - - - Translation vector - 8acddbb8-4abe-4d9b-81aa-f36b38b9dda4 - -x - Motion - T - false - 3441a608-3853-45f3-92c7-1d1941125460 - 1 - - - - - - -31 - 631 - 31 - 20 - - - -6 - 641 - - - - - - 1 - - - - - 1 - {0} - - - - - - 0 - 0 - 10 - - - - - - - - - - - - Translated geometry - 3b2b25a6-3d8c-4a41-b0a2-3ea3be957972 - Geometry - G - false - 0 - - - - - - 30 - 611 - 18 - 20 - - - 39 - 621 - - - - - - - - Transformation data - d8dfb3a4-eb51-4258-aa5c-b6584682d0ef - Transform - X - false - 0 - - - - - - 30 - 631 - 18 - 20 - - - 39 - 641 - - - - - - - - - - - - 79f9fbb3-8f1d-4d9a-88a9-f7961b1012cd - Unit X - - - - - Unit vector parallel to the world {x} axis. - true - a8a91d2c-6d94-4451-b47e-a81520b31d82 - Unit X - X - - - - - - -221 - 607 - 79 - 28 - - - -176 - 621 - - - - - - Unit multiplication - 0640aeed-9882-4ebf-a1b1-5080f3b20bb9 - -x - Factor - F - false - ae229730-bb17-41d8-826e-9f750d58d128 - 1 - - - - - - -219 - 609 - 28 - 24 - - - -195.5 - 621 - - - - - - 1 - - - - - 1 - {0} - - - - - 1 - - - - - - - - - - - World {x} vector - 20ce5606-82c9-43d0-b182-e8db425945b5 - Unit vector - V - false - 0 - - - - - - -161 - 609 - 17 - 24 - - - -152.5 - 621 - - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - ae229730-bb17-41d8-826e-9f750d58d128 - Number Slider - - false - 0 - - - - - - -395 - 611 - 163 - 20 - - - -394.2762 - 611.8264 - - - - - - 3 - 1 - 1 - 4000 - 0 - 0 - 500 - - - - - - - - - 4c4e56eb-2f04-43f9-95a3-cc46a14f495a - Line - - - - - Create a line between two points. - true - f29282aa-9bfd-49b7-a1a0-1f7fc87af0e9 - Line - Ln - - - - - - 75 - 589 - 63 - 44 - - - 106 - 611 - - - - - - Line start point - cb99cc28-9c59-4191-95b9-3cae3e6f1e9c - Start Point - A - false - 349dd0c5-02cc-4111-abf4-8728c5a86c2c - 1 - - - - - - 77 - 591 - 14 - 20 - - - 85.5 - 601 - - - - - - - - Line end point - fb12ca80-6fc6-404b-8d93-4fdb6c2c6520 - End Point - B - false - 3b2b25a6-3d8c-4a41-b0a2-3ea3be957972 - 1 - - - - - - 77 - 611 - 14 - 20 - - - 85.5 - 621 - - - - - - - - Line segment - b37fb167-edb3-4a28-b8fd-a498a7811210 - Line - L - false - 0 - - - - - - 121 - 591 - 15 - 40 - - - 128.5 - 611 - - - - - - - - - - - - 9103c240-a6a9-4223-9b42-dbd19bf38e2b - Unit Z - - - - - Unit vector parallel to the world {z} axis. - true - 54426880-0968-40ad-8b1e-e50de0a67289 - Unit Z - Z - - - - - - -203 - 641 - 63 - 28 - - - -174 - 655 - - - - - - Unit multiplication - 45ecdc35-f4be-4e29-97b3-ae200336ed76 - Factor - F - false - 46feaa45-4a40-458f-a4fd-9de5989af911 - 1 - - - - - - -201 - 643 - 12 - 24 - - - -193.5 - 655 - - - - - - 1 - - - - - 1 - {0} - - - - - 1 - - - - - - - - - - - World {z} vector - 31dfa7fb-7b92-4e78-8a6c-51149c8b2402 - Unit vector - V - false - 0 - - - - - - -159 - 643 - 17 - 24 - - - -150.5 - 655 - - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 46feaa45-4a40-458f-a4fd-9de5989af911 - Number Slider - - false - 0 - - - - - - -395 - 645 - 163 - 20 - - - -394.5755 - 645.9137 - - - - - - 3 - 1 - 1 - 2000 - 0 - 0 - 500 - - - - - - - - - a0d62394-a118-422d-abb3-6af115c75b25 - Addition - - - - - Mathematical addition - true - 31a8ef0b-5079-4e66-9612-dff6a751c5a8 - Addition - A+B - - - - - - -117 - 609 - 65 - 64 - - - -86 - 641 - - - - - - 3 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 1 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - - - - - First item for addition - d9d3d34d-5080-4bb5-aa7b-9e02635fbae5 - A - A - true - 20ce5606-82c9-43d0-b182-e8db425945b5 - 1 - - - - - - -115 - 611 - 14 - 20 - - - -106.5 - 621 - - - - - - - - Second item for addition - 3898220f-37d7-48fc-b80c-31e2b32274f5 - B - B - true - 31dfa7fb-7b92-4e78-8a6c-51149c8b2402 - 1 - - - - - - -115 - 631 - 14 - 20 - - - -106.5 - 641 - - - - - - - - Third item for addition - 13ca1130-de29-4026-94fc-c1ca22604c07 - C - C - true - 7a214201-5ed9-46c9-afe6-bf48e768f870 - 1 - - - - - - -115 - 651 - 14 - 20 - - - -106.5 - 661 - - - - - - - - Result of addition - 3441a608-3853-45f3-92c7-1d1941125460 - Result - R - false - 0 - - - - - - -71 - 611 - 17 - 60 - - - -62.5 - 641 - - - - - - - - - - - - - - 2e78987b-9dfb-42a2-8b76-3923ac8bd91a - Boolean Toggle - - - - - Boolean (true/false) toggle - ca0ea429-34fb-4ce1-a30e-2c14ddc1552e - Boolean Toggle - FlipCurve - false - 0 - true - - - - - - 258 - 569 - 115 - 22 - - - - - - - - - - eeafc956-268e-461d-8e73-ee05c6f72c01 - Stream Filter - - - - - Filters a collection of input streams - true - 9c98408b-5774-4f45-bb43-c16e5d4c92b4 - Stream Filter - Filter - - - - - - 469 - 575 - 77 - 64 - - - 501 - 607 - - - - - - 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 - be384cd0-c014-4922-86ee-f8be45625fad - Gate - G - false - ca0ea429-34fb-4ce1-a30e-2c14ddc1552e - 1 - - - - - - 471 - 577 - 15 - 20 - - - 480 - 587 - - - - - - 1 - - - - - 1 - {0} - - - - - 0 - - - - - - - - - - - 2 - Input stream at index 0 - b069b652-f7a4-47dc-a04c-9b3003b0e168 - false - Stream 0 - 0 - true - 2ace07a8-3cff-4c52-b37f-cd3e591aeddd - 1 - - - - - - 471 - 597 - 15 - 20 - - - 480 - 607 - - - - - - - - 2 - Input stream at index 1 - 4bbd6850-b99a-47c4-a371-8adee5564955 - false - Stream 1 - 1 - true - 0b2eef87-f147-4a36-b443-85031493ef71 - 1 - - - - - - 471 - 617 - 15 - 20 - - - 480 - 627 - - - - - - - - 2 - Filtered stream - 09fe95fb-9551-4690-abf6-4a0665002914 - false - Stream - S(1) - false - 0 - - - - - - 516 - 577 - 28 - 60 - - - 530 - 607 - - - - - - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - a8a91d2c-6d94-4451-b47e-a81520b31d82 - ae229730-bb17-41d8-826e-9f750d58d128 - 54426880-0968-40ad-8b1e-e50de0a67289 - 46feaa45-4a40-458f-a4fd-9de5989af911 - 780dd7ff-1451-4d20-b77b-f1c386f8a9ed - 27b7a426-ec72-4334-8c70-78c50fb834e2 - 6 - f05fce76-e87f-48e1-a86d-07f6d4084049 - Group - - - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - 18d2fa4a-de1b-4cfd-bf80-4b8d5fa0182f - 1 - e22e52d8-5a24-494f-8bd6-2f5c368cced0 - Group - CrossBeam - - - - - - - - - - 410755b1-224a-4c1e-a407-bf32fb45ea7e - 00000000-0000-0000-0000-000000000000 - GhPython Script - - - - - from compas_timber.connections import TDovetailJoint - -from compas_timber.model import TimberModel -from compas_timber.fabrication import BTLx - -from compas_rhino.conversions import brep_to_rhino - -from compas_rhino import unload_modules - -unload_modules("compas_timber") - -# Instantiate TimberModel & Add Beams -timber_model = TimberModel() -beams = [cross_beam, main_beam] -for beam in beams: - if beam.features: - beam.remove_features(beam.features) - timber_model.add_element(beam) - - - -# Create TStepJoint joint -dovetail_joint = TDovetailJoint.create( - timber_model, - main_beam, - cross_beam, - start_y=start_y, - start_depth=start_depth, - rotation=rotation, - length=length, - width=width, - cone_angle=cone_angle, - dovetail_shape=4, - tool_angle=15.0, - tool_diameter=60.034, - tool_height=28.0 - ) - -timber_model.process_joinery() -# Generate Geometry -geometry = [brep_to_rhino(beam.compute_geometry()) for beam in timber_model.beams] - -# Write BTLx -btlx = BTLx(timber_model) -BTLx = btlx.btlx_string() - GhPython provides a Python script component - - 816 - 115 - - - 901 - 818 - - true - true - false - false - 20be8b4b-0eba-41a5-8f13-25defa3e633d - false - true - GhPython Script - Python - - - - - - 2284 - 683 - 155 - 184 - - - 2365 - 775 - - - - - - 9 - 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 - 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 - 3 - 3ede854e-c753-40eb-84cb-b48008f14fd4 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - - - - - true - Script input cross_beam. - 36ebe6e6-4cdb-4b9d-8c4a-65feaf8cee5a - cross_beam - cross_beam - true - 0 - true - ed4dd89a-026f-43eb-81d4-433cea857301 - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 2286 - 685 - 64 - 20 - - - 2319.5 - 695 - - - - - - - - true - Script input main_beam. - 407e65c9-4ebe-4581-9401-a364b25f96c2 - main_beam - main_beam - true - 0 - true - 90fae02f-7750-462d-828f-cf5f2a0d39ae - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 2286 - 705 - 64 - 20 - - - 2319.5 - 715 - - - - - - - - true - Script input start_depth. - fbd107db-8f8a-4baa-876f-623012dd3bb0 - start_depth - start_depth - true - 0 - true - 4d710107-34a1-4586-be44-d6f80294f0e6 - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 2286 - 725 - 64 - 20 - - - 2319.5 - 735 - - - - - - - - true - Script input length. - dab8fd89-b668-48ad-91eb-c695241b0e94 - length - length - true - 0 - true - b29d9bba-e05a-4fa4-91a3-bf1ac143a41d - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 2286 - 745 - 64 - 20 - - - 2319.5 - 755 - - - - - - - - true - Script input width. - f4ca3577-e0dc-42fa-8923-d574fb19c330 - width - width - true - 0 - true - bbcbfdee-5b0e-4c92-bf29-b5811037ea03 - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 2286 - 765 - 64 - 20 - - - 2319.5 - 775 - - - - - - - - true - Script input cone_angle. - b96b8906-afc8-48f4-bd18-9fb45011a64d - cone_angle - cone_angle - true - 0 - true - 3ee8dc00-1eea-48ba-bc11-c2d1911c58a5 - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 2286 - 785 - 64 - 20 - - - 2319.5 - 795 - - - - - - - - true - Script input start_y. - 60f8fabd-f617-45e4-b530-2b80ab86ccd5 - start_y - start_y - true - 0 - true - e1131cec-2fb2-499e-93e5-55dce618ee47 - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 2286 - 805 - 64 - 20 - - - 2319.5 - 815 - - - - - - - - true - Script input rotation. - 0061a1c5-fb5e-4201-8fb0-ba12e32ff71e - rotation - rotation - true - 0 - true - 78334c0a-357d-4e7c-b3e4-fc940bcf9f1c - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 2286 - 825 - 64 - 20 - - - 2319.5 - 835 - - - - - - - - true - Script input farddoodle. - 9ba1246e-d991-44da-b36d-c30352fd34b8 - farddoodle - farddoodle - true - 0 - true - 0 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 2286 - 845 - 64 - 20 - - - 2319.5 - 855 - - - - - - - - The execution information, as output and error streams - fb496e59-6b43-4266-9c61-c466f3a89f8e - out - out - false - 0 - - - - - - 2380 - 685 - 57 - 60 - - - 2408.5 - 715 - - - - - - - - Script output geometry. - 188326e4-b130-4230-9b7f-f89e9a5dca84 - geometry - geometry - false - 0 - - - - - - 2380 - 745 - 57 - 60 - - - 2408.5 - 775 - - - - - - - - Script output BTLx. - 8674ed0a-6d18-41d1-9209-ae7aed0e558d - BTLx - BTLx - false - 0 - - - - - - 2380 - 805 - 57 - 60 - - - 2408.5 - 835 - - - - - - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - a31a3c97-3e91-47a8-add8-793f530b94e1 - Panel - - false - 0.88918887078762054 - ec68082b-6816-42e0-b242-ac0746b13092 - 1 - G:\Shared drives\2024_MAS\T2\03_finalization\Fabrication - Joints\BTLx\step_joint_joint_test.btlx - - - - - - 2346 - 919 - 455 - 420 - - 0 - 0 - 0 - - 2346.569 - 919.1592 - - - - - - - 255;255;250;90 - - true - true - true - false - true - D:\Papachap\Desktop\BTLx\dovetail_joint.btlx - true - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - dfdc288d-17d2-4daf-93bc-82b8f3f1816b - true - Panel - DovetailTenon BTLx Params - false - 0 - 6d4fe408-c656-48f6-88c9-67f2fbcdb1df - 1 - Double click to edit panel content… - - - - - - 2116 - 914 - 212 - 414 - - 0 - 0 - 0 - - 2116.989 - 914.9553 - - - - - - - 255;255;255;255 - - true - true - true - false - false - true - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - 1efbf060-c389-495d-aacf-3ce7dc0fcafc - true - Panel - StepJointNotch BTLx Params - false - 0 - 83bdcfa8-afbb-420d-9faa-98a158aee68d - 1 - Double click to edit panel content… - - - - - - 2813 - 920 - 212 - 418 - - 0 - 0 - 0 - - 2813.919 - 920.4133 - - - - - - - 255;255;255;255 - - true - true - true - false - false - true - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - d0efa1ab-d893-4335-8af7-dd6d94484ea7 - Panel - - false - 0.02266642265021801 - fb496e59-6b43-4266-9c61-c466f3a89f8e - 1 - Double click to edit panel content… - - - - - - 2285 - 584 - 370 - 107 - - 0 - 0 - 0 - - 2285.144 - 584.7254 - - - - - - - 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 - 20be8b4b-0eba-41a5-8f13-25defa3e633d - d0efa1ab-d893-4335-8af7-dd6d94484ea7 - 9f3e0877-7fa6-4696-83ae-f6281f1d75f8 - 3c27b464-0da3-49d8-922b-780384eb4127 - ba663821-ec0e-4ff9-9124-fe98533cab66 - 97e9efc3-9035-45ee-bac9-e1c0876defe3 - 47c9ac3d-5335-4e4b-8cf3-b22cd1284a8e - e9fbb74f-6b87-4a1e-a684-8202331f1480 - f11ad7e4-429f-4eac-92db-ff79b89a4fa3 - f02972d5-c58c-4216-b53b-7f078d1f7fdc - 5b8e4ee4-cb19-450a-ba61-866a3686f2b2 - c6f9d24c-2b1e-4276-8e76-0fd2049e3d3a - 12 - c6445b86-caf6-4180-b0be-5dcfc6eaea9a - Group - - - - - - - - - - - 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe - Scribble - - - - - true - - 2383.265 - 573.3698 - - - 2722.865 - 573.3698 - - - 2722.865 - 610.7477 - - - 2383.265 - 610.7477 - - A quick note - Microsoft Sans Serif - 9f3e0877-7fa6-4696-83ae-f6281f1d75f8 - false - Scribble - Scribble - 50 - TDovetailJoint - - - - - - 2378.265 - 568.3698 - 349.5996 - 47.37793 - - - 2383.265 - 573.3698 - - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - 9f3e0877-7fa6-4696-83ae-f6281f1d75f8 - 1 - 3c27b464-0da3-49d8-922b-780384eb4127 - Group - - - - - - - - - - - 537b0419-bbc2-4ff4-bf08-afe526367b2c - Custom Preview - - - - - Allows for customized geometry previews - true - false - ba663821-ec0e-4ff9-9124-fe98533cab66 - Custom Preview - Preview - - - - - - - 2726 - 811 - 64 - 44 - - - 2776 - 833 - - - - - - Geometry to preview - true - c34e1843-bfd6-4a82-b983-7194c9f9c18c - Geometry - G - false - e9fbb74f-6b87-4a1e-a684-8202331f1480 - 1 - - - - - - 2728 - 813 - 33 - 20 - - - 2754 - 823 - - - - - - - - The material override - 710c97a8-7564-4390-af09-089f9958717d - 1 - Material - M - false - d5779e9d-d95c-4279-bd0c-9036111f46eb - 1 - - - - - - 2728 - 833 - 33 - 20 - - - 2754 - 843 - - - - - - 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 - 97e9efc3-9035-45ee-bac9-e1c0876defe3 - Brep Edges - Edges - - - - - - 2620 - 741 - 72 - 64 - - - 2650 - 773 - - - - - - Base Brep - d76deb57-3846-4215-a6d3-b4cc65f5f623 - Brep - B - false - e9fbb74f-6b87-4a1e-a684-8202331f1480 - 1 - - - - - - 2622 - 743 - 13 - 60 - - - 2630 - 773 - - - - - - - - 1 - Naked edge curves - d6302059-08b9-4456-a7f4-fc4b73a03458 - Naked - En - false - 0 - - - - - - 2665 - 743 - 25 - 20 - - - 2677.5 - 753 - - - - - - - - 1 - Interior edge curves - 8db6122b-9378-4026-a86e-58c5dd430f2a - Interior - Ei - false - 0 - - - - - - 2665 - 763 - 25 - 20 - - - 2677.5 - 773 - - - - - - - - 1 - Non-Manifold edge curves - 0c2574f5-76b7-475f-80aa-c87143496df3 - Non-Manifold - Em - false - 0 - - - - - - 2665 - 783 - 25 - 20 - - - 2677.5 - 793 - - - - - - - - - - - - a77d0879-94c2-4101-be44-e4a616ffeb0c - 5f86fa9f-c62b-50e8-157b-b454ef3e00fa - Custom Preview Lineweights - - - - - Custom Preview with Lineweights - true - 47c9ac3d-5335-4e4b-8cf3-b22cd1284a8e - Custom Preview Lineweights - PreviewLW - - - - - - - 2726 - 721 - 62 - 84 - - - 2774 - 763 - - - - - - Geometry to preview - true - b386acb8-8321-49bf-ac12-f062d85c969d - Geometry - G - false - 8db6122b-9378-4026-a86e-58c5dd430f2a - 1 - - - - - - 2728 - 723 - 31 - 20 - - - 2753 - 733 - - - - - - - - The preview shader override - 11af4056-9698-4b92-b067-fae857f62252 - 2 - Shader - S - false - d5779e9d-d95c-4279-bd0c-9036111f46eb - 1 - - - - - - 2728 - 743 - 31 - 20 - - - 2753 - 753 - - - - - - 1 - - - - - 1 - {0} - - - - - - 255;255;105;180 - - - 255;76;32;54 - - 0.5 - - 255;255;255;255 - - 0 - - - - - - - - - - - The thickness of the wire display - f4113c88-a8ac-49cd-a656-a1e84f635519 - Thickness - T - true - 0 - - - - - - 2728 - 763 - 31 - 20 - - - 2753 - 773 - - - - - - - - Set to true to try to render curves with an absolute dimension. - 56fb3908-c9cb-478b-be37-49785e21754d - Absolute - A - false - 0 - - - - - - 2728 - 783 - 31 - 20 - - - 2753 - 793 - - - - - - 1 - - - - - 1 - {0} - - - - - false - - - - - - - - - - - - - - - 919e146f-30ae-4aae-be34-4d72f555e7da - Brep - - - - - Contains a collection of Breps (Boundary REPresentations) - true - e9fbb74f-6b87-4a1e-a684-8202331f1480 - Brep - Brep - false - 188326e4-b130-4230-9b7f-f89e9a5dca84 - 1 - - - - - - 2534 - 763 - 50 - 24 - - - 2559.388 - 775.3219 - - - - - - - - - - 9c53bac0-ba66-40bd-8154-ce9829b9db1a - Colour Swatch - - - - - Colour (palette) swatch - f11ad7e4-429f-4eac-92db-ff79b89a4fa3 - Colour Swatch - Swatch - false - 0 - - 29;0;102;255 - - - - - - - 2517 - 811 - 88 - 20 - - - 2517.752 - 811.7673 - - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - ba663821-ec0e-4ff9-9124-fe98533cab66 - 97e9efc3-9035-45ee-bac9-e1c0876defe3 - 47c9ac3d-5335-4e4b-8cf3-b22cd1284a8e - e9fbb74f-6b87-4a1e-a684-8202331f1480 - f11ad7e4-429f-4eac-92db-ff79b89a4fa3 - 5b8e4ee4-cb19-450a-ba61-866a3686f2b2 - c6f9d24c-2b1e-4276-8e76-0fd2049e3d3a - 7 - f02972d5-c58c-4216-b53b-7f078d1f7fdc - Group - GEOMETRY - - - - - - - - - - 9c53bac0-ba66-40bd-8154-ce9829b9db1a - Colour Swatch - - - - - Colour (palette) swatch - 5b8e4ee4-cb19-450a-ba61-866a3686f2b2 - Colour Swatch - Swatch - false - 0 - - 34;240;180;137 - - - - - - - 2517 - 835 - 88 - 20 - - - 2517.514 - 835.4163 - - - - - - - - - - c9785b8e-2f30-4f90-8ee3-cca710f82402 - Entwine - - - - - Flatten and combine a collection of data streams - true - true - c6f9d24c-2b1e-4276-8e76-0fd2049e3d3a - Entwine - Entwine - - - - - - 2619 - 808 - 79 - 44 - - - 2664 - 830 - - - - - - 2 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 1 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - - - - - 2 - Data to entwine - f1b60494-3bf8-4181-99bd-69acd3c3059a - false - Branch {0;0} - {0;0} - true - f11ad7e4-429f-4eac-92db-ff79b89a4fa3 - 1 - - - - - - 2621 - 810 - 28 - 20 - - - 2636.5 - 820 - - - - - - - - 2 - Data to entwine - 56b1c6dd-1a2e-4764-8c90-316095f2007a - false - Branch {0;1} - {0;1} - true - 5b8e4ee4-cb19-450a-ba61-866a3686f2b2 - 1 - - - - - - 2621 - 830 - 28 - 20 - - - 2636.5 - 840 - - - - - - - - Entwined result - d5779e9d-d95c-4279-bd0c-9036111f46eb - Result - R - false - 0 - - - - - - 2679 - 810 - 17 - 40 - - - 2687.5 - 830 - - - - - - - - - - - - - - 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 DovetailTenon -from compas_timber._fabrication import DovetailTenonParams -from compas_timber._fabrication import DovetailMortise -from compas_timber._fabrication import DovetailMortiseParams - -from compas_timber.connections import Joint -from compas_timber.connections.utilities import beam_ref_side_incidence, beam_ref_side_incidence_with_vector - -from compas_timber.model import TimberModel -from compas_timber.fabrication import BTLx - -from compas.geometry import Point, intersection_line_line, angle_vectors, angle_vectors_signed - -from compas_rhino import unload_modules -from compas.scene import SceneObject - -import math - -from compas_rhino.conversions import frame_to_rhino, plane_to_rhino, vector_to_rhino, surface_to_rhino, polyline_to_rhino, brep_to_rhino, point_to_rhino, surface_to_rhino - -import Rhino.Geometry as rg -unload_modules("compas_timber") - -geo_tenon = main_beam.compute_geometry(False) -geo_mortise = cross_beam.compute_geometry(False) - -#define ref_sides -cross_ref_side_dict = beam_ref_side_incidence(main_beam, cross_beam, ignore_ends=True) -cross_ref_side_index = min(cross_ref_side_dict, key=cross_ref_side_dict.get) -print(cross_ref_side_index, "cross") -cross_ref_side_normal = cross_beam.ref_sides[cross_ref_side_index].normal -main_ref_side_dict = beam_ref_side_incidence_with_vector(main_beam, cross_ref_side_normal, ignore_ends=True) -main_ref_side_index = min(main_ref_side_dict, key=main_ref_side_dict.get) -print(main_ref_side_index, "main") - -ref_side_main = frame_to_rhino(main_beam.ref_sides[main_ref_side_index]) -ref_side_cross = frame_to_rhino(cross_beam.ref_sides[cross_ref_side_index]) - -#create dovetail_tenon -DovetailTenon.define_dovetail_tool(15.0, 60.034, 28.0) -dovetail_tenon = DovetailTenon.from_plane_and_beam( - cross_beam.ref_sides[cross_ref_side_index], - main_beam, - start_y=start_y, - rotation=rotation, - start_depth=start_depth, - width=width, - length=length, - cone_angle=cone_angle, - ref_side_index=main_ref_side_index, - ) - -#cutting_frame -cutting_plane_tenon= dovetail_tenon.frame_from_params_and_beam(main_beam) -#tenon cutting planes -dovetail_tenon_planes = dovetail_tenon.dovetail_cutting_planes_from_params_and_beam(main_beam) -#tenon volume -tenon_volume = dovetail_tenon.dovetail_volume_from_params_and_beam(main_beam) - - -dovetail_mortise = DovetailMortise.from_frame_and_beam( - frame=cutting_plane_tenon, - beam=cross_beam, - start_depth=0.0, - angle=rotation, - length=dovetail_tenon.length, - width=dovetail_tenon.width, - depth=dovetail_tenon.height, - cone_angle=dovetail_tenon.cone_angle, - flank_angle=dovetail_tenon.flank_angle, - shape=dovetail_tenon.shape, - shape_radius=dovetail_tenon.shape_radius, - ref_side_index=cross_ref_side_index, - ) -#cutting frame -cutting_plane_mortise = dovetail_mortise.frame_from_params_and_beam(cross_beam) -#mortise cutting planes -dovetail_mortise_planes = dovetail_mortise.dovetail_cutting_planes_from_params_and_beam(cross_beam) -#mortise volue -mortise_volume = dovetail_mortise.dovetail_volume_from_params_and_beam(cross_beam) - -#get btlx params -dovetail_mortise_params = DovetailMortiseParams(dovetail_mortise).as_dict() -mortise_btlx_params = [] -for key, value in dovetail_mortise_params.items(): - mortise_btlx_params.append("{0}: {1}".format(key, value)) - -#get btlx params -dovetail_tenon_params = DovetailTenonParams(dovetail_tenon).as_dict() -tenon_btlx_params = [] -for key, value in dovetail_tenon_params.items(): - tenon_btlx_params.append("{0}: {1}".format(key, value)) - - -#vizualize in rhino - -cutting_plane_tenon = frame_to_rhino(cutting_plane_tenon) -cutting_plane_mortise = frame_to_rhino(cutting_plane_mortise) - -tenon_planes = [frame_to_rhino(plane) for plane in dovetail_tenon_planes] -mortise_planes = [frame_to_rhino(plane) for plane in dovetail_mortise_planes] - -geo_tenon = brep_to_rhino(dovetail_tenon.apply(geo_tenon, main_beam)) -geo_mortise = brep_to_rhino(dovetail_mortise.apply(geo_mortise, cross_beam)) - -#mortise = brep_to_rhino(mortise_volume) - - GhPython provides a Python script component - - 178 - 222 - - - 1586 - 781 - - true - false - false - 071ab375-9118-4d58-aba2-a9de6de2f088 - false - true - GhPython Script - Python - - - - - - 1636 - 76 - 214 - 204 - - - 1717 - 178 - - - - - - 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 - 10 - 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 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - - - - - true - Script variable Python - e17658fc-3064-4e83-9c8d-2ca7d71257bd - cross_beam - cross_beam - true - 0 - true - 11e2a181-d4ed-41f3-a20a-fdcafcd837a0 - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 1638 - 78 - 64 - 25 - - - 1671.5 - 90.5 - - - - - - - - true - Script input main_beam. - c5907a16-b1b8-4c71-bdc0-ccca293ad70f - main_beam - main_beam - true - 0 - true - 90fae02f-7750-462d-828f-cf5f2a0d39ae - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 1638 - 103 - 64 - 25 - - - 1671.5 - 115.5 - - - - - - - - true - Script input start_depth. - 004aac7d-efce-4814-98f9-6d6581b11a4a - start_depth - start_depth - true - 0 - true - c3c1dc6d-7ceb-4d7f-add6-fa924b4cc936 - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 1638 - 128 - 64 - 25 - - - 1671.5 - 140.5 - - - - - - - - true - Script input width. - b76082c7-47ee-49e6-90a5-7fed960a32bb - width - width - true - 0 - true - ab977350-6a8d-472b-9276-52a400da755b - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 1638 - 153 - 64 - 25 - - - 1671.5 - 165.5 - - - - - - - - true - Script input length. - 3e9be09b-b9b1-46ae-88bd-2a68cff46e13 - length - length - true - 0 - true - 244dd1d8-93d4-4afc-851d-064a07e08680 - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 1638 - 178 - 64 - 25 - - - 1671.5 - 190.5 - - - - - - - - true - Script input cone_angle. - 77eebdf9-6c87-4e51-b360-dd5f773e8cd2 - cone_angle - cone_angle - true - 0 - true - 1f382d1c-8a89-4e8a-8102-597801cd81a3 - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 1638 - 203 - 64 - 25 - - - 1671.5 - 215.5 - - - - - - - - true - Script input start_y. - 05be9a7a-6224-49b3-bcf0-791c623f7f77 - start_y - start_y - true - 0 - true - 89a39aa2-89d0-4ad6-9043-6ef61b51023c - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 1638 - 228 - 64 - 25 - - - 1671.5 - 240.5 - - - - - - - - true - Script input rotation. - 09a29b2e-a2b5-4147-81d7-21fa818dc6cc - rotation - rotation - true - 0 - true - 5a7f3b31-fffa-478e-b8ef-7eb827144b57 - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 1638 - 253 - 64 - 25 - - - 1671.5 - 265.5 - - - - - - - - The execution information, as output and error streams - fb966008-8d47-4262-8c09-ce71985833b0 - out - out - false - 0 - - - - - - 1732 - 78 - 116 - 20 - - - 1790 - 88 - - - - - - - - Script output cutting_plane_tenon. - 213adbf5-0592-48ab-b06a-06543b55b8da - cutting_plane_tenon - cutting_plane_tenon - false - 0 - - - - - - 1732 - 98 - 116 - 20 - - - 1790 - 108 - - - - - - - - Script output cutting_plane_mortise. - cc5eda18-08de-4b0d-91bd-9eefbfcc5dc7 - cutting_plane_mortise - cutting_plane_mortise - false - 0 - - - - - - 1732 - 118 - 116 - 20 - - - 1790 - 128 - - - - - - - - Script output ref_side_main. - d7c2e387-1413-47f3-96a4-1fd6a08f1e62 - ref_side_main - ref_side_main - false - 0 - - - - - - 1732 - 138 - 116 - 20 - - - 1790 - 148 - - - - - - - - Script output ref_side_cross. - a8110476-8bb3-4892-9423-09704614c7a3 - ref_side_cross - ref_side_cross - false - 0 - - - - - - 1732 - 158 - 116 - 20 - - - 1790 - 168 - - - - - - - - Script output mortise_btlx_params. - 83bdcfa8-afbb-420d-9faa-98a158aee68d - mortise_btlx_params - mortise_btlx_params - false - 0 - - - - - - 1732 - 178 - 116 - 20 - - - 1790 - 188 - - - - - - - - Script output tenon_btlx_params. - 6d4fe408-c656-48f6-88c9-67f2fbcdb1df - tenon_btlx_params - tenon_btlx_params - false - 0 - - - - - - 1732 - 198 - 116 - 20 - - - 1790 - 208 - - - - - - - - Script output geo_tenon. - be1a6a99-5e4d-460c-a8f0-e8312a661132 - geo_tenon - geo_tenon - false - 0 - - - - - - 1732 - 218 - 116 - 20 - - - 1790 - 228 - - - - - - - - Script output geo_mortise. - 389410e6-fbd0-4b13-ad00-528c4c2075fd - geo_mortise - geo_mortise - false - 0 - - - - - - 1732 - 238 - 116 - 20 - - - 1790 - 248 - - - - - - - - Script output mortise. - c5450653-c419-4dd1-ba43-0725a7758699 - mortise - mortise - false - 0 - - - - - - 1732 - 258 - 116 - 20 - - - 1790 - 268 - - - - - - - - - - - - - - 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 - Plane - - - - - Contains a collection of three-dimensional axis-systems - f1db2a34-33d7-489c-af3c-6723cd9cafed - Plane - Pln - false - d7c2e387-1413-47f3-96a4-1fd6a08f1e62 - 1 - - - - - - 1882 - 143 - 50 - 24 - - - 1907.574 - 155.2027 - - - - - - - - - - d3d195ea-2d59-4ffa-90b1-8b7ff3369f69 - Unit Y - - - - - Unit vector parallel to the world {y} axis. - true - 780dd7ff-1451-4d20-b77b-f1c386f8a9ed - Unit Y - Y - - - - - - -202 - 675 - 63 - 28 - - - -173 - 689 - - - - - - Unit multiplication - f46970bc-a15b-434c-931c-2ba17d942c80 - Factor - F - false - 27b7a426-ec72-4334-8c70-78c50fb834e2 - 1 - - - - - - -200 - 677 - 12 - 24 - - - -192.5 - 689 - - - - - - 1 - - - - - 1 - {0} - - - - - 1 - - - - - - - - - - - World {y} vector - 7a214201-5ed9-46c9-afe6-bf48e768f870 - Unit vector - V - false - 0 - - - - - - -158 - 677 - 17 - 24 - - - -149.5 - 689 - - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 27b7a426-ec72-4334-8c70-78c50fb834e2 - Number Slider - - false - 0 - - - - - - -391 - 680 - 163 - 20 - - - -390.1428 - 680.1044 - - - - - - 3 - 1 - 1 - 4000 - 0 - 0 - 0 - - - - - - - - - b6236720-8d88-4289-93c3-ac4c99f9b97b - Relay - - - - - 2 - A wire relay object - 11e2a181-d4ed-41f3-a20a-fdcafcd837a0 - Relay - - false - 3984d0df-294e-462f-b103-b87bb94e3021 - 1 - - - - - - 1532 - 78 - 40 - 16 - - - 1552 - 86 - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 244dd1d8-93d4-4afc-851d-064a07e08680 - Number Slider - length - false - 0 - - - - - - 1405 - 180 - 188 - 20 - - - 1405.231 - 180.6459 - - - - - - 3 - 1 - 1 - 200 - 0 - 0 - 60 - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - 2b407bc7-5cf8-4769-888d-66de2e16c241 - Panel - - false - 1 - fb966008-8d47-4262-8c09-ce71985833b0 - 1 - Double click to edit panel content… - - - - - - 1350 - -64 - 513 - 121 - - 0 - 0 - 0 - - 1350.064 - -63.0608 - - - - - - - 255;255;250;90 - - true - true - true - false - false - true - - - - - - - - - 0148a65d-6f42-414a-9db7-9a9b2eb78437 - Brep Edges - - - - - Extract the edge curves of a brep. - true - 1771f48a-32bc-4ec4-a491-a17a3372bf88 - Brep Edges - Edges - - - - - - 1207 - 428 - 72 - 64 - - - 1237 - 460 - - - - - - Base Brep - 12303237-bf2d-4c37-8f21-77c88e2212c3 - Brep - B - false - b0a6568e-06d8-4c68-b393-d8274f661640 - 1 - - - - - - 1209 - 430 - 13 - 60 - - - 1217 - 460 - - - - - - - - 1 - Naked edge curves - 9d38d3ad-c615-4e0c-9887-f61b66e89609 - Naked - En - false - 0 - - - - - - 1252 - 430 - 25 - 20 - - - 1264.5 - 440 - - - - - - - - 1 - Interior edge curves - 4669d49b-b906-42b2-9f31-ddced1ed687a - Interior - Ei - false - 0 - - - - - - 1252 - 450 - 25 - 20 - - - 1264.5 - 460 - - - - - - - - 1 - Non-Manifold edge curves - 9df9e457-8774-4250-9633-480660cd74b1 - Non-Manifold - Em - false - 0 - - - - - - 1252 - 470 - 25 - 20 - - - 1264.5 - 480 - - - - - - - - - - - - 919e146f-30ae-4aae-be34-4d72f555e7da - Brep - - - - - Contains a collection of Breps (Boundary REPresentations) - 5c4473da-8ccb-4a9f-8e42-e0447b1eaa1e - Brep - Brep - false - 0 - - - - - - 1881 - 203 - 50 - 24 - - - 1906.776 - 215.0259 - - - - - - - - - - 0148a65d-6f42-414a-9db7-9a9b2eb78437 - Brep Edges - - - - - Extract the edge curves of a brep. - true - 4e2a1cbf-d18f-4fe9-8794-b8b9b5231f50 - Brep Edges - Edges - - - - - - 1206 - 588 - 72 - 64 - - - 1236 - 620 - - - - - - Base Brep - 500ce405-e491-465b-930c-ffb6ef47822c - Brep - B - false - 55c66290-a177-4518-824a-6a531a1e8086 - 1 - - - - - - 1208 - 590 - 13 - 60 - - - 1216 - 620 - - - - - - - - 1 - Naked edge curves - c03958c4-925a-40e8-b29d-7363a45c43bd - Naked - En - false - 0 - - - - - - 1251 - 590 - 25 - 20 - - - 1263.5 - 600 - - - - - - - - 1 - Interior edge curves - 3d9ed233-4f5c-4cc4-b393-8cc7cf7457fe - Interior - Ei - false - 0 - - - - - - 1251 - 610 - 25 - 20 - - - 1263.5 - 620 - - - - - - - - 1 - Non-Manifold edge curves - 37f9aefb-3c7e-4731-b6c7-692870e8c6ec - Non-Manifold - Em - false - 0 - - - - - - 1251 - 630 - 25 - 20 - - - 1263.5 - 640 - - - - - - - - - - - - f31d8d7a-7536-4ac8-9c96-fde6ecda4d0a - Cluster - - - - - - 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 - - Contains a cluster of Grasshopper components - true - bc365232-0216-46dd-a05a-493450f8e675 - Cluster - Cluster - false - - - - - 1 - 6f220e32-ede9-4588-85dd-6f6d0925be60 - 2c214118-98c8-4e19-a17e-3d29b171a059 - - - - - - 1969 - 216 - 60 - 28 - - - 2015 - 230 - - - - - - 1 - 919e146f-30ae-4aae-be34-4d72f555e7da - 0 - - - - - Contains a collection of Breps (Boundary REPresentations) - true - 6f220e32-ede9-4588-85dd-6f6d0925be60 - Brep - Brep - true - 5c4473da-8ccb-4a9f-8e42-e0447b1eaa1e - 1 - - - - - - 1971 - 218 - 29 - 24 - - - 1987 - 230 - - - - - - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - f2af4f17-9955-4d61-93cd-76e0d692f241 - Panel - BTLx Params - false - 0 - 83bdcfa8-afbb-420d-9faa-98a158aee68d - 1 - Double click to edit panel content… - - - - - - 2239 - -241 - 206 - 333 - - 0 - 0 - 0 - - 2239.95 - -240.1865 - - - - - - - 255;255;255;255 - - true - true - true - false - false - true - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;56;56 - - A group of Grasshopper objects - f2af4f17-9955-4d61-93cd-76e0d692f241 - 1 - 02293eca-caf6-4507-8376-6b1f1bbf6472 - Group - - - - - - - - - - - 919e146f-30ae-4aae-be34-4d72f555e7da - Brep - - - - - Contains a collection of Breps (Boundary REPresentations) - 17656a19-e22f-448a-b26f-e7d025b96e6f - Brep - Brep - false - be1a6a99-5e4d-460c-a8f0-e8312a661132 - 1 - - - - - - 1880 - 250 - 50 - 24 - - - 1905.77 - 262.0995 - - - - - - - - - - d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 - Curve - - - - - Contains a collection of generic curves - true - 2ace07a8-3cff-4c52-b37f-cd3e591aeddd - Curve - Crv - false - b37fb167-edb3-4a28-b8fd-a498a7811210 - 1 - - - - - - 320 - 595 - 50 - 24 - - - 345.5917 - 607.4064 - - - - - - 1 - - - - - 1 - {0} - - - - - -1 - - Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyNy4bxpcrDPvOXz4/18+rHjlAagcQwpU3KHb70cS13q4OBMDAuxtjlpjZzvZAeSS6oIuv//1TA0wOW6GwQQA - - 00000000-0000-0000-0000-000000000000 - - - - - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - 2ace07a8-3cff-4c52-b37f-cd3e591aeddd - ca0ea429-34fb-4ce1-a30e-2c14ddc1552e - 2 - e0450338-f168-4770-aeb4-8e3b1b320b54 - Group - - - - - - - - - - - 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 - Plane - - - - - Contains a collection of three-dimensional axis-systems - 405d1b89-3c83-4839-aa6a-7e9ca46c1aad - Plane - Pln - false - 213adbf5-0592-48ab-b06a-06543b55b8da - 1 - - - - - - 1882 - 54 - 50 - 24 - - - 1907.971 - 66.13251 - - - - - - 1 - - - - - 1 - {0;0} - - - - - - 31287.423274001 - -3231.69101859564 - 48.2812000254933 - -0.259942858411819 - -0.929978182927627 - 0.259942858411848 - 0.963085199245858 - -0.269196766313353 - -1.70731025626947E-15 - - - - - - - - - - - - - - 2a3f7078-2e25-4dd4-96f7-0efb491bd61c - Vector Display - - - - - false - 0 - Preview vectors in the viewport - 0.1 - 15 - 46f3ebed-d260-45ff-81a6-62a31526fd14 - Vector Display - VDis - - - - - 3 - false - false - - - - - - 255;255;0;0 - - - 255;255;0;0 - - 0 - d0118fff-b195-4eeb-a27a-c2272bc6d756 - - - - - - 255;255;165;0 - - - 255;255;165;0 - - 0.5 - fac92592-5639-4b42-ba35-fbddafa8c63c - - - - - - 255;124;252;0 - - - 255;124;252;0 - - 1 - 6cf11a22-adb8-4caf-8bcb-23b1fa704b5d - - - - - - - - 794 - 464 - 61 - 44 - - - 841 - 486 - - - - - - Anchor point for preview vector - 5df1f47b-dea7-432b-bc6a-2040fee0fa83 - Anchor - A - true - 7542c648-8889-4d83-8f10-9e8b260fa85a - 1 - - - - - - 796 - 466 - 30 - 20 - - - 820.5 - 476 - - - - - - - - Vector to preview - 904658e2-ff3e-49c1-9c42-4f56b7d4805b - x*75 - Vector - V - true - 4c90d06e-9810-41a6-baa8-91b753ccec55 - 1 - - - - - - 796 - 486 - 30 - 20 - - - 820.5 - 496 - - - - - - - - - - - - 2a5cfb31-028a-4b34-b4e1-9b20ae15312e - Cross Product - - - - - Compute vector cross product. - true - 4dfed18b-2ae2-4401-932a-d35c5687b48f - Cross Product - XProd - - - - - - 672 - 510 - 66 - 64 - - - 704 - 542 - - - - - - First vector - 20c07560-21cb-462a-913e-33c8dfba4f1a - Vector A - A - false - 36c4deda-ceed-4920-a3f3-2d18ca613b35 - 1 - - - - - - 674 - 512 - 15 - 20 - - - 683 - 522 - - - - - - - - Second vector - d792952b-8d14-4258-93a8-f657e9d4e328 - Vector B - B - false - d2d51328-18f6-4ef3-8dd6-1df6b6af922e - 1 - - - - - - 674 - 532 - 15 - 20 - - - 683 - 542 - - - - - - - - Unitize output - ec1aee98-3178-4b5f-8943-45ff0468d2ad - Unitize - U - false - 0 - - - - - - 674 - 552 - 15 - 20 - - - 683 - 562 - - - - - - 1 - - - - - 1 - {0} - - - - - false - - - - - - - - - - - Cross product vector - 4c90d06e-9810-41a6-baa8-91b753ccec55 - Vector - V - false - 0 - - - - - - 719 - 512 - 17 - 30 - - - 727.5 - 527 - - - - - - - - Vector length - 6cfe60aa-eede-4d54-9b2b-e48c3287be06 - Length - L - false - 0 - - - - - - 719 - 542 - 17 - 30 - - - 727.5 - 557 - - - - - - - - - - - - 9103c240-a6a9-4223-9b42-dbd19bf38e2b - Unit Z - - - - - Unit vector parallel to the world {z} axis. - true - e98b3a90-fae4-407f-a38e-3f9d806bc67d - Unit Z - Z - - - - - - 313 - 412 - 63 - 28 - - - 342 - 426 - - - - - - Unit multiplication - 99a90f24-1411-4423-854c-1d9440888867 - Factor - F - false - 0 - - - - - - 315 - 414 - 12 - 24 - - - 322.5 - 426 - - - - - - 1 - - - - - 1 - {0} - - - - - 1 - - - - - - - - - - - World {z} vector - 3fa223fc-b370-43ff-9286-d236dfc1155a - Unit vector - V - false - 0 - - - - - - 357 - 414 - 17 - 24 - - - 365.5 - 426 - - - - - - - - - - - - 410755b1-224a-4c1e-a407-bf32fb45ea7e - 00000000-0000-0000-0000-000000000000 - GhPython Script - - - - - import Rhino.Geometry as rg -import math -import copy - -def rotate_vector(vector, angle, axis, point): - angle_rad = math.radians(angle) - vec_trans = rg.Transform.Rotation(angle_rad, axis.Direction, point) - rotated_vector = rg.Vector3d(vector) - rotated_vector.Transform(vec_trans) - return rotated_vector - -def sort_list(lst, key=None, reverse=False): - return sorted(lst, key=key, reverse=reverse) - - -def new_shifted_lines(main_centerline, cross_centerline, normal_cross): - - param = rg.Intersect.Intersection.LineLine(main_centerline, cross_centerline)[2] - int_point = cross_centerline.PointAt(param) - - ### Get normal vectors in all directions - all_vectors = [] - for i in range(4): - normal = rotate_vector(normal_cross, i*90, cross_centerline, int_point) - all_vectors.append(normal) - - ### Get angles between main centerline and all vectors - vec_angles = [] - for vec in all_vectors: - plane = rg.Plane(int_point, all_vectors[0], all_vectors[1]) - vec_angle = rg.Vector3d.VectorAngle(main_centerline.Direction, vec, plane) - vec_angles.append(vec_angle) - - ### Sort vectors based on angles - fisrt_vec_angle_pairs = list(zip(all_vectors, vec_angles)) - first_sorted_vec_angle_pairs = sort_list(fisrt_vec_angle_pairs, key=lambda x: x[1]) - - sorted_angles = [abs((math.pi/2)-sg) for sg in vec_angles] - second_vec_angle_pairs = list(zip(all_vectors, sorted_angles)) - second_sorted_vec_angle_pairs = sort_list(second_vec_angle_pairs, key=lambda x: x[1], reverse=True ) - - - ### if the angle between the main centerline and the normal vector of the cross centerline is greater than 45 degrees, shift the main centerline to the right - if min(vec_angles) > math.pi/4: - x = (math.pi*2) - max(vec_angles) - length = abs((((beam_width)/2)/math.cos(x)+(math.tan(x)*((beam_width)/2)))-((beam_width)/2)) - print ("offset_length: ", length) - second_sorted_vectors = [pair[0] for pair in second_sorted_vec_angle_pairs] - selected_products = [] - for i, vecs in enumerate(second_sorted_vectors): - if i%2 == 1: - selected_products.append(rg.Vector3d.Multiply(main_centerline.Direction, vecs)) - index = selected_products.index(min(selected_products)) - if index == 0: - shift_vector = second_sorted_vectors[1] - else: - shift_vector = second_sorted_vectors[3] - shift_vector.Unitize() - shift_length = (length) * shift_vector - s_pt_to_move = copy.deepcopy(main_centerline.From) - new_start_point = s_pt_to_move + shift_length - new_line = rg.Line(new_start_point, main_centerline.To) - - ### if the angle between the main centerline and the normal vector of the cross centerline is less than 45 degrees, shift the main centerline to the left - else: - min_vec_angle = abs(min(vec_angles)) - if min_vec_angle > 1: - x = min(vec_angles) % (2 * math.pi) - else: - x = min(vec_angles) - length = abs((((beam_width)/2)/math.cos(x)+(math.tan(x)*((beam_width)/2)))-((beam_width)/2)) - print ("offset_length: ", length) - first_sorted_vectors = [pair[0] for pair in first_sorted_vec_angle_pairs] - selected_products = [] - for i, vecs in enumerate(first_sorted_vectors): - if i%2 == 1: - selected_products.append(rg.Vector3d.Multiply(main_centerline.Direction, vecs)) - index = selected_products.index(min(selected_products)) - if index == 0: - shift_vector = first_sorted_vectors[1] - else: - shift_vector = first_sorted_vectors[3] - shift_vector.Unitize() - shift_length = (length) * shift_vector - s_pt_to_move = copy.deepcopy(main_centerline.From) - new_start_point = s_pt_to_move + shift_length - new_line = rg.Line(new_start_point, main_centerline.To) - - print(length) - return new_line, shift_vector, length - -eccentricity_line, shift_vector, length = new_shifted_lines(main_centerline, cross_centerline, normal_cross) - - -e = rg.Vector3d.VectorAngle(-new_line.Direction, main_centerline.Direction) -error_length = ((math.sqrt(2) * 60) * math.sin(e)) - GhPython provides a Python script component - - 94 - 147 - - - 1199 - 815 - - true - true - false - false - 667cfcd7-2db6-4d00-960b-e6e200fc891b - false - true - true - GhPython Script - Python - - - - - - 1008 - 698 - 205 - 84 - - - 1109 - 740 - - - - - - 4 - 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 - 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 - 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 - 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 - 4 - 3ede854e-c753-40eb-84cb-b48008f14fd4 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - - - - - true - Script variable Python - e26f6eb2-85f0-477b-ad84-3f5ba206efcf - true - main_centerline - main_centerline - true - 0 - true - 09fe95fb-9551-4690-abf6-4a0665002914 - 1 - f802a8cd-e699-4a94-97ea-83b5406271de - - - - - - 1010 - 700 - 84 - 20 - - - 1053.5 - 710 - - - - - - - - true - Script input cross_centerline. - 461e1986-9089-47c0-a179-1d0f268214e4 - true - cross_centerline - cross_centerline - true - 0 - true - 36c4deda-ceed-4920-a3f3-2d18ca613b35 - 1 - f802a8cd-e699-4a94-97ea-83b5406271de - - - - - - 1010 - 720 - 84 - 20 - - - 1053.5 - 730 - - - - - - - - true - Script input normal_cross. - 37b9bbe5-61ab-4d4e-94f8-d7521a2b14e7 - true - normal_cross - normal_cross - true - 0 - true - 0 - 15a50725-e3d3-4075-9f7c-142ba5f40747 - - - - - - 1010 - 740 - 84 - 20 - - - 1053.5 - 750 - - - - - - - - true - Script input beam_width. - 6c170075-c66b-47d4-8b87-88b886f172d5 - true - beam_width - beam_width - true - 0 - true - 478fc3b1-c4f8-4087-8fe6-c2905e21be9a - 1 - 87f87f55-5b71-41f4-8aea-21d494016f81 - - - - - - 1010 - 760 - 84 - 20 - - - 1053.5 - 770 - - - - - - - - The execution information, as output and error streams - 4e45fb34-2889-49d1-bf07-b5da2de1bbaa - true - out - out - false - 0 - - - - - - 1124 - 700 - 87 - 20 - - - 1167.5 - 710 - - - - - - - - Script output eccentricity_line. - 0aaaefae-ce6a-46bd-a098-afb849f637c9 - true - eccentricity_line - eccentricity_line - false - 0 - - - - - - 1124 - 720 - 87 - 20 - - - 1167.5 - 730 - - - - - - - - Script output shift_vector. - 4f86109c-f46b-4b49-9ac2-c179dadcae58 - true - shift_vector - shift_vector - false - 0 - - - - - - 1124 - 740 - 87 - 20 - - - 1167.5 - 750 - - - - - - - - Script output length. - 551bea16-0f41-4616-9a4f-418db04bc354 - true - length - length - false - 0 - - - - - - 1124 - 760 - 87 - 20 - - - 1167.5 - 770 - - - - - - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - be283d6e-d4d9-46e1-9a9d-f0f142489cc4 - Panel - Tenon BTLx Params - false - 0 - 6d4fe408-c656-48f6-88c9-67f2fbcdb1df - 1 - Double click to edit panel content… - - - - - - 2245 - 124 - 206 - 333 - - 0 - 0 - 0 - - 2245.078 - 124.5497 - - - - - - - 255;255;255;255 - - true - true - true - false - false - true - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;56;56 - - A group of Grasshopper objects - be283d6e-d4d9-46e1-9a9d-f0f142489cc4 - 1 - 87fa8c87-c926-4271-b108-197a068dafee - Group - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - bbcbfdee-5b0e-4c92-bf29-b5811037ea03 - Number Slider - width - false - 0 - - - - - - 2050 - 782 - 160 - 20 - - - 2050.36 - 782.0133 - - - - - - 3 - 1 - 1 - 200 - 0 - 0 - 25 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 3ee8dc00-1eea-48ba-bc11-c2d1911c58a5 - Number Slider - cone_angle - false - 0 - - - - - - 1970 - 807 - 240 - 20 - - - 1970.97 - 807.3304 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 10 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - b29d9bba-e05a-4fa4-91a3-bf1ac143a41d - Number Slider - length - false - 0 - - - - - - 2039 - 756 - 171 - 20 - - - 2039.322 - 756.2523 - - - - - - 3 - 1 - 1 - 200 - 0 - 0 - 60 - - - - - - - - - f31d8d7a-7536-4ac8-9c96-fde6ecda4d0a - Cluster - - - - - - 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 - - Contains a cluster of Grasshopper components - true - 9c0f68ef-d76a-47b0-8e49-544cf9321db9 - Cluster - Cluster - false - - - - - 6 - 889b2da6-e09d-4486-879f-2ca5073fe873 - 91116c7c-c6f6-4b91-b30e-651548dbb2cd - 957b3f47-111f-4a0f-9dfa-3dede52b857e - c08a55b9-8d03-46e8-9856-18fdb41e1daf - cf4db125-1c5e-46b5-899e-ec4fbe113fdd - d2d51328-18f6-4ef3-8dd6-1df6b6af922e - 205b16a3-be6e-4cf4-b6c8-545e13207a7a - 757d1752-e8de-4612-b5a0-3d53b66f04ea - c638130d-be5b-464c-b2f4-8c28d38362a7 - 4441038b-e8f1-4972-be88-7e8e0e9b491e - 9103c1fa-d594-44f2-a4ce-2d6b8016e92c - 6e96ab7a-377b-47d1-b788-514f4644a658 - - - - - - 573 - 575 - 99 - 84 - - - 621 - 617 - - - - - - 4 - 16ef3e75-e315-4899-b531-d3166b42dac9 - d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 - cb95db89-6165-43b6-9c41-5702bc5bf137 - 3e8ca6be-fda8-4aaf-b5c0-3c54c8bb7312 - 2 - d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 - 3e8ca6be-fda8-4aaf-b5c0-3c54c8bb7312 - - - - - Contains a collection of three-dimensional vectors - cf4db125-1c5e-46b5-899e-ec4fbe113fdd - Vector - Vec - true - 3fa223fc-b370-43ff-9286-d236dfc1155a - 1 - - - - - - 575 - 577 - 31 - 20 - - - 592 - 587 - - - - - - - - Contains a collection of generic curves - 957b3f47-111f-4a0f-9dfa-3dede52b857e - Curve - Crv - true - 09fe95fb-9551-4690-abf6-4a0665002914 - 1 - - - - - - 575 - 597 - 31 - 20 - - - 592 - 607 - - - - - - - - Contains a collection of boolean values - 889b2da6-e09d-4486-879f-2ca5073fe873 - Boolean - Bool - true - ca0ea429-34fb-4ce1-a30e-2c14ddc1552e - 1 - - - - - - 575 - 617 - 31 - 20 - - - 592 - 627 - - - - - - - - Contains a collection of floating point numbers - c08a55b9-8d03-46e8-9856-18fdb41e1daf - Number - Num - true - c0dd7c3a-81ff-41c2-b62c-72cfdce3816b - 1 - - - - - - 575 - 637 - 31 - 20 - - - 592 - 647 - - - - - - - - Contains a collection of generic curves - d2d51328-18f6-4ef3-8dd6-1df6b6af922e - Curve - Crv - false - 0 - - - - - - 636 - 577 - 34 - 40 - - - 653 - 597 - - - - - - - - Contains a collection of floating point numbers - 91116c7c-c6f6-4b91-b30e-651548dbb2cd - Number - Num - false - 0 - - - - - - 636 - 617 - 34 - 40 - - - 653 - 637 - - - - - - - - - - - - - - b6236720-8d88-4289-93c3-ac4c99f9b97b - Relay - - - - - 2 - A wire relay object - ed4dd89a-026f-43eb-81d4-433cea857301 - Relay - - false - 3984d0df-294e-462f-b103-b87bb94e3021 - 1 - - - - - - 2164 - 686 - 40 - 16 - - - 2184 - 694 - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - c0dd7c3a-81ff-41c2-b62c-72cfdce3816b - Number Slider - - false - 0 - - - - - - 371 - 665 - 173 - 20 - - - 371.0457 - 665.6685 - - - - - - 1 - 1 - 0 - 20 - 0 - 0 - 2 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 4d710107-34a1-4586-be44-d6f80294f0e6 - Number Slider - - false - 0 - - - - - - 2018 - 731 - 192 - 20 - - - 2018.859 - 731.8153 - - - - - - 2 - 1 - 0 - 100 - 0 - 0 - 0 - - - - - - - - - 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 - Plane - - - - - Contains a collection of three-dimensional axis-systems - 39d6e475-c4b6-4330-98aa-9fdff81c5724 - Plane - Pln - false - 389410e6-fbd0-4b13-ad00-528c4c2075fd - 1 - - - - - - 2021 - 280 - 50 - 24 - - - 2046.047 - 292.3867 - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - e1131cec-2fb2-499e-93e5-55dce618ee47 - Number Slider - - false - 0 - - - - - - 2020 - 834 - 192 - 20 - - - 2020.459 - 834.2153 - - - - - - 2 - 1 - 0 - 100 - 0 - 0 - 0 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 78334c0a-357d-4e7c-b3e4-fc940bcf9f1c - Number Slider - rotation - false - 0 - - - - - - 1971 - 858 - 240 - 20 - - - 1971.77 - 858.5305 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 0 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 6b6d7ea8-7a08-4879-939c-5f96604c4678 - Number Slider - - false - 0 - - - - - - 1407 - 246 - 186 - 20 - - - 1407.689 - 246.8536 - - - - - - 2 - 1 - 0 - 200 - 0 - 0 - 20 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 89a39aa2-89d0-4ad6-9043-6ef61b51023c - Number Slider - - false - 0 - - - - - - 1405 - 224 - 188 - 20 - - - 1405.608 - 224.0857 - - - - - - 3 - 1 - 1 - 50 - 0 - 0 - 10 - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - bbcbfdee-5b0e-4c92-bf29-b5811037ea03 - 3ee8dc00-1eea-48ba-bc11-c2d1911c58a5 - b29d9bba-e05a-4fa4-91a3-bf1ac143a41d - 4d710107-34a1-4586-be44-d6f80294f0e6 - e1131cec-2fb2-499e-93e5-55dce618ee47 - 78334c0a-357d-4e7c-b3e4-fc940bcf9f1c - 6 - 792ba2cf-3af6-498a-971d-99f5e5a1dea5 - Group - - - - - - - - - - - 410755b1-224a-4c1e-a407-bf32fb45ea7e - 00000000-0000-0000-0000-000000000000 - CT: T Topological Joint Rules - - - - - import inspect - -from ghpythonlib.componentbase import executingcomponent as component -from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning - -from compas_timber.connections import Joint -from compas_timber.connections import JointTopology -from compas_timber.connections import TButtJoint -from compas_timber.design import TopologyRule -from compas_timber.ghpython.ghcomponent_helpers import get_leaf_subclasses -from compas_timber.ghpython.ghcomponent_helpers import manage_dynamic_params -from compas_timber.ghpython.ghcomponent_helpers import rename_gh_output - - -class T_TopologyJointRule(component): - def __init__(self): - super(T_TopologyJointRule, self).__init__() - self.classes = {} - for cls in get_leaf_subclasses(Joint): - if cls.SUPPORTED_TOPOLOGY == JointTopology.TOPO_T: - self.classes[cls.__name__] = cls - if ghenv.Component.Params.Output[0].NickName == "Rule": - self.joint_type = TButtJoint - self.clicked = False - else: - self.joint_type = self.classes.get(ghenv.Component.Params.Output[0].NickName, None) - self.clicked = True - - def RunScript(self, *args): - if not self.clicked: - ghenv.Component.Message = "Default: TButtJoint" - self.AddRuntimeMessage(Warning, "TButtJoint is default, change in context menu (right click)") - return TopologyRule(JointTopology.TOPO_T, TButtJoint) - else: - ghenv.Component.Message = self.joint_type.__name__ - kwargs = {} - for i, val in enumerate(args): - if val is not None: - kwargs[self.arg_names()[i]] = val - if self.joint_type.SUPPORTED_TOPOLOGY != JointTopology.TOPO_T: - self.AddRuntimeMessage(Warning, "Joint type does not match topology. Joint may not be generated.") - return TopologyRule(JointTopology.TOPO_T, self.joint_type, **kwargs) - - def arg_names(self): - names = inspect.getargspec(self.joint_type.__init__)[0][3:] - 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 - - def on_item_click(self, sender, event_info): - self.clicked = True - 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=0, permanent_param_count=0) - ghenv.Component.ExpireSolution(True) - - GhPython provides a Python script component - - 96 - 96 - - - 741 - 702 - - true - true - true - - iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDAAACwwBP0AiyAAAAN5JREFUSEvtk7ENwkAMRTNC6JGIxAIZhREYgY6WCRAjpKbKCCkoKRiBEdjAfJ/uImPMXS6EAinFsy4++3/JvhRE9FPM5HpVdYA8J6tmKP0BQhUowcELS3ayKQcXILBRgp+4g1qLxHDBN1qCFq0WieECmuTMmQbwuHhsN58LdFokhgtoapVIGQpwrtXdKAO92MkNeCRShL95PJONSO8gxqglD32mD5D/TBluBNZImG2oWx4vC0AJzqG+N5BAUO7k5S9G8/cGOUDs6kX31v1bIpfZIMlskOT/DVKYyemg4glf8MWtha38JQAAAABJRU5ErkJggg== - - false - 68447cb4-778f-4e2c-a7ca-627a868c84e1 - true - true - CT: T Topological Joint Rules - T_Topo_Joint - - - - - - 977 - 1089 - 192 - 204 - - - 1073 - 1191 - - - - - - 10 - 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 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 1 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - - - - - start_y - 534626fc-7966-4736-9188-176756493fcc - start_y - start_y - true - a3e72ece-c329-479f-b17f-94062e976ee8 - 1 - - - - - - 979 - 1091 - 79 - 20 - - - 1020 - 1101 - - - - - - - - Script input start_depth. - 7597de76-5e70-4808-9b8e-e81cbcc37925 - start_depth - start_depth - true - fe8fa9fd-21f2-43ef-b49f-767b0753a1ae - 1 - - - - - - 979 - 1111 - 79 - 20 - - - 1020 - 1121 - - - - - - - - Script input rotation. - 151edfa6-82d1-4b59-96ef-2d94ed57e39e - rotation - rotation - true - 48898955-f881-4e56-b6e5-3c7ee5cdc4a2 - 1 - - - - - - 979 - 1131 - 79 - 20 - - - 1020 - 1141 - - - - - - - - Script input length. - d502ab54-077d-4a58-8129-a281e626ea22 - length - length - true - fb924a22-fb82-45ca-81fd-fb8a3ef8536a - 1 - - - - - - 979 - 1151 - 79 - 20 - - - 1020 - 1161 - - - - - - - - Script input width. - cf534226-abf9-4421-af45-780bfb2a9218 - width - width - true - dcc01bf8-eaab-475a-9a3d-34524bf3dfa7 - 1 - - - - - - 979 - 1171 - 79 - 20 - - - 1020 - 1181 - - - - - - - - Script input cone_angle. - d99cde1f-d7fd-4021-b596-b00c93659492 - cone_angle - cone_angle - true - 0cae4f91-95c7-4cfa-8d10-c084807de87e - 1 - - - - - - 979 - 1191 - 79 - 20 - - - 1020 - 1201 - - - - - - - - Script input dovetail_shape. - 347275da-3171-4d50-89da-fb719a724122 - dovetail_shape - dovetail_shape - true - dfa57b10-b759-4c01-8ef6-e8f27c2261c0 - 1 - - - - - - 979 - 1211 - 79 - 20 - - - 1020 - 1221 - - - - - - - - Script input tool_angle. - 3f15676d-0938-42ad-a0d7-8090bcb46e4f - tool_angle - tool_angle - true - 19c8f5b9-f818-4553-9fec-96ae2df55628 - 1 - - - - - - 979 - 1231 - 79 - 20 - - - 1020 - 1241 - - - - - - - - Script input tool_diameter. - aef3de77-ddf0-4ec7-ab3f-93300c6c15ae - tool_diameter - tool_diameter - true - 10946ab9-030f-41c8-8192-8fc73ecb49e4 - 1 - - - - - - 979 - 1251 - 79 - 20 - - - 1020 - 1261 - - - - - - - - Script input tool_height. - 883bd64a-9859-44a6-b61e-8c025315b39c - tool_height - tool_height - true - 697f731c-faf2-45c5-a9c4-a947431b741b - 1 - - - - - - 979 - 1271 - 79 - 20 - - - 1020 - 1281 - - - - - - - - Script output TDovetailJoint. - 9ef43da6-ada7-4c17-a8ec-f321d9379183 - TDovetailJoint - TDovetailJoint - false - 0 - - - - - - 1088 - 1091 - 79 - 200 - - - 1127.5 - 1191 - - - - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - dcc01bf8-eaab-475a-9a3d-34524bf3dfa7 - true - Number Slider - width - false - 0 - - - - - - 771 - 1153 - 160 - 20 - - - 771.9711 - 1153.291 - - - - - - 3 - 1 - 1 - 200 - 0 - 0 - 25 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 0cae4f91-95c7-4cfa-8d10-c084807de87e - true - Number Slider - cone_angle - false - 0 - - - - - - 692 - 1178 - 240 - 20 - - - 692.5809 - 1178.608 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 10 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - fb924a22-fb82-45ca-81fd-fb8a3ef8536a - true - Number Slider - length - false - 0 - - - - - - 760 - 1127 - 171 - 20 - - - 760.933 - 1127.53 - - - - - - 3 - 1 - 1 - 200 - 0 - 0 - 60 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - fe8fa9fd-21f2-43ef-b49f-767b0753a1ae - true - Number Slider - - false - 0 - - - - - - 741 - 1077 - 192 - 20 - - - 741.048 - 1077.661 - - - - - - 2 - 1 - 0 - 100 - 0 - 0 - 10 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - a3e72ece-c329-479f-b17f-94062e976ee8 - true - Number Slider - - false - 0 - - - - - - 741 - 1054 - 192 - 20 - - - 741.4919 - 1054.057 - - - - - - 2 - 1 - 0 - 100 - 0 - 0 - 10 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 48898955-f881-4e56-b6e5-3c7ee5cdc4a2 - true - Number Slider - rotation - false - 0 - - - - - - 693 - 1102 - 238 - 20 - - - 693.3779 - 1102.07 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 20 - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - dcc01bf8-eaab-475a-9a3d-34524bf3dfa7 - 0cae4f91-95c7-4cfa-8d10-c084807de87e - fb924a22-fb82-45ca-81fd-fb8a3ef8536a - fe8fa9fd-21f2-43ef-b49f-767b0753a1ae - a3e72ece-c329-479f-b17f-94062e976ee8 - 48898955-f881-4e56-b6e5-3c7ee5cdc4a2 - dfa57b10-b759-4c01-8ef6-e8f27c2261c0 - 7 - 0d673e88-5ab0-4910-98ed-aa50c52a5acc - Group - - - - - - - - - - - 00027467-0d24-4fa7-b178-8dc0ac5f42ec - Value List - - - - - Provides a list of preset values to choose from - true - dfa57b10-b759-4c01-8ef6-e8f27c2261c0 - 5 - 1 - true - Value List - List - false - 0 - - - - - 0 - Automatic - false - - - - - 1 - Square - false - - - - - 2 - Round - false - - - - - 3 - Rounded - false - - - - - 4 - Radius - true - - - - - - 833 - 1204 - 99 - 22 - - - - - - - - - - 410755b1-224a-4c1e-a407-bf32fb45ea7e - 00000000-0000-0000-0000-000000000000 - CT: Model - - - - - from compas.scene import Scene -from compas.tolerance import TOL -from ghpythonlib.componentbase import executingcomponent as component -from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning - -from compas_timber.connections import BeamJoinningError -from compas_timber.connections import ConnectionSolver -from compas_timber.connections import JointTopology -from compas_timber.connections import LMiterJoint -from compas_timber.connections import TButtJoint -from compas_timber.connections import XHalfLapJoint -from compas_timber.design import CategoryRule -from compas_timber.design import DebugInfomation -from compas_timber.design import DirectRule -from compas_timber.design import JointDefinition -from compas_timber.design import TopologyRule -from compas_timber.model import TimberModel - -JOINT_DEFAULTS = { - JointTopology.TOPO_X: XHalfLapJoint, - JointTopology.TOPO_T: TButtJoint, - JointTopology.TOPO_L: LMiterJoint, -} - - -# workaround for https://github.com/gramaziokohler/compas_timber/issues/280 -TOL.absolute = 1e-6 - - -class ModelComponent(component): - def get_joints_from_rules(self, beams, rules, topologies): - if not isinstance(rules, list): - rules = [rules] - rules = [r for r in rules if r is not None] - - joints = [] - # rules have to be resolved into joint definitions - topo_rules = {} - cat_rules = [] - direct_rules = [] - - # TODO: refactor this into some kind of a rule reloving class/function - for r in rules: # separate category and topo and direct joint rules - if isinstance(r, TopologyRule): - if topo_rules.get(r.topology_type, None): # if rule for this Topo exists - if (r.joint_type != JOINT_DEFAULTS[r.topology_type]) or ( - len(r.kwargs) != 0 - ): # if this rule is NOT default - topo_rules[r.topology_type] = r - else: - topo_rules[r.topology_type] = r - elif isinstance(r, CategoryRule): - cat_rules.append(r) - if isinstance(r, DirectRule): - direct_rules.append(r) - - for topo in topologies: - beam_a = topo["beam_a"] - beam_b = topo["beam_b"] - detected_topo = topo["detected_topo"] - pair = beam_a, beam_b - pair_joined = False - - if detected_topo == JointTopology.TOPO_UNKNOWN: - continue - - for rule in direct_rules: # apply direct rules first - if rule.comply(pair): - joints.append(JointDefinition(rule.joint_type, rule.beams, **rule.kwargs)) - pair_joined = True - break - - if not pair_joined: # if no direct rule applies, apply category rules next - for rule in cat_rules: - if not rule.comply(pair): - continue - if rule.joint_type.SUPPORTED_TOPOLOGY != detected_topo: - msg = "Conflict detected! Beams: {}, {} meet with topology: {} but rule assigns: {}" - self.AddRuntimeMessage( - Warning, - msg.format( - beam_a.guid, - beam_b.guid, - JointTopology.get_name(detected_topo), - rule.joint_type.__name__, - ), - ) - 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.guid, - beam_b.guid, - 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)) - break # first matching rule - - else: # no category rule applies, apply topology rules - if detected_topo not in topo_rules: - continue - else: - joints.append( - JointDefinition( - topo_rules[detected_topo].joint_type, - [beam_a, beam_b], - **topo_rules[detected_topo].kwargs - ) - ) - return joints - - def RunScript(self, Elements, JointRules, Features, MaxDistance, CreateGeometry): - if not Elements: - self.AddRuntimeMessage(Warning, "Input parameter Beams failed to collect data") - if not JointRules: - self.AddRuntimeMessage(Warning, "Input parameter JointRules failed to collect data") - if not (Elements): # shows beams even if no joints are found - return - if MaxDistance is None: - MaxDistance = TOL.ABSOLUTE # compared to calculted distance, so shouldn't be just 0.0 - - Model = TimberModel() - debug_info = DebugInfomation() - for element in Elements: - # prepare elements for downstream processing - if element is None: - continue - element.remove_features() - if hasattr(element, "remove_blank_extension"): - element.remove_blank_extension() - element.debug_info = [] - Model.add_element(element) - - topologies = [] - solver = ConnectionSolver() - found_pairs = solver.find_intersecting_pairs(list(Model.beams), rtree=True, max_distance=MaxDistance) - for pair in found_pairs: - beam_a, beam_b = pair - detected_topo, beam_a, beam_b = solver.find_topology(beam_a, beam_b, max_distance=MaxDistance) - if not detected_topo == JointTopology.TOPO_UNKNOWN: - topologies.append({"detected_topo": detected_topo, "beam_a": beam_a, "beam_b": beam_b}) - Model.set_topologies(topologies) - - joints = self.get_joints_from_rules(Model.beams, JointRules, topologies) - - if joints: - handled_beams = [] - joints = [j for j in joints if j is not None] - # apply reversed. later joints in orginal list override ealier ones - for joint in joints[::-1]: - beams_to_pair = joint.beams - beam_pair_ids = set([id(beam) for beam in beams_to_pair]) - if beam_pair_ids in handled_beams: - continue - try: - joint.joint_type.create(Model, *beams_to_pair, **joint.kwargs) - except BeamJoinningError as bje: - debug_info.add_joint_error(bje) - else: - handled_beams.append(beam_pair_ids) - - # applies extensions and features resulting from joints - Model.process_joinery() - - if Features: - features = [f for f in Features if f is not None] - for f_def in features: - for element in f_def.elements: - element.add_features(f_def.feature) - - Geometry = None - scene = Scene() - for element in Model.elements(): - if CreateGeometry: - scene.add(element.geometry) - if element.debug_info: - debug_info.add_feature_error(element.debug_info) - else: - scene.add(element.blank) - - if debug_info.has_errors: - self.AddRuntimeMessage(Warning, "Error found during joint creation. See DebugInfo output for details.") - - Geometry = scene.draw() - return Model, Geometry, debug_info - - GhPython provides a Python script component - - 160 - 160 - - - 741 - 702 - - true - true - true - - iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDAAACwwBP0AiyAAAAa1JREFUSEu1lc1NA0EMRqeElJASUkJK4MgxJaSElEAJKSFHjikhBw4cERUgcUNI4XsTe+Td8S4bJCw9MePPP7uezFKu1+tiZA+QaVOkzgzZQbCAQxaTkTojspU4WeFXgzW+VZYTSZ2ObC0ugg1vEMGHts5yndQJsq34MOrcZbW4rTkP17cxN5I7S9kJFm9iE/ytge03ghg2O/dHekcpR0s4i8GMZYMG5uOMiGVzjFrV2+IW6PPuAi2maxA0fzBqtAdz8ddXBdlkAyBXsGijxeJhtXlnyGYbADWE16N2m99/QO3yJL4FM+SnGcHHTH3/aPgebSqPmtSur83MeKXBpTHtHH0RNGJGPi4ntahJ/q2IOU6j4L804BNCrarh8Aa8GhHtVsruaiBrNcSwQUi4hIR7G3AmsVbXgPmx2Nt+cQPZXrCo5yjrG5jAnkPiZi9qIIglJ77NZAMP5ie2tAGx9aESrS8i8yv/bH/n8JjBJ0Y23SAEvIt40cagETOVP9uAAixexpqDZjHdPxzZoAHzwzHmU3yNfBE0YjKtHrqoT8oig28KNzPTAI2YTBNl+wPOvtI8NDHinQAAAABJRU5ErkJggg== - - false - fb2bee0a-2791-40d8-ba2d-3facd193d280 - true - true - CT: Model - Model - - - - - - 1424 - 1159 - 198 - 104 - - - 1543 - 1211 - - - - - - 5 - 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 - 3 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - - - - - 1 - true - Collection of Beams - 75b9cd26-8234-4296-a759-24e24b94d514 - 1 - Elements - Elements - true - 1 - true - 3984d0df-294e-462f-b103-b87bb94e3021 - 90fae02f-7750-462d-828f-cf5f2a0d39ae - 2 - 35915213-5534-4277-81b8-1bdc9e7383d2 - - - - - - 1426 - 1161 - 102 - 20 - - - 1486.5 - 1171 - - - - - - - - 1 - true - Script input JointRules. - 962ac6c9-86fb-4b6f-bb76-9baafd776740 - 1 - JointRules - JointRules - true - 1 - true - 9ef43da6-ada7-4c17-a8ec-f321d9379183 - 1 - 35915213-5534-4277-81b8-1bdc9e7383d2 - - - - - - 1426 - 1181 - 102 - 20 - - - 1486.5 - 1191 - - - - - - - - 1 - true - Script input Features. - b9026523-5f20-46e2-9ab8-e0dc7abcdd97 - Features - Features - true - 1 - true - 0 - 35915213-5534-4277-81b8-1bdc9e7383d2 - - - - - - 1426 - 1201 - 102 - 20 - - - 1486.5 - 1211 - - - - - - - - true - Script input MaxDistance. - f9095c56-0432-4f5d-9a51-f28ccd44fe4c - MaxDistance - MaxDistance - true - 0 - true - 09833aa5-1994-4337-85d5-341624343d48 - 1 - 39fbc626-7a01-46ab-a18e-ec1c0c41685b - - - - - - 1426 - 1221 - 102 - 20 - - - 1486.5 - 1231 - - - - - - - - true - Script input CreateGeometry. - 72e58a16-32c5-47b7-8f31-dd3b2de0d42a - CreateGeometry - CreateGeometry - true - 0 - true - ee37f1a7-f247-4dd1-9926-3498f06eec02 - 1 - d60527f5-b5af-4ef6-8970-5f96fe412559 - - - - - - 1426 - 1241 - 102 - 20 - - - 1486.5 - 1251 - - - - - - - - Script output Model. - 420b8f1c-7df1-405b-a1f3-387f3716017a - Model - Model - false - 0 - - - - - - 1558 - 1161 - 62 - 33 - - - 1589 - 1177.667 - - - - - - - - Script output Geometry. - 486668a9-de54-49fb-b662-03694889d429 - Geometry - Geometry - false - 0 - - - - - - 1558 - 1194 - 62 - 33 - - - 1589 - 1211 - - - - - - - - Script output DebugInfo. - 6c5ffdba-503c-435e-9b82-201c7ce03292 - DebugInfo - DebugInfo - false - 0 - - - - - - 1558 - 1227 - 62 - 34 - - - 1589 - 1244.333 - - - - - - - - - - - - - - 2e78987b-9dfb-42a2-8b76-3923ac8bd91a - Boolean Toggle - - - - - Boolean (true/false) toggle - ee37f1a7-f247-4dd1-9926-3498f06eec02 - Boolean Toggle - Toggle - false - 0 - true - - - - - - 1302 - 1246 - 104 - 22 - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 09833aa5-1994-4337-85d5-341624343d48 - Number Slider - - false - 0 - - - - - - 1211 - 1221 - 195 - 20 - - - 1211.673 - 1221.001 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 40 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 19c8f5b9-f818-4553-9fec-96ae2df55628 - true - Number Slider - - false - 0 - - - - - - 731 - 1253 - 184 - 20 - - - 731.2643 - 1253.693 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 15 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 10946ab9-030f-41c8-8192-8fc73ecb49e4 - true - Number Slider - - false - 0 - - - - - - 731 - 1277 - 200 - 20 - - - 731.2643 - 1277.886 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 60 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 697f731c-faf2-45c5-a9c4-a947431b741b - true - Number Slider - - false - 0 - - - - - - 731 - 1301 - 188 - 20 - - - 731.3165 - 1301.079 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 28 - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - 19c8f5b9-f818-4553-9fec-96ae2df55628 - 10946ab9-030f-41c8-8192-8fc73ecb49e4 - 697f731c-faf2-45c5-a9c4-a947431b741b - 3 - 74f12b35-8c0f-4016-92da-4457ad7215e5 - Group - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 13835904-23ad-43b2-a586-0ae141339040 - Number Slider - - false - 0 - - - - - - 828 - 452 - 166 - 20 - - - 828.7086 - 452.7064 - - - - - - 3 - 1 - 1 - 1000 - 0 - 0 - 120 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - b0579e2b-7024-4c03-8e13-7ddcca5e08a6 - Number Slider - - false - 0 - - - - - - 827 - 396 - 162 - 20 - - - 827.0381 - 396.3297 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 60 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 81d19eff-02b1-4406-a0c3-47dd897a152f - Number Slider - - false - 0 - - - - - - 825 - 570 - 162 - 20 - - - 825.3678 - 570.3737 - - - - - - 3 - 1 - 1 - 100 - 0 - 0 - 80 - - - - - - - - - 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 - Plane - - - - - Contains a collection of three-dimensional axis-systems - 61d94f4d-5239-4d5e-a848-ab890c2a7194 - Plane - Pln - false - cc5eda18-08de-4b0d-91bd-9eefbfcc5dc7 - 1 - - - - - - 1891 - 103 - 50 - 24 - - - 1916.005 - 115.5407 - - - - - - - - - - 4f8984c4-7c7a-4d69-b0a2-183cbb330d20 - Plane - - - - - Contains a collection of three-dimensional axis-systems - a5781cd0-b305-4ed7-99aa-69c993f66d09 - Plane - Pln - false - a8110476-8bb3-4892-9423-09704614c7a3 - 1 - - - - - - 1882 - 169 - 50 - 24 - - - 1907.219 - 181.47 - - - - - - - - - - 59daf374-bc21-4a5e-8282-5504fb7ae9ae - List Item - - - - - 0 - Retrieve a specific item from a list. - true - 4140c91c-1f45-4cd9-88e8-e8e12d1f8da2 - List Item - Item - - - - - - 1952 - 285 - 74 - 124 - - - 1986 - 347 - - - - - - 3 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 2e3ab970-8545-46bb-836c-1c11e5610bce - cb95db89-6165-43b6-9c41-5702bc5bf137 - 6 - 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 - - - - - 1 - Base list - 8024f13e-5f87-450a-8acd-b1813506d465 - List - L - false - 39d6e475-c4b6-4330-98aa-9fdff81c5724 - 1 - - - - - - 1954 - 287 - 17 - 40 - - - 1964 - 307 - - - - - - - - Item index - e9f2b2f9-1321-4844-b859-c172906e7d3a - Index - i - false - 0 - - - - - - 1954 - 327 - 17 - 40 - - - 1964 - 347 - - - - - - 1 - - - - - 1 - {0} - - - - - 0 - - - - - - - - - - - Wrap index to list bounds - 2844a904-d023-453b-a70c-b31dc032c930 - Wrap - W - false - 0 - - - - - - 1954 - 367 - 17 - 40 - - - 1964 - 387 - - - - - - 1 - - - - - 1 - {0} - - - - - true - - - - - - - - - - - Item at {i'} - 67a488e6-002d-4aa5-b61d-394d61348dc5 - false - Item - i - false - 0 - - - - - - 2001 - 287 - 23 - 20 - - - 2012.5 - 297 - - - - - - - - Item at {+1'} - d0209c5d-de16-4aa2-b549-02ed8c1a1c40 - false - Item +1 - +1 - false - 0 - - - - - - 2001 - 307 - 23 - 20 - - - 2012.5 - 317 - - - - - - - - Item at {+2'} - 2e6fd5ba-24aa-449f-a464-5831bd9c15fd - false - Item +2 - +2 - false - 0 - - - - - - 2001 - 327 - 23 - 20 - - - 2012.5 - 337 - - - - - - - - Item at {+3'} - d1ec9303-8326-4408-afb6-c1f5634a5e22 - false - Item +3 - +3 - false - 0 - - - - - - 2001 - 347 - 23 - 20 - - - 2012.5 - 357 - - - - - - - - Item at {+4'} - e2d3c2fa-8609-48f0-aa19-696b94a64fa7 - false - Item +4 - +4 - false - 0 - - - - - - 2001 - 367 - 23 - 20 - - - 2012.5 - 377 - - - - - - - - Item at {+5'} - 970e00a8-0c70-4691-9ec4-ad4e788ebc0e - false - Item +5 - +5 - false - 0 - - - - - - 2001 - 387 - 23 - 20 - - - 2012.5 - 397 - - - - - - - - - - - - - - 410755b1-224a-4c1e-a407-bf32fb45ea7e - 00000000-0000-0000-0000-000000000000 - CT: WriteBTLx - - - - - import Rhino -from ghpythonlib.componentbase import executingcomponent as component -from Grasshopper.Kernel.GH_RuntimeMessageLevel import Warning - -from compas_timber.fabrication import BTLx - - -class WriteBTLx(component): - def RunScript(self, model, path, write): - if not model: - self.AddRuntimeMessage(Warning, "Input parameter Model failed to collect data") - return - - btlx = BTLx(model) - btlx.history["FileName"] = Rhino.RhinoDoc.ActiveDoc.Name - - if write: - if not path: - self.AddRuntimeMessage(Warning, "Input parameter Path failed to collect data") - return - if path[-5:] != ".btlx": - path += ".btlx" - with open(path, "w") as f: - f.write(btlx.btlx_string()) - return btlx.btlx_string() - - GhPython provides a Python script component - true - true - true - - iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDAAACwwBP0AiyAAAAShJREFUSEu1lFERwjAQRCsBAYhAQiUgAQlIQAGDBCQggQ8EVAIScBB2MxyzCZvwQbiZB/S6d9smF6aU0l+xyZHY5EhsciQ26UAcAne/hU06EPzI1Pd6TOvj7QxW7qbyi0ECyzeTXw3IHWyciNQGiBnEvuxeOf4ueqgBeYBZBW/hpwGbRe5aaS4gr0htEOQnUqQYl/m6Z0DytLUMyImCQItf126J3hrwAKuewRLN62LNK4id6sC+ZXA2xVrYG4ZFdAdnYE8q4qqFDQ2XLTRZVxt8bG6A4GRoMZ/0BPIegC24A9XMYcDxbL42yeKyWOHb6VSRS65DY57ibvMAwSfldGgjUhsU5+Dr/5DCQkAjNuQSsTm/Y2yLg1oU/wObHIlNjsQmR2KT40jTExovdFkNMNc1AAAAAElFTkSuQmCC - - false - 04a8d391-5de1-43a3-bc1e-9148489eba13 - true - true - CT: WriteBTLx - WriteBTLx - - - - - - 1732 - 1232 - 104 - 64 - - - 1787 - 1264 - - - - - - 3 - 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 - 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 - 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 - 1 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - - - - - true - Model object. - a3efc012-177d-446f-8246-57f6fdc66a3e - Model - Model - true - 0 - true - 420b8f1c-7df1-405b-a1f3-387f3716017a - 1 - 35915213-5534-4277-81b8-1bdc9e7383d2 - - - - - - 1734 - 1234 - 38 - 20 - - - 1754.5 - 1244 - - - - - - - - true - Script input Path. - 9ec97830-a244-4a9a-9eaa-7025e1ca2aad - Path - Path - true - 0 - true - 6b5f5a99-98ff-4322-b2f6-76ed37c15310 - 1 - 35915213-5534-4277-81b8-1bdc9e7383d2 - - - - - - 1734 - 1254 - 38 - 20 - - - 1754.5 - 1264 - - - - - - - - true - Script input Write. - 15ed91b8-1bee-4f81-b07a-68f57f0c7c24 - Write - Write - true - 0 - true - fe63683a-84ba-462b-b688-9e3f081f52fb - 1 - d60527f5-b5af-4ef6-8970-5f96fe412559 - - - - - - 1734 - 1274 - 38 - 20 - - - 1754.5 - 1284 - - - - - - - - Script output BTLx. - ec68082b-6816-42e0-b242-ac0746b13092 - BTLx - BTLx - false - 0 - - - - - - 1802 - 1234 - 32 - 60 - - - 1818 - 1264 - - - - - - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - 6b5f5a99-98ff-4322-b2f6-76ed37c15310 - Panel - - false - 0 - 0 - D:\Papachap\Desktop\BTLx\TDovetailJoint.btlx - - - - - - 1472 - 1273 - 147 - 100 - - 0 - 0 - 0 - - 1472.726 - 1273.2 - - - - - - - 255;255;250;90 - - true - true - true - false - false - true - - - - - - - - - 2e78987b-9dfb-42a2-8b76-3923ac8bd91a - Boolean Toggle - - - - - Boolean (true/false) toggle - fe63683a-84ba-462b-b688-9e3f081f52fb - Boolean Toggle - Toggle - false - 0 - true - - - - - - 1536 - 1413 - 104 - 22 - - - - - - - - - - 4c4e56eb-2f04-43f9-95a3-cc46a14f495a - Line - - - - - Create a line between two points. - c34a085b-356b-4622-a2c2-8c93324c04f1 - Line - Ln - - - - - - 1975 - 54 - 63 - 44 - - - 2006 - 76 - - - - - - Line start point - 72e8522f-80cb-457b-91fe-8f0cc13c0ab7 - Start Point - A - false - 213adbf5-0592-48ab-b06a-06543b55b8da - 1 - - - - - - 1977 - 56 - 14 - 20 - - - 1985.5 - 66 - - - - - - - - Line end point - 47da55d9-8df7-4c19-b1e3-9e5d90055133 - End Point - B - false - a5781cd0-b305-4ed7-99aa-69c993f66d09 - 1 - - - - - - 1977 - 76 - 14 - 20 - - - 1985.5 - 86 - - - - - - - - Line segment - ce6dc462-63ba-4c7e-8670-c2e4d46bb69d - Line - L - false - 0 - - - - - - 2021 - 56 - 15 - 40 - - - 2028.5 - 76 - - - - - - - - - - - - a50fcd4a-cf42-4c3f-8616-022761e6cc93 - Deconstruct Vector - - - - - Deconstruct a vector into its component parts. - 35af3385-8992-4e83-b784-69eb595c78d1 - Deconstruct Vector - DeVec - - - - - - 1972 - -172 - 65 - 64 - - - 2003 - -140 - - - - - - Input vector - d91e9f12-67cf-4c4f-9fcd-db715d88daf4 - Vector - V - false - ce6dc462-63ba-4c7e-8670-c2e4d46bb69d - 1 - - - - - - 1974 - -170 - 14 - 60 - - - 1982.5 - -140 - - - - - - - - Vector {x} component - 56510800-a7a4-48c5-b46a-bc699b26dc50 - X component - X - false - 0 - - - - - - 2018 - -170 - 17 - 20 - - - 2026.5 - -160 - - - - - - - - Vector {y} component - 9c53ff46-e961-44c3-ae46-a4e377106bea - Y component - Y - false - 0 - - - - - - 2018 - -150 - 17 - 20 - - - 2026.5 - -140 - - - - - - - - Vector {z} component - 31ffbde6-9094-4a18-89bf-9a50fede1842 - Z component - Z - false - 0 - - - - - - 2018 - -130 - 17 - 20 - - - 2026.5 - -120 - - - - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - 587cf7d1-353f-422d-a57b-364604683ef6 - Panel - - false - 0 - 31ffbde6-9094-4a18-89bf-9a50fede1842 - 1 - Double click to edit panel content… - - - - - - 1935 - -88 - 160 - 100 - - 0 - 0 - 0 - - 1935.486 - -87.57 - - - - - - - 255;255;250;90 - - true - true - true - false - false - true - - - - - - - - - 8ec86459-bf01-4409-baee-174d0d2b13d0 - Data - - - - - Contains a collection of generic data - b89acdcc-fd6b-4db1-9f2d-3460b1c61f9f - Data - Data - false - 0 - - - - - - 2084 - -136 - 50 - 24 - - - 2109.122 - -123.692 - - - - - - 1 - - - - - 1 - {0;0} - - - - - Grasshopper.Kernel.Types.GH_Number - -123.85757554219845 - - - - - - - - - - - - - 56b92eab-d121-43f7-94d3-6cd8f0ddead8 - Vector XYZ - - - - - Create a vector from {xyz} components. - 1d8c0f26-dd97-4a50-aea3-d223cf427dea - Vector XYZ - Vec - - - - - - 1654 - -294 - 65 - 64 - - - 1685 - -262 - - - - - - Vector {x} component - 3c06af3c-420e-4235-9f23-2c5b6b8caf10 - X component - X - false - 81b2d562-f2e4-45fd-b695-c1cbaef757e4 - 1 - - - - - - 1656 - -292 - 14 - 20 - - - 1664.5 - -282 - - - - - - 1 - - - - - 1 - {0} - - - - - 0 - - - - - - - - - - - Vector {y} component - 4f98aafa-d128-4471-9453-1527c155e3e8 - Y component - Y - false - 57f61497-d466-442e-8d37-c9954804167d - 1 - - - - - - 1656 - -272 - 14 - 20 - - - 1664.5 - -262 - - - - - - 1 - - - - - 1 - {0} - - - - - 0 - - - - - - - - - - - Vector {z} component - 19ca8d8b-7ee4-443a-b1ed-32a9a0c65f0d - Z component - Z - false - 8def7c05-9133-40c5-a740-0ed9e7a41229 - 1 - - - - - - 1656 - -252 - 14 - 20 - - - 1664.5 - -242 - - - - - - 1 - - - - - 1 - {0} - - - - - 0 - - - - - - - - - - - Vector construct - 260659d9-0c72-4130-820d-16c404b4e462 - Vector - V - false - 0 - - - - - - 1700 - -292 - 17 - 30 - - - 1708.5 - -277 - - - - - - - - Vector length - 83e0c8b0-74fa-4620-9852-7e57c1f4586e - Length - L - false - 0 - - - - - - 1700 - -262 - 17 - 30 - - - 1708.5 - -247 - - - - - - - - - - - - 56b92eab-d121-43f7-94d3-6cd8f0ddead8 - Vector XYZ - - - - - Create a vector from {xyz} components. - 55af1f9d-c8f0-4329-979f-c4fda3f1fd9e - Vector XYZ - Vec - - - - - - 1655 - -205 - 65 - 64 - - - 1686 - -173 - - - - - - Vector {x} component - 77215e04-a8d4-45cd-93d8-886b01c83e71 - X component - X - false - 6655ae15-3d89-4b93-99e5-c57fcab0da34 - 1 - - - - - - 1657 - -203 - 14 - 20 - - - 1665.5 - -193 - - - - - - 1 - - - - - 1 - {0} - - - - - 0 - - - - - - - - - - - Vector {y} component - 7e327792-ec79-4823-aa41-ab4303285025 - Y component - Y - false - b82aee47-37f2-4478-8eeb-89065f3d2272 - 1 - - - - - - 1657 - -183 - 14 - 20 - - - 1665.5 - -173 - - - - - - 1 - - - - - 1 - {0} - - - - - 0 - - - - - - - - - - - Vector {z} component - c9829849-c054-420a-8dce-cdf7bded82eb - Z component - Z - false - 8a0da811-cdf8-40a9-8bf6-b9ca6e808e93 - 1 - - - - - - 1657 - -163 - 14 - 20 - - - 1665.5 - -153 - - - - - - 1 - - - - - 1 - {0} - - - - - 0 - - - - - - - - - - - Vector construct - ab9d29a4-cf3d-48d5-af54-608beb680f54 - Vector - V - false - 0 - - - - - - 1701 - -203 - 17 - 30 - - - 1709.5 - -188 - - - - - - - - Vector length - b47023cf-4dd2-4a55-a2d9-f8b3bc343308 - Length - L - false - 0 - - - - - - 1701 - -173 - 17 - 30 - - - 1709.5 - -158 - - - - - - - - - - - - bc3e379e-7206-4e7b-b63a-ff61f4b38a3e - Construct Plane - - - - - Construct a plane from an origin point and {x}, {y} axes. - 2e6c7a1b-d345-4966-b81c-10969bf5f760 - Construct Plane - Pl - - - - - - 1751 - -309 - 68 - 64 - - - 1783 - -277 - - - - - - Origin of plane - 67ddfd78-b229-4feb-965e-3344a07f7190 - Origin - O - false - 86990d0f-35da-4def-8414-369478a9cd09 - 1 - - - - - - 1753 - -307 - 15 - 20 - - - 1762 - -297 - - - - - - 1 - - - - - 1 - {0} - - - - - - - 0 - 0 - 0 - - - - - - - - - - - - X-Axis direction of plane - d3b445f2-8916-453d-a6b3-bdd628258c0b - X-Axis - X - false - 260659d9-0c72-4130-820d-16c404b4e462 - 1 - - - - - - 1753 - -287 - 15 - 20 - - - 1762 - -277 - - - - - - 1 - - - - - 1 - {0} - - - - - - 1 - 0 - 0 - - - - - - - - - - - - Y-Axis direction of plane - 20543322-9a73-4694-9338-0c99d9169227 - Y-Axis - Y - false - ab9d29a4-cf3d-48d5-af54-608beb680f54 - 1 - - - - - - 1753 - -267 - 15 - 20 - - - 1762 - -257 - - - - - - 1 - - - - - 1 - {0} - - - - - - 0 - 1 - 0 - - - - - - - - - - - - Constructed plane - a029cb6f-5b4e-49f4-88b4-5b60063bbc9f - Plane - Pl - false - 0 - - - - - - 1798 - -307 - 19 - 60 - - - 1807.5 - -277 - - - - - - - - - - - - 3581f42a-9592-4549-bd6b-1c0fc39d067b - Construct Point - - - - - Construct a point from {xyz} coordinates. - 68be8389-b3bd-406f-b874-05df8e51d3f4 - Construct Point - Pt - - - - - - 1660 - -379 - 68 - 64 - - - 1691 - -347 - - - - - - {x} coordinate - 7b110d33-1894-45b6-bc07-f08da80e6257 - X coordinate - X - false - 559cb751-0e45-4685-808e-8040a029dde6 - 1 - - - - - - 1662 - -377 - 14 - 20 - - - 1670.5 - -367 - - - - - - 1 - - - - - 1 - {0} - - - - - 0 - - - - - - - - - - - {y} coordinate - e2e25de6-ed1c-42b0-aa56-37f0fe63a41b - Y coordinate - Y - false - 8ebde2e8-e3d0-4cf0-be05-661ffc26be01 - 1 - - - - - - 1662 - -357 - 14 - 20 - - - 1670.5 - -347 - - - - - - 1 - - - - - 1 - {0} - - - - - 0 - - - - - - - - - - - {z} coordinate - 874021cb-57cf-4bf0-9ce7-91d99fdeaca3 - Z coordinate - Z - false - fe2b2e28-edc4-464a-9506-878d8c6f1c5e - 1 - - - - - - 1662 - -337 - 14 - 20 - - - 1670.5 - -327 - - - - - - 1 - - - - - 1 - {0} - - - - - 0 - - - - - - - - - - - Point coordinate - 86990d0f-35da-4def-8414-369478a9cd09 - Point - Pt - false - 0 - - - - - - 1706 - -377 - 20 - 60 - - - 1716 - -347 - - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 559cb751-0e45-4685-808e-8040a029dde6 - Number Slider - - false - 0 - - - - - - 1388 - -419 - 195 - 20 - - - 1388 - -418.8 - - - - - - 1 - 1 - 0 - 100000 - 0 - 0 - 31332.1 - - - - - - - - - 9c007a04-d0d9-48e4-9da3-9ba142bc4d46 - Subtraction - - - - - Mathematical subtraction - 8d08acff-fbba-4a7b-a85e-5d28d9b37d13 - Subtraction - A-B - - - - - - 1321 - -382 - 65 - 44 - - - 1352 - -360 - - - - - - 2 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - 1 - 8ec86459-bf01-4409-baee-174d0d2b13d0 - - - - - First operand for subtraction - f1996b6d-7e59-4e9b-872b-daa2abd15661 - A - A - true - 0 - - - - - - 1323 - -380 - 14 - 20 - - - 1331.5 - -370 - - - - - - - - Second operand for subtraction - 314c5234-8b41-43d3-b455-f3517783d8dc - B - B - true - 0 - - - - - - 1323 - -360 - 14 - 20 - - - 1331.5 - -350 - - - - - - 1 - - - - - 1 - {0} - - - - - Grasshopper.Kernel.Types.GH_Number - 3287.543 - - - - - - - - - - - Result of subtraction - 0f236a19-5b41-4c02-8f8a-3feb4a99d165 - Result - R - false - 0 - - - - - - 1367 - -380 - 17 - 40 - - - 1375.5 - -360 - - - - - - - - - - - - - - a3371040-e552-4bc8-b0ff-10a840258e88 - Negative - - - - - Compute the negative of a value. - f81ccc3f-2b82-494a-844a-8425db0adb84 - Negative - Neg - - - - - - 1436 - -370 - 61 - 28 - - - 1465 - -356 - - - - - - Input value - b882bd9d-3905-411d-b237-c608471237b6 - Value - x - false - 0f236a19-5b41-4c02-8f8a-3feb4a99d165 - 1 - - - - - - 1438 - -368 - 12 - 24 - - - 1445.5 - -356 - - - - - - - - Output value - 8ebde2e8-e3d0-4cf0-be05-661ffc26be01 - Result - y - false - 0 - - - - - - 1480 - -368 - 15 - 24 - - - 1487.5 - -356 - - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - fe2b2e28-edc4-464a-9506-878d8c6f1c5e - Number Slider - - false - 0 - - - - - - 1354 - -338 - 195 - 20 - - - 1354.4 - -337.2 - - - - - - 4 - 1 - 0 - 100 - 0 - 0 - 54.3408 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - f91d1868-865b-4b09-84ee-18c9589f121f - Number Slider - - false - 0 - - - - - - 1324 - -298 - 160 - 20 - - - 1324.4 - -297.2 - - - - - - 4 - 1 - 0 - 1 - 0 - 0 - 0.9397 - - - - - - - - - a3371040-e552-4bc8-b0ff-10a840258e88 - Negative - - - - - Compute the negative of a value. - 7133e965-5be9-44f6-9acc-ef9f5ab72d6e - Negative - Neg - - - - - - 1525 - -302 - 61 - 28 - - - 1554 - -288 - - - - - - Input value - be7ffc81-5af3-4599-9452-76d7182da4fb - Value - x - false - f91d1868-865b-4b09-84ee-18c9589f121f - 1 - - - - - - 1527 - -300 - 12 - 24 - - - 1534.5 - -288 - - - - - - - - Output value - 81b2d562-f2e4-45fd-b695-c1cbaef757e4 - Result - y - false - 0 - - - - - - 1569 - -300 - 15 - 24 - - - 1576.5 - -288 - - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 57f61497-d466-442e-8d37-c9954804167d - Number Slider - - false - 0 - - - - - - 1324 - -259 - 198 - 20 - - - 1324.344 - -258.8 - - - - - - 4 - 1 - 0 - 10 - 0 - 0 - 0 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 21ef7a03-065e-4239-9090-d0ec4672a335 - Number Slider - - false - 0 - - - - - - 1324 - -226 - 160 - 20 - - - 1324.8 - -226 - - - - - - 3 - 1 - 0 - 1 - 0 - 0 - 0.342 - - - - - - - - - a3371040-e552-4bc8-b0ff-10a840258e88 - Negative - - - - - Compute the negative of a value. - dbc590d5-832a-4015-b497-96f86456345b - Negative - Neg - - - - - - 1522 - -230 - 61 - 28 - - - 1551 - -216 - - - - - - Input value - c1f8e07d-4f57-4e12-a867-3db1ef9b622b - Value - x - false - 21ef7a03-065e-4239-9090-d0ec4672a335 - 1 - - - - - - 1524 - -228 - 12 - 24 - - - 1531.5 - -216 - - - - - - - - Output value - 8def7c05-9133-40c5-a740-0ed9e7a41229 - Result - y - false - 0 - - - - - - 1566 - -228 - 15 - 24 - - - 1573.5 - -216 - - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 41f882f0-98c7-4dee-a166-f1d8a7ac30cb - Number Slider - - false - 0 - - - - - - 1320 - -184 - 160 - 20 - - - - - - 4 - 1 - 0 - 1 - 0 - 0 - 0.342 - - - - - - - - - a3371040-e552-4bc8-b0ff-10a840258e88 - Negative - - - - - Compute the negative of a value. - 70c11d4f-3dab-4c19-a059-cac49c426f21 - Negative - Neg - - - - - - 1520 - -189 - 61 - 28 - - - 1549 - -175 - - - - - - Input value - f45919ba-f892-4023-a0cf-bfc2a641959f - Value - x - false - 41f882f0-98c7-4dee-a166-f1d8a7ac30cb - 1 - - - - - - 1522 - -187 - 12 - 24 - - - 1529.5 - -175 - - - - - - - - Output value - 6655ae15-3d89-4b93-99e5-c57fcab0da34 - Result - y - false - 0 - - - - - - 1564 - -187 - 15 - 24 - - - 1571.5 - -175 - - - - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - b82aee47-37f2-4478-8eeb-89065f3d2272 - Number Slider - - false - 0 - - - - - - 1319 - -146 - 198 - 20 - - - 1319.944 - -145.6 - - - - - - 4 - 1 - 0 - 10 - 0 - 0 - 0 - - - - - - - - - 57da07bd-ecab-415d-9d86-af36d7073abc - Number Slider - - - - - Numeric slider for single values - 8a0da811-cdf8-40a9-8bf6-b9ca6e808e93 - Number Slider - - false - 0 - - - - - - 1320 - -113 - 198 - 20 - - - 1320.4 - -112.8 - - - - - - 3 - 1 - 0 - 1 - 0 - 0 - 0.94 - - - - - - - - - bc3e379e-7206-4e7b-b63a-ff61f4b38a3e - Construct Plane - - - - - Construct a plane from an origin point and {x}, {y} axes. - ecac92db-7448-402c-b3cf-ff3e6e6899df - Construct Plane - Pl - - - - - - 1778 - -467 - 68 - 64 - - - 1810 - -435 - - - - - - Origin of plane - 499578c3-f0b0-4532-ad9c-d8f29a0317f3 - Origin - O - false - 86990d0f-35da-4def-8414-369478a9cd09 - 1 - - - - - - 1780 - -465 - 15 - 20 - - - 1789 - -455 - - - - - - 1 - - - - - 1 - {0} - - - - - - - 0 - 0 - 0 - - - - - - - - - - - - X-Axis direction of plane - 9ab3ee88-a0cf-4f8c-9c00-655609c50c66 - X-Axis - X - false - 0 - - - - - - 1780 - -445 - 15 - 20 - - - 1789 - -435 - - - - - - 1 - - - - - 1 - {0} - - - - - - 1 - 0 - 0 - - - - - - - - - - - - Y-Axis direction of plane - 1242e202-ab1c-4bd4-8758-3e8a01c6ad1e - Y-Axis - Y - false - 0 - - - - - - 1780 - -425 - 15 - 20 - - - 1789 - -415 - - - - - - 1 - - - - - 1 - {0} - - - - - - 0 - 1 - 0 - - - - - - - - - - - - Constructed plane - 95c8982c-bf0e-42d6-878b-a91bdf0ce279 - Plane - Pl - false - 0 - - - - - - 1825 - -465 - 19 - 60 - - - 1834.5 - -435 - - - - - - - - - - - - b464fccb-50e7-41bd-9789-8438db9bea9f - Angle - - - - - Compute the angle between two vectors. - 675ea98b-dcbe-4567-8b05-b956161c3abd - Angle - Angle - - - - - - 1934 - -370 - 65 - 64 - - - 1965 - -338 - - - - - - First vector - f7ce62cc-b107-4528-850c-5262e0477a2f - Vector A - A - false - 72567da6-0377-4dd3-813f-06c874b0500a - 1 - - - - - - 1936 - -368 - 14 - 20 - - - 1944.5 - -358 - - - - - - - - Second vector - 0ec1d0fe-fb8d-4dc7-a70b-5413f7315163 - Vector B - B - false - 260659d9-0c72-4130-820d-16c404b4e462 - 1 - - - - - - 1936 - -348 - 14 - 20 - - - 1944.5 - -338 - - - - - - - - Optional plane for 2D angle - 600f5434-81cc-4422-8787-742266d9cc43 - Plane - P - true - 0 - - - - - - 1936 - -328 - 14 - 20 - - - 1944.5 - -318 - - - - - - - - Angle (in radians) between vectors - 8b46d8d5-832a-4eeb-a447-207623299a11 - Angle - A - false - 0 - - - - - - 1980 - -368 - 17 - 30 - - - 1988.5 - -353 - - - - - - - - Reflex angle (in radians) between vectors - 603840f6-b261-4ebc-aa08-c748d4d266db - Reflex - R - false - 0 - - - - - - 1980 - -338 - 17 - 30 - - - 1988.5 - -323 - - - - - - - - - - - - c73e1ed0-82a2-40b0-b4df-8f10e445d60b - Flip Plane - - - - - Flip or swap the axes of a plane - 40b4dcec-ab3d-48ae-900a-7fa7065785dd - Flip Plane - PFlip - - - - - - 1863 - -504 - 80 - 84 - - - 1910 - -462 - - - - - - Plane to adjust - 0dbcaff4-7f38-4225-a0a9-bee4947ea2a8 - Plane - P - false - 95c8982c-bf0e-42d6-878b-a91bdf0ce279 - 1 - - - - - - 1865 - -502 - 30 - 20 - - - 1889.5 - -492 - - - - - - 1 - - - - - 1 - {0} - - - - - - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - - - - - - - - - - Reverse the x-axis direction - e7d8f9ef-4171-4b1a-ab69-4a15ed947dfc - true - Reverse X - X - false - 0 - - - - - - 1865 - -482 - 30 - 20 - - - 1889.5 - -472 - - - - - - 1 - - - - - 1 - {0} - - - - - false - - - - - - - - - - - Reverse the y-axis direction - 55be9c4c-99e0-4792-848b-97dc21ccbd72 - Reverse Y - Y - false - 0 - - - - - - 1865 - -462 - 30 - 20 - - - 1889.5 - -452 - - - - - - 1 - - - - - 1 - {0} - - - - - false - - - - - - - - - - - Swap the x and y axis directions - 014e4a00-fc61-439a-a08d-ee676ad1a7c0 - true - Swap axes - S - false - 0 - - - - - - 1865 - -442 - 30 - 20 - - - 1889.5 - -432 - - - - - - 1 - - - - - 1 - {0} - - - - - true - - - - - - - - - - - Flipped plane - 3d42bdab-d3a7-4999-9fa1-5775536451be - Plane - P - false - 0 - - - - - - 1925 - -502 - 16 - 80 - - - 1933 - -462 - - - - - - - - - - - - 0d77c51e-584f-44e8-aed2-c2ddf4803888 - Degrees - - - - - Convert an angle specified in radians to degrees - 67c0d4e8-0067-4e24-a46a-0639442d92fb - Degrees - Deg - - - - - - 2016 - -367 - 66 - 28 - - - 2047 - -353 - - - - - - Angle in radians - 3f198962-b4e3-4cde-a697-da7232934f3f - Radians - R - false - 8b46d8d5-832a-4eeb-a447-207623299a11 - 1 - - - - - - 2018 - -365 - 14 - 24 - - - 2026.5 - -353 - - - - - - - - Angle in degrees - 900686d0-979a-486d-9fa9-1bfcfc37d4d2 - Degrees - D - false - 0 - - - - - - 2062 - -365 - 18 - 24 - - - 2071 - -353 - - - - - - - - - - - - a50fcd4a-cf42-4c3f-8616-022761e6cc93 - Deconstruct Vector - - - - - Deconstruct a vector into its component parts. - 9ecc241f-225a-4955-acf8-1678ddef6b39 - Deconstruct Vector - DeVec - - - - - - 1989 - -494 - 65 - 64 - - - 2020 - -462 - - - - - - Input vector - cfbe4b74-1485-474d-ad23-b0354f98ed2b - Vector - V - false - 95c8982c-bf0e-42d6-878b-a91bdf0ce279 - 1 - - - - - - 1991 - -492 - 14 - 60 - - - 1999.5 - -462 - - - - - - - - Vector {x} component - 129fe0e4-95ad-4604-91ff-48cb3619ef0b - X component - X - false - 0 - - - - - - 2035 - -492 - 17 - 20 - - - 2043.5 - -482 - - - - - - - - Vector {y} component - e1aaa859-ee1d-4b6c-945d-5977b6e6bc78 - Y component - Y - false - 0 - - - - - - 2035 - -472 - 17 - 20 - - - 2043.5 - -462 - - - - - - - - Vector {z} component - e11b04e9-327f-4e26-9d53-af632808ba50 - Z component - Z - false - 0 - - - - - - 2035 - -452 - 17 - 20 - - - 2043.5 - -442 - - - - - - - - - - - - a50fcd4a-cf42-4c3f-8616-022761e6cc93 - Deconstruct Vector - - - - - Deconstruct a vector into its component parts. - cc4f2080-8879-46f9-9bd4-33fe0e6f06a7 - Deconstruct Vector - DeVec - - - - - - 1847 - -309 - 65 - 64 - - - 1878 - -277 - - - - - - Input vector - 25f78783-acd2-4be5-8d67-cb35df6adacc - Vector - V - false - a029cb6f-5b4e-49f4-88b4-5b60063bbc9f - 1 - - - - - - 1849 - -307 - 14 - 60 - - - 1857.5 - -277 - - - - - - - - Vector {x} component - 2d5ca2ed-4cdf-4467-a388-6b1ce2a32327 - X component - X - false - 0 - - - - - - 1893 - -307 - 17 - 20 - - - 1901.5 - -297 - - - - - - - - Vector {y} component - 4c32d96e-93e6-4032-a2eb-b03984ab1412 - Y component - Y - false - 0 - - - - - - 1893 - -287 - 17 - 20 - - - 1901.5 - -277 - - - - - - - - Vector {z} component - 06bb0fa2-4579-46a1-a5c6-328b32ee8b4f - Z component - Z - false - 0 - - - - - - 1893 - -267 - 17 - 20 - - - 1901.5 - -257 - - - - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - 859bdc6a-fb55-4907-95fa-42bcb11b161e - Panel - - false - 0 - 0 - 1 - - - - - - 1791 - -368 - 36 - 20 - - 0 - 0 - 0 - - 1791.14 - -367.948 - - - - - - - 255;255;250;90 - - true - true - true - false - false - true - - - - - - - - - 79f9fbb3-8f1d-4d9a-88a9-f7961b1012cd - Unit X - - - - - Unit vector parallel to the world {x} axis. - 4528f945-8eab-4d55-b3a6-a9b08362cacf - Unit X - X - - - - - - 1849 - -372 - 63 - 28 - - - 1878 - -358 - - - - - - Unit multiplication - bb427121-1130-486d-a1a7-a496ae0e9a39 - Factor - F - false - 859bdc6a-fb55-4907-95fa-42bcb11b161e - 1 - - - - - - 1851 - -370 - 12 - 24 - - - 1858.5 - -358 - - - - - - 1 - - - - - 1 - {0} - - - - - 1 - - - - - - - - - - - World {x} vector - 72567da6-0377-4dd3-813f-06c874b0500a - Unit vector - V - false - 0 - - - - - - 1893 - -370 - 17 - 24 - - - 1901.5 - -358 - - - - - - - - - - - - 22990b1f-9be6-477c-ad89-f775cd347105 - Flip Curve - - - - - Flip a curve using an optional guide curve. - true - 906af723-08ba-430d-ad6e-ce07b5200482 - Flip Curve - Flip - - - - - - 306 - 247 - 66 - 44 - - - 338 - 269 - - - - - - Curve to flip - bd1ba6e6-2103-43e7-879b-abc57ddb7e9b - Curve - C - false - e2fec716-2636-48c7-b126-85ba3955f210 - 1 - - - - - - 308 - 249 - 15 - 20 - - - 317 - 259 - - - - - - - - Optional guide curve - 5008ee96-d5d7-4eb5-9a37-ea1e8e51e171 - Guide - G - true - 0 - - - - - - 308 - 269 - 15 - 20 - - - 317 - 279 - - - - - - - - Flipped curve - acefae73-90c1-40be-b9e0-9dacb241a229 - Curve - C - false - 0 - - - - - - 353 - 249 - 17 - 20 - - - 361.5 - 259 - - - - - - - - Flip action - cf03ee7a-3fab-46f1-ad0d-ca67432e84fe - Flag - F - false - 0 - - - - - - 353 - 269 - 17 - 20 - - - 361.5 - 279 - - - - - - - - - - - - 2e78987b-9dfb-42a2-8b76-3923ac8bd91a - Boolean Toggle - - - - - Boolean (true/false) toggle - f0df0e81-ffad-41f2-a721-b13a2d9713ac - Boolean Toggle - FlipCurve - false - 0 - false - - - - - - 173 - 201 - 115 - 22 - - - - - - - - - - eeafc956-268e-461d-8e73-ee05c6f72c01 - Stream Filter - - - - - Filters a collection of input streams - true - c8935f57-0127-4738-af16-55bef27daede - Stream Filter - Filter - - - - - - 384 - 207 - 77 - 64 - - - 416 - 239 - - - - - - 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 - 2150f2e4-0536-4061-bcc7-82a78f2ce165 - Gate - G - false - f0df0e81-ffad-41f2-a721-b13a2d9713ac - 1 - - - - - - 386 - 209 - 15 - 20 - - - 395 - 219 - - - - - - 1 - - - - - 1 - {0} - - - - - 0 - - - - - - - - - - - 2 - Input stream at index 0 - 52165d88-897d-4411-b229-40c33d6dcacf - false - Stream 0 - 0 - true - e2fec716-2636-48c7-b126-85ba3955f210 - 1 - - - - - - 386 - 229 - 15 - 20 - - - 395 - 239 - - - - - - - - 2 - Input stream at index 1 - ef6ce42a-3047-4a1a-9ecd-2c6bcc799ad5 - false - Stream 1 - 1 - true - acefae73-90c1-40be-b9e0-9dacb241a229 - 1 - - - - - - 386 - 249 - 15 - 20 - - - 395 - 259 - - - - - - - - 2 - Filtered stream - 36c4deda-ceed-4920-a3f3-2d18ca613b35 - false - Stream - S(0) - false - 0 - - - - - - 431 - 209 - 28 - 60 - - - 445 - 239 - - - - - - - - - - - - - - d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 - Curve - - - - - Contains a collection of generic curves - true - e2fec716-2636-48c7-b126-85ba3955f210 - Curve - Crv - false - 18d2fa4a-de1b-4cfd-bf80-4b8d5fa0182f - 1 - - - - - - 236 - 227 - 50 - 24 - - - 261.4741 - 239.9949 - - - - - - 1 - - - - - 1 - {0} - - - - - -1 - - Y2BkYGD4DwQgGgR4mIBEeFBGZl6+c35ubn6ejkJYalFxZn6erbmesYmekbGRmbmeoaGBgaGOgnNpTklpUaptXmppSVFijo5CQGlSTmayd2plSH52ap6tqamRkYVhqqV5srmpqamxASvIFhmw4Xruqfm5qSVFlXoB+TmVOZl5qc6lRWWpLEAF7GUQC7kSi5IzMstSjVNyOfMLUvPySouSillSEksSQYo4ODiYQG4VUGdgMALS9f/4eDiZgQx+EDEViJl+1TMxdEL99fs/E4MIlP3synU/95eXBfc/ZRBoZlT64Ddn9+0/QPlAqLwAyNy4bxpcrDPvOXz4/18+rHjlAagcQwpU3KHb70cS13q4OBMDAuxtjlpjZzvZAeSS6oIuv//1TA0wOW6GwQQA - - 00000000-0000-0000-0000-000000000000 - - - - - - - - - - - - - c552a431-af5b-46a9-a8a4-0fcbc27ef596 - Group - - - - - 1 - - 150;255;255;255 - - A group of Grasshopper objects - e2fec716-2636-48c7-b126-85ba3955f210 - f0df0e81-ffad-41f2-a721-b13a2d9713ac - 2 - c4bae22a-eb6f-4c74-a53a-12421686e963 - Group - - - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - e96e7f8c-fbda-4b4e-b878-1e3a5af5d17b - Panel - BTLx Params - false - 0 - 9d870029-3b28-4cf0-b9f2-93c9376334f2 - 1 - Double click to edit panel content… - - - - - - 2611 - -367 - 206 - 333 - - 0 - 0 - 0 - - 2611.206 - -366.2764 - - - - - - - 255;255;255;255 - - true - true - true - false - false - true - - - - - - - - - 8ec86459-bf01-4409-baee-174d0d2b13d0 - Data - - - - - Contains a collection of generic data - 9d870029-3b28-4cf0-b9f2-93c9376334f2 - Data - Data - false - 0 - - - - - - 2123 - -273 - 50 - 24 - - - 2148 - -260.8 - - - - - - 1 - - - - - 20 - {0;0;0} - - - - - Grasshopper.Kernel.Types.GH_String - false - Name: DovetailMortise - - - - - Grasshopper.Kernel.Types.GH_String - false - Process: yes - - - - - Grasshopper.Kernel.Types.GH_String - false - Priority: 0 - - - - - Grasshopper.Kernel.Types.GH_String - false - ProcessID: 0 - - - - - Grasshopper.Kernel.Types.GH_String - false - ReferencePlaneID: 4 - - - - - Grasshopper.Kernel.Types.GH_String - false - StartX: 549.649 - - - - - Grasshopper.Kernel.Types.GH_String - false - StartY: 19.205 - - - - - Grasshopper.Kernel.Types.GH_String - false - StartDepth: 0.000 - - - - - Grasshopper.Kernel.Types.GH_String - false - Angle: 90.000 - - - - - Grasshopper.Kernel.Types.GH_String - false - Slope: 90.000 - - - - - Grasshopper.Kernel.Types.GH_String - false - LimitationTop: limited - - - - - Grasshopper.Kernel.Types.GH_String - false - LengthLimitedBottom: yes - - - - - Grasshopper.Kernel.Types.GH_String - false - Length: 60.000 - - - - - Grasshopper.Kernel.Types.GH_String - false - Width: 45.029 - - - - - Grasshopper.Kernel.Types.GH_String - false - Depth: 28.000 - - - - - Grasshopper.Kernel.Types.GH_String - false - ConeAngle: 10.000 - - - - - Grasshopper.Kernel.Types.GH_String - false - UseFlankAngle: no - - - - - Grasshopper.Kernel.Types.GH_String - false - FlankAngle: 15.000 - - - - - Grasshopper.Kernel.Types.GH_String - false - Shape: automatic - - - - - Grasshopper.Kernel.Types.GH_String - false - ShapeRadius: 22.514 - - - - - - - - - - - - - 6b7ba278-5c9d-42f1-a61d-6209cbd44907 - Curve Proximity - - - - - Find the pair of closest points between two curves. - f108ae57-2009-4f60-8f2d-15faa523d976 - Curve Proximity - CrvProx - - - - - - 667 - 342 - 66 - 64 - - - 698 - 374 - - - - - - First curve - c738ea7a-d604-42f9-a5ef-30c6c6ddce02 - Curve A - A - false - 36c4deda-ceed-4920-a3f3-2d18ca613b35 - 1 - - - - - - 669 - 344 - 14 - 30 - - - 677.5 - 359 - - - - - - - - Second curve - 71da35f8-2834-47e3-a13e-7a2936ab42c0 - Curve B - B - false - d2d51328-18f6-4ef3-8dd6-1df6b6af922e - 1 - - - - - - 669 - 374 - 14 - 30 - - - 677.5 - 389 - - - - - - - - Point on curve A closest to curve B - 7542c648-8889-4d83-8f10-9e8b260fa85a - Point A - A - false - 0 - - - - - - 713 - 344 - 18 - 20 - - - 722 - 354 - - - - - - - - Point on curve B closest to curve A - 3819d11f-35d9-4e55-b397-0509416544db - Point B - B - false - 0 - - - - - - 713 - 364 - 18 - 20 - - - 722 - 374 - - - - - - - - Smallest distance between two curves - 51674317-ad4b-4b8d-aefb-154a53c3be9f - Distance - D - false - 0 - - - - - - 713 - 384 - 18 - 20 - - - 722 - 394 - - - - - - - - - - - - 919e146f-30ae-4aae-be34-4d72f555e7da - Brep - - - - - Contains a collection of Breps (Boundary REPresentations) - 8bd29712-ff83-438b-b8f1-1d5f93dba350 - Brep - Brep - false - 389410e6-fbd0-4b13-ad00-528c4c2075fd - 1 - - - - - - 1878 - 304 - 50 - 24 - - - 1903.265 - 316.8058 - - - - - - - - - - d2da1306-259a-4994-85a4-672d8a4c7805 - Unit Vector - - - - - Unitize vector. - a9436695-3954-44b4-aae3-32ec284e7381 - Unit Vector - Unit - - - - - - 788 - 272 - 65 - 28 - - - 819 - 286 - - - - - - Base vector - 6016a9d4-590c-4c16-9666-d6f61bb42855 - Vector - V - false - 4c90d06e-9810-41a6-baa8-91b753ccec55 - 1 - - - - - - 790 - 274 - 14 - 24 - - - 798.5 - 286 - - - - - - - - Unit vector - 7340ce74-ba19-4774-8009-78fd26d19e4b - Vector - V - false - 0 - - - - - - 834 - 274 - 17 - 24 - - - 842.5 - 286 - - - - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - 2344469e-f0a8-4b55-bd93-416708bd4b8f - Panel - - false - 0 - 7340ce74-ba19-4774-8009-78fd26d19e4b - 1 - Double click to edit panel content… - - - - - - 714 - 146 - 187 - 100 - - 0 - 0 - 0 - - 714.4128 - 146.7059 - - - - - - - 255;255;250;90 - - true - true - true - false - false - true - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - 0c4e35ca-557d-470f-95d2-4cf5846483d2 - Panel - BTLx Params - false - 0 - 83bdcfa8-afbb-420d-9faa-98a158aee68d - 1 - Double click to edit panel content… - - - - - - 129 - 232 - 206 - 333 - - 0 - 0 - 0 - - 129.2169 - 232.1959 - - - - - - - 255;255;255;255 - - true - true - true - false - false - true - - - - - - - - - 59e0b89a-e487-49f8-bab8-b5bab16be14c - Panel - - - - - A panel for custom notes and text values - be041dc1-b473-45b4-a41f-6e3d871e6182 - Panel - - false - 0.81688592955470085 - ec68082b-6816-42e0-b242-ac0746b13092 - 1 - G:\Shared drives\2024_MAS\T2\03_finalization\Fabrication - Joints\BTLx\step_joint_joint_test.btlx - - - - - - -288 - 74 - 455 - 420 - - 0 - 0 - 0 - - -287.0021 - 74.40424 - - - - - - - 255;255;250;90 - - true - true - true - false - true - D:\Papachap\Desktop\BTLx\dovetail_joint.btlx - true - - - - - - - - - 3cd2949b-4ea8-4ffb-a70c-5c380f9f46ea - Deconstruct Plane - - - - - Deconstruct a plane into its component parts. - 865c30f6-b561-4871-a50c-ecd9f31c5e9e - Deconstruct Plane - DePlane - - - - - - 1964 - 139 - 65 - 84 - - - 1994 - 181 - - - - - - Plane to deconstruct - 4921bd95-db88-4938-a2ab-031a1bdbd283 - Plane - P - false - a5781cd0-b305-4ed7-99aa-69c993f66d09 - 1 - - - - - - 1966 - 141 - 13 - 80 - - - 1974 - 181 - - - - - - 1 - - - - - 1 - {0} - - - - - - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - - - - - - - - - - Origin point - cdcaa9a0-4d91-4482-86b7-86be2cda44b1 - Origin - O - false - 0 - - - - - - 2009 - 141 - 18 - 20 - - - 2018 - 151 - - - - - - - - X-Axis vector - d1e3671d-a71b-4d78-b593-81a36a647a0e - X-Axis - X - false - 0 - - - - - - 2009 - 161 - 18 - 20 - - - 2018 - 171 - - - - - - - - Y-Axis vector - 7d146df4-fb05-4842-baef-b21818d33e42 - Y-Axis - Y - false - 0 - - - - - - 2009 - 181 - 18 - 20 - - - 2018 - 191 - - - - - - - - Z-Axis vector - 88bddd76-b302-4c78-a0e9-35bc4b391b6b - Z-Axis - Z - false - 0 - - - - - - 2009 - 201 - 18 - 20 - - - 2018 - 211 - - - - - - - - - - - - e9eb1dcf-92f6-4d4d-84ae-96222d60f56b - Move - - - - - Translate (move) an object along a vector. - 69027599-f85b-4df6-a905-640e9354acc8 - Move - Move - - - - - - 2135 - 61 - 67 - 44 - - - 2167 - 83 - - - - - - Base geometry - 11854871-a4b0-4632-9734-2c92f39bd6e2 - Geometry - G - true - 0 - - - - - - 2137 - 63 - 15 - 20 - - - 2146 - 73 - - - - - - - - Translation vector - fa75702c-db09-4f3d-8b4d-9c4113d2c4fd - Motion - T - false - 0 - - - - - - 2137 - 83 - 15 - 20 - - - 2146 - 93 - - - - - - 1 - - - - - 1 - {0} - - - - - - 0 - 0 - 10 - - - - - - - - - - - - Translated geometry - 0060d1e4-4dbd-4989-ad5c-c635ced49a6d - Geometry - G - false - 0 - - - - - - 2182 - 63 - 18 - 20 - - - 2191 - 73 - - - - - - - - Transformation data - e630803b-d52f-410b-a74e-0533b5adb7fd - Transform - X - false - 0 - - - - - - 2182 - 83 - 18 - 20 - - - 2191 - 93 - - - - - - - - - - - - a3371040-e552-4bc8-b0ff-10a840258e88 - Negative - - - - - Compute the negative of a value. - 7526f9a6-8359-4b37-9c5e-cbee913b3ef8 - Negative - Neg - - - - - - 949 - 1023 - 61 - 28 - - - 978 - 1037 - - - - - - Input value - 5afb0642-aa38-48c2-866b-65ac743bd828 - Value - x - false - a3e72ece-c329-479f-b17f-94062e976ee8 - 1 - - - - - - 951 - 1025 - 12 - 24 - - - 958.5 - 1037 - - - - - - - - Output value - 268a388f-8c6d-4802-b21e-c9fdcefc3839 - Result - y - false - 0 - - - - - - 993 - 1025 - 15 - 24 - - - 1000.5 - 1037 - - - - - - - - - - - - a3371040-e552-4bc8-b0ff-10a840258e88 - Negative - - - - - Compute the negative of a value. - 685030bd-f114-48e8-8d19-4be9039d542e - Negative - Neg - - - - - - 1552 - 294 - 61 - 28 - - - 1581 - 308 - - - - - - Input value - b86e2643-6e28-4ba1-ba12-340d36937ccf - Value - x - false - 6b6d7ea8-7a08-4879-939c-5f96604c4678 - 1 - - - - - - 1554 - 296 - 12 - 24 - - - 1561.5 - 308 - - - - - - - - Output value - 5a7f3b31-fffa-478e-b8ef-7eb827144b57 - Result - y - false - 0 - - - - - - 1596 - 296 - 15 - 24 - - - 1603.5 - 308 - - - - - - - - - - - - 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 - - iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDAAACwwBP0AiyAAAAhJJREFUSEullLFLQlEUxt/WECgETQYKCS6BJLQlSoSCg7ZIRILiEEKbDQ5v0K1Baskx0L3gbREtz6Hd/oDAsdGmCKJu97t57L77zkulAz8e7977fYd33rnHEkKwbFw+dgC3Z9JsNg8TicSbZVlCp1qt8gJpHJO8TolxZ4h6vX4dCoW+TPN+vy/G4zEvkqYDiZgy4M7Yth3N5XLPpnE0GhWj0Ui4rivC4bBfKA2zmjmR1c8ElSSTyYjJZCLa7fbvui4E0mxomIMh7VcqFUc3JWAK81Kp5N0zzGuG8Yyt7v1ZOp1+8YglKIPjOKosKI+5zyVA93j+QercuYnkjz9NcTKZVD8SP1TV29hX6Am0RLP/sH/SeuKEaEGURLUisz9jXoKV+LZPRC2ILzD3fHAJCvZVj0vga0HdKAjTvFwuD7mDbAsuAhm3Wq1drrdBYAtOWd0pKMx13HJl3mg0zrnrPrcFp4TydVXO9dOeKmkkEvnAZYS3VSwWR5xoXgvCiFg7slUCYvPCvZVPNcPwBYHxVwvqhgFgUHbkWd4Awa0ThhnH/xJQeeJ7B++J7sOdYY5J8FMiXaQzLwHAuMbYlmYYLzDGoPRMXoRPCBDcOoEWJBNpihlWo3cdhE8MENy63oKLgPCZAIS5lkqlJigJiRcB4TMCCP0dI4REy4DwGBEIPHHDcdNJsCwIjzGBwGzCjKLDyyOsb83ZZgK8ltr3AAAAAElFTkSuQmCC - - false - a9ce3e7a-6c1c-4572-a3de-4c9f2b90a244 - true - true - CT: DecomposeBeam - DecomposeBeam - - - - - - 1491 - 474 - 156 - 104 - - - 1571 - 526 - - - - - - 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 - e5d6bec6-04a7-4002-ac35-9b4259344b67 - Beam - Beam - true - 1 - true - 90fae02f-7750-462d-828f-cf5f2a0d39ae - 1 - 35915213-5534-4277-81b8-1bdc9e7383d2 - - - - - - 1493 - 476 - 63 - 33 - - - 1526 - 492.6667 - - - - - - - - true - Script input ShowFrame. - 7f4fda41-cbe9-4054-af0d-3fcb07967a5e - ShowFrame - ShowFrame - true - 0 - true - 47ff7ca2-adef-4499-810b-6e4c01b3bc23 - 1 - d60527f5-b5af-4ef6-8970-5f96fe412559 - - - - - - 1493 - 509 - 63 - 33 - - - 1526 - 526 - - - - - - - - true - Script input ShowFaces. - 0610d8df-83d0-4efa-be35-2b855fa8b7c7 - ShowFaces - ShowFaces - true - 0 - true - 0 - d60527f5-b5af-4ef6-8970-5f96fe412559 - - - - - - 1493 - 542 - 63 - 34 - - - 1526 - 559.3334 - - - - - - - - Script output Frame. - 9ce0b74d-024e-4803-ab40-8f1894bddfc7 - Frame - Frame - false - 0 - - - - - - 1586 - 476 - 59 - 20 - - - 1615.5 - 486 - - - - - - - - Script output Centerline. - 406aa56b-e577-4896-9649-5abbf8f8264e - Centerline - Centerline - false - 0 - - - - - - 1586 - 496 - 59 - 20 - - - 1615.5 - 506 - - - - - - - - Script output Box. - c1c31314-d156-4509-8d4e-2ee79ece2b88 - Box - Box - false - 0 - - - - - - 1586 - 516 - 59 - 20 - - - 1615.5 - 526 - - - - - - - - Script output Width. - ebb35db7-496b-4eef-91a1-a7727e7c7abc - Width - Width - false - 0 - - - - - - 1586 - 536 - 59 - 20 - - - 1615.5 - 546 - - - - - - - - Script output Height. - 2f18ca4a-b883-4a4c-afe0-eb75ffe432b2 - Height - Height - false - 0 - - - - - - 1586 - 556 - 59 - 20 - - - 1615.5 - 566 - - - - - - - - - - - - - - 2e78987b-9dfb-42a2-8b76-3923ac8bd91a - Boolean Toggle - - - - - Boolean (true/false) toggle - 47ff7ca2-adef-4499-810b-6e4c01b3bc23 - Boolean Toggle - Toggle - false - 0 - true - - - - - - 1343 - 586 - 104 - 22 - - - - - - - - - - - - - - - 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/fsPHj58zKTJM+bNW/z552kbN24z8WDOEeucPn3x3LnLZ899qXLy5HmL2+IrZWFMXt5REiTFY8eOgUiPHj0mTZp09uxZ8j59+nTfvn2rVas2YcKEVatWpaWlPffcc8uXL9cOW2fOnJkzZ07Hjh2NjDsp7dH/4OnkqVOnDEDs06xZswqDppi+FuF49N9FHz1+/Dh2o/CfUu3fv5932LBhw+effz5//vypU6empKT079+/a1cwateqVavWrVt36NChe/fuSUlJ4f/AWrRo0Zo1a7Zu3Sr4sGx8QYC4/19/Ncasli1bvv322+zHrl27rMCt/Md//Mcnn3wybty4kSNHrlixYsyYMZUrV+aSBDS7d+92vLp1606cOPHChQtQcuLEib1793JhwJSamsqpvf/++x988IEAqBg0T4IIGG6AibwJIy57XaRFwPR+yZIlJEqQgwYNAh2+A4wQSH344YcDBgwI/4maYenp6du3b4dC0AmrwVMcRuQ9ffr0Ro0amVK9evWZM2cGQEDPb3/724EDB4KLRZo2bfrjH/+YKYIMkY0xCxYseOeddzIyMsCCfbJpwDH7BDHWdDaGytxvJWiCDArTfZTvQYhQnzCRdLBJcfuvooX279ixg1kiYIo+fvz45OTkXr16derUCYZQ586dvQ4ePJjZmDt37urVq2ECjKwg8m3WrBkoXLt2jRuaPHkyQyIQ0TJkyJCXX365SZMm//RP/0TiZcqUif/HgIACsh999BGItGjRgrVbuHAhaDqkI3FhnhcvXuTOnOdbBhqRGgVFe/fu2bUre/fuXfGC4IbmFRk6lIzGM8jfLPEjBO8wsh5GCBEqAEHA4sWLiZazIFRhEdwwJ548EcvUs2fPsWPH1qpVS3IEBFCCG7whSHmuXLnSylWrVv3Xf/3Xp5566k9/+hMnZSNX1u7JnFhEeiUthxJzISaRmeq6HONbABpnjROl3LhxI8s5evT4Tz6ZP336nFBmzJg7deqszp270AOQClYnTrGF7k00PmSklEnY+PdJ586dE218+eWXkp2rV69evnz50qVLKrTl008/dXGREDtRqlQpKRLx83EcCkcDZzARcCNI+uI2cXOwyFYJVqAQXkPYhHsxvtxJGMuY/X25J9J1XMYZxuMmMfj+AALA53rffvud73//+z16DJ42bcmECfNCmTTp03Hj5vzyl//P73//u6VLl7p8+KjKFNMtEl/Q4lqgJA4sWxsQgkEiIZvCRGYEhoLwHpAMJlcytqwKinU8OrIyozJt2jS7QDzrIqaGDM5FDCTK9soCgVTgJM4gTDAYE4YNG9a8eXOBefCSgRsFCKPMdRcVkTKQfcOgcUrHdSYSVRHkw74LT5kyhbWUXLiwNE84JhtEjRs3+eUvfwk0XbsOGDt2dkrKtFBkGyNGTP31r3/3gx98v0aNGsH3G69iukVokmxFziIloXZCP3sBFkbgIGWtV68eG6YeIkqH0YWPIezw5OCZIufE+sDieJfxBhcmva5jR16Aj5CYhGUfITkMrNevX19gi2ni3FdeeYXJ4cKGDh3q7o0bNw4BEM9iPJ47g9DHqRgkQYz4yaXuChdENAYIm6xmZfE1PnwzoHFETHdWHOe5RfhOT8Dh/9wW0nt1bXYVgNhVlpOPF7Klpa0pUaLE9773vXbteqWkTB88eEIoQ4dO9vzP//y/gYZfZzYsS2DBLFtE3sFW4ymjDUw2QgFYvXv3Llu2rDjAwcjAYH6dAGgnDXY2dV18ORyD3QSWbd48Cic+FRYICIKOFibisQKwuo4g1PgQJTxCwkBCDVcQF8t3ypUrR9koiVdXlvVIi2iFrYEGXFgmWiRY5qG8ao/K5C7EMMOWwFn8FD4CkF65/pMGDT7Cioq8AB+JzT379OkjyHcHwsaIYHiCb6L6RGIWwiCXJDAMat26c1LSiL59h4TSr9+w3r0Hv/DCi9hhfHBApgSDbJGwJlLHJr5Z4hA+O2dgoOGtt97SYjykhhABPnBcTACFhgkIAMWZcY3lF4HOnj3bAGCyRbhdAbJRSE+YKCD2JGAXjHU/CnJHK1MAi7sy18y6uAV8eFVxcaSOnxpZO2aJKXI27bFV7kbGYwJ/xNkFcfBQLDT+PCHQ4FSQHAnxoyHaJwyWgI9wIOSGbvKVPA1XZSSj/uJvZfv2bTy6dYIRvg/Zwhh7xYElOGCBGTN1cuW59FrN2Vh1LfyLk4ePRjy16Iotd28yJuwSNlKPdTw6siZQ8lDYQqMYNlZNJbDR077hddasWawLmyEXCwFKWOGuZFkGqUGDBhBpemgMa1LaJwGaYC2k+OIyYRe1DuKBX8+vlHFhui0Jz8RypMhSMRfoJLdhBdwh78CjQImLh/bEXoO/kgwzJVCsKYHC4rGX2xRd+ysWx704aPCTc+eMVDA8PFlTjp6WskCfffaZFnvRBM+gMK7mNU5hTasxtNwceIVjBNLF0z1e0DgT1QeX4IaA3Zkg13HxLjbo74AwjkpRQayMyuKRkQXd1Prq+/bt40QI2PUDCjUSg1dbE1hQIa/ILOMNCHIN45GKMZGlo+SVBnLKhnHxH374obm8PJ7DijARXAQ3wvDweQ+TGTwyF8zRCLM8tWsMXWw/l0pGoiKBIPHFeHSb7P64QGNpG4N5sC6SugAg7bERf0/kbGSJd47H9cSJVPSGehgZ6g9IViM89ly4JpgYPnx4iK9FQuHrJ+uLGMSY4iT+Ua861fIKNEuWLCFUwzideKRlHeEg9MS34EY5nd/85jelSpUS3GB4mzZtZEzynWXLlhkjLXc7oLx27Zr6rVu31GvWrPn8889Xr17917/+NTGRvq7Lly+TGv25dOmShMuOvES4eCI9etBgBBtIA2QW8ljwVweXb9y0OABeU0QQcUIW2KkQNqn37duXnpEBiis35mK3weZSX6qvywrGRKxBlHQZFkRYgAwDApImPwEcNIALEIigtdiR9ntNTk6GErGIhGDx4sVCbAmX7ZgH8Z+RJsJNSKRDNpQIGieklvJnoTpieMDIObknFMIXpkiM4pqhXUApfwZigx2jYsWK58+fD1fDEDkmU8Q+ObkpMfYl0KMHDRnYskWLFpJbB/X6jcAlyJWi4BFG4IhG/hib6D0lxhGSIC1ikyO0atUqOA7ZkHYDyMwYdsITLMiD3rMcjIQVSI5tYMCpacBNYSJU8iN+Bl9wbX0HEEc7SbA96enpAORIWvDKGL0mGuYY2AimYYqlDAgGI4wJZGtuBezc0U2Durq7ihb7fv7557Vq1RLQqJtuPGX+3e9+Z336DJSCOdeHVF1hCwcDQV0yR4tEuHknPUrQOCuIUIs6derghTuQQazviRD9CyjxxG7cZGCpePgFAvUKn83w9ABNwyi3qFwijWsyCywzEUoot6SafTaM0sPKhg0biFm+rUWviez/mDFjcFaW65oxGRYiwo6EHgkUsQ8HDwbo4BhSiQ8LvSpB0wo0xuux1Q8cMIZXBaygFQhoSMHde/fuzQK5+9tvv92xY0dWDW7sy2L9/Oc/B3q64VJ82a9+9St3wTEZtTHqjRo1mjlzprDm8YLGWZkybG3SpInzOXes4/ETmQWg4B3zTpPEg3ghlcA4rxBM4SguWITxBmMHMtFRVdhkeg92VI1tQIASGM0AMDMMT1hBtsK6EJW6YcYnSjGRgkkIveQNB56hBanHB8TRgEJLvCve4mmF0BJIi+sIQZzEFdzLXTCBsBs3bsxgOJsW7RyfKzh5QFiVKlXCh5w//vGPif6dd95hEXW5lzHUScWy1AxDAnwTqeigSbwnxFidqMhJO9THOh4n2RGn7EW6jAFbEhJLtmHhwoUu77bAAcpsNcYZjzQW5oJerMSmRKGGrlAPZKJnaEeh0XgCvivpor5gZ1lKHHITQCQhvQAXBgAlZ2GYV40GGxC6oCH4LMfzdFPIDhPDGMdgVEAkQJnlYyQ8DQYX9zUAE+y+aNEi09euXesAHCtj88///M8/+clPnnrqKeyCmPAFO+1ifsy1u4TXsoQbve7fqCigCbyzaMBNWJTl79evHxE6aJSZj4tsGhw2HjGktMHdRG3sLW7qCuEesx+Ol0gYHa5QgFwBYhgSdex+VGS1EDlx2ZzaoEGD+EpRFOMnpOUZHYl3UwF0XQIL7UYye+aSH6WHAI3MBo9pmIqnFbjIEKPYyMolS5akMGJb+IjDJZAx4CWT4qxxyVPEJkIX08jX5GVe410IfE3Hxh49eoBXgVhYVxFB46AEI0kL39Fb3cWs4FW2pv2RU1jWFvJG0oUS1pV7Vr948aJ2mWT4PrkAmWhAILyDpNg1Eghowif9einDvch0F4+97NsXwUXCa2GymqiZimOOkFmFDLSED1G4ToYHVkAftmACFGTgWqRIomOyNBgBigjDK4MUvrsIC9rd4RkD+bNFgrctbBgQkWkPIVQg2sUCIZVYU5QMC4CzGlTBsTXDIkgvq1x00JgcftgBMUOGJF+9euXMmdNQ+eDkNJ7h6F9J7uB61CXEs3TXDR3gwu0ftN6L9MJN+GFDYdAEbspLyYAItQRJaA8jVRAT5TXuEUI7O2FwMGAxmBQivZ5mhcFhvLkcAc2GDDdiIN1Fuy2M1GsYZwENNtIY5obeQGGMlTUaiRusi8ZwtkdC5OuQQkNnszIkBXhBdtFBYwlTGMmOHTtt27Z948ZN69dnFC4ZGZs2bNgYf92wQUvkdePGzYsXL/ES+dLI/OgPD1Tidc/ECuK8mVOqxtM7ACsaxt+feDGD2ac4aJwfUIAJZL0KF1h1KQa/rsuOFFoO5Wy4JrJmHrRbil9YsWIFbCHWQkZK6UO0ATf3IqINz3jF00lwEho8w/R4b6joMkalMMVHehrD1jqzG0WFU5CCvB+EjIzNiZJXBDQiIbpnCwxh4Fu1alV00FBffrFp0yarV6/fsmW3EF7ZuHHn5s0iykh9/XpI2pmevnXdOkH7bu1KRkaWljBy2bKVbOH5KFEUKOTpmB96r06ooTFINwwzgMdRMeZc9FdO0Z8i3aWCTPfKK5E6FXHBsBodgg+hRs+ePcNHqGXKlJFfCDkN4yAk2+KMwCAeUJSNazJzGQcmstjJyckyFMGHgEMQYFZUmnchjCJXCCBjIYi6io2C8fAa4twAERRmeQ2VryRT6BLc4BsFiEnoNjmYxV1W8BsIxM1yBoNZuHiXinbjYzOjZE2XpRja+W5yt516UUCDcB+zRBXuPG7cxyNGTOvRA4s/7NVriEr37h81bdpx5Mjpw4ZNqVu3RevW3bp3jzR26TKgadMODRq0TkoanZo6e8KE6fDrVg4kUX/vvffo8WeffcYA8uLcvCCA5MiPTruhC7M3NF7FRMTkFK4YEwYb6dVpRQDvv/8+28BJM41SPLFz//79bcEO4QVxNm3aFFwMNl1wytgIJoQRFhGQsjfqnupOJeygdpJYJ7dCwEFh0h7kYQzkOR7ryEp5FX46j8WN8QxJjd6QYQEBEYZF7k/gxRK89dZbZlEP4E4UvF4LYkUgImeqO3XqJMOqUaOGLMkALNKFA0aSBW7EJkd/UCCWoiGrV692ths3boQwsSiggRjMqlevHrQePXpk2LDxyckTatasV6dOs9q1m7z00iuNG7dt2LBNSsq0Nm26v/XWBxUrVqtZs/677zZ4772GBgBN8+adRo36eNSoifjp5lI+165bt+6QIUMIgxKLCgkGo9XZAHWMxlZPFMSA4i0FKgYEgoAgiSpVqmCW+8MNQGBWiKhYdWxSwTgqi2uk5V4GhMtqQdbxDC34a3AYo5HUtQQRFiBjwF3Ay3TxgFIH5o0a0AqZJjMGwQ5AMAbwfZImUGbbjHFmMo4tdG9yAAemVyVKlPAEaJsysfZCeq1z8+ZNkpYo8EGwIs9iXN944w0emdAZb6SXTN3LLCuEm2ILHhJNu3bt4DggsiiWxhzrNm/enNc3xbmTklKSkyf17Jncu/ewrl2TPvxQApjap8+Itm17du060GuvXsN69Ehu1Khdv34p6tgyYMDoIUMmDR2aunFjRrAHgn/pJV10Svdkcug0VfZEkK5LYGgw+sqKZ7zihEQSftnq2hjh/G4Ru0+USA7LAmggoDBZJFaL1skp9nJfMowBIEgxLzPmIsyzoJWS8OxIRSPjSukZHkoiYnN3r84T4Hh/cmCWhvgpA/DJulu2bAmgFIO5bdiwIZvtynAAMY0bN27QoAGTaUe27fXXX9eLJ9DvaevatWs7s5F4wo87QIAjkNFGTINj9NCgESVQlM6dO4srr169ht19+w7p3HkAB9St20fAoQCKepcuADTQa8+eQ7QYo1FRB6YuXQZ27Nhj/vx5fAGz75L46z5Y7ImDLoZUQt2YohE5paenu939U2726T6gKRpRXHy3abAHpEs9HEBLsGTxxogoomcL1guBZvAa9yfrux3WifNC8MdUM1rdunVjXGvVqmUd6DHSsJ/97GeSROaNk8JVyl2hQgX7MsbOYCRUsfHBzdFYeTFXDpHhw5sQ06CHA421KD202sMRGT0bLFiwcMwYrmSiMmHCpMLPwYM5hSnTps2YNm361KmxEq1HfoEL4IkE+5RGhUbGqcDrA1KYRaFx//r16/dKuRFNwFPGgLQMvivhe7A37k7YQbQqWmIj7kt3tU/aH3yFu5LpsM57wn24kTCf5yUpjTVr1mRibc3ogs6zzz7L6IIpk1auXLnvfe97XKFe9tgZMIongkL3EgXynkBjMJCRCEtv8XDrhwAN68RwNWvWjPqy8A4nj7XH55+v2bXrUHa2kOpgZuaunTsPbN++Vz0ra5+n17VrN0i1rly5wnd6BsrPv2XHq1evUhHICx+lhAGe4BiegfSGSmLjXeuFZ9mCMaOCwamHBApbPd0CYtzLgOrVq8MNjgRhFCaqhu+sNLVBEyZM4Fz4HUzXGzR1/z5l18EDERxoQUEGwEqE+K6uMai+Wdq9RibeJuPDlLBCdOf7EdDAOokUzp7gxkbUxsk5fQsyM88991zp0qX/4R/+gcRBJCBGrzEWcUjukpWSJNJeJ8FDYYO6LuuH4z0EaIRXAlIrqrhVAI1Kauo02dPAgWMUqRNnVKtWYyGwaHfYsEmpqXR9tlTAoW0cGGFj5wg/8hBh0QaQZw/jnPJ0jShboHAndutCGuOsjNfD4PgA4zWq204FJjhm1pG82WSWVjTKgIe/0dK+ffsPP/zwL3/5ixjZFEy0WmFyTdzklAXm5gpUTWTexa1ww6e4nihk3fpNa9ZuW7J8XdBdq4FXSAnF+NRduMb5ahTDsbJiF2NwwADXD9EMck6nDVe7PwENfySqZVYpTAhH4kQlQIFKLIsSLyZJfOGFF958802I4aREBaHXU9QhwWZgPAGRmrFepCygmTt3rvO4pu3Qg4LGZHeuX78+SVDQRNCMGDFx0KCxr732To0aEttGSvXq79Wu3bROneaS8NGjZ0qtd+wg9ywbhwQHtFksR3caQUz4UJw3tbiuQGQQKpGkKDorTEehPXGAeuEByIL21Vu5cmURInxAqiTFjrhMSMwv2ajw3DgFzTBXmIyxSDgnlDAzcmapgImEbVbe4b1jx04oWan3qx0OPF9r6Zz5Sw7mHhPLjI9+usPOux0RSqYoLoB6NmnSxEmoL/2hjerADVtwSTMJG29j29+bQBN0zPrzn/9sERJlQWMyi8ZqYOrMwVPjNp3xSm2mT59ui+DE58yZY1PWBXMMMJGV8mSV8bB169ZgjVHsIoijBwWNo7i8YzEzXuOgccqkpJHJyRND3tSr19COHfsKgQW8ffumKBKr0aMnZmZGJEr/ArktaPOspjslO0/VqDIZx0Y8IrKpS+IFtgb3hB3BPdEkTHELjS6FLwyAwUEYhYlscA0+IroW/XwsykCRyp4tW7YOTJ7VoO3E0u/O/GD4xaptNw9qUm72wKY7svcwA7QZsAgP2pgZas2WuLWKK9MZwnN9I7U4Q4j6jQeI2N73JieB9bp165o1bNgwBtVcIVoIccCUCvH4vAw7xFODpgBZ4v3UU0+xNISuC924ccMBKBjOmGVuYFTHjh0BXYvz2IvcPR8INOZTKZYNf1l7SwTQOIS67Kl37+H9+4+WS/frx8SNVkI9mmPrSo4G+GmuFwhrhG90V8VpAkkCvcZGPDoiMEJyu/tnTw4jpmFROLiHIsHJpg3rarbbXrHt0Zrd0mv3S69Ya+Degd9Z1PRHazN2BmAhK9NayAto80RgERpJwgBPXZ7hNbbBfckwjKVs56KfhruvDAgyrAMlTAsS2NEQz/nz5z///PNsPC1laf74xz/ihol64QbsmE8IE2WCjoMxzByxiSwrABA6FtGuBwVNu3btWONg+uKgsZM9li9fkZIySgI1Zsy4u5Wxqaljhd+Cc2eKE4+uRVTB5jOSsdZHTUwx7nDGznnX7CkQ0OAF7hcJNNnw/lytvSVf/zhjzH/f9/G/HJ3+v+SP+84ntX4MNAARGxcNtsIzcZf4a4H2ByRTKJsKcbgI8Xsyq3wKkbMorFeIRUQXJUqU4CUFTCIqT16yXr16rIBFjGERxUZMg3BNxFOmTBl2i0UU09SuXZtSAaJMig/9atA4B7vK4THmwXDFQUMSXtPS1u3ff3jfvpw9ew7Gy969Ofv3H9q375C63rS0tQHUIJxIFvfkHcIrXbGmV0TGIA+X8d5ABV4DJTYWqEM8fgVLgzXh/IkU7khm7BwZR4KvQqTdABXiCS1BYNr1bNy4qcJb08tVbHNx0v+8J/kf57T5+cT3fz6uRfXMrF3sRjAtcTKRIwh1smQkGF116zO3WgxQD8YmDFPxGif2KZwB6WJKgQDrkItQbLfmlVq0aPHuu+8SttWcUlDy85//XLQrxnBTxkPWXatWLaJ0BgOMZKVkkSIqIVcYaWWLkH5I2iUB5n4FaPCUFgohATagODQG0ISUe/r0eRMnzh0+fOLMmcumTVs4bdqCGTMWTZ48b+TIKYMGjVLXPnv2QqYXqIOuB1GFCgrar1eFBVKxPlXARC7fALPCvomz1O/aGOphEXXQkea4rQtq5GHdKJECYurUqSPCSJRHnDCUYIKkSdSrJ0Ybj4OmeN1/YO/EYd2zmn3n83rfafDn/336zCW7DhyWUjHPlNuluAkhJ7Mn8vAMkSlbSOrDhw8P7cHoEh4YCTiEfQZoCdGrlhCA8zLOEM5mOhtJ2BUrVpSmsBBClrJly5YqVapSpUo//elPe/XqhQ98DbQ1atRI9GPB8uXLy7r1cmcOr9ctnNMK1tSCbKGRmqEOHTqIxuwlTPT8CtCArdBaNBRHDCKSOGhURo6cnJSU+uabtd95p17dui0kTQ0btn333YZePaPfXH48duw0UWnY1RHDkzZEgtXbP7mFv969e0M6Jjqi/JYxxEoCi0TR0TjayMRZoa4Lo0Ml3ohUXB4g9IbsiTfsVIiwtXTp0pJnODDYswBhNxmHaJpxJtrwpZjUlEZSJ8zdvWfv8qWLRnZ+f2T7dwa3q5+REfk1sfsaKcJABkvyBZWmW8TEtm3bqjghN2GAxceNG0c8vCSo2c6ReBncgPjmzZsbhiiAwWaRrrM5sJv26dPn3//93wFFmPL73//+N7/5ze9+9zv1p59+2nhjIB6HPUuWLPm9KH3/+993HjzHNFZERUoloWOfbErivBIH5ykBIhca4kZ2DGb7nqABDsiQuFN6Rj7WWsjSJCenSrkbNmzTqFG7zp37d+jQ+4MPmr71Vp3Wrbt57dSp35Ahk1JSJmRkbLBfRPj3IIygQ0RLw/hpwMdEuhVAEBv08ESgQ4cOZUhAB/5Q9KOQvxG1HjVqlPw/BMJRnNxBGiED4wyjpqQeEIDLTAjfbYuI9c7etXNfrrLnwGF30WKuw7MEnjZyKY2eLChk8BcOY4VgU72GMDN8BqGdjM0y12AmzfmRkcxDQAwiSOIUcUIGQxiB7+0PqwK3LY6rbBXCWKgV2wYg2gKmMQc6aY5QBpeYIvZGsEzB3BFMeSiAto5lA0vvBxrWxU6wn4gYVAA0PXsOHjhw3ODBEwcOHDtoUKTSvn2ftm17qXhVkpLGJiWNWLs23X5ugjCiMOEILmCHAdQiDPYMNqnIZLowXEAWUm7HPlaIBFuUG18CrwtTOJjDBDRMnDhRrqEeFVxE+e5FZgWychjvicJr4jORjA+V4IZUjIkuE6vHVo/+ixMBLFgTltslOt9wU8/YP36JfrGl/Xj0J57Iq/XxBygl6tCPCTSBurKjDAxjL76JGsqBmGN3g9E9QQMZ1mVCLZfom1AcNJIx0eX06TN79x6YlDQklAEDhgwaNFyUrXK7cWjfvgOnTZvK0yUnDwZb1l5mA+mRDOdxUvggi/LduHHj/tkTY0at8SUmjbtRHB9BeKF+H7LmvSAVusJ2llLREroeikwMoCEsFyGaQOFeIrvDuUdE/wdzDkfKwUN5RyJ/jilKJ3IO5SoGUKVjx09KQ0TQ4cdrhItpjGJUZMliJjCwV9DDe4KGdWGThc3QGj9EIK8BNJcvXxb0sKKbNjHC9ymMyObobz03Ll362bJly1UyMjZ/+ukC1jiuZ84E+PGK9mBpvcYpOvBvihga70VhDGFQqfD3uu+fcnMWZhn/qIhQMQc4gsFwI/VgMxyMSDgdr8BK112WJYucO9prisGJ41Vi6yaQdjaPPXAvEokbGKAgmuPHjm1asXjTsrlbPpuvbFu5YMUnE2aOGT4pecDHKYO3rZi/ZfmnoWvjkjnbM9bv2r2bl1yxYgWTw5EJuXgui4sZgMZhvgI0thQEMQYqsabbFAdN+ER4/vyla9ZsXbNmi5KWtjU9PdNrevo2r3IOTy3aQ9eyZWnhdfXqLYsXL8/Ly40niowW6+qpjgXuj496Q/KMaIAupBJruhuFXk+4N1jS7v7BqAaGIhvJpOLKoIWyAg2+xKTxAPSVgwleGCR6EDcQAKfmJAI1r+ACK7yAdsZffqvLfVlHAY2RxrCRKgawzWEd+UFQgzjBE40UsZYoUUIsEqhp06bi2fYdO/Xs1Cl31YT8w/Pz983Oz5l3ZcfUFo1qy6oaNWzw05/+bM7wlvknl0S69s/KPzR/Tkr/Lh9251sEwp5iGojhqgBI6seCwDTVQncHDSYKD0VDhIe5sdbblAiaAwci2dOwYVPEvB9+OLBDhz4tW37Yvn3vVq0E3kljx87u0iWpdevuguIuXQa0adNDsNy8eedOnZxm5rhxUxnvoGGCOJawXr162CROwkdMxDiCNABrMIiq0d14BcUrWBmvBFaqWNYAR+WkJGVubgvBILUmb1bHFeAVLumlbIVITAyLBDLdMyg92HkNFHqtE++yV2EykiOW2oTrQIYIFALcUUBNDAEuolGYUKfEEkb5jrAUDhxbkoXgjPCEpTNmzLBjbPUo2Z2kOAQpN0nzIyGvrlWrVtVXX/vtL35xZE6L/DWN8z9vnJ/eNLVztT88/Wxq6ti5c+d179mvzH/99wuL6+avapK/omF+Rts+9SrXa9T806Wfrd+0mS2gV0HrOCyXxRzHYzjR3UFDTSUIwmaVWFMCJYJm//59w4aNHzBgVKNGbZs16xR+8SnNfuWVN9u16zV06KS33677+uvvwtAHHzSrWbN+rVqNq1d/H4ZGjfp45MgJW7ZE/qiYy1N029WsWRPviFPoSuGAhsMmRVJxYs84RaxktCWxEu25Y6S5JAcoVatWxXQCIAz5JP6ikG8TpH2pF3YYzAaQKHixskG64UN055w+fTrtnzJlCvwRJHnrsriu2H53kns5DNW0sjo0E7B2pwpfMIVXvYZ5SnOmTp3KbXllP+JdkbVu160TXgPZGvjcQpesamH0rwtinbNVrPJKp9atL40vnT/yB/mpP9nX/Qf/589+NHHKdBbB1TC5xrv1ur74P+RP/El+yr/kj/w/Nk7qVPb5l+qWebpH6+ZDR42ZPXeebI4yUypPp3URzgvdBTT8At5J2T3VQ2MiJYLGcv360Z7JffqM6Ns3pU8fIXAkYxowYHTPnkOYnF69hqoPHTq5e/fB773XyJikpDFKcvKk5OTR0Z97YmaE6JA7Ux08xTJHDLllrLtIFOBIAdzZBVmU4JvC5xPMmPSQ+WXMKShpsWpQEhwKjR82bJgEFbwggzdp3rw55AWlDxmpXNcKFDEmw0JkFxROEq9od0c3jbcH0oJiL9FhiQPicxPJeCm3NMchW7Vq5UklWE2aUK9h45YNG1xI+XP+iB/kj/zRoR7f/7cf/fPCJSvkQcKUESkpT/2l9Mga/1t+6o/yh/1L/oj/9tmgOlVfqdG32otdnv7393/zs9Lo5cqvv/562zZtsCJYmnuCRkBAjTD6rmYGxUFz5coVFmzo0DE9enzUt++wPn1kSZ5DevceohIKSMnJO3bs46kY07u3MqRXr+Ru3frSLfIg0UAU2uFUNCI6FNq/DhGq27pdPHtyfj6XPgCQ80cDocinxosWLYJRg+GDvUHBSHBDDsP2EE+wDSIPfkQXWHsWlmWcouL+G4XGRGQkUuh9KLIUEHBbWOfYDuMKnIsLHjt5elj/voe7/2v+kH/OH/zD/NE/HFDhf/rVn0oNSxnTq2/Sf/62xIu/+l/zh/4gf8gP8wf/IH/oP01p/vyK9M2nL13et2f3zjH9Vlf7w6gGb7bo2uPV6m+ULFmSA7X4qlUrV68u9BfLA0NFyziFpwElBSgOGjGmrJsRmz17DvHflWT/rLqYWh3rY5JcHPk9wMKFkSeUPD6yvgMAyv2/sHQXdg7faTNJeAYKsmQVwqtKaME+2Iq3qN+VLMVkwlmYRUe1AKKNVAwIXZ7qetWj8x6CgIZqiXxliNJDFwkxvksdOX5y7/btuR1/kN/rH/J7fTe/z3ev9fjH0j/9zlP/138r+4d//88f/I8bG343P+m7+T2/m9/rH292+k7W2BbHzl2NRLFHjh45d+l8VkZ+/7pXU7vtydyyfMPm1HHj27frMG7c9BEjCv3xaYEhhWPiqGCUn3ehBPd0VSX6c8+c7OyDu3cfys4+oOzaFalDvDBUUc/I2HLsWORzHZK7eFGJkVd048YNns6d5fCkqx0cvYZelFh/cIrPEhjZ2so4e1fQsDpkSWXhICaN+xKRB6nfn0BKcMaLCaSEU5ydgMMW6r179/Zk3vgR8Qe7rk5RHxY3VoNLW7z11luCVkKJX5CYDh7K2zxz6MZRzTaPabl5dMvMsS3Xp7RYnNRIWTWs+faxLSLtY1puGt1y06gW2Rlrco/8zUzkHD9lidNje1/p8sa1yf3bNWvUqWvP6dOXdu068C6gYRWYYicIkwtTAmgi3z2NGyfymjV06ATeZ+hQKeLkQYNSOazx4+eMGjVdGTt21rRpc0RIFJ1CixvYT8GQithCI9OHmwybXMPWwk+ugYDDSGPMNV5dS2hMrOsSuBRojM9yzhCX8EH2sosKlQAUFwk3MobKBksTk8ajIKCRNLVv317uKmQWDAmihcCQ5EiSJgG1oFW7YVyeGOthQWMLKlE7Sh06dHDxxDDU/Q6fOJtz4mLOiQuh5J26cOz0xWOnLxw9feHQ7Ubl0MmLEcTcoVE5h3LzDp46e2zH1r0je75T+aU585fIedu27XEHaPCOwgn3CKxwph2nAqBJSZkk1A2ZkeypSpU36tdvpYwbN9cGDRu2TUmZnpo6lWqSYmBKeFIRISS3JXmpU6cOgWGcRCB8RGGwAUYiFdPjs+KNoa7LsSO6H9X+eKM6B49wtnLlykJ70SsVJySSg7OQb8OQ6E3aIgwPiluYLAhV1jHA05phpKeNwpjCpJfZtrIphllEDCTGCvXAh/g6oSVMfHAykQumaVevXpXMS+9dKianR0Q5R44ev3RlxMiUunUajhkzs1+/yO8F/gYavGNCGcx7hcCBEkGzb9/eQYNGy5gk2F26DGjZsqvsun//kV27JnXpktSkSQe4SUmZMXz4uHt9YQk3shVxDwvBwBCnujgpMVoMPL0P3WcAYwMo1J3twV/6LdN+4403qlevDqmQhCpVqvTee+8JJIMICxAZswEA7WCskcgsGAlIFRpT9HsJO0DZrWPv0aUSX78+WZBXtSbbSdWbNWvmynfNeb8mnT9/btKk6QMGSHsn3gEauzIzjgIQsbF3o0TQmNK9+6C+fUcOHJialJQ6cOBYJfzis0ePyL+Rk2PLUvv0Sf7ii5VivXV3o6CIMl4BJkaTwb1Gag9jAssCadEunPRM7AqytHL4xIzjZ8DDl/5MDug0btz4zTffZNj//Oc/01HTDbZCAQJfKDHXOiaqJCUlcSjsjVlSdOePDS1EwZxYFql41RjBcrSu0TNc3y00hpYw90HIePG+uzOZVF2cNHPmzEdubNDx48fGjp3UqVMSsd4BGlZOyHafaCZQHDQhe0pLWzt06Ihhw1KEdPGSkjJ60KDkxo2bR9tHDRkybOrUyB/Jpaxfh8Jn8ERFci2i1Lp1ayAQSDJX/A4THexK6G3Tpg0x6xIt8QueWMyi4DKjwgjJNfBa8CgBkWdpjEkjgUiRNjMtVnAGXoxFJBur2U70CpqxoXeSdv6IZWKNbGoRFlRj+CjBRC2eVg7OUZ3pMuVeCxYmOLM+w8kW8lDc+ogRI+QTfC45Mj/E5I5fSfeJRgIZwzNPmTJj6tSP7wAN5XP0r8RpImikJNnZOxnd3bv3C0aV6PeMgtDdWVnZovvs7D1CAmrkAvHzeUpt3Epde/h2jVFVRw5g8TAskcLFbE3YKBryRv5tkfDWkRDZ80HxLqQegmK3u3nzZvhgJnzEZztrmmVNO4rQ4Qk+HLUwaQ8eMDy9kivoQINKbFAhYgbgGGrZb9oYwmGN3aIE+sLhntF/UqOLLdTYsmVLqsX2xJb4KgoHlkn85Cc/4XBRxYoVqVAItEmTeXZgZF+mMZIs3P4DTVoSu+6PG1Mw7ORJ0jlxB2ioZuB+bOA9yOrkhPUQc+vWzVWr1sydu3zixFnTpy+YMmXe/Pkr5VMLFqyikAsWrPY6e/YyLgX2g+BNRNhHpRjV8Kk5DdPlhrSHUhI2uYIOCmlO/BWFFVQ0qgQEhNd4I3BY0KuUmz0QkbggZxrPSBPJMKyn/RDAST0IRUUW+R8DY+93I8LgxRhFBpIVZ04kiYhpYdW0SKN4N3GSxvB9BXL9Bz+GLVia8AcAxo4dW61atVKlSlmZyRGbQirrBR+ifiLDXmaYaRDAMdi4qj1oFxFADwHFOHJfugM01IKtthZ2m08ScQHQRaSiRRfdxX313NzDM2dKrT9u375P3botBMIffNDsvfcatm/fu3nzzu+8Uy8paUxKytTlyz83BZxdkuS43vr167sqvruh1+TkZJYfi/kaOqcuQKbWgTCR8gXf73oqoTH0ovgAvcZoUVexCI6wB0JdoroXU4DGCg8FmgchCiCuD0mZg3kSG/VQD+cMZFNPLUHv8SQ2/wHI3ODXwodeQAA0kEea169f10steSukhfI8/fTTLN8HH3zwi1/8IhhgAQa/hgMWCZ46xpR70x2gYaJBJNiukB7z/TjOB8+bN482sHjig2BU5cZg++GHXTt27DJy5PSkpNENG7aRK4ksmzbtGP3msqny0Udjk5PHL1q02OK4Zk1SnDhxIsSIQ61vNWaAJ7Z+apRkcDwFeUd5+LXIjvjo2O+//74sCX/hPnb12+S+mMXXCFlw2ZESiQijwUMkstGrQsDBIsYtTWzo3cgAE2Mvt0N1E2PvX5ushlc0hNRdBG7w87nnnmO3cNKV6b92txaEPfXUU+HbAALt3LkzEQRxMxMAVKtWrQcMou8ADebakq/lXBmxtm3bCiRbRf+f8XbR/4SNuYMVPhhmwZmNFeGNGCE5Sgm/9ZRAKUOHTg4/9JShee3de8Ts2XOZmYh+RVkPEFQQBwk13Fw7YahoMYC8w+CvTxYMXx1jkyfzGbv6bRJdcZQMO0gZH4QRyAk5C7YBURuOwCtwq/MpcIb71rwXbmDrrnexnacuFBtaVLICrBME70/8QkNGmoxY7j/96U+YLPXDbdB57bXX3JFBYnFZd3f5t3/7N4BjIAwAO4jhtuhPjC/3pjtAIxwTQ/GFQIrRsoNFixYJy0PYQeqMBOfCyMMmu3frVuQvP2Rn7xo4cPjgwaOSk0cnJ48aPnxst279u3TpM2xYarRF+j1s4sRJLsD+x8mrc6s4d6BQjz8fCVnK+d2CAqgExYpdPUoUS0bzzDPP8IlkTAs94wTHuIEnkm2Yk2lToRDSGs/Qdu/eXfQQbE9hshqJijaALPpF3Hw2lak2RT2ENQAXG10kAhrArVGjBihDDOiIMQQ35AI3DRo0IDWAYEjYgj/+8Y/wGhxFyZIlX331Vf5EL2C5gkUcFapirLk33QEagAjBYzyIQSGO0QgrekPEE8+eqCl/ef78uTNnTitnz565cuVyr149ly1bqhJvdJnYck+KHPvcuXNCddCXTuOvCwoGE0FjDODykmKpd999lyDJIAgjEKlrtIJIlsEXPMIQdTJeS0ADWDCQsQl3Ek1jktlsgRo5eRIYOw18Agtph/q95j4gOSGVFhTSCvKGG3VHxQE8Z1RYI7YWcdOlS5f+wx/+4DwlSpT44Q9/CG0awQVuDKtduzb1UGFsSDzGo7vRHaABCBTruTcZAzTWBRe4QZcvR/4wDBJ8GUApOVfhVWj8Rsh12EJCIioH9uqciaDR6Art27dnjW7cuEF4EEDvySCRtBAMMiDiTqIJtnog9cJT4kSoDKr1QZONsT7vxgnCGRsDi9oJKTa6SOQMYC0cIfsgaRGFU1Fprw4AN8Fy23rMmDHCnfLly5ctW1awIVrVFY5nmNW4NgrGuzkVzDHMgVcF6A7QxNq+irCbTYIblUTSZSexDtMdXGOs4wmSTUUt4EKNGjZsyDYEwxk5d/TPlYUKYjh5W+EabcMdjMZ9tgEIHiEBWQhfRDbkSsZekTrSHhtXVLIUCDIkOO/ihA00cVYgO4KOdk878kccVghiNAbS5SQYQmr0igRBh+eFKpxhvQpknUUBTSAqawPoSSTnprvUi6gK9z5Wsh1yyeC/uXNBDFY6ajiJZzh5IIzAO1Z9z549jg1AtJ/CfeuIxXJ4MUPQWOFXuHUggngQiucHYR3CFXgJ4Dp06MDZYalGLi+EKEUHTWGyN+DbiYQsHWt9UhQUhYEBF4yjai4Z67sbOSHDAzTCwMALtjNo4beIHNixgyVgUIVKPFHcshaZAnQIlCJhUZ06H/To0YNJ27Yt8qv+Rwka24gQRXmJSH8yFPAhrhTVSo+hJ/DxPgRVWMMu8uW4E1oCer5F5MDBE6lAf8uWLWmC9ugVvxZZkGvbsGFjZub2JUs+mzp1+syZs1euXL1u3d1+I1xkeoRIf3AKFkUm2bx5c2FvCGg870+B0c7Jcz/hAz8mwgSuSo4mBIk1fT3CouXLV+zfn3vgAFwey8s7mZt7QgDi9ZGBhiTEVpDO/z0SpD8I2ZSR4HTr1KmTmprKXFMOkZ2oNk4h1ouToE/8KL7BFPyVZD6m3xI8YWLdOWWW/lGBhhCXLv1s6dK0xYvXLFmSllgeGWicVcLWr1+/J+abIEbwNG7cOAbZ7lxSwJCn2BYJD5GW0BhIXRDAJTG/jgo0H3/88f8HQONenTt3llff/yOWByf8WbhwycSJ88ePnzthwrzE8ihBI1aaN2/ekxEAO0EVevfuTerh9+rnoqQiGJcrpkX/3wpuKz09/eLFi6EXnT9/3gl1QYwzd+zYcfny5ff6QOLbQljBdrZr107uTTFirVHBe/UMBFhuigArsV29gHPQglELFy6ePPnTiRPneU6dunDSpPmhPBrQ2JJmy5s4CIeItT5OCobtzTff7N+/v9fwoRHPyLSIUdzZSWbMmCH55312RX8YEIYh+WS3bt2ACcRbtGihvQDLvnXk/O4uzZFMxfmvcUv0z4gwqy7LKauvjP61Yj6aH9eoC2nHrjgTcNJr3759mzZtMWvWcqAZN27WgAGjpkxZoK7cAZpiKqYHpBhoiqmYHoK+853/F3rCW7zKW2iWAAAAAElFTkSuQmCC - - - - - \ No newline at end of file