def inPolygon(points, poly, debug_dir=None, convex_hull=False): assert points.shape[1] == 2, "Only handles 2D!" #Check that polygon is valid if np.any(np.isnan(poly)): return np.zeros(points.shape[0], dtype=np.bool) if convex_hull: s_poly = MultiPoint(poly).convex_hull else: s_poly = Polygon(poly) if not s_poly.is_valid: # Buffer is used to trim overlapping segments s_poly = s_poly.buffer(0) if debug_dir: _plotPoly(points, poly, s_poly, debug_dir) # Buffer will split into multiPoly if necessary try: poly_iterator = iter(s_poly) except TypeError: return _inCleanPolygon(points, s_poly) inside = np.zeros(points.shape[0], dtype=np.bool) for clean_poly in poly_iterator: inside |= _inCleanPolygon(points, clean_poly) return inside
def outline_clusters(cluster): points = MultiPoint(cluster['locations']['coordinates']) geom = {} geom['type'] = 'Polygon' try: p = points.convex_hull p = p.buffer(np.sqrt(p.area) * 0.33) geom['coordinates'] = list(p.simplify(0.0005).exterior.coords) except: p = points.buffer(0.005) p = p.convex_hull geom['coordinates'] = list(p.simplify(0.0005).exterior.coords) centroid = {'type': 'Point'} centroid['coordinates'] = list(p.centroid.coords)[0] n = len(cluster['locations']['coordinates']) distance = 0 if (n > 1): for j in range(n - 1): distance += vincenty( (cluster['locations']['coordinates'][j][1], cluster['locations']['coordinates'][j][0]), (cluster['locations']['coordinates'][j + 1][1], cluster['locations']['coordinates'][j + 1][0])).meters / 1000 cluster['boundary'] = geom cluster['centroid'] = centroid cluster['distance'] = distance return cluster
def get_distance_order(tri, tripts, pindex, lines): from shapely.ops import unary_union #Get centroids of all high deformation triangles ctrd = [] for p in pindex: ctrd.append(Polygon(tripts[p]).centroid) #make buffer multipoint = MultiPoint(ctrd) ctrd_buff = unary_union(multipoint.buffer(200)) #Get centroids of all triangles ctrd_all = [] for i in range(0, len(tripts)): ctrd_all.append(Polygon(tripts[i]).centroid) #collect all centroids inside the buffer lkfs = [] if ctrd_buff.geom_type == 'MultiPolygon': for geom in ctrd_buff.geoms: lkf_ctrd = [] for j in ctrd_all: if geom.contains(Point(j)): lkf_ctrd.append(j) #get minimal distance from centroid buffer dist1 = [] for j in ctrd_all: d = ctrd_buff.distance(Point(j)) dist1.append(d) dist2 = 0 #uncoment this if you really want dist2 #currently the angle lines are not good enough for this to be useful!!! #print(lines) #poly=[] #for geom in lines: #print(geom) #poly.append(geom.buffer(200)) #lkf_buff = unary_union(poly) #print(lkf_buff) ##get minimal distance from angle line buffer #dist2=[] #for j in ctrd_all: #d = lkf_buff.distance(Point(j)) #dist2.append(d) #print(dist2) return (dist1, dist2)
def __init__( self, data: gpd.GeoDataFrame, variable: str, kernel: Kernel, cell_size, polygon=None, ): if not isinstance(data, gpd.GeoDataFrame): raise TypeError('data should be a geopandas GeoDataFrame') if 'geometry' not in data.columns: data['geometry'] = data[data._geometry_column_name] data = data.drop([data._geometry_column_name], axis=1) data = data.set_geometry('geometry') self.polygon = polygon data = data.rename(columns={ variable: 'variable', }) self.cell_size = cell_size data.points = data.geometry.centroid convex = MultiPoint(data.geometry).convex_hull if not self.polygon: self.polygon = convex.buffer(kernel.bandwidth) xmin, ymin, xmax, ymax = self.bbox = self.polygon.bounds x = np.arange(xmin, xmax, self.cell_size) y = np.arange(ymin, ymax, self.cell_size) y = np.flipud(y) x, y = np.meshgrid(x, y) self.shape = x.shape flat = x.flatten()[:, np.newaxis], y.flatten()[:, np.newaxis] df = pd.DataFrame(np.hstack(flat), columns=['x', 'y']) outside = [row.Index for row in df.itertuples() if not self.polygon.contains(Point(row.x, row.y))] self.df = df.drop(outside) self.kernel = kernel x1, x2 = np.meshgrid(self.df['x'], data.geometry.x) y1, y2 = np.meshgrid(self.df['y'], data.geometry.y) self.d = np.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2) self.w = self.kernel(self.d) vals = data['variable'].values.reshape(len(data), 1) self.df['density'] = np.sum(self.w * vals, axis=0) zeros = pd.Series(np.zeros(len(outside)), index=outside) grid = self.df['density'].append(zeros, verify_integrity=True).sort_index() self.grid = grid.values.reshape(self.shape)
def clip_images(directory, points, dist): buffer_dist = dist files = os.listdir(directory) regex = re.compile('.tif$', re.IGNORECASE) files = [os.path.join(directory, f) for f in files if regex.search(f)] from_crs = Proj({'init': 'epsg:4326'}) with rasterio.open(files[0]) as src: dest_crs = Proj(src.crs) # points = ['57.232,-2.971'] points = [x.split(',') for x in points] points = [[float(x), float(y)] for y, x in points] points = [transform(from_crs, dest_crs, x, y) for x, y in points] if len(points) > 1: points = MultiPoint(points) boundary = points.bounds points = [[boundary[0], boundary[1]], [boundary[2], boundary[3]]] else: points = Point(points[0][0], points[0][1]) area = points.buffer(buffer_dist) boundary = area.bounds points = [[boundary[0], boundary[1]], [boundary[2], boundary[3]]] [[ulx, lry], [lrx, uly]] = points for image in files: output_image_new = image + '.tmp' command_new = 'gdalwarp -overwrite -of GTiff '\ '-te %s %s %s %s %s %s' % (ulx, lry, lrx, uly, image, output_image_new) return_code = call(command_new, shell=True) os.remove(image) os.rename(output_image_new, image)
def getZones(tpolygon,d): ozones=[] zones=[] for unique in udensity: mps=MultiPoint(xy[density==unique]).buffer(d) _d = DF.getD_l(unique,minGrowth,d) _d = np.maximum(minDensity,_d) ozone=mps.intersection(tpolygon) zone=ozone.buffer(-_d*0.2).buffer(_d*0.2).removeHoles(cArea(_d*0.2)).simplify(_d*0.01) if not zone.is_empty: ozones.append(zone.getExterior().union(mps.buffer(-_d*0.2))) # ozones.append(mps) zones.append(zone) ozones=cascaded_union(ozones) zones=cascaded_union(zones) # zones.plot("o-") return zones,ozones
def get_inlier_guess(rect_pts, horz_idx, vert_idx, lines1, lines2, dist=300, radius_multiple=5): accepted_pts = set() for (horz, vert) in itertools.product(horz_idx, vert_idx): hp1, hp2 = lines1[horz], lines2[horz] vp1, vp2 = lines1[vert], lines2[vert] hu = hp2 - hp1 vu = vp2 - vp1 A = np.array([[hu[0], -vu[0]], [hu[1], -vu[1]]]) b = np.array([vp1[0] - hp1[0], vp1[1] - hp1[1]]) mult = np.linalg.solve(A, b) pt = np.mean([hp1 + mult[0] * hu, vp1 + mult[1] * vu], 0) dists = np.sum((rect_pts - pt)**2, 1) idx = np.argmin(dists) if dists[idx] < 10: accepted_pts.add(idx) accepted_pts = list(accepted_pts) # Broaden the search to any nearby points hull = MultiPoint(rect_pts[accepted_pts, :]).convex_hull hull = prep(hull.buffer(np.sqrt(hull.area) * radius_multiple)) inlier_guess = [ i for i in range(rect_pts.shape[0]) if hull.contains(Point(rect_pts[i, :])) ] # plt.scatter(rect_pts[:,0], rect_pts[:,1], c='r') # plt.scatter(rect_pts[inlier_guess,0], rect_pts[inlier_guess,1], c='y') # plt.scatter(rect_pts[accepted_pts,0], rect_pts[accepted_pts,1], c='g') # plt.show() return inlier_guess
def update_cluster(cluster_id): print(cluster_id) clusters = list(db.clusters.find({'_id': ObjectId(cluster_id)})) if (len(clusters) > 1): return jsonify({'error': 'too many clusters'}), 500 if (len(clusters) == 0): return jsonify({'error': 'no cluster with id'}), 500 cluster = clusters[0] points = MultiPoint(cluster['locations']['coordinates']) geom = {} geom['type'] = 'Polygon' try: p = points.convex_hull p = p.buffer(np.sqrt(p.area) * 0.33) geom['coordinates'] = list(p.simplify(0.0005).exterior.coords) except: p = points.buffer(0.005) p = p.convex_hull geom['coordinates'] = list(p.simplify(0.0005).exterior.coords) centroid = {'type': 'Point'} centroid['coordinates'] = list(p.centroid.coords)[0] print(centroid) db.clusters.update_one({'_id': cluster['_id']}, {'$set': { 'boundary': geom, 'centroid': centroid }}) return jsonify({'response': 'okay'})
def extract_outflow_channel_props(islands, network_lines, interior_channels, save=True, load_saved=False, file_root=''): if load_saved: outflow_angles = pickle.load( open(file_root + '/outflow_angles.p', "rb")) outflow_stats = pickle.load(open(file_root + '/outflow_stats.p', "rb")) num_outflow = pickle.load(open(file_root + '/outflow_number.p', "rb")) else: outflow_angles = [] num_outflow = np.zeros((len(islands), )) for n in range(len(islands)): lines = [i for i in interior_channels[n]] outflow = [] for l in lines: if islands[n].exterior.touches(network_lines[l]): outflow.append(l) angle = [] num_out = 0 for l in outflow: inside_line = islands[n].intersection(network_lines[l]) node = islands[n].boundary.intersection(network_lines[l]) if inside_line.type is 'LineString': if node.type is 'LineString': node = MultiPoint(node.coords) if node.type is 'MultiPoint': dists = np.array( [nn.distance(islands[n].exterior) for nn in node]) loc = np.where(dists == dists.min())[0][0] node = node[loc] buffer_l = np.min( [inside_line.simplify(100).length * 0.8, 250]) node_b = node.buffer(buffer_l).exterior try: intersect0 = inside_line.intersection(node_b) if intersect0.type is 'MultiPoint': intersect0 = intersect0[0] az0 = azimuth(node, intersect0) except: intersect0 = Point(inside_line.coords[-1]) if intersect0.intersects(node.buffer(10)): intersect0 = Point(inside_line.coords[0]) az0 = azimuth(node, intersect0) b = islands[n].boundary outside_intersects = b.intersection(node_b) intersect1 = outside_intersects[0] intersect2 = outside_intersects[1] az3 = azimuth(intersect1, intersect2) az = np.abs(az0 - az3) diff_az = az if az < 180 else az - 180 diff_az = diff_az if diff_az < 90 else 180 - diff_az angle.append(diff_az) num_out += 1 outflow_angles.append(angle) num_outflow[n] = num_out flat_angles = np.array( [item for sublist in outflow_angles for item in sublist]) outflow_stats = np.array( [[np.min(m), np.max(m), np.mean(m), np.median(m), np.std(m)] if len(m) > 0 else [0, 0, 0, 0, 0] for m in outflow_angles]) if save: pickle.dump(outflow_angles, open(file_root + '/outflow_angles' + '.p', "wb")) pickle.dump(outflow_stats, open(file_root + 'outflow_stats' + '.p', "wb")) pickle.dump(num_outflow, open(file_root + 'outflow_number' + '.p', "wb")) return outflow_angles, outflow_stats, num_outflow
def generate_meter_projected_chunks( route_shape: LineString, custom_stops: Optional[List[List[float]]] = None, stop_distance_distribution: int = None, from_proj='epsg:4326', to_proj='epsg:2163', existing_graph_nodes: Optional[pd.DataFrame] = None ) -> List[LineString]: # Reproject 4326 lat/lon coordinates to equal area project = partial( pyproj.transform, # source coordinate system pyproj.Proj(init=from_proj, preserve_units=True), # destination coordinate system pyproj.Proj(init=to_proj, preserve_units=True)) rs2 = transform(project, route_shape) # apply projection # Two ways to break apart this route into chunks: # 1. Using custom stops as break points (this one takes precedence) # 2. Using a custom distance to segment out the route # In either case, we need to generate mp_array such that we have # target stops or "break points" for the route line shape # Path 1 if available if custom_stops is not None: mp_array = [] for custom_stop in custom_stops: # Now reproject with cast point geometry custom_stop_proj = transform(project, Point(custom_stop)) interp_stop = rs2.interpolate(rs2.project(custom_stop_proj)) mp_array.append(interp_stop) # Otherwise we go with path 2 else: # Sanity check (this should never occur due to checks in class init) if stop_distance_distribution is None: raise ValueError(('Auto stop assignment triggered, but ' 'stop_distance_distribution is Nonetype')) # Divide the target route into roughly equal length segments # and get the number that would be needed to accomplish this stop_count = round(rs2.length / stop_distance_distribution) # Create the array of break points/joints mp_array = [] for i in range(1, stop_count): fr = (i / stop_count) mp_array.append(rs2.interpolate(fr, normalized=True)) # At this point, we have an array of what might be described as # "potential stops." From these stops, we want to look to see if there # are nearby stop alternatives that are existing stops used by the # current network graph. If there are, then we should use those # instead. if existing_graph_nodes is not None and len(existing_graph_nodes) > 0: mp_array_override = _generate_point_array_override( mp_array, rs2, existing_graph_nodes, stop_distance_distribution) # Now that mp_array_override has been fully populated, # can now override the original array holding the estimated # stop point locations mp_array = mp_array_override # Cast array as a Shapely object splitter = MultiPoint(mp_array) # 1 meter buffer to address floating point discrepencies chunks = split(rs2, splitter.buffer(1)) # TODO: Potential for length errors with this 1 meter # threshold check # Take chunks and merge in the small lines # from intersection inside of the buffered circles # and attach to nearest larger line clean_chunks = [chunks[0]] r = len(chunks) for c in range(1, r): latest = clean_chunks[-1] current = chunks[c] # Again, this is a week point of the buffer of # 1 meter method if latest.length <= 2: # Merge in the small chunks with the larger chunks clean_chunks[-1] = linemerge([latest, current]) else: clean_chunks.append(current) return clean_chunks
return {"type": "Polygon", "coordinates": [poly]} vorGeoJSON = { "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": makeGeoPolygon(stations_vor.vertices, region) } for region in stations_vor.regions if (-1 not in region) and (len(region) > 0)] } # %% Boundary # from https://stackoverflow.com/questions/34968838/python-finite-boundary-voronoi-cells restaurants_points = list([ (i, j) for i, j in zip(list(restaurants.Long), list(restaurants.Lat)) ]) all_points = restaurants_points + stations_points points = np.array(all_points) lines = [ LineString(stations_vor.vertices[line]) for line in stations_vor.ridge_vertices if -1 not in line ] pts = MultiPoint([Point(i) for i in all_points]) mask = pts.convex_hull.union(pts.buffer(.01, resolution=10, cap_style=1)) result = MultiPolygon([poly.intersection(mask) for poly in polygonize(lines)]) vor_gdf = gpd.GeoDataFrame(geometry=[i for i in result]).to_json()
def calc_geometry_for_type(self, lane_types, num, calc_gap=False): '''Given a list of lane types, returns a tuple of: - List of lists of points along the reference line, with same indexing as self.lane_secs - List of region polygons, with same indexing as self.lane_secs - List of dictionary of lane id to polygon, with same indexing as self.lane_secs - List of polygons for each lane (not necessarily by id, but respecting lane successor/predecessor) - Polygon for entire region. If calc_gap=True, fills in gaps between connected roads. This is fairly expensive.''' road_polygons = [] ref_points = self.get_ref_points(num) cur_lane_polys = {} sec_points = [] sec_polys = [] sec_lane_polys = [] lane_polys = [] last_lefts = None last_rights = None for i in range(len(self.lane_secs)): cur_sec = self.lane_secs[i] cur_sec_points = [] if i < len(self.lane_secs) - 1: next_sec = self.lane_secs[i + 1] s_stop = next_sec.s0 else: s_stop = float('inf') left_bounds = {} right_bounds = {} cur_sec_lane_polys = {} cur_sec_polys = [] # Last point in left/right lane boundary line for last road piece: start_of_sec = True end_of_sec = False while ref_points and not end_of_sec: if not ref_points[0] or ref_points[0][0][2] >= s_stop: # Case 1: The current list of ref_points (corresponding to current piece) # is empty, so we move onto the next list of points. # Case 2: The s-coordinate has exceeded s_stop, so we should move # onto the next LaneSection. # Either way, we collect all the bound points so far into polygons. if not ref_points[0]: ref_points.pop(0) else: end_of_sec = True cur_last_lefts = {} cur_last_rights = {} for id_ in left_bounds.keys(): # Polygon for piece of lane: bounds = left_bounds[id_] + right_bounds[id_][::-1] if len(bounds) < 3: continue poly = Polygon(bounds).buffer(0) if poly.is_valid and not poly.is_empty: if poly.geom_type == 'MultiPolygon': poly = MultiPolygon([ p for p in list(poly) if not p.is_empty and p.exterior ]) cur_sec_polys.extend(list(poly)) else: cur_sec_polys.append(poly) if id_ in cur_sec_lane_polys: cur_sec_lane_polys[id_].append(poly) else: cur_sec_lane_polys[id_] = [poly] if calc_gap: # Polygon for gap between lanes: if start_of_sec: prev_id = cur_sec.lanes[id_].pred else: prev_id = id_ if last_lefts is not None and prev_id in last_lefts.keys( ): gap_poly = MultiPoint([ last_lefts[prev_id], last_rights[prev_id], left_bounds[id_][0], right_bounds[id_][0] ]).convex_hull assert gap_poly.is_valid, 'Gap polygon not valid.' # Assume MultiPolygon cannot result from convex hull. if gap_poly.geom_type == 'Polygon' and not gap_poly.is_empty: # plot_poly(gap_poly, 'b') gap_poly = gap_poly.buffer(0) cur_sec_polys.append(gap_poly) if id_ in cur_sec_lane_polys: cur_sec_lane_polys[id_].append( gap_poly) else: cur_sec_lane_polys[id_] = [gap_poly] cur_last_lefts[id_] = left_bounds[id_][-1] cur_last_rights[id_] = right_bounds[id_][-1] if (start_of_sec and i == 0) or not self.start_bounds_left: self.start_bounds_left[id_] = left_bounds[id_][0] self.start_bounds_right[id_] = right_bounds[id_][0] left_bounds = {} right_bounds = {} if cur_last_lefts and cur_last_rights: last_lefts = cur_last_lefts last_rights = cur_last_rights start_of_sec = False else: cur_p = ref_points[0].pop(0) cur_sec_points.append(cur_p) offsets = cur_sec.get_offsets(cur_p[2]) offsets[0] = 0 for id_ in offsets.keys(): offsets[id_] += self.get_ref_line_offset(cur_p[2]) if ref_points[0]: next_p = ref_points[0][0] tan_vec = (next_p[0] - cur_p[0], next_p[1] - cur_p[1]) else: if len(cur_sec_points) >= 2: prev_p = cur_sec_points[-2] else: assert len(sec_points) > 0 if sec_points[-1]: prev_p = sec_points[-1][-1] else: prev_p = sec_points[-2][-1] tan_vec = (cur_p[0] - prev_p[0], cur_p[1] - prev_p[1]) tan_norm = np.sqrt(tan_vec[0]**2 + tan_vec[1]**2) # if tan_norm < 0.01: # continue normal_vec = (-tan_vec[1] / tan_norm, tan_vec[0] / tan_norm) for id_ in offsets.keys(): if cur_sec.get_lane(id_).type_ in lane_types: if id_ > 0: prev_id = id_ - 1 else: prev_id = id_ + 1 left_bound = [ cur_p[0] + normal_vec[0] * offsets[id_], cur_p[1] + normal_vec[1] * offsets[id_] ] right_bound = [ cur_p[0] + normal_vec[0] * offsets[prev_id], cur_p[1] + normal_vec[1] * offsets[prev_id] ] if id_ not in left_bounds: left_bounds[id_] = [left_bound] else: left_bounds[id_].append(left_bound) if id_ not in right_bounds: right_bounds[id_] = [right_bound] else: right_bounds[id_].append(right_bound) sec_points.append(cur_sec_points) sec_polys.append(buffer_union(cur_sec_polys)) for id_ in cur_sec_lane_polys: cur_sec_lane_polys[id_] = buffer_union(cur_sec_lane_polys[id_]) sec_lane_polys.append(cur_sec_lane_polys) next_lane_polys = {} for id_ in cur_sec_lane_polys: pred_id = cur_sec.get_lane(id_).pred if pred_id and pred_id in cur_lane_polys: next_lane_polys[id_] = cur_lane_polys.pop(pred_id) \ + [cur_sec_lane_polys[id_]] else: next_lane_polys[id_] = [cur_sec_lane_polys[id_]] for id_ in cur_lane_polys: lane_polys.append(buffer_union(cur_lane_polys[id_])) cur_lane_polys = next_lane_polys for id_ in cur_lane_polys: lane_polys.append(buffer_union(cur_lane_polys[id_])) union_poly = buffer_union(sec_polys) if last_lefts and last_rights: self.end_bounds_left.update(last_lefts) self.end_bounds_right.update(last_rights) return sec_points, sec_polys, sec_lane_polys, lane_polys, union_poly
x, y = transform(wgs84, nyp, lon, lat) points = MultiPoint(zip(x, y)) points = MultiPoint([p for p in points.geoms if manhattan.contains(p)]) pt_arr = np.asarray(points) # make a small buffer that aproximates 59th Street mp = MultiPoint([Point([978887, 224975]), Point([1009023, 207566])]) s59 = LineString(mp).buffer(0.5) sp = manhattan.difference(s59) lower_manhattan = sp.geoms[1] man_arr = np.asarray(manhattan.exterior) # TODO: calculate area fractions below 59th Street # draw buffers around bike stations with 1, 2, and 3 block radius block = 260 # Manhattan city block (feet) buffer = points.buffer(1 * block) one_block = buffer.intersection(manhattan) buffer = points.buffer(2 * block) two_blocks = buffer.intersection(manhattan) buffer = points.buffer(3 * block) three_blocks = buffer.intersection(manhattan) fig = plt.figure() fig.add_subplot(111, aspect='equal') ax = plt.gca() west, south, east, north = manhattan.bounds plt.plot(man_arr[:,0], man_arr[:, 1], 'black') plot_multipolygon(ax, one_block, 'blue') plot_multipolygon(ax, two_blocks, 'blue') plot_multipolygon(ax, three_blocks, 'blue') plt.plot(pt_arr[:,0], pt_arr[:,1], marker='o', markersize=1, linestyle='None')
def merge_and_cut(filename_low, filename_height, output_dir, start_zoom, end_zoom): if not os.path.exists(filename_low) or not os.path.exists(filename_height): return None data_set_low = gdal.Open(filename_low) if data_set_low is None: print('Read %s failed' % filename_low) return None data_set_height = gdal.Open(filename_height) if data_set_height is None: print('Read %s failed' % filename_height) return None band_low = data_set_low.GetRasterBand(1) if band_low is None: print('Read %s band failed' % filename_low) return None x_size_low, y_size_low = data_set_low.RasterXSize, data_set_low.RasterYSize x0_low, dx_low, _, y0_low, _, dy_low = data_set_low.GetGeoTransform() band_height = data_set_height.GetRasterBand(1) if band_height is None: print('Read %s band failed' % filename_height) return None x_size_height, y_size_height = data_set_height.RasterXSize, data_set_height.RasterYSize x0_height, dx_height, _, y0_height, _, dy_height = data_set_height.GetGeoTransform() min_lng_height = x0_height min_lat_height = y0_height max_lng_height = x0_height + x_size_height * dx_height max_lat_height = y0_height + y_size_height * dy_height min_lng_low = x0_low min_lat_low = y0_low max_lng_low = x0_low + x_size_low * dx_low max_lat_low = y0_low + y_size_low * dy_low x_offset = round((min_lng_height - min_lng_low) / dx_low) y_offset = round((min_lat_height - min_lat_low) / dy_low) x_size = round((max_lng_height - min_lng_height) / dx_low) y_size = round((max_lat_height - min_lat_height) / dy_low) bounds = get_tif_tile_bounds(filename_height, output_dir, start_zoom) if bounds == {}: return _, value = next(iter(bounds.items())) _zoom_size_low = round((value[2] - value[0]) / dx_low) buf_size = _zoom_size_low + 128 # 设置 buf 大小大于一块地形的 size,保证按块取数据时,块是完整的 z_low_with_buf = band_low.ReadAsArray(x_offset - buf_size, y_offset - buf_size, x_size + buf_size * 2, y_size + buf_size * 2).astype('f4') # z_height = band_height.ReadAsArray(0, 0, x_size_height, y_size_height).astype('f4') for zoom in range(start_zoom, end_zoom + 1): ratio = 2 ** (zoom - start_zoom) dsize_low = ((x_size + buf_size * 2) * ratio, (y_size + buf_size * 2) * ratio) _z_low_with_buf = cv2.resize(src=z_low_with_buf, dsize=dsize_low, interpolation=cv2.INTER_LINEAR) dsize_height = (x_size * ratio, y_size * ratio) _z_height = cv2.resize(src=z_height, dsize=dsize_height, interpolation=cv2.INTER_CUBIC) z_height = band_height.ReadAsArray(0, 0, x_size_height, y_size_height, x_size * ratio, y_size * ratio).\ astype('f4') _z_height = z_height bound_yx = get_data_bound(_z_height, 0.8) # 如果没有边界 则,不融合,直接采用低精度数据 cut if bound_yx.shape[0] != 0: bound_yx = bound_yx.astype('i4') _x = np.zeros(shape=(0, 1)) # x y z 添加边界值 _y = np.zeros(shape=(0, 1)) _z = np.zeros(shape=(0, 1)) for _bound_yx in bound_yx: _bound_y_height = _bound_yx[0] _bound_x_height = _bound_yx[1] _bound_z_height = _z_height[_bound_y_height, _bound_x_height] _bound_y_low = _bound_yx[0] + buf_size * ratio _bound_x_low = _bound_yx[1] + buf_size * ratio _bound_z_low = _z_low_with_buf[_bound_y_low, _bound_x_low] _z_d = _bound_z_height - _bound_z_low _x = np.vstack((_x, _bound_x_low)) _y = np.vstack((_y, _bound_y_low)) _z = np.vstack((_z, _z_d)) # x y z 添加边界值缓冲边界 0 值 _xy = np.hstack((_x, _y)) _m_point = MultiPoint(_xy) _zero_bound = _m_point.buffer(50) _zero_bound_xy = _zero_bound.exterior.coords.xy _zero_bound_x = np.around(np.array(_zero_bound_xy[0])).reshape(len(_zero_bound_xy[0]), -1) _zero_bound_y = np.around(np.array(_zero_bound_xy[1])).reshape(len(_zero_bound_xy[1]), -1) _zero_bound_z = np.zeros(shape=(_zero_bound_x.shape)) _x = np.vstack((_x, _zero_bound_x)) _y = np.vstack((_y, _zero_bound_y)) _z = np.vstack((_z, _zero_bound_z)) # x y z 添加数据边界 0 值 for _x_edge in range(0, (x_size + buf_size * 2) * ratio): _x = np.vstack((_x, [_x_edge])) _y = np.vstack((_y, [0])) _x = np.vstack((_x, [_x_edge])) _y = np.vstack((_y, [(y_size + buf_size * 2) * ratio])) _z = np.vstack((_z, [[0], [0]])) for _y_edge in range(0, (y_size + buf_size * 2) * ratio): _y = np.vstack((_y, [_y_edge])) _x = np.vstack((_x, [0])) _y = np.vstack((_y, [_y_edge])) _x = np.vstack((_x, [(x_size + buf_size * 2) * ratio])) _z = np.vstack((_z, [[0], [0]])) # _xy = np.hstack((_x, _y)) # grid = np.mgrid[0:(x_size + buf_size * 2) * ratio, 0:(y_size + buf_size * 2) * ratio] # _z_d_new = interpolate.griddata(_xy, _z, grid, method='linear') func = interpolate.interp2d(_x, _y, _z, kind='linear') _x_new = np.arange(0, (x_size + buf_size * 2) * ratio) _y_new = np.arange(0, (y_size + buf_size * 2) * ratio) _z_d_new = func(_x_new, _y_new) _z_low_with_buf = _z_low_with_buf + _z_d_new for y in range(y_size * ratio): for x in range(x_size * ratio): _z_height_v = _z_height[y][x] y_low = y + buf_size * ratio x_low = x + buf_size * ratio _z_low_v = _z_low_with_buf[y_low][x_low] if abs(_z_height_v - 0) > 0.001 and abs(_z_height_v - _z_low_v) > 0.001: _z_low_with_buf[y_low][x_low] = _z_height_v # cut z_merged = _z_low_with_buf blc_bounds = get_tif_tile_bounds(filename_height, output_dir, zoom) for fname in blc_bounds: blc_bound = blc_bounds[fname] blc_x_min_low = round((blc_bound[0] - min_lng_low) / dx_low) blc_y_min_low = round((blc_bound[3] - min_lat_low) / dy_low) blc_x_max_low = round((blc_bound[2] - min_lng_low) / dx_low) blc_y_max_low = round((blc_bound[1] - min_lat_low) / dy_low) blc_x_offset_low = (blc_x_min_low - x_offset + buf_size) * ratio blc_y_offset_low = (blc_y_min_low - y_offset + buf_size) * ratio blc_x_size_low = (blc_x_max_low - blc_x_min_low) * ratio blc_y_size_low = (blc_y_max_low - blc_y_min_low) * ratio blc_z_low = z_merged[blc_y_offset_low:blc_y_offset_low + blc_y_size_low, blc_x_offset_low:blc_x_offset_low + blc_x_size_low] points_xyz = [] z_low = np.array(blc_z_low) for x in range(blc_z_low.shape[1]): for y in range(blc_z_low.shape[0]): point_xyz = [x, y, blc_z_low[y, x]] points_xyz.append(point_xyz) points_xyz = np.array(points_xyz) points_xy = points_xyz[:, 0:2] tri = Delaunay(points_xy) index = tri.simplices points_xyz = (points_xyz + (blc_x_min_low, blc_y_min_low, 0)) * (dx_low, dy_low, 1) + (x0_low, y0_low, 0) write_terrain(fname, points_xyz, index)
def generate_geometry(self, type, **kwargs): """Generate a `shapely` entity according to the geometry description provided. The input `type` containts the name of the geometry to be generated and the necessary arguments must be provided in the `dict` input `description`. Possible geometries according to the different input values in `type` are: * `area` ```python description=dict( points=[ [0, 0, 0], [0, 1, 1], ... ] # List of 3D points that describe the vertices of the plane area ) ``` * `line` ```python description=dict( points=[ [0, 0, 0], [0, 1, 1], ... ] # List of 3D points that describe the line ) ``` * `circle` ```python description=dict( center=[-6.8, -6.8, 0] # Center of the circle radius=0.2 # Radius of the circle ) ``` **Others are still not implemented** > *Input arguments* * `type` (*type:* `str`): Geometry type. Options are: `line`, `area`, `volume`, `multi_line`, `multi_point`, `circle` * `description` (*type:* `dict`): Arguments to describe the geometry """ if type == 'area' and 'points' in kwargs: return MultiPoint([(x[0], x[1]) for x in kwargs['points']]).convex_hull elif type == 'line' and 'points' in kwargs: line = LineString([(x[0], x[1]) for x in kwargs['points']]) if 'buffer' in kwargs: assert kwargs['buffer'] > 0, \ 'Buffer around line must be greater than 0' return line.buffer(kwargs['buffer']) else: return line elif type == 'multipoint' and 'points' in kwargs: points = MultiPoint([(x[0], x[1]) for x in kwargs['points']]) if 'buffer' in kwargs: assert kwargs['buffer'] > 0, \ 'Buffer around line must be greater than 0' return points.buffer(kwargs['buffer']) else: return points elif type == 'multiline' and 'lines' in kwargs: lines = MultiLineString(kwargs['lines']) if 'buffer' in kwargs: assert kwargs['buffer'] > 0, \ 'Buffer around line must be greater than 0' return lines.buffer(kwargs['buffer']) else: return lines elif type == 'circle' and \ 'center' in kwargs and 'radius' in kwargs: return shapes.circle(**kwargs) elif type == 'polygon' and 'polygon' in kwargs: assert isinstance(kwargs['polygon'], (Polygon, MultiPolygon)) assert not kwargs['polygon'].is_empty, 'Polygon is empty' assert kwargs['polygon'].area > 0, 'Polygon area is zero' return kwargs['polygon'] elif type == 'box': assert 'size' in kwargs return trimesh.creation.box(extents=kwargs['size']) elif type == 'sphere': assert 'radius' in kwargs assert kwargs['radius'] > 0 return trimesh.creation.icosphere(radius=kwargs['radius']) elif type == 'cylinder': assert 'radius' in kwargs assert kwargs['radius'] > 0 assert 'length' in kwargs assert kwargs['length'] > 0 return trimesh.creation.cylinder(radius=kwargs['radius'], height=kwargs['length']) elif type == 'mesh': if 'mesh' in kwargs: if isinstance(kwargs['mesh'], trimesh.base.Trimesh): return kwargs['mesh'] elif isinstance(kwargs['mesh'], trimesh.scene.Scene): return kwargs['mesh'].convex_hull else: raise ValueError('Invalid input mesh') elif 'model' in kwargs: if 'mesh_type' in kwargs: assert kwargs['mesh_type'] in ['collision', 'visual'] mesh_type = kwargs['mesh_type'] else: mesh_type = 'collision' if isinstance(kwargs['model'], SimulationModel): return kwargs['model'].create_scene( mesh_type=mesh_type).convex_hull else: raise ValueError('Invalid input simulation model') elif 'entity' in kwargs: if 'mesh_type' in kwargs: assert kwargs['mesh_type'] in ['collision', 'visual'] mesh_type = kwargs['mesh_type'] else: mesh_type = 'collision' if isinstance(kwargs['entity'], Entity) and \ not isinstance(kwargs['entity'], SimulationModel): return kwargs['entity'].create_scene(mesh_type=mesh_type, ignore_models=[ 'ground_plane' ]).convex_hull elif 'points' in kwargs: points = np.array(kwargs['points']) assert points.shape[1] == 3 assert points.shape[0] > 3 points = trimesh.points.PointCloud(points) return points.convex_hull else: raise NotImplementedError( 'Invalid geometry type, provided={}'.format(type))
def get_lkf_angle(tri, tripts, threshold, pindex): from shapely.ops import unary_union from shapely.ops import split from shapely.affinity import scale, rotate #get a list to store LKF lines lkfs = [] #Get cetroids of all high deformation triangles ctrd = [] for p in pindex: ctrd.append(Polygon(tripts[p]).centroid) #sort them so they are ordered from south-west origin = Point(0, 0) dist = [] cx = [] cy = [] for i in range(0, len(ctrd)): d = origin.distance(ctrd[i]) dist.append(d) tmp1, tmp2 = ctrd[i].xy cx.append(np.array(tmp1)[0]) cy.append(np.array(tmp1)[0]) ctrd = [ctrd for _, ctrd in sorted(zip(dist, ctrd))] #make buffers around these centroids and unify multipoint = MultiPoint(ctrd) ctrd_buff = unary_union(multipoint.buffer(400)) #long and complicated lines will be lost, shorter are easier to work with #can we split this polygons to several features? x_min = np.min(cx) x_max = np.max(cx) y_min = np.min(cy) y_max = np.max(cy) #construct a split line split_line = LineString([ Point((x_max - x_min) / 4, y_min), Point((x_max - x_min) / 4, y_max), Point((x_max - x_min) / 2, y_max), Point((x_max - x_min) / 2, y_min), Point(3 * (x_max - x_min) / 4, y_min), Point(3 * (x_max - x_min) / 4, y_max), Point(x_max, y_max), Point(x_max, (y_max - y_min) / 4), Point(x_min, (y_max - y_min) / 4), Point(x_min, (y_max - y_min) / 2), Point(x_max, (y_max - y_min) / 2), Point(x_max, 3 * (y_max - y_min) / 4), Point(x_min, 3 * (y_max - y_min) / 4) ]) split_line_b = split_line.buffer(50) #split the polygons ctrd_buff = ctrd_buff.difference(split_line_b) #for each polygon get all centroids inside an connect to a line lkfs = [] if ctrd_buff.geom_type == 'MultiPolygon': for geom in ctrd_buff.geoms: lkf_ctrd = [] for j in ctrd: if geom.contains(Point(j)): lkf_ctrd.append(j) if len(lkf_ctrd) > 10: line = LineString(lkf_ctrd) #simplify simple = line.simplify(tolerance=500, preserve_topology=False) #check if line has a lot of nods #rotate the origin and do several iterations #incrasing tolerance will reduce most of the lines to two-point features simple = sort_and_simplify(simple, origin=Point(0, 200000), tolerance=500) simple = sort_and_simplify(simple, origin=Point(0, 0), tolerance=1000) simple = sort_and_simplify(simple, origin=Point(0, 200000), tolerance=2000) simple = sort_and_simplify( simple, origin=Point(0, 0), tolerance=4000 ) #finish off with this origin as most features are aligned this way #store lkfs.append(simple) #prepare LKF buffer to work with (larger than the centroid buffer) lkf_buff = unary_union(multipoint.buffer(3000)) #divide the lines at all nods lkfs_long = [] for i in range(0, len(lkfs)): #spliting the line on the nods xl, yl = lkfs[i].xy mp = [Point(p) for p in zip(xl, yl)] mp = MultiPoint(mp) segments = split(lkfs[i], mp) #throw away all short lines i = 0 for segment in segments.geoms: #print(segment.length) if segment.length > 7000: #5km is a good min lenght for a 60km radius area #keep only lines that are inside the initial buffers if lkf_buff.contains(segment): ##uncomment if no line buffering is used ##extend this segment #segment = scale(segment, xfact=2.5,yfact=2.5) ##store #lkfs_long.append(segment) #uncomment if line buffering is used if i == 1: #check if we already have a very similar line if not segment_buffer.contains( segment): #or touches if just lines #extend this segment segment = scale(segment, xfact=2.5, yfact=2.5) #store lkfs_long.append(segment) #extend the buffer of known lines segment_buffer = unary_union( [segment_buffer, segment.buffer(2000)]) #segment_buffer = unary_union([segment_buffer,segment]) #for lines else: #extend this segment segment = scale(segment, xfact=3, yfact=3) #store lkfs_long.append(segment) #create the buffer of known lines segment_buffer = segment.buffer(2000) #segment_buffer = segment #for lines ##import ipdb; ipdb.set_trace() #measure all intersection angles angles = [] for l1 in lkfs_long: for l2 in lkfs_long: if l1.intersects(l2) and not l1.__eq__(l2): #print(l1) #print(l2) angle = lines_angle(l1, l2) #get smallest postive angle angle = abs(angle) if angle > 180: angle = angle - 180 #filter out very small angles (angles that are close to 0 or 180) if angle > 10 and angle < 170: angles.append(angle) #convert to plottable multistring/multilines lkfs = MultiLineString(lkfs_long) #lkfs=MultiLineString(lkfs) return (lkfs, lkf_buff, split_line, angles)
x, y = transform(wgs84, nyp, lon, lat) points = MultiPoint(zip(x, y)) points = MultiPoint([p for p in points.geoms if manhattan.contains(p)]) pt_arr = np.asarray(points) # make a small buffer that aproximates 59th Street mp = MultiPoint([Point([978887, 224975]), Point([1009023, 207566])]) s59 = LineString(mp).buffer(0.5) sp = manhattan.difference(s59) lower_manhattan = sp.geoms[1] man_arr = np.asarray(manhattan.exterior) # TODO: calculate area fractions below 59th Street # draw buffers around bike stations with 1, 2, and 3 block radius block = 260 # Manhattan city block (feet) buffer = points.buffer(1 * block) one_block = buffer.intersection(manhattan) buffer = points.buffer(2 * block) two_blocks = buffer.intersection(manhattan) buffer = points.buffer(3 * block) three_blocks = buffer.intersection(manhattan) fig = plt.figure() fig.add_subplot(111, aspect='equal') ax = plt.gca() west, south, east, north = manhattan.bounds plt.plot(man_arr[:, 0], man_arr[:, 1], 'black') plot_multipolygon(ax, one_block, 'blue') plot_multipolygon(ax, two_blocks, 'blue') plot_multipolygon(ax, three_blocks, 'blue') plt.plot(pt_arr[:, 0],
def generate_meter_projected_chunks( route_shape: LineString, custom_stops: List[List[float]] = None, stop_distance_distribution: int = None) -> List[LineString]: # Reproject 4326 lat/lon coordinates to equal area project = partial( pyproj.transform, pyproj.Proj(init='epsg:4326'), # source coordinate system pyproj.Proj(init='epsg:2163')) # destination coordinate system rs2 = transform(project, route_shape) # apply projection # Two ways to break apart this route into chunks: # 1. Using custom stops as break points (this one takes precedence) # 2. Using a custom distance to segment out the route # In either case, we need to generate mp_array such that we have # target stops or "break points" for the route line shape # Path 1 if available if custom_stops is not None: mp_array = [] for custom_stop in custom_stops: # Now reproject with cast point geometry custom_stop_proj = transform(project, Point(custom_stop)) interp_stop = rs2.interpolate(rs2.project(custom_stop_proj)) mp_array.append(interp_stop) # Otherwise we go with path 2 else: stop_count = round(rs2.length / stop_distance_distribution) # Create the array of break points/joints mp_array = [] for i in range(1, stop_count): fr = (i / stop_count) mp_array.append(rs2.interpolate(fr, normalized=True)) # Cast array as a Shapely object splitter = MultiPoint(mp_array) # 1 meter buffer to address floating point discrepencies chunks = split(rs2, splitter.buffer(1)) # TODO: Potential for length errors with this 1 meter # threshold check # Take chunks and merge in the small lines # from intersection inside of the buffered circles # and attach to nearest larger line clean_chunks = [chunks[0]] r = len(chunks) for c in range(1, r): latest = clean_chunks[-1] current = chunks[c] # Again, this is a week point of the buffer of # 1 meter method if latest.length <= 2: # Merge in the small chunks with the larger chunks clean_chunks[-1] = linemerge([latest, current]) else: clean_chunks.append(current) return clean_chunks