def test_dg_noskel(): """Test the dg with no skeleton""" # Points pt_array = [[0, 0], [6, 0], [6, 6], [3, 9], [0, 6]] # Make the polygon polygon = Polygon2D.from_array(pt_array) # Make the check cases chk_pt_lst = [Point2D.from_array(p) for p in pt_array] # Inititalize a dg object d = PolygonDirectedGraph(1e-10) vertices = polygon.vertices # Add edges to dg for i in range(len(vertices) - 1): k = d.add_node(vertices[i], [vertices[i + 1]]) if i == 0: d.outer_root_key = k d.add_node(vertices[-1], [vertices[0]]) # Test number assert len(chk_pt_lst) == d.num_nodes, _cmpstr(len(chk_pt_lst), d.num_nodes) # Test root assert d.node(d.outer_root_key)._order == 0 # Test adjacencies are correct curr_node = d.node(d.outer_root_key) for chk_pt in chk_pt_lst: assert chk_pt.is_equivalent(curr_node.pt, TOL), _cmpstr(chk_pt, curr_node.pt) # Increment curr_node = curr_node.adj_lst[0] # Test the adj matrix amtx = d.adj_matrix() # Adj matrix to test against chk_amtx = [ [0, 1, 0, 0, 0], # 0 [0, 0, 1, 0, 0], # 1 [0, 0, 0, 1, 0], # 2 [0, 0, 0, 0, 1], # 3 [1, 0, 0, 0, 0] ] # 4 # 0, 1, 2, 3, 4 # Test if the adj matrix is correct for i in range(len(chk_amtx)): for j in range(len(chk_amtx[0])): assert amtx[i][j] == chk_amtx[i][j], _cmpstr( amtx[i][j], chk_amtx[i][j])
def test_sub_polygon_traversal(): # Graph methods to retrieve subpolygons tol = 1e-10 pts = [[0, 0], [6, 0], [6, 8], [0, 8]] poly = Polygon2D.from_array(pts) # Test retrieval of exterior cycle form root node g = polysplit._skeleton_as_directed_graph(poly, None, tol) chk_nodes = [[0, 0], [6, 0], [6, 8], [0, 8], [3, 5], [3, 3]] assert len(chk_nodes) == len(g.ordered_nodes) for i, n in enumerate(g.ordered_nodes): assert n.pt.is_equivalent(Point2D.from_array(chk_nodes[i]), tol) # Check root assert g.outer_root_key == _vector2hash(Vector2D(0, 0), 1e-5) # Get exterior cycle exterior = g.exterior_cycle(g.node(g.outer_root_key)) chk_nodes = [[0, 0], [6, 0], [6, 8], [0, 8]] assert len(chk_nodes) == len(exterior) for i, n in enumerate(exterior): assert n.pt.is_equivalent(Point2D.from_array(chk_nodes[i]), tol)
def _compute_colored_mesh_array(hist_data, hist_data_stacked, bin_vecs, min_radius, max_radius, show_freq): """Compute a colored mesh from this object's histogram. Args: hist_data: Histogram of analysis values greater then zero. hist_data_stacked: Histogram of analysis values averaged by number of stacks. bin_vecs: Array of histogram bin edge vectors. min_radius: Minimum radius for windrose mesh. max_radius: Maximum radius for windrose mesh. show_freq: Boolean indicating if stacked histogram. Returns: A colored Mesh2D. """ # Default rose is a unit circle centered at origin. We can scale and translate # the resulting mesh. vec_cpt = (0, 0) # Compute histogram array hist_coords = WindRose._histogram_array_radial( bin_vecs, vec_cpt, hist_data, hist_data_stacked, (min_radius, max_radius), show_freq) # Construct color array based on show_freq parameter color_array = [] if show_freq: for stack in hist_data_stacked: i = 0 for j in range(len(stack)): try: mean_val = sum(stack[j]) / float(len(stack[j])) color_array.append(mean_val) except ZeroDivisionError: mean_val = 0 i += 1 else: for stack in hist_data_stacked: # Value is already averaged vals = [b for a in stack for b in a] if len(vals) > 0: color_array.append(vals[0]) # Make mesh mesh_array = [[Point2D.from_array(vec) for vec in vecs] for vecs in hist_coords] return mesh_array, color_array
def from_dict(cls, data): """Create RectangularWindows from a dictionary. .. code-block:: python { "type": "RectangularWindows", "origins": [(1, 1), (3, 0.5)], # array of (x, y) floats in wall plane "widths": [1, 3], # array of floats for window widths "heights": [1, 2.5] # array of floats for window heights } """ assert data['type'] == 'RectangularWindows', \ 'Expected RectangularWindows. Got {}.'.format(data['type']) return cls(tuple(Point2D.from_array(pt) for pt in data['origins']), data['widths'], data['heights'])
def from_dict(cls, data): """Create DetailedWindows from a dictionary. .. code-block:: python { "type": "DetailedWindows", "polygons": [((0.5, 0.5), (2, 0.5), (2, 2), (0.5, 2)), ((3, 1), (4, 1), (4, 2))] } """ assert data['type'] == 'DetailedWindows', \ 'Expected DetailedWindows dictionary. Got {}.'.format(data['type']) return cls( tuple( Polygon2D(tuple(Point2D.from_array(pt) for pt in poly)) for poly in data['polygons']))
def _compute_colored_mesh_array(hist_data, hist_data_stacked, bin_vecs, ytick_num, min_radius, max_radius, show_stack): """Compute a colored mesh from this object's histogram. Args: hist_data: Histogram of analysis values greater then zero. hist_data_stacked: Histogram of analysis values averaged by number of stacks. bin_vecs: Array of histogram bin edge vectors. ytick_num: Number of Y-axis intervals. min_radius: Minimum radius for windrose mesh. max_radius: Maximum radius for windrose mesh. show_stack: Boolean indicating if stacked histogram. Returns: A colored Mesh2D. """ # Default rose is a unit circle centered at origin. We can scale and translate # the resulting mesh. vec_cpt = (0, 0) # Compute histogram array hist_array = WindRose._histogram_array_radial(bin_vecs, vec_cpt, hist_data, hist_data_stacked, (min_radius, max_radius), show_stack) # Flatten and add coordinates if not show_stack: hist_array = ([v] for v in hist_array) # Make mesh hist_coords = [interval for bar in hist_array for interval in bar] mesh_array = [[Point2D.from_array(vec) for vec in vecs] for vecs in hist_coords] # Extract analysis values for color color_array = [ interval for bar in hist_data_stacked for interval in bar ] return mesh_array, color_array
def infinite_line2d_intersection(seg1, seg2): """Intersects two line2D assuming they are infinite. This method computes the linear equation from the segments. Then solves the linear system to find the intersection for both: A * x = C x = A^-1 * C """ # Compute the A,B coefficients seg1_3d = Point3D(*(seg1.p2 - seg1.p1).to_array(), 0) seg2_3d = Point3D(*(seg2.p2 - seg2.p1).to_array(), 0) z = Point3D(0, 0, 1) norm1 = seg1_3d.cross(z) norm2 = seg2_3d.cross(z) norm1 = norm1 / norm1.magnitude norm2 = norm2 / norm2.magnitude # Simplify naming for the A matrix (linear equation coefficeints) _a, _b, _c, _d = norm1.x, norm1.y, norm2.x, norm2.y # Substitute point in each line to solve for C array c1 = (_a * seg1.p2.x) + (_b * seg1.p2.y) c2 = (_c * seg2.p2.x) + (_d * seg2.p2.y) # Check the determinate det = (_a * _d) - (_b * _c) if abs(det) < 1e-10: return # Solve for x my multiplying Ainv by C x = [(_d / det * c1) + (-_b / det * c2), (-_c / det * c1) + (_a / det * c2)] intersection_pt = Point2D.from_array(x) return intersection_pt
geo for geo in data['features'] if 'geometry' in geo and geo['geometry']['type'] in geo_types ] if not all_to_bldg: # exclude anything with a Building key geo_data = [ geo for geo in geo_data if 'type' not in geo['properties'] or geo['properties']['type'] != 'Building' ] # convert all of the geoJSON data into Rhino geometry other_geo = [] for geo_dat in geo_data: if geo_dat['geometry']['type'] == 'LineString': coords = lon_lat_to_polygon(geo_dat['geometry']['coordinates'], origin_lon_lat, convert_facs) pts = tuple(Point2D.from_array(pt) for pt in coords) line = LineSegment2D.from_end_points(pts[0], pts[1]) \ if len(pts) == 2 else Polyline2D(pts) if con_fac != 1: line = line.scale(con_fac, pt) if len(pts) == 2: other_geo.append(from_linesegment2d(line)) else: other_geo.append(from_polyline2d(line)) else: # is's a polygon coords = lon_lat_to_polygon( geo_dat['geometry']['coordinates'][0], origin_lon_lat, convert_facs) pts = tuple(Point2D.from_array(pt) for pt in coords) poly = Polyline2D(pts) if con_fac != 1: