Skip to content

Commit

Permalink
fix(extra): Add an option for custom 2D legend
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswmackey authored and Chris Mackey committed Feb 3, 2023
1 parent 64c275e commit 274f6a3
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 46 deletions.
Binary file modified ladybug_grasshopper/icon/LB Create Legend.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 9 additions & 2 deletions ladybug_grasshopper/json/LB_Create_Legend.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.6.0",
"version": "1.6.1",
"nickname": "CreateLegend",
"outputs": [
[
Expand Down Expand Up @@ -68,10 +68,17 @@
"description": "Optional legend parameters from the Legend Parameters component.",
"type": "System.Object",
"default": null
},
{
"access": "item",
"name": "leg_par2d_",
"description": "Optional 2D LegendParameters from the \"LB Legend Parameters 2D\"\ncomponent, which will be used to customize a legend in the plane\nof the screen so that it functions like a head-up display (HUD).\nIf unspecified, the VisualizationSet will be rendered with 3D\nlegends in the Rhino scene much like the other native Ladybug\nTools components.",
"type": "System.Object",
"default": null
}
],
"subcategory": "4 :: Extra",
"code": "\ntry:\n from ladybug.datacollection import BaseCollection\n from ladybug.legend import Legend, LegendParameters\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug:\\n\\t{}'.format(e))\n\ntry:\n from ladybug_{{cad}}.togeometry import to_plane\n from ladybug_{{cad}}.fromobjects import legend_objects\n from ladybug_{{cad}}.color import color_to_color\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs\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 # set default values\n legend_par_ = legend_par_.duplicate() if legend_par_ is not None else \\\n LegendParameters()\n if _base_plane_:\n legend_par_.base_plane = to_plane(_base_plane_)\n legend_par_.title = title_\n\n # create the legend\n values = []\n for val in _values:\n try:\n values.append(float(val))\n except AttributeError: # assume it's a data collection\n values.extend(val.values)\n legend = Legend(values, legend_par_)\n\n # separate all of the outputs from this component\n {{cad}}_objs = legend_objects(legend)\n mesh = {{cad}}_objs[0]\n title_obj = {{cad}}_objs[1]\n label_objs = {{cad}}_objs[2:]\n label_text = legend.segment_text\n colors = [color_to_color(col) for col in legend.value_colors]\n",
"code": "",
"category": "Ladybug",
"name": "LB Create Legend",
"description": "Create a custom legend for any set of data or range. Creating a legend with this\ncomponent allows for a bit more flexibility than what can be achieved by working\nwith the legends automatically output from different studies.\n-"
Expand Down
177 changes: 133 additions & 44 deletions ladybug_grasshopper/src/LB Create Legend.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
title_: A text string representing a legend title. Legends are usually
titled with the units of the data.
legend_par_: Optional legend parameters from the Legend Parameters component.
leg_par2d_: Optional 2D LegendParameters from the "LB Legend Parameters 2D"
component, which will be used to customize a legend in the plane
of the screen so that it functions like a head-up display (HUD).
If unspecified, the VisualizationSet will be rendered with 3D
legends in the Rhino scene much like the other native Ladybug
Tools components.
Returns:
mesh: A colored mesh for the legend colors.
Expand All @@ -34,49 +40,132 @@
be used to color geometry that aligns with the values.
"""

ghenv.Component.Name = "LB Create Legend"
ghenv.Component.NickName = 'CreateLegend'
ghenv.Component.Message = '1.6.0'
ghenv.Component.Category = 'Ladybug'
ghenv.Component.SubCategory = '4 :: Extra'
ghenv.Component.AdditionalHelpFromDocStrings = '0'
from ghpythonlib.componentbase import executingcomponent as component
import Grasshopper, GhPython
import System
import Rhino
import rhinoscriptsyntax as rs

try:
from ladybug.datacollection import BaseCollection
from ladybug.legend import Legend, LegendParameters
except ImportError as e:
raise ImportError('\nFailed to import ladybug:\n\t{}'.format(e))

try:
from ladybug_rhino.togeometry import to_plane
from ladybug_rhino.fromobjects import legend_objects
from ladybug_rhino.color import color_to_color
from ladybug_rhino.grasshopper import all_required_inputs
except ImportError as e:
raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e))


if all_required_inputs(ghenv.Component):
# set default values
legend_par_ = legend_par_.duplicate() if legend_par_ is not None else \
LegendParameters()
if _base_plane_:
legend_par_.base_plane = to_plane(_base_plane_)
legend_par_.title = title_

# create the legend
values = []
for val in _values:
class MyComponent(component):

def RunScript(self, _values, _base_plane_, title_, legend_par_, leg_par2d_):
ghenv.Component.Name = "LB Create Legend"
ghenv.Component.NickName = 'CreateLegend'
ghenv.Component.Message = '1.6.1'
ghenv.Component.Category = 'Ladybug'
ghenv.Component.SubCategory = '4 :: Extra'
ghenv.Component.AdditionalHelpFromDocStrings = '0'

try:
values.append(float(val))
except AttributeError: # assume it's a data collection
values.extend(val.values)
legend = Legend(values, legend_par_)

# separate all of the outputs from this component
rhino_objs = legend_objects(legend)
mesh = rhino_objs[0]
title_obj = rhino_objs[1]
label_objs = rhino_objs[2:]
label_text = legend.segment_text
colors = [color_to_color(col) for col in legend.value_colors]
from ladybug.datacollection import BaseCollection
from ladybug.legend import Legend, LegendParameters
except ImportError as e:
raise ImportError('\nFailed to import ladybug:\n\t{}'.format(e))

try:
import scriptcontext as sc
import Rhino.Display as rd
import Rhino.Geometry as rg
from System.Drawing import Color
from ladybug_rhino.togeometry import to_plane
from ladybug_rhino.fromobjects import legend_objects
from ladybug_rhino.color import color_to_color
from ladybug_rhino.grasshopper import all_required_inputs
except ImportError as e:
raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e))


if all_required_inputs(ghenv.Component):
# set default values
legend_par_ = legend_par_.duplicate() if legend_par_ is not None else \
LegendParameters()
if _base_plane_:
legend_par_.base_plane = to_plane(_base_plane_)
legend_par_.title = title_

# create the legend
values = []
for val in _values:
try:
values.append(float(val))
except AttributeError: # assume it's a data collection
values.extend(val.values)
legend = Legend(values, legend_par_)

if leg_par2d_ is None: # output a 3D legend
self.draw_2d_text, self.draw_sprite = None, None
rhino_objs = legend_objects(legend)
mesh = rhino_objs[0]
title_obj = rhino_objs[1]
label_objs = rhino_objs[2:]
label_text = legend.segment_text
colors = [color_to_color(col) for col in legend.value_colors]
else: # output a 2D legend that is oriented to the screen
# set the 3D legend outputs to None
mesh, title_obj, label_objs, label_text, colors = \
None, None, None, None, None
self.draw_2d_text, self.draw_sprite = [], []
legend.legend_parameters.properties_2d = leg_par2d_

# figure out the dimensions of the active viewport
active_view = sc.doc.Views.ActiveView.ActiveViewport
v_size = active_view.Size
vw, vh = v_size.Width, v_size.Height

# translate the color matrix to a bitmap
l_par = legend.legend_parameters
color_mtx = legend.color_map_2d(vw, vh)
color_mtx = [[color_to_color(c) for c in row] for row in color_mtx]
net_bm = System.Drawing.Bitmap(len(color_mtx[0]), len(color_mtx))
for y, row in enumerate(color_mtx):
for x, col in enumerate(row):
net_bm.SetPixel(x, y, col)
rh_bm = rd.DisplayBitmap(net_bm)
or_x, or_y, sh, sw, th = legend._pixel_dims_2d(vw, vh)
s_count = l_par.segment_count
s_count = s_count - 1 if l_par.continuous_legend else s_count
leg_width = sw if l_par.vertical else sw * s_count
leg_height = sh if not l_par.vertical else sh * s_count
cent_pt = rg.Point2d(or_x + (leg_width / 2), or_y + (leg_height / 2))
self.draw_sprite.append((rh_bm, cent_pt, leg_width, leg_height))

# translate the legend text
_height = legend.parse_dim_2d(l_par.text_height_2d, vh)
_font = l_par.font
txt_pts = legend.segment_text_location_2d(vw, vh)
cent_txt = False if l_par.vertical else True
legend_text = [
(txt, Color.Black, rg.Point2d(loc.x, loc.y), cent_txt, _height, _font)
for txt, loc in zip(legend.segment_text, txt_pts)]
t_pt = legend.title_location_2d(vw, vh)
legend_title = (legend.title, Color.Black, rg.Point2d(t_pt.x, t_pt.y),
False, _height, _font)
legend_text.insert(0, legend_title)
self.draw_2d_text.extend(legend_text)
else:
mesh, title_obj, label_objs, label_text, colors = \
None, None, None, None, None
self.draw_2d_text, self.draw_sprite = None, None

# return outputs if you have them; here I try it for you
self.colored_mesh = mesh
return (mesh, title_obj, label_objs, label_text, colors)

def DrawViewportMeshes(self, args):
try:
# get the DisplayPipeline from the event arguments
display = args.Display
# draw the objects in the scene
if self.colored_mesh is not None:
display.DrawMeshFalseColors(self.colored_mesh)
if self.draw_2d_text is not None:
for draw_args in self.draw_2d_text:
display.Draw2dText(*draw_args)
if self.draw_sprite is not None:
for draw_args in self.draw_sprite:
display.DrawSprite(*draw_args)
except Exception, e:
System.Windows.Forms.MessageBox.Show(str(e), "script error")

def get_ClippingBox(self):
return Rhino.Geometry.BoundingBox()
Binary file modified ladybug_grasshopper/user_objects/LB Create Legend.ghuser
Binary file not shown.

0 comments on commit 274f6a3

Please sign in to comment.