def square_grid(bbox, cell_size, units): fc = FeatureCollection([]) x_fraction = cell_size / distance(Point((bbox[0], bbox[1])), Point((bbox[2], bbox[1])), units) cell_width = x_fraction * (bbox[2] - bbox[0]) y_fraction = cell_size / distance(Point((bbox[0], bbox[1])), Point((bbox[0], bbox[3])), units) cell_height = y_fraction * (bbox[3] - bbox[1]) current_x = bbox[0] while current_x <= bbox[2]: current_y = bbox[1] while current_y <= bbox[3]: cell_poly = Polygon(([ [current_x, current_y], [current_x, current_y + cell_height], [current_x + cell_width, current_y + cell_height], [current_x + cell_width, current_y], [current_x, current_y] ],)) fc["features"].append(cell_poly) current_y += cell_height current_x += cell_width return fc
def square(bbox): horizontal_distance = distance(bbox.slice(0, 2), [bbox[2], bbox[1]], 'miles') vertical_distance = distance(bbox.slice(0, 2), [bbox[0], bbox[3]], 'miles') if horizontal_distance >= vertical_distance: vertical_midpoint = (bbox[1] + bbox[3]) / 2 return [ bbox[0], vertical_midpoint - ((bbox[2] - bbox[0]) / 2), bbox[2], vertical_midpoint + ((bbox[2] - bbox[0]) / 2) ] else: horizontal_midpoint = (bbox[0] + bbox[2]) / 2 return [ horizontal_midpoint - ((bbox[3] - bbox[1]) / 2), bbox[1], horizontal_midpoint + ((bbox[3] - bbox[1]) / 2), bbox[3] ]
def idw(control_points, value_field, b, cell_width, units): # check if field containing data exists.. filtered = filter( lambda feature: (feature["properties"] and value_field in feature["properties"]), control_points["features"]) if len(filtered) != 0: # create a sample square grid # compared to a point grid helps visualizing the output sampling_grid = square_grid(bbox(control_points), cell_width, units) for i in range(len(sampling_grid["features"])): zw = 0 sw = 0 # calculate the distance from each control point to cell's centroid for j in range(len(control_points["features"])): d = distance(centroid(sampling_grid["features"][j]), control_points["features"][j], units) if d == 0: zw = control_points["features"][j]["properties"][ value_field] w = 1.0 / pow(d, b) sw += w zw += w * control_points["features"][j]["properties"][ value_field] # write IDW value for each grid cell sampling_grid["features"][i]["properties"]["z"] = zw / sw return sampling_grid else: print('Specified Data Field is Missing')
def point_grid(bbox, cellSize, units): fc = FeatureCollection([]) x_fraction = cellSize / distance(Point( (bbox[0], bbox[1])), Point((bbox[2], bbox[1])), units) cell_width = x_fraction * (bbox[2] - bbox[0]) y_fraction = cellSize / distance(Point( (bbox[0], bbox[1])), Point((bbox[0], bbox[3])), units) cell_height = y_fraction * (bbox[3] - bbox[1]) current_x = bbox[0] while current_x <= bbox[2]: current_y = bbox[1] while current_y <= bbox[3]: fc["features"].append(Point((current_x, current_y))) current_y += cell_height current_x += cell_width return fc
def inner_function(pt, coords, units): closest_pt = Point((float("inf"), float("inf")), { "dist": float("inf") }) for i in range(len(coords)): start = Point(coords[i]) stop = Point(coords[i + 1]) # start start.properties.dist = distance(pt, start, units) # stop stop.properties.dist = distance(pt, stop, units) # perpendicular height_distance = max(start.properties.dist, stop.properties.dist) direction = bearing(start, stop) perpendicular_pt1 = destination(pt, height_distance, direction + 90, units) perpendicular_pt2 = destination(pt, height_distance, direction - 90, units) intersect = line_intersects( perpendicular_pt1.geometry.coordinates[0], perpendicular_pt1.geometry.coordinates[1], perpendicular_pt2.geometry.coordinates[0], perpendicular_pt2.geometry.coordinates[1], start.geometry.coordinates[0], start.geometry.coordinates[1], stop.geometry.coordinates[0], stop.geometry.coordinates[1] ) if intersect: intersect_pt = Point(intersect) intersect_pt.properties.dist = distance(pt, intersect_pt, units) if start.properties.dist < closest_pt.properties.dist: closest_pt = start closest_pt.properties.index = i if stop.properties.dist < closest_pt.properties.dist: closest_pt = stop closest_pt.properties.index = i if intersect_pt and intersect_pt.properties.dist < closest_pt.properties.dist: closest_pt = intersect_pt closest_pt.properties.index = i return closest_pt
def nearest(target_point, points): nearest_point = None min_dist = float("inf") for i in range(len(points["features"])): distance_to_point = distance(target_point, points["features"][i], 'miles') if distance_to_point < min_dist: nearest_point = points["features"][i] min_dist = distance_to_point return nearest_point
def length(coords, units): travelled = 0 prev_coords = Point(coords[0]) cur_coords = Point(coords[0]) for i in range(len(coords)): cur_coords.geometry.coordinates = coords[i] travelled += distance(prev_coords, cur_coords, units) temp = prev_coords prev_coords = cur_coords cur_coords = temp return travelled
def line_slice_along(line, start_dist, stop_dist, units): slice = [] if line["type"] == 'Feature': coords = line.geometry.coordinates elif line["type"] == 'LineString': coords = line.coordinates else: raise ValueError('input must be a LineString Feature or Geometry') travelled = 0 for i in range(len(coords)): if start_dist >= travelled and i == coords.length - 1: break elif travelled > start_dist and len(slice) == 0: overshot = start_dist - travelled if not overshot: return slice.append(coords[i]) direction = bearing(coords[i], coords[i - 1]) - 180 interpolated = destination(coords[i], overshot, direction, units) slice.append(interpolated.geometry.coordinates) if travelled >= stop_dist: overshot = stop_dist - travelled if not overshot: return slice.append(coords[i]) direction = bearing(coords[i], coords[i - 1]) - 180 interpolated = destination(coords[i], overshot, direction, units) slice.append(interpolated.geometry.coordinates) return LineString(tuple(slice)) if travelled >= start_dist: slice.append(coords[i]) travelled += distance(coords[i], coords[i + 1], units) return LineString(coords[coords.length - 1])
def hex_grid(bbox, cell_size, units, triangles): x_fraction = cell_size / (distance(Point( (bbox[0], bbox[1])), Point((bbox[2], bbox[1])), units)) cell_width = x_fraction * (bbox[2] - bbox[0]) y_fraction = cell_size / (distance(Point( (bbox[0], bbox[1])), Point((bbox[0], bbox[3])), units)) cell_height = y_fraction * (bbox[3] - bbox[1]) radius = cell_width / 2 hex_width = radius * 2 hex_height = math.sqrt(3) / 2 * cell_height box_width = bbox[2] - bbox[0] box_height = bbox[3] - bbox[1] x_interval = 3 / 4 * hex_width y_interval = hex_height x_span = box_width / (hex_width - radius / 2) x_count = math.ceil(x_span) if round(x_span) == x_count: x_count += 1 x_adjust = ( (x_count * x_interval - radius / 2) - box_width) / 2 - radius / 2 y_count = math.ceil(box_height / hex_height) y_adjust = (box_height - y_count * hex_height) / 2 has_offset_y = y_count * hex_height - box_height > hex_height / 2 if has_offset_y: y_adjust -= hex_height / 4 fc = FeatureCollection([]) for x in range(x_count): for y in range(y_count): is_odd = x % 2 == 1 if y == 0 and is_odd: continue if y == 0 and has_offset_y: continue center_x = x * x_interval + bbox[0] - x_adjust center_y = y * y_interval + bbox[1] + y_adjust if is_odd: center_y -= hex_height / 2 if triangles: fc["features"] += [ hex_triangles([center_x, center_y], cell_width / 2, cell_height / 2) ] else: fc["features"] += [ hexagon([center_x, center_y], cell_width / 2, cell_height / 2) ] return fc
def midpoint(point_from, point_to): dist = distance(point_from, point_to, 'miles') heading = bearing(point_from, point_to) return destination(point_from, dist / 2, heading, 'miles')
def triangle_grid(bbox, cell_size, units): fc = FeatureCollection([]) x_fraction = cell_size / (distance([bbox[0], bbox[1]], [bbox[2], bbox[1]], units)) cell_width = x_fraction * (bbox[2] - bbox[0]) y_fraction = cell_size / (distance([bbox[0], bbox[1]], [bbox[0], bbox[3]], units)) cell_height = y_fraction * (bbox[3] - bbox[1]) xi = 0 current_x = bbox[0] while current_x <= bbox[2]: yi = 0 current_y = bbox[1] while current_y <= bbox[3]: if xi % 2 == 0 and yi % 2 == 0: fc["features"].append( Polygon([[[current_x, current_y], [current_x, current_y + cell_height], [current_x + cell_width, current_y], [current_x, current_y]]]), Polygon( [[[current_x, current_y + cell_height], [current_x + cell_width, current_y + cell_height], [current_x + cell_width, current_y], [current_x, current_y + cell_height]]])) elif xi % 2 == 0 and yi % 2 == 1: fc["features"].append( Polygon( [[[current_x, current_y], [current_x + cell_width, current_y + cell_height], [current_x + cell_width, current_y], [current_x, current_y]]]), Polygon( [[[current_x, current_y], [current_x, current_y + cell_height], [current_x + cell_width, current_y + cell_height], [current_x, current_y]]])) elif yi % 2 == 0 and xi % 2 == 1: fc["feautres"].append( Polygon( [[[current_x, current_y], [current_x, current_y + cell_height], [current_x + cell_width, current_y + cell_height], [current_x, current_y]]]), Polygon( [[[current_x, current_y], [current_x + cell_width, current_y + cell_height], [current_x + cell_width, current_y], [current_x, current_y]]])) elif yi % 2 == 1 and xi % 2 == 1: fc["feautres"].append( Polygon([[[current_x, current_y], [current_x, current_y + cell_height], [current_x + cell_width, current_y], [current_x, current_y]]]), Polygon( [[[current_x, current_y + cell_height], [current_x + cell_width, current_y + cell_height], [current_x + cell_width, current_y], [current_x, current_y + cell_height]]])) current_y += cell_height yi += 1 xi += 1 current_x += cell_width return fc
def point_on_surface(feature_collection): # normalize if feature_collection.type != "FeatureCollection": if feature_collection.type != "Feature": feature_collection = Feature(feature_collection) feature_collection = FeatureCollection([feature_collection]) # get centroid cent = centroid(feature_collection) # check to see if centroid is on surface on_surface = False i = 0 while not on_surface and i < len(feature_collection["features"]): geom = feature_collection["features"][i]["geometry"] on_line = False if geom["type"] == "Point": if cent["geometry"]["coordinates"][0] == geom["coordinates"][0] and \ cent["geometry"]["coordinates"][1] == geom["coordinates"][1]: on_surface = True elif geom["type"] == "MultiPoint": on_multi_point = False k = 0 while not on_multi_point and k < len(geom["coordinates"]): if cent["geometry"]["coordinates"][0] == geom["coordinates"][k][0] and \ cent["geometry"]["coordinates"][1] == geom["coordinates"][k][1]: on_surface = True on_multi_point = True k += 1 elif geom["type"] == "LineString": k = 0 while not on_line and k < len(geom["coordinates"]) - 1: x = cent["geometry"]["coordinates"][0] y = cent["geometry"]["coordinates"][1] x1 = geom["coordinates"][k][0] y1 = geom["coordinates"][k][1] x2 = geom["coordinates"][k + 1][0] y2 = geom["coordinates"][k + 1][1] if point_on_segment(x, y, x1, y1, x2, y2): on_line = True on_surface = True k += 1 elif geom["type"] == "MultiLineString": j = 0 while j < len(geom["coordinates"]): on_line = False k = 0 line = geom["coordinates"][j] while not on_line and k < len(line) - 1: x = cent["geometry"]["coordinates"][0] y = cent["geometry"]["coordinates"][1] x1 = line[k][0] y1 = line[k][1] x2 = line[k + 1][0] y2 = line[k + 1][1] if point_on_segment(x, y, x1, y1, x2, y2): on_line = True on_surface = True k += 1 j += 1 elif geom["type"] == "Polygon" or geom["type"] == "MultiPolygon": f = Feature(geom) if inside(cent, f): on_surface = True i += 1 if on_surface: return cent else: vertices = FeatureCollection([]) for i in range(len(feature_collection["features"])): vertices.features = \ vertices["features"] + \ explode(feature_collection["features"][i])["features"] closest_distance = float("inf") for i in range(len(vertices["feautres"])): dist = distance(cent, vertices["features"][i], "miles") if dist < closest_distance: closest_distance = dist closest_vertex = vertices.features[i] return closest_vertex