diff --git a/README.md b/README.md index 879a7bc0..3f01162c 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ The ladybug-grasshopper plugin has the following dependencies (other than Rhino/ * [ladybug-geometry](https://github.com/ladybug-tools/ladybug-geometry) * [ladybug-comfort](https://github.com/ladybug-tools/ladybug-comfort) * [ladybug-display](https://github.com/ladybug-tools/ladybug-display) +* [ladybug-radiance](https://github.com/ladybug-tools/ladybug-radiance) * [ladybug-rhino](https://github.com/ladybug-tools/ladybug-rhino) ## Installation diff --git a/ladybug_grasshopper/icon/LB Solar Envelope.png b/ladybug_grasshopper/icon/LB Solar Envelope.png index 56b293b5..2d5c51ef 100644 Binary files a/ladybug_grasshopper/icon/LB Solar Envelope.png and b/ladybug_grasshopper/icon/LB Solar Envelope.png differ diff --git a/ladybug_grasshopper/json/LB_Solar_Envelope.json b/ladybug_grasshopper/json/LB_Solar_Envelope.json index 07e764cd..425b1752 100644 --- a/ladybug_grasshopper/json/LB_Solar_Envelope.json +++ b/ladybug_grasshopper/json/LB_Solar_Envelope.json @@ -65,7 +65,7 @@ { "access": "item", "name": "solar_rights_", - "description": "Set to True to compute a solar rights boundary and False to compute\na solar collection boundary. Solar rights boundaries represent the\nboundary below which one can build without shading the surrounding\nobstacles from any of the _vectors. Solar collection boundaries\nrepresent the boundary above which the one will have direct solar\naccess to all of the input _vectors. (Default: False).", + "description": "Set to True to compute a solar rights boundary and False to compute\na solar collection boundary. Solar rights boundaries represent the\nboundary below which one can build without shading the surrounding\nobstacles from any of the _vectors. Solar collection boundaries\nrepresent the boundary above which one will have direct solar\naccess to all of the input _vectors. (Default: False).", "type": "bool", "default": null }, diff --git a/ladybug_grasshopper/json/LB_Surface_Ray_Tracing.json b/ladybug_grasshopper/json/LB_Surface_Ray_Tracing.json index 3883dd1f..fe923006 100644 --- a/ladybug_grasshopper/json/LB_Surface_Ray_Tracing.json +++ b/ladybug_grasshopper/json/LB_Surface_Ray_Tracing.json @@ -71,7 +71,7 @@ } ], "subcategory": "3 :: Analyze Geometry", - "code": "\nimport math\n\ntry:\n from ladybug_geometry.geometry3d.ray import Ray3D\n from ladybug_geometry.geometry3d.polyline import Polyline3D\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_joined_gridded_mesh3d, to_point3d, \\\n to_vector3d\n from ladybug_{{cad}}.fromgeometry import from_point3d, from_vector3d, from_ray3d, \\\n from_polyline3d\n from ladybug_{{cad}}.intersect import join_geometry_to_brep, bounding_box_extents, \\\n trace_ray, normal_at_point\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, list_to_data_tree, \\\n hide_output\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 # check the _bounce_count_\n _bounce_count_ = 0 if _bounce_count_ is None else _bounce_count_ - 1\n assert _bounce_count_ >= 0, 'The input _bounce_count_ must be greater ' \\\n 'than zero. Got {}.'.format(_bounce_count_ + 1)\n # process the input sun vector\n lb_vec = to_vector3d(_vector).normalize()\n neg_lb_vec = -lb_vec\n vec = from_vector3d(lb_vec)\n\n # convert all of the _source_geo and contex into a single Brep for ray tracing\n rtrace_brep = join_geometry_to_brep(_source_geo + context_)\n\n # autocompute the first and last bounce length if it's unspecified\n if _first_length_ is None or _last_length_ is None:\n max_pt, min_pt = (to_point3d(p) for p in bounding_box_extents(rtrace_brep))\n diag_dist = max_pt.distance_to_point(min_pt)\n _first_length_ = diag_dist if _first_length_ is None else _first_length_\n _last_length_ = diag_dist if _last_length_ is None else _last_length_\n\n # create the gridded mesh from the _source_geo and set up the starting rays\n study_mesh = to_joined_gridded_mesh3d(_source_geo, _grid_size)\n move_vec = neg_lb_vec * _first_length_\n source_points = [pt + move_vec for pt in study_mesh.face_centroids]\n lb_rays = [Ray3D(pt, lb_vec) for pt in source_points]\n start_rays = [from_ray3d(ray) for ray in lb_rays]\n\n # trace each ray through the geometry\n cutoff_ang = math.pi / 2\n rtrace_geo = [rtrace_brep]\n rays, int_pts = [], []\n for ray, pt, norm in zip(start_rays, source_points, study_mesh.face_normals):\n if norm.angle(neg_lb_vec) < cutoff_ang:\n pl_pts = trace_ray(ray, rtrace_geo, _bounce_count_ + 1)\n # if the intersection was successful, create a polyline represeting the ray\n if pl_pts:\n # gather all of the intersection points\n all_pts = [pt]\n for i_pt in pl_pts:\n all_pts.append(to_point3d(i_pt))\n # compute the last point\n if len(pl_pts) < _bounce_count_ + 2:\n int_norm = normal_at_point(rtrace_brep, pl_pts[-1])\n int_norm = to_vector3d(int_norm)\n last_vec = all_pts[-2] - all_pts[-1]\n last_vec = last_vec.normalize()\n final_vec = last_vec.reflect(int_norm).reverse()\n final_pt = all_pts[-1] + (final_vec * _last_length_)\n all_pts.append(final_pt)\n # create a Polyline3D from the points\n lb_ray_line = Polyline3D(all_pts)\n rays.append(from_polyline3d(lb_ray_line))\n int_pts.append([from_point3d(p) for p in all_pts])\n\n # convert the intersection points to a data tree\n int_pts = list_to_data_tree(int_pts)\n hide_output(ghenv.Component, 1)\n", + "code": "\nimport math\n\ntry:\n from ladybug_geometry.geometry3d.ray import Ray3D\n from ladybug_geometry.geometry3d.polyline import Polyline3D\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_joined_gridded_mesh3d, to_point3d, \\\n to_vector3d\n from ladybug_{{cad}}.fromgeometry import from_point3d, from_vector3d, from_ray3d, \\\n from_polyline3d\n from ladybug_{{cad}}.intersect import join_geometry_to_brep, bounding_box_extents, \\\n trace_ray, normal_at_point\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, list_to_data_tree, \\\n hide_output\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 # check the _bounce_count_\n _bounce_count_ = 0 if _bounce_count_ is None else _bounce_count_ - 1\n assert _bounce_count_ >= 0, 'The input _bounce_count_ must be greater ' \\\n 'than zero. Got {}.'.format(_bounce_count_ + 1)\n # process the input sun vector\n lb_vec = to_vector3d(_vector).normalize()\n neg_lb_vec = -lb_vec\n vec = from_vector3d(lb_vec)\n\n # convert all of the _source_geo and contex into a single Brep for ray tracing\n rtrace_brep = join_geometry_to_brep(_source_geo + context_)\n\n # autocompute the first and last bounce length if it's unspecified\n if _first_length_ is None or _last_length_ is None:\n max_pt, min_pt = (to_point3d(p) for p in bounding_box_extents(rtrace_brep))\n diag_dist = max_pt.distance_to_point(min_pt)\n _first_length_ = diag_dist if _first_length_ is None else _first_length_\n _last_length_ = diag_dist if _last_length_ is None else _last_length_\n\n # create the gridded mesh from the _source_geo and set up the starting rays\n study_mesh = to_joined_gridded_mesh3d(_source_geo, _grid_size)\n move_vec = neg_lb_vec * _first_length_\n source_points = [pt + move_vec for pt in study_mesh.face_centroids]\n lb_rays = [Ray3D(pt, lb_vec) for pt in source_points]\n start_rays = [from_ray3d(ray) for ray in lb_rays]\n\n # trace each ray through the geometry\n cutoff_ang = math.pi / 2\n rtrace_geo = [rtrace_brep]\n rays, int_pts = [], []\n for ray, pt, norm in zip(start_rays, source_points, study_mesh.face_normals):\n if norm.angle(neg_lb_vec) < cutoff_ang:\n pl_pts = trace_ray(ray, rtrace_geo, _bounce_count_ + 2)\n # if the intersection was successful, create a polyline represeting the ray\n if pl_pts:\n # gather all of the intersection points\n all_pts = [pt]\n for i_pt in pl_pts:\n all_pts.append(to_point3d(i_pt))\n # compute the last point\n if len(pl_pts) < _bounce_count_ + 2:\n int_norm = normal_at_point(rtrace_brep, pl_pts[-1])\n int_norm = to_vector3d(int_norm)\n last_vec = all_pts[-2] - all_pts[-1]\n last_vec = last_vec.normalize()\n final_vec = last_vec.reflect(int_norm).reverse()\n final_pt = all_pts[-1] + (final_vec * _last_length_)\n all_pts.append(final_pt)\n # create a Polyline3D from the points\n lb_ray_line = Polyline3D(all_pts)\n rays.append(from_polyline3d(lb_ray_line))\n int_pts.append([from_point3d(p) for p in all_pts])\n\n # convert the intersection points to a data tree\n int_pts = list_to_data_tree(int_pts)\n hide_output(ghenv.Component, 1)\n", "category": "Ladybug", "name": "LB Surface Ray Tracing", "description": "Get a ray tracing visualization of direct sunlight rays reflected off of _source_geo\nand subsequently bouncing through a set of context_ geometries.\n_\nExamples where this visualization could be useful include understading the\nreflection of light by a light shelf or testing to see whether a parabolic\nglass or metal building geometry might focus sunlight to dangerous levels at\ncertain times of the year.\n_\nNote that this component assumes that all sun light is reflected specularly\n(like a mirror) and, for more detailed raytracing analysis with diffuse\nscattering, the Honeybee Radiance components should be used.\n-" diff --git a/ladybug_grasshopper/json/LB_Wind_Rose.json b/ladybug_grasshopper/json/LB_Wind_Rose.json index 27f35284..ffb76f99 100644 --- a/ladybug_grasshopper/json/LB_Wind_Rose.json +++ b/ladybug_grasshopper/json/LB_Wind_Rose.json @@ -183,7 +183,7 @@ } ], "subcategory": "2 :: Visualize Data", - "code": "\nimport math\n\ntry:\n from ladybug.datacollection import HourlyContinuousCollection\n from ladybug.windrose import WindRose\n from ladybug.datatype.speed import Speed\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug:\\n\\t{}'.format(e))\n\ntry:\n from ladybug_geometry.geometry2d.pointvector import Point2D, Vector2D\n from ladybug_geometry.geometry3d.pointvector import Point3D, Vector3D\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_geometry:\\n\\t{}'.format(e))\n\ntry:\n from ladybug_{{cad}}.config import conversion_to_meters\n from ladybug_{{cad}}.togeometry import to_point3d, to_vector2d\n from ladybug_{{cad}}.fromgeometry import from_mesh2d, from_linesegment2d, \\\n from_polygon2d\n from ladybug_{{cad}}.text import text_objects\n from ladybug_{{cad}}.fromobjects import legend_objects, compass_objects\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, list_to_data_tree, \\\n objectify_output, hide_output\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\n\ndef title_text(data_col):\n \"\"\"Get a text string for the title of the windrose.\"\"\"\n title_array = ['{} ({})'.format(data_col.header.data_type,\n data_col.header.unit)]\n for key, val in data_col.header.metadata.items():\n title_array.append('{}: {}'.format(key, val))\n title_array.append('period: {}'.format(data_col.header.analysis_period))\n return '\\n'.join(title_array)\n\n\nif all_required_inputs(ghenv.Component):\n # Apply any analysis periods and conditional statement to the input collections\n if period_ is not None:\n _data = [dat.filter_by_analysis_period(period_) for dat in _data]\n _wind_direction = _wind_direction.filter_by_analysis_period(period_)\n if statement_ is not None and statement_.strip() != \"\":\n _fdata = HourlyContinuousCollection.filter_collections_by_statement(\n _data + [_wind_direction], statement_)\n _data = _fdata[:-1]\n _wind_direction = _fdata[-1]\n\n # filter zero speed values out of collections if the speed is input\n pattern = []\n filt_wind_dir = _wind_direction\n for dat in _data:\n if isinstance(dat.header.data_type, Speed):\n for val in dat.values:\n pat = True if val > 1e-10 else False\n pattern.append(pat)\n break\n if len(pattern) != 0:\n for i, dat in enumerate(_data):\n if not isinstance(dat.header.data_type, Speed):\n _data[i] = dat.filter_by_pattern(pattern)\n filt_wind_dir = _wind_direction.filter_by_pattern(pattern)\n\n # check errors in dir_count and process the north input\n _dir_count_ = 36 if _dir_count_ is None else _dir_count_\n assert _dir_count_ > 2, 'The number of directions must be greater than 3 ' \\\n 'to plot the wind rose. Got: {}'.format(_dir_count_)\n if north_ is not None: # process the north_\n try:\n north_ = math.degrees(to_vector2d(north_).angle_clockwise(Vector2D(0, 1)))\n except AttributeError: # north angle instead of vector\n north_ = float(north_)\n assert -360.0 <= north_ <= 360.0, 'The north orientation must be greater ' \\\n 'then -360 and less then 360 to plot the wind rose. ' \\\n 'Got: {}'.format(north_)\n else:\n north_ = 0.0\n\n # set default values for the center point\n _center_pt_ = to_point3d(_center_pt_) if _center_pt_ is not None else Point3D()\n center_pt_2d = Point2D(_center_pt_.x, _center_pt_.y)\n\n # set defaults frequency hours and distance so chart is same scale as other LB plots\n if _freq_hours_ is None:\n _freq_hours_ = 50.0\n if _freq_dist_ is None:\n _freq_dist_ = 5.0 / conversion_to_meters()\n\n # set default show_freq and show_calm_\n show_calm_ = False if show_calm_ is None else show_calm_\n show_freq_ = True if show_avg_ is None else not show_avg_\n\n # set up empty lists of objects to be filled\n all_windrose_lines = []\n mesh = []\n all_compass = []\n all_orient_line = []\n all_freq_line = []\n all_legends = []\n title = []\n calm_hours = []\n histogram = []\n\n # Calculate _max_freq_lines_ if it's not already set, to use to\n # determine spacing for multiple plots.\n if len(_data) > 1 and _max_freq_lines_ is None:\n max_freqs = []\n for i, _data_item in enumerate(_data):\n win_dir = _wind_direction if isinstance(_data_item.header.data_type, Speed) \\\n else filt_wind_dir\n w = WindRose(win_dir, _data_item, _dir_count_)\n w.frequency_hours = _freq_hours_\n w.frequency_spacing_distance = _freq_dist_\n max_freqs.append(w.frequency_intervals_compass)\n _max_freq_lines_ = max(max_freqs)\n\n # plot the windroses\n first_windrose = None\n for i, speed_data in enumerate(_data):\n # make the windrose\n win_dir = _wind_direction if isinstance(speed_data.header.data_type, Speed) \\\n else filt_wind_dir\n windrose = WindRose(win_dir, speed_data, _dir_count_)\n if i == 0:\n first_windrose = windrose\n\n # set the wind rose properties\n if len(legend_par_) > 0:\n try: # sense when several legend parameters are connected\n lpar = legend_par_[i]\n except IndexError:\n lpar = legend_par_[-1]\n windrose.legend_parameters = lpar\n windrose.frequency_hours = _freq_hours_\n if _max_freq_lines_ is not None:\n windrose.frequency_intervals_compass = _max_freq_lines_\n windrose.frequency_spacing_distance = _freq_dist_\n windrose.north = north_\n windrose.show_freq = show_freq_\n\n calm_text = ''\n if isinstance(speed_data.header.data_type, Speed):\n windrose.show_zeros = show_calm_\n calm_text = '\\nCalm for {}% of the time = {} hours.'.format(\n round(windrose._zero_count / \n len(windrose.analysis_values) * 100.0, 2),\n windrose._zero_count)\n windrose.base_point = Point2D(center_pt_2d.x, center_pt_2d.y)\n\n # Make the mesh\n msh = from_mesh2d(windrose.colored_mesh, _center_pt_.z)\n\n # Make the other graphic outputs\n lb_legend = windrose.legend\n ttl_pt = windrose.container.lower_title_location\n if _center_pt_.z != 0:\n move_vec = Vector3D(0, 0, _center_pt_.z)\n ttl_pt = ttl_pt.move(move_vec)\n if lb_legend.legend_parameters.is_base_plane_default:\n lb_legend = lb_legend.duplicate()\n lb_legend.legend_parameters.base_plane = \\\n lb_legend.legend_parameters.base_plane.move(move_vec)\n legend = legend_objects(lb_legend)\n freq_per = windrose._frequency_hours / \\\n len([b for a in windrose.histogram_data for b in a])\n freq_text = '\\nEach closed polyline shows frequency of {}% = {} hours.'.format(\n round(freq_per * 100, 1), windrose._frequency_hours)\n titl = text_objects(title_text(speed_data) + calm_text + freq_text, ttl_pt,\n windrose.legend_parameters.text_height,\n windrose.legend_parameters.font)\n compass = compass_objects(windrose.compass, _center_pt_.z, None)\n orient_line = [from_linesegment2d(seg, _center_pt_.z)\n for seg in windrose.orientation_lines]\n freq_line = [from_polygon2d(poly, _center_pt_.z) for poly in windrose.frequency_lines]\n windrose_lines = [from_polygon2d(poly, _center_pt_.z) for poly in windrose.windrose_lines]\n fac = (i + 1) * windrose.compass_radius * 3\n center_pt_2d = Point2D(_center_pt_.x + fac, _center_pt_.y)\n\n # collect everything to be output\n mesh.append(msh)\n all_compass.append(compass)\n all_orient_line.append(orient_line)\n all_freq_line.append(freq_line)\n all_windrose_lines.append(windrose_lines)\n all_legends.append(legend)\n title.append(titl)\n calm = windrose.zero_count if isinstance(speed_data.header.data_type, Speed) else None\n calm_hours.append(calm)\n histogram.append(objectify_output('WindRose {}'.format(i), windrose.histogram_data))\n\n # convert nested lists into data trees\n compass = list_to_data_tree(all_compass)\n orient_line = list_to_data_tree(all_orient_line)\n freq_line = list_to_data_tree(all_freq_line)\n windrose_line = list_to_data_tree(all_windrose_lines)\n legend = list_to_data_tree(all_legends)\n hide_output(ghenv.Component, 5) # keep the devault visual simple\n\n # compute direction angles and prevailing direction\n theta = 180.0 / windrose._number_of_directions\n angles = [(angle + theta) % 360.0 for angle in windrose.angles[:-1]]\n prevailing = windrose.prevailing_direction\n vis_set = objectify_output(\n 'VisualizationSet Aruments [Sunpath]', [first_windrose, _center_pt_.z])\n", + "code": "\nimport math\n\ntry:\n from ladybug.datacollection import HourlyContinuousCollection\n from ladybug.windrose import WindRose\n from ladybug.datatype.speed import Speed\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug:\\n\\t{}'.format(e))\n\ntry:\n from ladybug_geometry.geometry2d.pointvector import Point2D, Vector2D\n from ladybug_geometry.geometry3d.pointvector import Point3D, Vector3D\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_geometry:\\n\\t{}'.format(e))\n\ntry:\n from ladybug_{{cad}}.config import conversion_to_meters\n from ladybug_{{cad}}.togeometry import to_point3d, to_vector2d\n from ladybug_{{cad}}.fromgeometry import from_mesh2d, from_linesegment2d, \\\n from_polygon2d\n from ladybug_{{cad}}.text import text_objects\n from ladybug_{{cad}}.fromobjects import legend_objects, compass_objects\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, list_to_data_tree, \\\n objectify_output, hide_output\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\n\ndef title_text(data_col):\n \"\"\"Get a text string for the title of the windrose.\"\"\"\n title_array = ['{} ({})'.format(data_col.header.data_type,\n data_col.header.unit)]\n for key, val in data_col.header.metadata.items():\n title_array.append('{}: {}'.format(key, val))\n title_array.append('period: {}'.format(data_col.header.analysis_period))\n return '\\n'.join(title_array)\n\n\nif all_required_inputs(ghenv.Component):\n # Apply any analysis periods and conditional statement to the input collections\n if period_ is not None:\n _data = [dat.filter_by_analysis_period(period_) for dat in _data]\n _wind_direction = _wind_direction.filter_by_analysis_period(period_)\n if statement_ is not None and statement_.strip() != \"\":\n _fdata = HourlyContinuousCollection.filter_collections_by_statement(\n _data + [_wind_direction], statement_)\n _data = _fdata[:-1]\n _wind_direction = _fdata[-1]\n\n # filter zero speed values out of collections if the speed is input\n pattern = []\n filt_wind_dir = _wind_direction\n for dat in _data:\n if isinstance(dat.header.data_type, Speed):\n for val in dat.values:\n pat = True if val > 1e-10 else False\n pattern.append(pat)\n break\n if len(pattern) != 0:\n for i, dat in enumerate(_data):\n if not isinstance(dat.header.data_type, Speed):\n _data[i] = dat.filter_by_pattern(pattern)\n filt_wind_dir = _wind_direction.filter_by_pattern(pattern)\n\n # check errors in dir_count and process the north input\n _dir_count_ = 36 if _dir_count_ is None else _dir_count_\n assert _dir_count_ > 2, 'The number of directions must be greater than 3 ' \\\n 'to plot the wind rose. Got: {}'.format(_dir_count_)\n if north_ is not None: # process the north_\n try:\n north_ = math.degrees(to_vector2d(north_).angle_clockwise(Vector2D(0, 1)))\n except AttributeError: # north angle instead of vector\n north_ = float(north_)\n assert -360.0 <= north_ <= 360.0, 'The north orientation must be greater ' \\\n 'then -360 and less then 360 to plot the wind rose. ' \\\n 'Got: {}'.format(north_)\n else:\n north_ = 0.0\n\n # set default values for the center point\n _center_pt_ = to_point3d(_center_pt_) if _center_pt_ is not None else Point3D()\n center_pt_2d = Point2D(_center_pt_.x, _center_pt_.y)\n\n # set defaults frequency hours and distance so chart is same scale as other LB plots\n if _freq_hours_ is None:\n _freq_hours_ = 50.0\n if _freq_dist_ is None:\n _freq_dist_ = 5.0 / conversion_to_meters()\n\n # set default show_freq and show_calm_\n show_calm_ = False if show_calm_ is None else show_calm_\n show_freq_ = True if show_avg_ is None else not show_avg_\n\n # set up empty lists of objects to be filled\n all_windrose_lines = []\n mesh = []\n all_compass = []\n all_orient_line = []\n all_freq_line = []\n all_legends = []\n title = []\n calm_hours = []\n histogram = []\n\n # Calculate _max_freq_lines_ if it's not already set, to use to\n # determine spacing for multiple plots.\n if len(_data) > 1 and _max_freq_lines_ is None:\n max_freqs = []\n for i, _data_item in enumerate(_data):\n win_dir = _wind_direction if isinstance(_data_item.header.data_type, Speed) \\\n else filt_wind_dir\n w = WindRose(win_dir, _data_item, _dir_count_)\n w.frequency_hours = _freq_hours_\n w.frequency_spacing_distance = _freq_dist_\n max_freqs.append(w.frequency_intervals_compass)\n _max_freq_lines_ = max(max_freqs)\n\n # plot the windroses\n first_windrose = None\n for i, speed_data in enumerate(_data):\n # make the windrose\n win_dir = _wind_direction if isinstance(speed_data.header.data_type, Speed) \\\n else filt_wind_dir\n windrose = WindRose(win_dir, speed_data, _dir_count_)\n if i == 0:\n first_windrose = windrose\n\n # set the wind rose properties\n if len(legend_par_) > 0:\n try: # sense when several legend parameters are connected\n lpar = legend_par_[i]\n except IndexError:\n lpar = legend_par_[-1]\n windrose.legend_parameters = lpar\n windrose.frequency_hours = _freq_hours_\n if _max_freq_lines_ is not None:\n windrose.frequency_intervals_compass = _max_freq_lines_\n windrose.frequency_spacing_distance = _freq_dist_\n windrose.north = north_\n windrose.show_freq = show_freq_\n\n calm_text = ''\n if isinstance(speed_data.header.data_type, Speed):\n windrose.show_zeros = show_calm_\n calm_text = '\\nCalm for {}% of the time = {} hours.'.format(\n round(windrose._zero_count / \n len(windrose.analysis_values) * 100.0, 2),\n windrose._zero_count)\n windrose.base_point = Point2D(center_pt_2d.x, center_pt_2d.y)\n\n # Make the mesh\n msh = from_mesh2d(windrose.colored_mesh, _center_pt_.z)\n\n # Make the other graphic outputs\n lb_legend = windrose.legend\n ttl_pt = windrose.container.lower_title_location\n if _center_pt_.z != 0:\n move_vec = Vector3D(0, 0, _center_pt_.z)\n ttl_pt = ttl_pt.move(move_vec)\n if lb_legend.legend_parameters.is_base_plane_default:\n lb_legend = lb_legend.duplicate()\n lb_legend.legend_parameters.base_plane = \\\n lb_legend.legend_parameters.base_plane.move(move_vec)\n legend = legend_objects(lb_legend)\n freq_per = windrose._frequency_hours / \\\n len([b for a in windrose.histogram_data for b in a])\n freq_text = '\\nEach closed polyline shows frequency of {}% = {} hours.'.format(\n round(freq_per * 100, 1), windrose._frequency_hours)\n titl = text_objects(title_text(speed_data) + calm_text + freq_text, ttl_pt,\n windrose.legend_parameters.text_height,\n windrose.legend_parameters.font)\n compass = compass_objects(windrose.compass, _center_pt_.z, None)\n orient_line = [from_linesegment2d(seg, _center_pt_.z)\n for seg in windrose.orientation_lines]\n freq_line = [from_polygon2d(poly, _center_pt_.z) for poly in windrose.frequency_lines]\n windrose_lines = [from_polygon2d(poly, _center_pt_.z) for poly in windrose.windrose_lines]\n fac = (i + 1) * windrose.compass_radius * 3\n center_pt_2d = Point2D(_center_pt_.x + fac, _center_pt_.y)\n\n # collect everything to be output\n mesh.append(msh)\n all_compass.append(compass)\n all_orient_line.append(orient_line)\n all_freq_line.append(freq_line)\n all_windrose_lines.append(windrose_lines)\n all_legends.append(legend)\n title.append(titl)\n calm = windrose.zero_count if isinstance(speed_data.header.data_type, Speed) else None\n calm_hours.append(calm)\n histogram.append(objectify_output('WindRose {}'.format(i), windrose.histogram_data))\n\n # convert nested lists into data trees\n compass = list_to_data_tree(all_compass)\n orient_line = list_to_data_tree(all_orient_line)\n freq_line = list_to_data_tree(all_freq_line)\n windrose_line = list_to_data_tree(all_windrose_lines)\n legend = list_to_data_tree(all_legends)\n hide_output(ghenv.Component, 5) # keep the devault visual simple\n\n # compute direction angles and prevailing direction\n theta = 180.0 / _dir_count_\n angles = [(angle + theta) % 360.0 for angle in windrose.angles[:-1]]\n prevailing = windrose.prevailing_direction\n vis_set = objectify_output(\n 'VisualizationSet Aruments [Sunpath]', [first_windrose, _center_pt_.z])\n", "category": "Ladybug", "name": "LB Wind Rose", "description": "Create a plot of any hourly data by wind directions.\n-" diff --git a/ladybug_grasshopper/src/LB Solar Envelope.py b/ladybug_grasshopper/src/LB Solar Envelope.py index 3bed71d0..8e6b6aed 100644 --- a/ladybug_grasshopper/src/LB Solar Envelope.py +++ b/ladybug_grasshopper/src/LB Solar Envelope.py @@ -48,7 +48,7 @@ a solar collection boundary. Solar rights boundaries represent the boundary below which one can build without shading the surrounding obstacles from any of the _vectors. Solar collection boundaries - represent the boundary above which the one will have direct solar + represent the boundary above which one will have direct solar access to all of the input _vectors. (Default: False). _run: Set to "True" to run the component and get a solar envelope. diff --git a/ladybug_grasshopper/src/LB Surface Ray Tracing.py b/ladybug_grasshopper/src/LB Surface Ray Tracing.py index c97efe0e..8bae7275 100644 --- a/ladybug_grasshopper/src/LB Surface Ray Tracing.py +++ b/ladybug_grasshopper/src/LB Surface Ray Tracing.py @@ -109,7 +109,7 @@ rays, int_pts = [], [] for ray, pt, norm in zip(start_rays, source_points, study_mesh.face_normals): if norm.angle(neg_lb_vec) < cutoff_ang: - pl_pts = trace_ray(ray, rtrace_geo, _bounce_count_ + 1) + pl_pts = trace_ray(ray, rtrace_geo, _bounce_count_ + 2) # if the intersection was successful, create a polyline represeting the ray if pl_pts: # gather all of the intersection points diff --git a/ladybug_grasshopper/src/LB Wind Rose.py b/ladybug_grasshopper/src/LB Wind Rose.py index 10d5ab25..f0c6d2e6 100644 --- a/ladybug_grasshopper/src/LB Wind Rose.py +++ b/ladybug_grasshopper/src/LB Wind Rose.py @@ -42,7 +42,7 @@ show_calm_ is True, then the initial frequency interval corresponds to the number of calm hours in the data collection, which may not align with this freq_dist_ (Default: 5 meters) - _freq_hours_: The number of hours in each frequency interval (Default: 50). + _freq_hours_: The number of hours in each frequency interval (Default: 50). _max_freq_lines_: A number representing the maximum frequency intervals in the rose, which determines the maximum amount of hours represented by the outermost ring of the windrose. Specifically, this number multiplied by the @@ -310,7 +310,7 @@ def title_text(data_col): hide_output(ghenv.Component, 5) # keep the devault visual simple # compute direction angles and prevailing direction - theta = 180.0 / windrose._number_of_directions + theta = 180.0 / _dir_count_ angles = [(angle + theta) % 360.0 for angle in windrose.angles[:-1]] prevailing = windrose.prevailing_direction vis_set = objectify_output( diff --git a/ladybug_grasshopper/user_objects/LB Solar Envelope.ghuser b/ladybug_grasshopper/user_objects/LB Solar Envelope.ghuser index faa1a36e..56124958 100644 Binary files a/ladybug_grasshopper/user_objects/LB Solar Envelope.ghuser and b/ladybug_grasshopper/user_objects/LB Solar Envelope.ghuser differ diff --git a/ladybug_grasshopper/user_objects/LB Surface Ray Tracing.ghuser b/ladybug_grasshopper/user_objects/LB Surface Ray Tracing.ghuser index edf658b3..dc3d5b10 100644 Binary files a/ladybug_grasshopper/user_objects/LB Surface Ray Tracing.ghuser and b/ladybug_grasshopper/user_objects/LB Surface Ray Tracing.ghuser differ diff --git a/ladybug_grasshopper/user_objects/LB Wind Rose.ghuser b/ladybug_grasshopper/user_objects/LB Wind Rose.ghuser index 4f370d45..ebd50a86 100644 Binary files a/ladybug_grasshopper/user_objects/LB Wind Rose.ghuser and b/ladybug_grasshopper/user_objects/LB Wind Rose.ghuser differ diff --git a/samples/comfort_in_a_street_canyon.gh b/samples/comfort_in_a_street_canyon.gh index 3079285d..15159877 100644 Binary files a/samples/comfort_in_a_street_canyon.gh and b/samples/comfort_in_a_street_canyon.gh differ diff --git a/samples/direct_sun_study.gh b/samples/direct_sun_study.gh index 892331c8..de93dc2f 100644 Binary files a/samples/direct_sun_study.gh and b/samples/direct_sun_study.gh differ diff --git a/samples/outdoor_comfort.gh b/samples/outdoor_comfort.gh index 4735fa3a..46902954 100644 Binary files a/samples/outdoor_comfort.gh and b/samples/outdoor_comfort.gh differ diff --git a/samples/psychrometric_chart.gh b/samples/psychrometric_chart.gh index f90cb1d3..4f3200f9 100644 Binary files a/samples/psychrometric_chart.gh and b/samples/psychrometric_chart.gh differ diff --git a/samples/radiation_benefit_on_sunpath.gh b/samples/radiation_benefit_on_sunpath.gh index f43809d3..5796e00d 100644 Binary files a/samples/radiation_benefit_on_sunpath.gh and b/samples/radiation_benefit_on_sunpath.gh differ diff --git a/samples/radiation_graphics.gh b/samples/radiation_graphics.gh index 4c0b8211..3af6d6e5 100644 Binary files a/samples/radiation_graphics.gh and b/samples/radiation_graphics.gh differ diff --git a/samples/radiation_study.gh b/samples/radiation_study.gh index c422b3c9..56e1b278 100644 Binary files a/samples/radiation_study.gh and b/samples/radiation_study.gh differ diff --git a/samples/raytracing_study.gh b/samples/raytracing_study.gh index 0affa89d..6f51f594 100644 Binary files a/samples/raytracing_study.gh and b/samples/raytracing_study.gh differ diff --git a/samples/solar_envelope.gh b/samples/solar_envelope.gh index 7a7686da..3878cd09 100644 Binary files a/samples/solar_envelope.gh and b/samples/solar_envelope.gh differ diff --git a/samples/visualization_set.gh b/samples/visualization_set.gh index 735c4191..2cc57c71 100644 Binary files a/samples/visualization_set.gh and b/samples/visualization_set.gh differ diff --git a/samples/windrose_plot.gh b/samples/windrose_plot.gh index 97f8abb9..891bcd0e 100644 Binary files a/samples/windrose_plot.gh and b/samples/windrose_plot.gh differ