From ccff8e5f1265ad0b5f52a4501fc79514731f165e Mon Sep 17 00:00:00 2001 From: Chris Mackey Date: Thu, 7 Mar 2024 11:50:55 -0800 Subject: [PATCH] feat(extra): Add a component to set the view --- .../icon/LB Legend 2D Parameters.png | Bin 1323 -> 1325 bytes ladybug_grasshopper/icon/LB Set View.png | Bin 0 -> 870 bytes ladybug_grasshopper/icon/LB View From Sun.png | Bin 929 -> 929 bytes .../json/LB_Legend_2D_Parameters.json | 40 ++++---- ladybug_grasshopper/json/LB_Set_View.json | 63 ++++++++++++ .../json/LB_View_From_Sun.json | 4 +- .../src/LB Legend 2D Parameters.py | 4 +- ladybug_grasshopper/src/LB Set View.py | 94 ++++++++++++++++++ ladybug_grasshopper/src/LB View From Sun.py | 14 ++- .../LB Legend 2D Parameters.ghuser | Bin 5416 -> 5389 bytes .../user_objects/LB Set View.ghuser | Bin 0 -> 4782 bytes .../user_objects/LB View From Sun.ghuser | Bin 4494 -> 4589 bytes 12 files changed, 191 insertions(+), 28 deletions(-) create mode 100644 ladybug_grasshopper/icon/LB Set View.png create mode 100644 ladybug_grasshopper/json/LB_Set_View.json create mode 100644 ladybug_grasshopper/src/LB Set View.py create mode 100644 ladybug_grasshopper/user_objects/LB Set View.ghuser diff --git a/ladybug_grasshopper/icon/LB Legend 2D Parameters.png b/ladybug_grasshopper/icon/LB Legend 2D Parameters.png index ef9c44da8894d8ca449a04490e460e55f3fc34d2..657a2ff7ec1fedc3ccfb926fd3b54bdcf77e48dd 100644 GIT binary patch delta 1255 zcmV$r5M= z_=kmOziW#zTVgVn?2mntC%?Pz^Yr`e{qB0D{y)^y{Mt6g;D5A*@m=*qcAD?9YWP`fPF)%$MObo#i|I=UCOexr;HPSu+PMM7QY}G^q^<#G0a|X;V0@ zHET7@UT=C5G=Ih zRHy45edjQddt+4R;CoRqg2%F~oD7Kb1SgAYZPYew=79~ffK7sC0~z!yf=9N-!qM!Z ze|3|G*6Fj6X+U3!4!aF9tT!+)FeTOU#lbLzqCz2)UlG zRjjw;U#MQ8Tb~>|2hIn-qVoI8Se^W)JN2#9C+E(b!QkK^7A=TJNKnXYB9UlG)|Rd4 z>F!3i(|?KH-d=Lt180{L*K2B#ZZbjQ=eg>?vAMkb6xtiCm^M2BisLO$s15mvq<-Y` zrAzqX%2kl#EU8qgoW*hXFPuM*M-Lw&dBsY1TB_;ss<+d|j+K^TWMl-E?K^~QuF&); z%H;QRQ&LPwm^UBvaXUEM7-Gi9Lx~kxm~TPn-G957DiVL;O;d5^++5te(IhlFO{5~? zh|H_g(#Ic!9hS*tI$u0)Vt`aEDfQJRh}&6Eh_==?Ocjei_tnU|=E8#%?%Gg2 zd(~x=6`UQ=8;rQu-inTn4$z@t{j#8-oNzka^TQ)NZ-Bv^lZ#vJxA5Xr=?PzrqJr`p z*1c48zgrZa>6{xGIr!-3e$>{~Kt6NkU4LS05)%_8-lT`;4Vbrk=PtCiI3N*;OMEqo z3NHR}OW^VyFeRM4t zl$VtW_uvC>i4d${zRJtmiZS;SSn{?L(;p&f$cZTwwP!}qj6PPaZYHmc1HQN=FMoF% z>`ga?Car!HRYY`n=Je@}M-Cl^%jH50*#+VSd(r|NP2a=#I0Wi#HdIws!e+Ii?z$DN zj#ga!_B-;#i1+*Z`^T+GOUJ;#fG2yswib2PI?rc%dwTIxUmun)St<-Rc{}@v&}#4G zWMw0teEXt(`*E=N01gxt;~-J-$6!Us+>`;OOm;LNAb?xG?2XYqyFNmp#X@o9UZM9s{l*1nCMww`1gw>`Y)lVKLL{xDl#Ki R8;$?~002ovPDHLkV1g4Ycc=gW delta 1253 zcmV0z+i2cSw#(i`8|)1#o+nlSt6`UNESs!UDy6>k1Q>cxzt)o; z)8$^T?;0lZY>Me}y&n@Ncr44x$$$iJaH6==Vzy%o4{V$PY!);VNT**BJhC+wj%E-2 ztD8KuPM?Jg1Nu{R*kh1kgMop8QQ0LTQ37US)iqd@xBydwgHP%8`cR|MC{`&H2O|`U%Lh4bbkEF|nTkw~;SbL%$r z_Vl2~>3>9DUmrQ{g|pj<>ov7VHJKm@@Lu)b*iun(673CEOqrPo#j%zr)W*CdQZKo5 z@gjb>auwt_Q!14zXK>uT^XJat;e!WQxjfmEYI^7Kn$@YJN6X6a=+PrscI*_gIYQH? zC|7)tlagXW;+(mlkJ-W5MiDnQ7EY|_f;e$U0H>1zCJDFxA{th$P2%iV;n$K^)RApN1!Tc^hB`Q zVSh(cBRV@ep;m?u%VaX0Kb|l?Kq{7$`D^1O?8+}dTWcF8i^ZS&Yvf&X{(cH~ZK$5T z>bA-9&kX7fM%-<0MMp;m=E(F?=Iq(E8?7x4NJQdNe~qF- zi+sGWn zT5;jq@5mD)J`flfn6P$rDh3A!z1i!vwWzb!c|X(F+lQa}`>|~C5@E2(*V#{$R@<4K znT0&^?F;uGz`>$o6c-lZAW_jLgoaIos+nYY{dtOwjn$APx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0{clsK~zXf?UY?e zlTjGQ&-PMMmtr9fB>TW9jDocx=BPzxg^C|RVWuO~qE-?Slw=@X_!+6)ltocETawzQ z%hV*jkfaRMP|8eer5CXe+?;zix2I?4J+dyg)IRR~!Na@voag_4&ikBmMwa;>tYFW7 z#%c_eGJdz_T47Pwi5%7Vk&KL?)Z~;J98bddtAcV>j%q-!)4}xgH2jK-cR_Pw6C^12 z4Pu@`NM9Q2vXT;J7aX4Fp{nwxC4}P=nQl=it``?G3jwXs1(|&_pzOB6(LOuWedXDV zz=iV#fI7J#|2?bJXVtw-2R64Clsz^e56wX8FtiwtF*Ih_i{loTm*zR0PEhQMf6F|A zBPQZ3LrV)4`8d#Php=W7Xg-iCO42rX1LgIrtht9hJYlU0nyb4AO;@DQ!IjC)Ahqm=cgtoVPjO(ZDti1Jc?~J z8z~yb6=Pe%J7%G%V-Tb_O-ahyN-PAK3bJtd`IunIz2a`F(%h3YXU-AtmJ z!B&j}w?2lNbCH{YJQxL{#|7Yg=|?A102HXz_nB2-Vr8;g9#4c1qr(F$o3PIfSfmBp zrJVv%*-KpYci|n!Io#|qyNBj~nV5h`iKLQQ1!kQ@A~&=esKCdq`LB3_@yw2WpTjT0 zr|(^3g7Q)S>T9ZK8{-70;Dp46J%Vy+Naa##Pko)n^UY`k-s%7U85tgd8x<9ho|=9a^EL?Sf6kWZP0^)F wg`(|nTH34p+}zrTu(hQ)zTk!~vjBwr1f8g#fMKSWbN~PV07*qoM6N<$f*8+}2LJ#7 literal 0 HcmV?d00001 diff --git a/ladybug_grasshopper/icon/LB View From Sun.png b/ladybug_grasshopper/icon/LB View From Sun.png index 16ebd006e11e5115ae7707eb633d23b54f094a7b..6783beee87b52d43b94b1dd59496a87b0cc9f026 100644 GIT binary patch delta 839 zcmV-N1GxO52cZX$XMY^g7A&z6+>$o(M@3sedsih{tR zk~A$8&7>H0DiKP;EeNtw3tNaXBnbax5MS?i&dlVUnH=+h2i|k~L3?>R&NNg+I< z86X!%sFIO&aHEbM+=3@{9Dg5Hn5?6VYp`BN14%Fj znpDY+4X_NlPhHmg2b`u#nw4<$4E*73*r`hYK-TRIJfuoSj>AZp0CS_G>7pr+s*sDJ zbG;wJSvro*Y$y$7x}&MfvJwxxAZCVx#O-$Cl63lwdzW<;53=DU9gXBeX}DSnbE4?Z z<0ePP@coY^{C{=C;ws;-B}TPYsp~*qj(sp5sy@6SGl+v1o;K@_T0SQ-RrWAdp;XHp zTi?gF&#CHOb(tDOI?aLa;Ckqjki>Z1dE1wT?1xT^dzdZHais~?!7}Eq!DXt>jtu&M zHu3_D50iU7xD01eU>ra(dZ73n&Z??8}u zT=L77dOd)}{)EYfbjHp!$;<%(X7)R4W5SQ0*Vv`%Ji=_zrrptY7Zh$d^h#vGAw584 z-xj8;NPo?+yccW#iph?Ag}L-~ma4OVj~XCKH}%b2xGW};o=IczXm=6QO{BZ99wO&- zoKyG2nPJqeoBBq!;vtv@1G0DO4#cOQ61cFlgimyw=GKoXuIt+~)UOYP@~ZBEURmg{ z2+FqLWbK+X`t|AU-+`RI?IBK0R-HTdCfU=5p?_@k2IQ&tLvLSR7%T}5q3c#Feb39I z;ru+}%uE^#GE+J3$@V>(5V#6%gQ;>skTs9h(STGKfs0g0H$DZ|!YOhAY=&|UxU(C| zS3TwdBpcr`9bHsIIk}w3F8U2_QY9nP;S3!;*$b!YXy6`PtfLFrx0dMW8#yj3-~gN~ z7eL&=hpY}6cecW#I*yGDAQfk-k`Xx$Wh?M@Z#i^5)QKYhC}i)K*Lj=}{Q*eZYR*03 Raqa*B002ovPDHLkV1j)?nmqsj delta 839 zcmV-N1GxO52cZX$XMbiyTd>43a4TA*exz9-X~L3?>R&NNg+I> z;RYQ&xCu|_IDa;*Fj+?zS7EJ=29jVj zG^vssYhgKbpSrB~Ae^E~n&oih4E*68*rrPVK-TRY%u^*J$6y3p26LmL=z=MLZX*{% z=XyVeGj#M#7?g%G-I3H}S&4gJ5i`Sn;um(}lJ)c(_b%xw9%RFdIvOc}(r~2|W<}E7 zCk>8{;m5&P{(m+c=PEy_CPuYpsp~*qj=eAesy@6SGgt`EKYOG*YWkAMbgPr;HcHjZ zvunH9_9a!_t1MT8NT++?2e<}~N^oL=?!4t|4Ev$e;!ftcm$=dZYhXEZdw;yDvps`8 zp^dx%W5Z;kr1}~?zjA=TSeh2*nYrgUfQZe|e;o$uU=DluUe#%}sR8PwElh!e^ea*sl0 zcUIOf~@&$9Sul@VYon*bmNmS9Zr%9U=x&cz@1%C zzG|NbkZgQMb#ze)<>YcAyXbegQI(8Lh0}EOWH+3wqk;Qyk&Z58--^|7bmX|a0ej&@ zxj^6sK4f*sxU&Tw*3maIfK;5WN=D>3l&!$qy(Q4~P{)h>qmaE{Ugt4F^aoFKYR@T$ R_67g|002ovPDHLkV1h2dme~LR diff --git a/ladybug_grasshopper/json/LB_Legend_2D_Parameters.json b/ladybug_grasshopper/json/LB_Legend_2D_Parameters.json index df66ca5..df74282 100644 --- a/ladybug_grasshopper/json/LB_Legend_2D_Parameters.json +++ b/ladybug_grasshopper/json/LB_Legend_2D_Parameters.json @@ -1,57 +1,57 @@ { - "description": "Customize the properties of a screen-oreinted 2D legend displaying with the\n\"LB Preview VisualizationSet\" component.\n-", + "version": "1.7.2", + "nickname": "Legend2D", "outputs": [ [ { - "type": null, + "access": "None", "name": "leg_par2d", "description": "A legend parameter object that can be plugged into any of the\nLadybug components with a legend.", - "access": "None", + "type": null, "default": null } ] ], - "code": "\n\ntry:\n from ladybug.legend import Legend2DParameters\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug:\\n\\t{}'.format(e))\ntry:\n from ladybug_{{cad}}.{{plugin}} import turn_off_old_tag\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\nturn_off_old_tag(ghenv.Component)\n\n\ndef parse_dim_text(dim_text):\n \"\"\"Parse text representing a dimension into an input for legend parameters.\"\"\"\n try:\n px_txt = int(dim_text)\n return '{}px'.format(px_txt)\n except ValueError:\n return dim_text\n\n\n# parse all of the inputs\norigin_x_ = parse_dim_text(origin_x_) if origin_x_ is not None else None\norigin_y_ = parse_dim_text(origin_y_) if origin_y_ is not None else None\nseg_height_ = parse_dim_text(seg_height_) if seg_height_ is not None else None\nseg_width_ = parse_dim_text(seg_width_) if seg_width_ is not None else None\ntext_height_ = parse_dim_text(text_height_) if text_height_ is not None else None\n\n# make the 2D legend parameters\nleg_par2d = Legend2DParameters(origin_x_, origin_y_, seg_height_, seg_width_, text_height_)\n", - "name": "LB Legend 2D Parameters", - "version": "1.7.1", - "category": "Ladybug", - "subcategory": "4 :: Extra", - "nickname": "Legend2D", "inputs": [ { - "type": "string", + "access": "item", "name": "origin_x_", "description": "An integer in pixels to note the X coordinate of the base point from\nwhere the 2D legend will be generated (assuming an origin in the\nupper-left corner of the screen with higher positive values of\nX moving to the right). Alternatively, this can be a text string\nending in a % sign to denote the percentage of the screen where\nthe X coordinate exists (eg. 5%). The default is set to make the\nlegend clearly visible in the upper-left corner of the\nscreen (10 pixels).", - "access": "item", + "type": "string", "default": null }, { - "type": "string", + "access": "item", "name": "origin_y_", "description": "An integer in pixels to note the Y coordinate of the base point from\nwhere the legend will be generated (assuming an origin in the\nupper-left corner of the screen with higher positive values of\nY moving downward). Alternatively, this can be a text string\nending in a % sign to denote the percentage of the screen where\nthe X coordinate exists (eg. 5%). The default is set to make the\nlegend clearly visible in the upper-left corner of the\nscreen (50 pixels).", - "access": "item", + "type": "string", "default": null }, { - "type": "string", + "access": "item", "name": "seg_height_", "description": "A integer in pixels to note the height for each of the legend segments.\nAlternatively, this can be a text string ending in a % sign to\ndenote the percentage of the screen (eg. 5%). The default is set\nto make most legends readable on standard resolution\nscreens (25px for horizontal and 36px for vertical).", - "access": "item", + "type": "string", "default": null }, { - "type": "string", + "access": "item", "name": "seg_width_", "description": "An integer in pixels to set the width of each of the legend segments.\nAlternatively, this can be a text string ending in a % sign to\ndenote the percentage of the screen (eg. 5%). The default is set\nto make most legends readable on standard resolution\nscreens (36px for horizontal and 25px for vertical).", - "access": "item", + "type": "string", "default": null }, { - "type": "string", + "access": "item", "name": "text_height_", "description": "An integer in pixels to set the height for the legend text.\nAlternatively, this can be a text string ending in a % sign to\ndenote the percentage of the screen (eg. 2%).", - "access": "item", + "type": "string", "default": null } - ] + ], + "subcategory": "4 :: Extra", + "code": "\n\ntry:\n from ladybug.legend import Legend2DParameters\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug:\\n\\t{}'.format(e))\ntry:\n from ladybug_{{cad}}.{{plugin}} import turn_off_old_tag\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\nturn_off_old_tag(ghenv.Component)\n\n\ndef parse_dim_text(dim_text):\n \"\"\"Parse text representing a dimension into an input for legend parameters.\"\"\"\n try:\n px_txt = int(dim_text)\n return '{}px'.format(px_txt)\n except ValueError:\n return dim_text\n\n\n# parse all of the inputs\norigin_x_ = parse_dim_text(origin_x_) if origin_x_ is not None else None\norigin_y_ = parse_dim_text(origin_y_) if origin_y_ is not None else None\nseg_height_ = parse_dim_text(seg_height_) if seg_height_ is not None else None\nseg_width_ = parse_dim_text(seg_width_) if seg_width_ is not None else None\ntext_height_ = parse_dim_text(text_height_) if text_height_ is not None else None\n\n# make the 2D legend parameters\nleg_par2d = Legend2DParameters(origin_x_, origin_y_, seg_height_, seg_width_, text_height_)\n", + "category": "Ladybug", + "name": "LB Legend 2D Parameters", + "description": "Customize the properties of a screen-oreinted 2D legend displaying with the\n\"LB Preview VisualizationSet\" component.\n-" } \ No newline at end of file diff --git a/ladybug_grasshopper/json/LB_Set_View.json b/ladybug_grasshopper/json/LB_Set_View.json new file mode 100644 index 0000000..023d499 --- /dev/null +++ b/ladybug_grasshopper/json/LB_Set_View.json @@ -0,0 +1,63 @@ +{ + "version": "1.7.0", + "nickname": "SetView", + "outputs": [ + [] + ], + "inputs": [ + { + "access": "item", + "name": "_direction", + "description": "A sun vector from which the the Rhino view will be generated.\nUse the \"LB SunPath\" component to generate sun vectors.", + "type": "Vector3d", + "default": null + }, + { + "access": "item", + "name": "_position_", + "description": "The target point of the camera for the Rhino view that will be\ngenerated. This point should be close to the Rhino geometry that\nyou are interested in viewing from the sun. If no point is provided,\nthe Rhino origin will be used (0, 0, 0).", + "type": "Point3d", + "default": null + }, + { + "access": "item", + "name": "look_around_", + "description": "An optional interger for the width (in pixels) of the Rhino\nviewport that will be generated.", + "type": "Point3d", + "default": null + }, + { + "access": "item", + "name": "width_", + "description": "An optional interger for the width (in pixels) of the Rhino\nviewport that will be generated.", + "type": "int", + "default": null + }, + { + "access": "item", + "name": "height_", + "description": "An optional interger for the height (in pixels) of the Rhino\nviewport that will be generated.", + "type": "int", + "default": null + }, + { + "access": "item", + "name": "lens_len_", + "description": "An optional interger for the height (in pixels) of the Rhino\nviewport that will be generated.", + "type": "double", + "default": null + }, + { + "access": "item", + "name": "mode_", + "description": "An optional text input for the display mode of the Rhino viewport\nthat will be generated. For example: Wireframe, Shaded, Rendered, etc.", + "type": "string", + "default": null + } + ], + "subcategory": "4 :: Extra", + "code": "\nimport math\n\ntry:\n from ladybug_geometry.geometry3d import Vector3D\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_geometry:\\n\\t{}'.format(e))\n\ntry:\n from ladybug_{{cad}}.togeometry import to_vector3d, to_point2d\n from ladybug_{{cad}}.fromgeometry import from_vector3d\n from ladybug_{{cad}}.viewport import open_viewport, viewport_by_name, \\\n set_view_direction, set_view_display_mode\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, component_guid, \\\n get_sticky_variable, set_sticky_variable\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 # get the name of the view and the previous width/height\n view_name = 'SetView_{}'.format(component_guid(ghenv.Component))\n print(view_name) # print so that the user has the name if needed\n vw = get_sticky_variable('set_view_width')\n vh = get_sticky_variable('set_view_height')\n\n # if there are look-around coordinates, rotate the direction\n if look_around_ is not None:\n uv_pt = to_point2d(look_around_)\n dir_vec = to_vector3d(_direction)\n v = (uv_pt.y - 0.5) * math.pi\n dir_vec = dir_vec.rotate(dir_vec.cross(Vector3D(0, 0, 1)), v)\n u = -(uv_pt.x - 0.5) * math.pi\n dir_vec = dir_vec.rotate_xy(u)\n _direction = from_vector3d(dir_vec)\n\n # get the viewport from which the direction will be set\n view_port = None\n if width_ == vw and height_ == vh: # no need to generate new view; get existing one\n try:\n view_port = viewport_by_name(view_name)\n except ValueError: # the viewport does not yet exist\n pass\n if view_port is None:\n view_port = open_viewport(view_name, width_, height_)\n set_sticky_variable('set_view_width', width_)\n set_sticky_variable('set_view_height', height_)\n\n # set the direction of the viewport camera\n set_view_direction(view_port, _direction, _position_, lens_len_)\n\n # set the display mode if requested\n if mode_:\n set_view_display_mode(view_port, mode_)\n", + "category": "Ladybug", + "name": "LB Set View", + "description": "Open a new viewport in Rhino that shows the parallel-projected view from the sun.\n_\nThis is useful for understanding what parts of Rhino geometry are shaded at a\nparticular hour of the day.\n-" +} \ No newline at end of file diff --git a/ladybug_grasshopper/json/LB_View_From_Sun.json b/ladybug_grasshopper/json/LB_View_From_Sun.json index d94eebf..41d874e 100644 --- a/ladybug_grasshopper/json/LB_View_From_Sun.json +++ b/ladybug_grasshopper/json/LB_View_From_Sun.json @@ -1,5 +1,5 @@ { - "version": "1.7.1", + "version": "1.7.2", "nickname": "ViewFromSun", "outputs": [ [] @@ -42,7 +42,7 @@ } ], "subcategory": "3 :: Analyze Geometry", - "code": "\ntry:\n from ladybug_{{cad}}.viewport import viewport_by_name, open_viewport, \\\n set_iso_view_direction, set_view_display_mode\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, component_guid\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 view_name = 'ViewFromSun_{}'.format(component_guid(ghenv.Component))\n print(view_name) # print so that the user has the name if needed\n\n # get the viewport from which the direction will be set\n view_port = None\n if not width_ and not height_: # no need to generate new view; get existing one\n try:\n view_port = viewport_by_name(view_name)\n except ValueError: # the viewport does not yet exist\n pass\n if view_port is None:\n view_port = open_viewport(view_name, width_, height_)\n\n # set the direction of the viewport camera\n set_iso_view_direction(view_port, _vector, _center_pt_)\n\n # set the display mode if requested\n if mode_:\n set_view_display_mode(view_port, mode_)\n", + "code": "\ntry:\n from ladybug_{{cad}}.viewport import viewport_by_name, open_viewport, \\\n set_iso_view_direction, set_view_display_mode\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, component_guid, \\\n get_sticky_variable, set_sticky_variable\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 # get the name of the view and the previous width/height\n view_name = 'ViewFromSun_{}'.format(component_guid(ghenv.Component))\n print(view_name) # print so that the user has the name if needed\n vw = get_sticky_variable('sun_view_width')\n vh = get_sticky_variable('sun_view_height')\n\n # get the viewport from which the direction will be set\n view_port = None\n if width_ == vw and height_ == vh: # no need to generate new view; get existing one\n try:\n view_port = viewport_by_name(view_name)\n except ValueError: # the viewport does not yet exist\n pass\n if view_port is None:\n view_port = open_viewport(view_name, width_, height_)\n set_sticky_variable('sun_view_width', width_)\n set_sticky_variable('sun_view_height', height_)\n\n # set the direction of the viewport camera\n set_iso_view_direction(view_port, _vector, _center_pt_)\n\n # set the display mode if requested\n if mode_:\n set_view_display_mode(view_port, mode_)\n", "category": "Ladybug", "name": "LB View From Sun", "description": "Open a new viewport in Rhino that shows the parallel-projected view from the sun.\n_\nThis is useful for understanding what parts of Rhino geometry are shaded at a\nparticular hour of the day.\n-" diff --git a/ladybug_grasshopper/src/LB Legend 2D Parameters.py b/ladybug_grasshopper/src/LB Legend 2D Parameters.py index 981c4ba..7c0f490 100644 --- a/ladybug_grasshopper/src/LB Legend 2D Parameters.py +++ b/ladybug_grasshopper/src/LB Legend 2D Parameters.py @@ -51,10 +51,10 @@ ghenv.Component.Name = 'LB Legend 2D Parameters' ghenv.Component.NickName = 'Legend2D' -ghenv.Component.Message = '1.7.1' +ghenv.Component.Message = '1.7.2' ghenv.Component.Category = 'Ladybug' ghenv.Component.SubCategory = '4 :: Extra' -ghenv.Component.AdditionalHelpFromDocStrings = '0' +ghenv.Component.AdditionalHelpFromDocStrings = '2' try: diff --git a/ladybug_grasshopper/src/LB Set View.py b/ladybug_grasshopper/src/LB Set View.py new file mode 100644 index 0000000..fbf74e4 --- /dev/null +++ b/ladybug_grasshopper/src/LB Set View.py @@ -0,0 +1,94 @@ +# Ladybug: A Plugin for Environmental Analysis (GPL) +# This file is part of Ladybug. +# +# Copyright (c) 2023, Ladybug Tools. +# You should have received a copy of the GNU Affero General Public License +# along with Ladybug; If not, see . +# +# @license AGPL-3.0-or-later + +""" +Open a new viewport in Rhino that shows the parallel-projected view from the sun. +_ +This is useful for understanding what parts of Rhino geometry are shaded at a +particular hour of the day. +- + + Args: + _vector: A sun vector from which the the Rhino view will be generated. + Use the "LB SunPath" component to generate sun vectors. + _center_pt_: The target point of the camera for the Rhino view that will be + generated. This point should be close to the Rhino geometry that + you are interested in viewing from the sun. If no point is provided, + the Rhino origin will be used (0, 0, 0). + width_: An optional interger for the width (in pixels) of the Rhino + viewport that will be generated. + height_: An optional interger for the height (in pixels) of the Rhino + viewport that will be generated. + mode_: An optional text input for the display mode of the Rhino viewport + that will be generated. For example: Wireframe, Shaded, Rendered, etc. + + Returns: + report: The name of the viewport that was opened. +""" + +ghenv.Component.Name = 'LB Set View' +ghenv.Component.NickName = 'SetView' +ghenv.Component.Message = '1.7.0' +ghenv.Component.Category = 'Ladybug' +ghenv.Component.SubCategory = '4 :: Extra' +ghenv.Component.AdditionalHelpFromDocStrings = '2' + +import math + +try: + from ladybug_geometry.geometry3d import Vector3D +except ImportError as e: + raise ImportError('\nFailed to import ladybug_geometry:\n\t{}'.format(e)) + +try: + from ladybug_rhino.togeometry import to_vector3d, to_point2d + from ladybug_rhino.fromgeometry import from_vector3d + from ladybug_rhino.viewport import open_viewport, viewport_by_name, \ + set_view_direction, set_view_display_mode + from ladybug_rhino.grasshopper import all_required_inputs, component_guid, \ + get_sticky_variable, set_sticky_variable +except ImportError as e: + raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e)) + + +if all_required_inputs(ghenv.Component): + # get the name of the view and the previous width/height + view_name = 'SetView_{}'.format(component_guid(ghenv.Component)) + print(view_name) # print so that the user has the name if needed + vw = get_sticky_variable('set_view_width') + vh = get_sticky_variable('set_view_height') + + # if there are look-around coordinates, rotate the direction + if look_around_ is not None: + uv_pt = to_point2d(look_around_) + dir_vec = to_vector3d(_direction) + v = (uv_pt.y - 0.5) * math.pi + dir_vec = dir_vec.rotate(dir_vec.cross(Vector3D(0, 0, 1)), v) + u = -(uv_pt.x - 0.5) * math.pi + dir_vec = dir_vec.rotate_xy(u) + _direction = from_vector3d(dir_vec) + + # get the viewport from which the direction will be set + view_port = None + if width_ == vw and height_ == vh: # no need to generate new view; get existing one + try: + view_port = viewport_by_name(view_name) + except ValueError: # the viewport does not yet exist + pass + if view_port is None: + view_port = open_viewport(view_name, width_, height_) + set_sticky_variable('set_view_width', width_) + set_sticky_variable('set_view_height', height_) + + # set the direction of the viewport camera + set_view_direction(view_port, _direction, _position_, lens_len_) + + # set the display mode if requested + if mode_: + set_view_display_mode(view_port, mode_) diff --git a/ladybug_grasshopper/src/LB View From Sun.py b/ladybug_grasshopper/src/LB View From Sun.py index 837b9f9..9e46227 100644 --- a/ladybug_grasshopper/src/LB View From Sun.py +++ b/ladybug_grasshopper/src/LB View From Sun.py @@ -29,12 +29,12 @@ that will be generated. For example: Wireframe, Shaded, Rendered, etc. Returns: - report: ... + report: The name of the viewport that was opened. """ ghenv.Component.Name = 'LB View From Sun' ghenv.Component.NickName = 'ViewFromSun' -ghenv.Component.Message = '1.7.1' +ghenv.Component.Message = '1.7.2' ghenv.Component.Category = 'Ladybug' ghenv.Component.SubCategory = '3 :: Analyze Geometry' ghenv.Component.AdditionalHelpFromDocStrings = '5' @@ -42,24 +42,30 @@ try: from ladybug_rhino.viewport import viewport_by_name, open_viewport, \ set_iso_view_direction, set_view_display_mode - from ladybug_rhino.grasshopper import all_required_inputs, component_guid + from ladybug_rhino.grasshopper import all_required_inputs, component_guid, \ + get_sticky_variable, set_sticky_variable except ImportError as e: raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e)) if all_required_inputs(ghenv.Component): + # get the name of the view and the previous width/height view_name = 'ViewFromSun_{}'.format(component_guid(ghenv.Component)) print(view_name) # print so that the user has the name if needed + vw = get_sticky_variable('sun_view_width') + vh = get_sticky_variable('sun_view_height') # get the viewport from which the direction will be set view_port = None - if not width_ and not height_: # no need to generate new view; get existing one + if width_ == vw and height_ == vh: # no need to generate new view; get existing one try: view_port = viewport_by_name(view_name) except ValueError: # the viewport does not yet exist pass if view_port is None: view_port = open_viewport(view_name, width_, height_) + set_sticky_variable('sun_view_width', width_) + set_sticky_variable('sun_view_height', height_) # set the direction of the viewport camera set_iso_view_direction(view_port, _vector, _center_pt_) diff --git a/ladybug_grasshopper/user_objects/LB Legend 2D Parameters.ghuser b/ladybug_grasshopper/user_objects/LB Legend 2D Parameters.ghuser index 39cc4c5cc074da5d73d2f826e0f7541fea417e19..65ae1134dbd924be04c077aae19f411c3808d9bf 100644 GIT binary patch literal 5389 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 literal 5416 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 SV33?U3IX{a00030{{sMWyPF^Y diff --git a/ladybug_grasshopper/user_objects/LB Set View.ghuser b/ladybug_grasshopper/user_objects/LB Set View.ghuser new file mode 100644 index 0000000000000000000000000000000000000000..ce16e3a709f79124425bacdc870a7d6a17f279d6 GIT binary patch literal 4782 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 literal 0 HcmV?d00001 diff --git a/ladybug_grasshopper/user_objects/LB View From Sun.ghuser b/ladybug_grasshopper/user_objects/LB View From Sun.ghuser index 234ac6ce531b1a4f8684c2f7953250f85cf48d97..c803cc068d80feef5dd431d864c0c42e070aed43 100644 GIT binary patch literal 4589 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 XheZ;kpa4>bL)^T5pdg+9e3bkjN^1=! literal 4494 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