Source code for reV.bespoke.pack_turbs

# -*- coding: utf-8 -*-
"""
turbine packing module.
"""
import numpy as np
from shapely.geometry import Polygon, MultiPolygon, Point
from reV.bespoke.plotting_functions import get_xy
from reV.utilities.exceptions import WhileLoopPackingError


[docs]class PackTurbines(): """Framework to maximize plant capacity in a provided wind plant area. """ def __init__(self, min_spacing, safe_polygons, weight_x=0.0013547): """ Parameters ---------- min_spacing : float The minimum allowed spacing between wind turbines. safe_polygons : Polygon | MultiPolygon The "safe" area(s) where turbines can be placed without violating boundary, setback, exclusion, or other constraints. weight_x : float, optional """ self.min_spacing = min_spacing self.safe_polygons = safe_polygons self.weight_x = weight_x # turbine locations self.turbine_x = np.array([]) self.turbine_y = np.array([])
[docs] def pack_turbines_poly(self): """Fast packing algorithm that maximizes plant capacity in a provided wind plant area. Sets the the optimal locations to self.turbine_x and self.turbine_y """ if self.safe_polygons.area > 0.0: can_add_more = True leftover = MultiPolygon(self.safe_polygons) iters = 0 while can_add_more: iters += 1 if iters > 10000: msg = ('Too many points placed in packing algorithm') raise WhileLoopPackingError(msg) if leftover.area > 0: nareas = len(leftover.geoms) areas = np.zeros(len(leftover.geoms)) for i in range(nareas): areas[i] = leftover.geoms[i].area m = min(i for i in areas if i > 0) ind = np.where(areas == m)[0][0] # smallest_area = leftover.geoms[np.argmin(areas)] smallest_area = leftover.geoms[ind] exterior_coords = smallest_area.exterior.coords[:] x, y = get_xy(exterior_coords) metric = self.weight_x * x + y index = np.argmin(metric) self.turbine_x = np.append(self.turbine_x, x[index]) self.turbine_y = np.append(self.turbine_y, y[index]) new_turbine = Point(x[index], y[index] ).buffer(self.min_spacing) else: break leftover = leftover.difference(new_turbine) if isinstance(leftover, Polygon): leftover = MultiPolygon([leftover])
[docs] def clear(self): """Reset the packing algorithm by clearing the x and y turbine arrays """ self.turbine_x = np.array([]) self.turbine_y = np.array([])
[docs]def smallest_area_with_tiebreakers(g): """_summary_ This function helps break ties in the area of two different geometries using their exterior coordinate values. Parameters ---------- g : _type_ A geometry object with an `area` and an `exterior.coords` coords attribute. Returns ------- tuple Tuple with the following elements: - area of the geometry - minimum exterior coordinate (southwest) - maximum exterior coordinate (northeast) """ return g.area, min(g.exterior.coords), max(g.exterior.coords)