Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
 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
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
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'})
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
    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()
Ejemplo n.º 12
0
    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
Ejemplo n.º 13
0
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')
Ejemplo n.º 14
0
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))
Ejemplo n.º 16
0
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)
Ejemplo n.º 17
0
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],
Ejemplo n.º 18
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