From c5143ba60a1ef23160a26d2154d8fbc0b2cca339 Mon Sep 17 00:00:00 2001 From: Chris Mackey Date: Sat, 1 Feb 2025 10:07:30 -0800 Subject: [PATCH] fix(organize): Expose the ability to filter rooms/faces by attribute --- .../icon/HB Faces by Attribute.png | Bin 1313 -> 1306 bytes .../icon/HB Rooms by Attribute.png | Bin 1265 -> 1256 bytes .../json/HB_Faces_by_Attribute.json | 61 ++++++++++-------- .../json/HB_Rooms_by_Attribute.json | 61 ++++++++++-------- .../src/HB Faces by Attribute.py | 43 ++++++++---- .../src/HB Rooms by Attribute.py | 34 +++++++--- .../user_objects/HB Faces by Attribute.ghuser | Bin 5228 -> 5596 bytes .../user_objects/HB Rooms by Attribute.ghuser | Bin 4962 -> 5306 bytes 8 files changed, 123 insertions(+), 76 deletions(-) diff --git a/honeybee_grasshopper_core/icon/HB Faces by Attribute.png b/honeybee_grasshopper_core/icon/HB Faces by Attribute.png index 7c170bb41519698c91a0cfcccc1a6225dd5ff201..8c1a2b8e0bc64a9d056234036b7ec99883d3a91e 100644 GIT binary patch delta 1236 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 A`2YX_ delta 1195 zcmV;c1XTOz3GoS#R)2;`L_t(YOVw0uP*i0UKKEXh{baw`ue&b0ARimB0g?!q4wzs4 zXf(_6vn-vgA2n%|IEZ3N13IV}!%*J3a0|Ud; zDV`xQ7-0Le@x+OEG@JQtvb2o4DC|b56xTXoGon>cOA4Nr+5B7#xtqM=*Jbs1K*8>6DkudJw8a$7*7z2Vq-fX&E2& zh3LW2NRb)js5IRE-+rFVAPe_@5XExKC1nPOAe7vTrfH#4NK-R1L2Q}=Y(G8?Yphe) zq1>b-^?ycIhS8~!CrFy6Ad7RcqQWz-M72jF9oXTV8a(ds1V6Pn(NBU+Vob2h9)(|v z9xTvDvO^0s8m_Xbk-Y~g!IKS%!B(38wo?h%cG?#_-|oem13rB7b=w05O65HI?a%@2 z(E#kG_(Nj75nz{+_9(6-wi7*|3d^Ro)2xP4wSNN2D6SyZTePrK;9xJs>})e}IZ+0$ zwXA^ToV$?n^mRyI+|TE{+6Ac#uYvE$8(hY+UVcGdH;75>R#{+HE`VImFl4%Kz}%Rx zV3n^E9(Vl!Y4#ssQNkrylhy-K29{eaiI1SpP|%6yid$$Z9Y9mbxAH2nA1#N5Q1@~* zJAX7A!s*dlRv}zmhtU2a!kHHk&eF=r{(t`l!j@SG3XWCcKI$S~t3_kcMKrwAGLEJl zy{KDV$qbS}pby)T#R$irL#SCYo~^49HqAuPhZoAy1Wu_d*KhEnv9M=i19}S0Qw7Xm zE?6{$@bR+<4NE6BIQJ65npBoM`X+N)bAPEJuNjS7&OgLp;2(oI;Ec$F2D*Lyzc3(7 zUZUbY)UMde4y96w4o_Ml){~8y2wKIvvb2m4J-C9pmF3JJC8R+c8RTUl=)#L+X#%I# zmoXvZw$IRz-;RdOXJzJ}p|u@NW!F)&Xe%>#0z_RtG(ImI)KM>3KNxGDk=F}r5r5XE zjV%!uuB|p~YD3e`t7zQ*1vR@{qUpWM(o;q5`vo;icCbV9!KN;Slgs2%_?IIzk`Xg( zUWwBFm#-kKpElNjP|oYEs7RRA!N*MR7EIz*-sHTdh|g)`UCEaOdu%_i*WaPMOyFQU zSk(9E1u&keIzesHMPuO_zVC5002ov JPDHLkV1n5AO}_vD diff --git a/honeybee_grasshopper_core/json/HB_Faces_by_Attribute.json b/honeybee_grasshopper_core/json/HB_Faces_by_Attribute.json index e9c77d7..a0ac6de 100644 --- a/honeybee_grasshopper_core/json/HB_Faces_by_Attribute.json +++ b/honeybee_grasshopper_core/json/HB_Faces_by_Attribute.json @@ -1,43 +1,50 @@ { - "version": "1.8.0", + "code": "\ntry: # import the core honeybee dependencies\n from honeybee.model import Model\n from honeybee.room import Room\n from honeybee.face import Face\n from honeybee.colorobj import ColorFace\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee:\\n\\t{}'.format(e))\n\ntry: # import the ladybug_{{cad}} dependencies\n \n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, list_to_data_tree\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\n\nif all_required_inputs(ghenv.Component):\n # extract any faces from input Rooms or Models\n faces = []\n for hb_obj in _hb_objs:\n if isinstance(hb_obj, Room):\n faces.extend(hb_obj.faces)\n faces.extend(hb_obj.shades)\n elif isinstance(hb_obj, Room):\n faces.append(hb_obj)\n elif isinstance(hb_obj, Model):\n for room in hb_obj.rooms:\n faces.extend(room.faces)\n faces.extend(room.shades)\n faces.extend(hb_obj.orphaned_faces)\n faces.extend(hb_obj.orphaned_apertures)\n faces.extend(hb_obj.orphaned_doors)\n faces.extend(hb_obj.orphaned_shades)\n faces.extend(hb_obj.shade_meshes)\n else:\n msg = 'Expected Face, Room or Model. Got {}.'.format(type(hb_obj))\n raise TypeError(msg)\n\n # use the ColorFace object to get a set of attributes assigned to the faces\n color_obj = ColorFace(faces, _attribute)\n\n # loop through each of the hb_objs and get the attribute\n if len(value_) == 0:\n values = color_obj.attributes_unique\n hb_objs = [[] for val in values]\n for atr, face in zip(color_obj.attributes, color_obj.flat_faces):\n atr_i = values.index(atr)\n hb_objs[atr_i].append(face)\n else:\n values = [atr for atr in color_obj.attributes_unique if atr in value_]\n hb_objs = [[] for val in values]\n for atr, face in zip(color_obj.attributes, color_obj.flat_faces):\n if atr in values:\n atr_i = values.index(atr)\n hb_objs[atr_i].append(face)\n hb_objs = list_to_data_tree(hb_objs)\n", + "category": "Honeybee", + "inputs": [ + { + "type": "System.Object", + "name": "_hb_objs", + "access": "list", + "default": null, + "description": "An array of honeybee Rooms, Faces, Apertures, Doors or Shades\nto be separated by their attributes in the Rhino scene." + }, + { + "type": "string", + "name": "_attribute", + "access": "item", + "default": null, + "description": "Text for the name of the Face attribute with which the\nFaces should be labeled. The Honeybee \"Face Attributes\" component\nlists all of the core attributes of the room. Also, each Honeybee\nextension (ie. Radiance, Energy) includes its own component that\nlists the Face attributes of that extension." + }, + { + "type": "System.Object", + "name": "value_", + "access": "list", + "default": null, + "description": "An optional value of the attribute that can be used to filter\nthe output rooms. For example, if the input attribute is \"Azimuth\"\na value for the orientation of the Face can be plugged in here\n(eg. \"180\" for south-facing) in order to get Faces with only\nthis oreintation." + } + ], "nickname": "FacesByAttr", + "version": "1.8.1", "outputs": [ [ { - "access": "None", - "name": "values", - "description": "A list of values with one attribute value for each branch of the\noutput hb_objs.", "type": null, - "default": null + "name": "values", + "access": "None", + "default": null, + "description": "A list of values with one attribute value for each branch of the\noutput hb_objs." }, { - "access": "None", - "name": "hb_objs", - "description": "A data tree of honeybee faces and sub-faces with each branc\nof the tree representing a different attribute value.", "type": null, - "default": null + "name": "hb_objs", + "access": "None", + "default": null, + "description": "A data tree of honeybee faces and sub-faces with each branc\nof the tree representing a different attribute value." } ] ], - "inputs": [ - { - "access": "list", - "name": "_hb_objs", - "description": "An array of honeybee Rooms, Faces, Apertures, Doors or Shades\nto be separated by their attributes in the Rhino scene.", - "type": "System.Object", - "default": null - }, - { - "access": "item", - "name": "_attribute", - "description": "Text for the name of the Face attribute with which the\nFaces should be labeled. The Honeybee \"Face Attributes\" component\nlists all of the core attributes of the room. Also, each Honeybee\nextension (ie. Radiance, Energy) includes its own component that\nlists the Face attributes of that extension.", - "type": "string", - "default": null - } - ], "subcategory": "2 :: Organize", - "code": "\ntry: # import the core honeybee dependencies\n from honeybee.model import Model\n from honeybee.room import Room\n from honeybee.colorobj import ColorFace\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee:\\n\\t{}'.format(e))\n\ntry: # import the ladybug_{{cad}} dependencies\n \n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, list_to_data_tree\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\n\nif all_required_inputs(ghenv.Component):\n # extract any faces from input Rooms or Models\n faces = []\n for hb_obj in _hb_objs:\n if isinstance(hb_obj, Model):\n for room in hb_obj.rooms:\n faces.extend(room.faces)\n faces.extend(room.shades)\n faces.extend(hb_obj.orphaned_faces)\n faces.extend(hb_obj.orphaned_apertures)\n faces.extend(hb_obj.orphaned_doors)\n faces.extend(hb_obj.orphaned_shades)\n faces.extend(hb_obj.shade_meshes)\n elif isinstance(hb_obj, Room):\n faces.extend(hb_obj.faces)\n faces.extend(hb_obj.shades)\n else:\n faces.append(hb_obj)\n\n # use the ColorRoom object to get a set of attributes assigned to the faces\n color_obj = ColorFace(faces, _attribute)\n values = color_obj.attributes_unique\n\n # loop through each of the hb_objs and get the floor height\n hb_objs = [[] for val in values]\n for atr, face in zip(color_obj.attributes, color_obj.flat_faces):\n atr_i = values.index(atr)\n hb_objs[atr_i].append(face)\n hb_objs = list_to_data_tree(hb_objs)\n", - "category": "Honeybee", "name": "HB Faces by Attribute", "description": "Separate and group Honeybee Faces, Apertures, Doors and Shades by any attribute\nthat the objects possess.\n_\nThis can be used to group faces by construction, modifier, etc.\n-" } \ No newline at end of file diff --git a/honeybee_grasshopper_core/json/HB_Rooms_by_Attribute.json b/honeybee_grasshopper_core/json/HB_Rooms_by_Attribute.json index 3751edd..5b359fe 100644 --- a/honeybee_grasshopper_core/json/HB_Rooms_by_Attribute.json +++ b/honeybee_grasshopper_core/json/HB_Rooms_by_Attribute.json @@ -1,43 +1,50 @@ { - "version": "1.8.0", + "code": "\ntry: # import the core honeybee dependencies\n from honeybee.model import Model\n from honeybee.room import Room\n from honeybee.colorobj import ColorRoom\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee:\\n\\t{}'.format(e))\n\ntry: # import the ladybug_{{cad}} dependencies\n \n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, list_to_data_tree\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\n\nif all_required_inputs(ghenv.Component):\n # extract any rooms from input Models\n in_rooms = []\n for hb_obj in _rooms:\n if isinstance(hb_obj, Room):\n in_rooms.append(hb_obj)\n elif isinstance(hb_obj, Model):\n in_rooms.extend(hb_obj.rooms)\n else:\n raise TypeError('Expected Room or Model. Got {}.'.format(type(hb_obj)))\n\n # use the ColorRoom object to get a set of attributes assigned to the rooms\n color_obj = ColorRoom(in_rooms, _attribute)\n\n # loop through each of the rooms and get the attributes\n if len(value_) == 0:\n values = color_obj.attributes_unique\n rooms = [[] for val in values]\n for atr, room in zip(color_obj.attributes, in_rooms):\n atr_i = values.index(atr)\n rooms[atr_i].append(room)\n else:\n values = [atr for atr in color_obj.attributes_unique if atr in value_]\n rooms = [[] for val in values]\n for atr, room in zip(color_obj.attributes, in_rooms):\n if atr in values:\n atr_i = values.index(atr)\n rooms[atr_i].append(room)\n rooms = list_to_data_tree(rooms)\n", + "category": "Honeybee", + "inputs": [ + { + "type": "System.Object", + "name": "_rooms", + "access": "list", + "default": null, + "description": "An array of honeybee Rooms or honeybee Models to be separated\nand grouped based on their attributes." + }, + { + "type": "string", + "name": "_attribute", + "access": "item", + "default": null, + "description": "Text for the name of the Room attribute with which the\nRooms should be labeled. The Honeybee \"Room Attributes\" component\nlists all of the core attributes of the room. Also, each Honeybee\nextension (ie. Radiance, Energy) includes its own component that\nlists the Room attributes of that extension." + }, + { + "type": "string", + "name": "value_", + "access": "list", + "default": null, + "description": "An optional value of the attribute that can be used to filter\nthe output rooms. For example, if the input attribute is \"Program\"\na value for the name of a program can be plugged in here\n(eg. \"2019::LargeOffice::OpenOffice\") in order to get only the\nrooms that have this program assigned." + } + ], "nickname": "RoomsByAttr", + "version": "1.8.1", "outputs": [ [ { - "access": "None", - "name": "values", - "description": "A list of values with one attribute value for each branch of the\noutput rooms.", "type": null, - "default": null + "name": "values", + "access": "None", + "default": null, + "description": "A list of values with one attribute value for each branch of the\noutput rooms." }, { - "access": "None", - "name": "rooms", - "description": "A data tree of honeybee rooms with each branch of the tree\nrepresenting a different attribute value.", "type": null, - "default": null + "name": "rooms", + "access": "None", + "default": null, + "description": "A data tree of honeybee rooms with each branch of the tree\nrepresenting a different attribute value." } ] ], - "inputs": [ - { - "access": "list", - "name": "_rooms", - "description": "An array of honeybee Rooms or honeybee Models to be separated\nand grouped based on their attributes.", - "type": "System.Object", - "default": null - }, - { - "access": "item", - "name": "_attribute", - "description": "Text for the name of the Room attribute with which the\nRooms should be labeled. The Honeybee \"Room Attributes\" component\nlists all of the core attributes of the room. Also, each Honeybee\nextension (ie. Radiance, Energy) includes its own component that\nlists the Room attributes of that extension.", - "type": "string", - "default": null - } - ], "subcategory": "2 :: Organize", - "code": "\ntry: # import the core honeybee dependencies\n from honeybee.model import Model\n from honeybee.colorobj import ColorRoom\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee:\\n\\t{}'.format(e))\n\ntry: # import the ladybug_{{cad}} dependencies\n \n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, list_to_data_tree\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\n\nif all_required_inputs(ghenv.Component):\n # extract any rooms from input Models\n in_rooms = []\n for hb_obj in _rooms:\n if isinstance(hb_obj, Model):\n in_rooms.extend(hb_obj.rooms)\n else:\n in_rooms.append(hb_obj)\n\n # use the ColorRoom object to get a set of attributes assigned to the rooms\n color_obj = ColorRoom(in_rooms, _attribute)\n values = color_obj.attributes_unique\n\n # loop through each of the rooms and get the attributes\n rooms = [[] for val in values]\n for atr, room in zip(color_obj.attributes, in_rooms):\n atr_i = values.index(atr)\n rooms[atr_i].append(room)\n rooms = list_to_data_tree(rooms)\n", - "category": "Honeybee", "name": "HB Rooms by Attribute", "description": "Separate and group honeybee Rooms by any attribute that the room possesses.\n_\nThis can be used to group rooms by program, whether rooms are conditioned, etc.\n-" } \ No newline at end of file diff --git a/honeybee_grasshopper_core/src/HB Faces by Attribute.py b/honeybee_grasshopper_core/src/HB Faces by Attribute.py index c639994..47df796 100644 --- a/honeybee_grasshopper_core/src/HB Faces by Attribute.py +++ b/honeybee_grasshopper_core/src/HB Faces by Attribute.py @@ -22,6 +22,11 @@ lists all of the core attributes of the room. Also, each Honeybee extension (ie. Radiance, Energy) includes its own component that lists the Face attributes of that extension. + value_: An optional value of the attribute that can be used to filter + the output rooms. For example, if the input attribute is "Azimuth" + a value for the orientation of the Face can be plugged in here + (eg. "180" for south-facing) in order to get Faces with only + this oreintation. Returns: values: A list of values with one attribute value for each branch of the @@ -32,7 +37,7 @@ ghenv.Component.Name = "HB Faces by Attribute" ghenv.Component.NickName = 'FacesByAttr' -ghenv.Component.Message = '1.8.0' +ghenv.Component.Message = '1.8.1' ghenv.Component.Category = 'Honeybee' ghenv.Component.SubCategory = '2 :: Organize' ghenv.Component.AdditionalHelpFromDocStrings = '1' @@ -40,6 +45,7 @@ try: # import the core honeybee dependencies from honeybee.model import Model from honeybee.room import Room + from honeybee.face import Face from honeybee.colorobj import ColorFace except ImportError as e: raise ImportError('\nFailed to import honeybee:\n\t{}'.format(e)) @@ -55,7 +61,12 @@ # extract any faces from input Rooms or Models faces = [] for hb_obj in _hb_objs: - if isinstance(hb_obj, Model): + if isinstance(hb_obj, Room): + faces.extend(hb_obj.faces) + faces.extend(hb_obj.shades) + elif isinstance(hb_obj, Room): + faces.append(hb_obj) + elif isinstance(hb_obj, Model): for room in hb_obj.rooms: faces.extend(room.faces) faces.extend(room.shades) @@ -64,19 +75,25 @@ faces.extend(hb_obj.orphaned_doors) faces.extend(hb_obj.orphaned_shades) faces.extend(hb_obj.shade_meshes) - elif isinstance(hb_obj, Room): - faces.extend(hb_obj.faces) - faces.extend(hb_obj.shades) else: - faces.append(hb_obj) + msg = 'Expected Face, Room or Model. Got {}.'.format(type(hb_obj)) + raise TypeError(msg) - # use the ColorRoom object to get a set of attributes assigned to the faces + # use the ColorFace object to get a set of attributes assigned to the faces color_obj = ColorFace(faces, _attribute) - values = color_obj.attributes_unique - # loop through each of the hb_objs and get the floor height - hb_objs = [[] for val in values] - for atr, face in zip(color_obj.attributes, color_obj.flat_faces): - atr_i = values.index(atr) - hb_objs[atr_i].append(face) + # loop through each of the hb_objs and get the attribute + if len(value_) == 0: + values = color_obj.attributes_unique + hb_objs = [[] for val in values] + for atr, face in zip(color_obj.attributes, color_obj.flat_faces): + atr_i = values.index(atr) + hb_objs[atr_i].append(face) + else: + values = [atr for atr in color_obj.attributes_unique if atr in value_] + hb_objs = [[] for val in values] + for atr, face in zip(color_obj.attributes, color_obj.flat_faces): + if atr in values: + atr_i = values.index(atr) + hb_objs[atr_i].append(face) hb_objs = list_to_data_tree(hb_objs) diff --git a/honeybee_grasshopper_core/src/HB Rooms by Attribute.py b/honeybee_grasshopper_core/src/HB Rooms by Attribute.py index 1975050..489863a 100644 --- a/honeybee_grasshopper_core/src/HB Rooms by Attribute.py +++ b/honeybee_grasshopper_core/src/HB Rooms by Attribute.py @@ -21,7 +21,12 @@ lists all of the core attributes of the room. Also, each Honeybee extension (ie. Radiance, Energy) includes its own component that lists the Room attributes of that extension. - + value_: An optional value of the attribute that can be used to filter + the output rooms. For example, if the input attribute is "Program" + a value for the name of a program can be plugged in here + (eg. "2019::LargeOffice::OpenOffice") in order to get only the + rooms that have this program assigned. + Returns: values: A list of values with one attribute value for each branch of the output rooms. @@ -31,13 +36,14 @@ ghenv.Component.Name = "HB Rooms by Attribute" ghenv.Component.NickName = 'RoomsByAttr' -ghenv.Component.Message = '1.8.0' +ghenv.Component.Message = '1.8.1' ghenv.Component.Category = 'Honeybee' ghenv.Component.SubCategory = '2 :: Organize' ghenv.Component.AdditionalHelpFromDocStrings = '1' try: # import the core honeybee dependencies from honeybee.model import Model + from honeybee.room import Room from honeybee.colorobj import ColorRoom except ImportError as e: raise ImportError('\nFailed to import honeybee:\n\t{}'.format(e)) @@ -53,18 +59,28 @@ # extract any rooms from input Models in_rooms = [] for hb_obj in _rooms: - if isinstance(hb_obj, Model): + if isinstance(hb_obj, Room): + in_rooms.append(hb_obj) + elif isinstance(hb_obj, Model): in_rooms.extend(hb_obj.rooms) else: - in_rooms.append(hb_obj) + raise TypeError('Expected Room or Model. Got {}.'.format(type(hb_obj))) # use the ColorRoom object to get a set of attributes assigned to the rooms color_obj = ColorRoom(in_rooms, _attribute) - values = color_obj.attributes_unique # loop through each of the rooms and get the attributes - rooms = [[] for val in values] - for atr, room in zip(color_obj.attributes, in_rooms): - atr_i = values.index(atr) - rooms[atr_i].append(room) + if len(value_) == 0: + values = color_obj.attributes_unique + rooms = [[] for val in values] + for atr, room in zip(color_obj.attributes, in_rooms): + atr_i = values.index(atr) + rooms[atr_i].append(room) + else: + values = [atr for atr in color_obj.attributes_unique if atr in value_] + rooms = [[] for val in values] + for atr, room in zip(color_obj.attributes, in_rooms): + if atr in values: + atr_i = values.index(atr) + rooms[atr_i].append(room) rooms = list_to_data_tree(rooms) diff --git a/honeybee_grasshopper_core/user_objects/HB Faces by Attribute.ghuser b/honeybee_grasshopper_core/user_objects/HB Faces by Attribute.ghuser index b762e6d39f785dba366cc69d549f8b32d2d28f50..bb6c6022c7c8e193873077271bbf426d4116efed 100644 GIT binary patch literal 5596 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 literal 5228 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 diff --git a/honeybee_grasshopper_core/user_objects/HB Rooms by Attribute.ghuser b/honeybee_grasshopper_core/user_objects/HB Rooms by Attribute.ghuser index a21fd1ee3ecb8245d25c78b2dfbf2d15bb113438..489183020f2810a0adee63fe442153ffd9e77d92 100644 GIT binary patch literal 5306 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 Mg!~5p0RR630QD+`!~g&Q literal 4962 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