class LinearReferencingTestCase(unittest.TestCase):
    def setUp(self):
        self.point = Point(1, 1)
        self.line1 = LineString(([0, 0], [2, 0]))
        self.line2 = LineString(([3, 0], [3, 6]))
        self.multiline = MultiLineString(
            [list(self.line1.coords),
             list(self.line2.coords)])

    def test_line1_project(self):
        self.assertEqual(self.line1.project(self.point), 1.0)
        self.assertEqual(self.line1.project(self.point, normalized=True), 0.5)

    def test_line2_project(self):
        self.assertEqual(self.line2.project(self.point), 1.0)
        self.assertAlmostEqual(self.line2.project(self.point, normalized=True),
                               0.16666666666, 8)

    def test_multiline_project(self):
        self.assertEqual(self.multiline.project(self.point), 1.0)
        self.assertEqual(self.multiline.project(self.point, normalized=True),
                         0.125)

    def test_not_supported_project(self):
        with pytest.raises(shapely.GEOSException,
                           match="IllegalArgumentException"):
            self.point.buffer(1.0).project(self.point)

    def test_not_on_line_project(self):
        # Points that aren't on the line project to 0.
        self.assertEqual(self.line1.project(Point(-10, -10)), 0.0)

    def test_line1_interpolate(self):
        self.assertTrue(self.line1.interpolate(0.5).equals(Point(0.5, 0.0)))
        self.assertTrue(self.line1.interpolate(-0.5).equals(Point(1.5, 0.0)))
        self.assertTrue(
            self.line1.interpolate(0.5, normalized=True).equals(Point(1, 0)))
        self.assertTrue(
            self.line1.interpolate(-0.5, normalized=True).equals(Point(1, 0)))

    def test_line2_interpolate(self):
        self.assertTrue(self.line2.interpolate(0.5).equals(Point(3.0, 0.5)))
        self.assertTrue(
            self.line2.interpolate(0.5, normalized=True).equals(Point(3, 3)))

    def test_multiline_interpolate(self):
        self.assertTrue(self.multiline.interpolate(0.5).equals(Point(0.5, 0)))
        self.assertTrue(
            self.multiline.interpolate(0.5,
                                       normalized=True).equals(Point(3.0,
                                                                     2.0)))

    def test_line_ends_interpolate(self):
        # Distances greater than length of the line or less than
        # zero yield the line's ends.
        self.assertTrue(self.line1.interpolate(-1000).equals(Point(0.0, 0.0)))
        self.assertTrue(self.line1.interpolate(1000).equals(Point(2.0, 0.0)))
class LinearReferencingTestCase(unittest.TestCase):
    def setUp(self):
        self.point = Point(1, 1)
        self.line1 = LineString(([0, 0], [2, 0]))
        self.line2 = LineString(([3, 0], [3, 6]))
        self.multiline = MultiLineString([
            list(self.line1.coords), list(self.line2.coords)
        ]) 

    def test_line1_project(self):
        self.assertEqual(self.line1.project(self.point), 1.0)
        self.assertEqual(self.line1.project(self.point, normalized=True), 0.5)

    def test_line2_project(self):
        self.assertEqual(self.line2.project(self.point), 1.0)
        self.assertAlmostEqual(self.line2.project(self.point, normalized=True),
            0.16666666666, 8)

    def test_multiline_project(self):
        self.assertEqual(self.multiline.project(self.point), 1.0)
        self.assertEqual(self.multiline.project(self.point, normalized=True),
            0.125)

    def test_not_supported_project(self):
        self.assertRaises(TypeError, self.point.buffer(1.0).project,
            self.point)

    def test_not_on_line_project(self):
        # Points that aren't on the line project to 0.
        self.assertEqual(self.line1.project(Point(-10,-10)), 0.0)

    def test_line1_interpolate(self):
        self.failUnless(self.line1.interpolate(0.5).equals(Point(0.5, 0.0)))
        self.failUnless(
            self.line1.interpolate(0.5, normalized=True).equals(
                Point(1.0, 0.0)))

    def test_line2_interpolate(self):
        self.failUnless(self.line2.interpolate(0.5).equals(Point(3.0, 0.5)))
        self.failUnless(
            self.line2.interpolate(0.5, normalized=True).equals(
                Point(3.0, 3.0)))

    def test_multiline_interpolate(self):
        self.failUnless(self.multiline.interpolate(0.5).equals(
            Point(0.5, 0.0)))
        self.failUnless(
            self.multiline.interpolate(0.5, normalized=True).equals(
                Point(3.0, 2.0)))

    def test_line_ends_interpolate(self):
        # Distances greater than length of the line or less than
        # zero yield the line's ends.
        self.failUnless(self.line1.interpolate(-1000).equals(Point(0.0, 0.0)))
        self.failUnless(self.line1.interpolate(1000).equals(Point(2.0, 0.0)))
Exemple #3
0
def get_center_point(segment):
    """
    Get the centerpoint for a linestring or multiline string
    Args:
        segment - Geojson LineString or MultiLineString
    Returns:
        Geojson point
    """

    if segment['geometry']['type'] == 'LineString':
        point = LineString(segment['geometry']['coordinates']).interpolate(
            .5, normalized=True)
        return point.x, point.y
    elif segment['geometry']['type'] == 'MultiLineString':
        # Make a rectangle around the multiline
        coords = [
            item for coords in segment['geometry']['coordinates']
            for item in coords
        ]

        minx = min([x[0] for x in coords])
        maxx = max([x[0] for x in coords])
        miny = min([x[1] for x in coords])
        maxy = max([x[1] for x in coords])

        point = LineString([[minx, miny], [maxx,
                                           maxy]]).interpolate(.5,
                                                               normalized=True)
        mlstring = MultiLineString(segment['geometry']['coordinates'])
        point = mlstring.interpolate(mlstring.project(point))

        return point.x, point.y

    return None, None
def generate_sample_points(points_X, points_Y):
    '''Generate 100 sampled points for a gesture.

    In this function, we should convert every gesture or template to a set of 100 points, such that we can compare
    the input gesture and a template computationally.

    :param points_X: A list of X-axis values of a gesture.
    :param points_Y: A list of Y-axis values of a gesture.

    :return:
        sample_points_X: A list of X-axis values of a gesture after sampling, containing 100 elements.
        sample_points_Y: A list of Y-axis values of a gesture after sampling, containing 100 elements.
    '''
    sample_points_X, sample_points_Y = [], []
    # TODO: Start sampling (12 points)
    final_len = 0
    all_points = []
    for i in range(len(points_X) - 1):
        for j in range(len(points_Y) - 1):
            point_1 = (points_X[i], points_Y[i])
            point_2 = (points_X[i + 1], points_Y[i + 1])
            line = LineString([point_1, point_2])
            final_len += line.length
        all_points.append((point_1, point_2))
    # print(all_points)
    t = final_len / 99
    # print(final_len)
    cp = line.interpolate(t)
    lines = MultiLineString(all_points)
    splitter = MultiPoint(
        [lines.interpolate((i / 100), normalized=True) for i in range(1, 100)])
    print(splitter)
    gs = GeoSeries(splitter)
    gs.plot(marker="$", color="red")

    return sample_points_X, sample_points_Y
Exemple #5
0
class LinearReferencingTestCase(unittest.TestCase):

    def setUp(self):
        self.point = Point(1, 1)
        self.line1 = LineString(([0, 0], [2, 0]))
        self.line2 = LineString(([3, 0], [3, 6]))
        self.multiline = MultiLineString([
            list(self.line1.coords), list(self.line2.coords)
        ])

    @unittest.skipIf(geos_version < (3, 2, 0), 'GEOS 3.2.0 required')
    def test_line1_project(self):
        self.assertEqual(self.line1.project(self.point), 1.0)
        self.assertEqual(self.line1.project(self.point, normalized=True), 0.5)

    @unittest.skipIf(geos_version < (3, 2, 0), 'GEOS 3.2.0 required')
    def test_line2_project(self):
        self.assertEqual(self.line2.project(self.point), 1.0)
        self.assertAlmostEqual(
            self.line2.project(self.point, normalized=True), 0.16666666666, 8)

    @unittest.skipIf(geos_version < (3, 2, 0), 'GEOS 3.2.0 required')
    def test_multiline_project(self):
        self.assertEqual(self.multiline.project(self.point), 1.0)
        self.assertEqual(
            self.multiline.project(self.point, normalized=True), 0.125)

    @unittest.skipIf(geos_version < (3, 2, 0), 'GEOS 3.2.0 required')
    def test_not_supported_project(self):
        with self.assertRaises(TypeError):
            self.point.buffer(1.0).project(self.point)

    @unittest.skipIf(geos_version < (3, 2, 0), 'GEOS 3.2.0 required')
    def test_not_on_line_project(self):
        # Points that aren't on the line project to 0.
        self.assertEqual(self.line1.project(Point(-10, -10)), 0.0)

    @unittest.skipIf(geos_version < (3, 2, 0), 'GEOS 3.2.0 required')
    def test_line1_interpolate(self):
        self.assertTrue(self.line1.interpolate(0.5).equals(Point(0.5, 0.0)))
        self.assertTrue(
            self.line1.interpolate(0.5, normalized=True).equals(Point(1, 0)))

    @unittest.skipIf(geos_version < (3, 2, 0), 'GEOS 3.2.0 required')
    def test_line2_interpolate(self):
        self.assertTrue(self.line2.interpolate(0.5).equals(Point(3.0, 0.5)))
        self.assertTrue(
            self.line2.interpolate(0.5, normalized=True).equals(Point(3, 3)))

    @unittest.skipIf(geos_version < (3, 2, 0), 'GEOS 3.2.0 required')
    def test_multiline_interpolate(self):
        self.assertTrue(self.multiline.interpolate(0.5).equals(Point(0.5, 0)))
        self.assertTrue(
            self.multiline.interpolate(0.5, normalized=True).equals(
                Point(3.0, 2.0)))

    @unittest.skipIf(geos_version < (3, 2, 0), 'GEOS 3.2.0 required')
    def test_line_ends_interpolate(self):
        # Distances greater than length of the line or less than
        # zero yield the line's ends.
        self.assertTrue(self.line1.interpolate(-1000).equals(Point(0.0, 0.0)))
        self.assertTrue(self.line1.interpolate(1000).equals(Point(2.0, 0.0)))
        list_points = []
        ## set the current distance to place the point
        current_dist = distance
        ## get the geometry of the line as wkt
        line_geom = ln.geometry().ExportToWkt()
        ## make shapely MultiLineString object
        shapely_line = MultiLineString(wkt.loads(line_geom))
        ## get the total length of the line
        line_length = shapely_line.length
        ## append the starting coordinate to the list
        list_points.append(Point(list(shapely_line[0].coords)[0]))
        ## https://nathanw.net/2012/08/05/generating-chainage-distance-nodes-in-qgis/
        ## while the current cumulative distance is less than the total length of the line
        while current_dist < line_length:
            ## use interpolate and increase the current distance
            list_points.append(shapely_line.interpolate(current_dist))
            current_dist += distance
        ## append end coordinate to the list
        list_points.append(Point(list(shapely_line[0].coords)[-1]))

        ## add points to the layer
        ## for each point in the list
        for num, pt in enumerate(list_points, 1):
            ## create a point object
            pnt = ogr.Geometry(ogr.wkbPoint)
            pnt.AddPoint(pt.x, pt.y)
            feat_dfn = out_lyr.GetLayerDefn()
            feat = ogr.Feature(feat_dfn)
            feat.SetGeometry(pnt)
            ## populate the distance values for each point.
            ## start point
def create_points_at_uniform_length(str_net_path, str_diss_path, str_pts_path, p_interp_spacing_m):
    
    print('Dissolve line features...')

    lst_all=[]
    
    # Open the delineated stream network...
    with fiona.open(str_net_path) as lines:
        
        crs = lines.crs
        
        # Open an output file for dissolved lines...THIS IS NOT REALLY NEEDED, ONLY FOR TESTING
        schema = {'geometry':'MultiLineString', 'properties':{'linkno':'int:6'}}         
        with fiona.open(str_diss_path, 'w', 'ESRI Shapefile', schema, crs) as output:           
            
            for line in lines:
                
                lst_all.append(line['geometry']['coordinates'])
                            
            output.write({'properties':{'linkno':9999}, 'geometry':{'type':'MultiLineString','coordinates':lst_all}})   

        print('Points along line features...')    
        # Open the dissolve network...(skip this write/read step?)
        with fiona.open(str_diss_path) as line:
            
            crs = line.crs
            line = line[0]        
            
            # NOTE:  Need to check whether or not to convert units here!
            
            # Geometry transform function based on pyproj.transform to convert length between decimal degrees and meters
            project = partial(
                pyproj.transform,
                pyproj.Proj(init=crs['init']),  
                pyproj.Proj(init='EPSG:26914')) # UTM14N For TX data;  NOTE: HARDCODED FOR NOW!      
        
            # Open output point shapefile...                                     
            schema = {'geometry':'Point', 'properties':{'id':'int:6'}}         
            with fiona.open(str_pts_path, 'w', 'ESRI Shapefile', schema, crs) as pt_output:
                        
                line_shply = MultiLineString(line['geometry']['coordinates'])
                                        
                line2 = transform(project, line_shply)  
                length_m = line2.length
               
                length_deg = line_shply.length # units depend on crs
                
                p_interp_spacing = (length_deg*p_interp_spacing_m)/(length_m) # convert from meters to dec. degrees
                   
                step_lens = np.arange(0, length_deg, p_interp_spacing) # p_interp_spacing in projection units?
                
#                # Open the output line segment shapefile...
#                schema = {'geometry':'LineString', 'properties':{'id':'int:6', 'len_m':'float'}}         
#                with fiona.open(str_segs_path, 'w', 'ESRI Shapefile', schema, crs) as ln_output:                
        
#                i_pt_prev=np.empty(0)
                for i, step in enumerate(step_lens): # lambda here instead?              
                    i_pt = np.array(line_shply.interpolate(step))
                    
#                        if i_pt_prev.any():
#                            ls = LineString([i_pt, i_pt_prev])
#                            
#                            # Write out the lines (with length)...
#                            len_m = transform(project, ls).length
#                            
#                            ln_output.write({'geometry': mapping(ls), 'properties':{'id':i, 'len_m':len_m}})
#                    
#                        i_pt_prev = i_pt
                    
                    # Write out the point...
                    pt_output.write({'properties':{'id':i}, 'geometry':{'type':'Point','coordinates':i_pt}}) 
Exemple #8
0
class WaySet:
    ways_cache = ObjectCache()

    def __init__(self, lines):
        self.multiline = MultiLineString(lines)
        self.headings = [
            Route.get_heading(l.coords[0][1], l.coords[0][0], l.coords[1][1],
                              l.coords[1][0]) for l in lines
        ]

    @staticmethod
    def download_all_ways(sector, tram_only=False, timestamp=None):

        bbox = "%f,%f,%f,%f" % sector
        ext = 0.01
        ext_bbox = "%f,%f,%f,%f" % (sector[0] - ext, sector[1] - ext,
                                    sector[2] + ext, sector[3] + ext)

        if tram_only:
            query = '[out:json]{{date}};(node({{ext_bbox}});way["railway"="tram"]({{bbox}}););out;'
        else:
            query = '[out:json]{{date}};(way["highway"]({{bbox}});node({{ext_bbox}}););out;'

        query = query.replace("{{bbox}}", bbox)
        query = query.replace("{{ext_bbox}}", ext_bbox)

        timestamp = "[date:\"%s\"]" % timestamp if timestamp is not None else ""
        query = query.replace("{{date}}", timestamp)

        ways = WaySet.ways_cache.get_from_cache(query)
        if ways is None:
            api = overpy.Overpass()
            try:
                result = api.query(query)
            except overpy.OverpassTooManyRequests:
                time.sleep(20)
                result = api.query(query)

            ways = []
            for w in result.ways:
                try:
                    nodes = w.get_nodes(resolve_missing=False)
                except overpy.exception.DataIncomplete:
                    try:
                        nodes = w.get_nodes(resolve_missing=True)
                    except overpy.exception.DataIncomplete:
                        print("Overpass can't resolve nodes. Skipping way.")
                        continue
                nodes = [[float(n.lon), float(n.lat)] for n in nodes]
                ways += [nodes]

            WaySet.ways_cache.store_in_cache(query, ways)

        lines = [LineString(c) for c in ways]

        return WaySet(lines)

    def snap_point_to_lines(self, point, next_point, priority_line_index):
        distances = [line.distance(point) for line in self.multiline]

        if priority_line_index > -1:
            distances[priority_line_index] /= 2

        min_distance = min(distances)
        i_dist = distances.index(min_distance)

        projection = self.multiline[i_dist].project(point)
        next_proj = 1 if next_point is None else self.multiline[
            i_dist].project(next_point)
        new_point = self.multiline[i_dist].interpolate(projection)
        new_next_point = self.multiline[i_dist].interpolate(next_proj)

        heading = Route.get_heading(new_point.y, new_point.x, new_next_point.y,
                                    new_next_point.x)

        return new_point, i_dist, heading

    def snap_point_to_multilines(self, point):
        return self.multiline.interpolate(self.multiline.project(point))

    def plot(self):
        for l in self.multiline:
            lon, lat = l.xy
            plt.plot(lon, lat)

    def get_closest_way(self, point):
        distances = [line.distance(point) for line in self.multiline]
        min_distance = min(distances)
        i_min_dist = distances.index(min_distance)
        return self.multiline[i_min_dist]

    def get_closest_way_with_heading(self,
                                     point,
                                     heading,
                                     heading_tolerance=45):
        heading = heading % 360
        lines = self.multiline
        projections = [l.project(point, normalized=True) for l in lines]
        lines = [l for l, p in zip(lines, projections) if 0 < p < 1]

        headings = np.array([
            WaySet.get_linestring_heading_at_projection(l, p)
            for l, p in zip(lines, projections)
        ])
        headings_diff = np.abs(headings % 360 - heading)
        # print(headings_diff)
        if (headings_diff < heading_tolerance).any():
            lines = [
                l for l, hd in zip(lines, headings_diff)
                if hd < heading_tolerance
            ]

        distances = [line.distance(point) for line in lines]

        min_distance = min(distances)
        i_min_dist = distances.index(min_distance)

        return lines[i_min_dist]

    @staticmethod
    def get_linestring_heading_at_projection(linestring, projection):

        ps = [
            linestring.project(Point(c), normalized=True)
            for c in linestring.coords
        ]

        for prev_c, c in zip(linestring.coords[:-1], linestring.coords[1:]):
            p = linestring.project(Point(c))
            if p > projection:
                return Route.get_heading(prev_c[1], prev_c[0], c[1], c[0])

        prev_c = linestring.coords[-2]
        c = linestring.coords[-1]
        return Route.get_heading(prev_c[1], prev_c[0], c[1], c[0])

    def snap_points(self, points):
        last_way = None
        snapped_points = []
        last_distance = None

        # headings before snapping
        headings = []
        for i, p in enumerate(points):
            if i < len(points) - 1:
                next_point = points[i + 1]
                headings.append(
                    Route.get_heading(p.y, p.x, next_point.y, next_point.x))
        headings.append(headings[-1])

        h_diff = []

        for point_index in range(len(points)):

            point = points[point_index]
            heading = headings[point_index]

            # if last_way is not None:
            #     projection = last_way.project(point)
            #     distance = last_way.distance(point)
            #     if 0 <= projection <= 1 and distance < 1.1 * last_distance:
            #         snapped_point = last_way.interpolate(projection)
            #         last_distance = distance
            #         snapped_points += [snapped_point]
            #         continue

            last_way = self.get_closest_way_with_heading(point, heading)

            # last_way = self.get_closest_way(point)
            projection = last_way.project(point)
            # last_distance = last_way.distance(point)
            snapped_point = last_way.interpolate(projection)

            h = WaySet.get_linestring_heading_at_projection(
                last_way, projection)

            h_diff += [headings[point_index] - h]

            snapped_points += [snapped_point]

        # plt.plot(h_diff)
        # plt.show()

        # headings after snapping
        headings = []
        for i, p in enumerate(snapped_points):
            if i < len(snapped_points) - 1:
                next_point = snapped_points[i + 1]
                headings.append(
                    Route.get_heading(p.y, p.x, next_point.y, next_point.x))
        headings.append(headings[-1])

        return Route.from_points(snapped_points, headings)