¿Es posible ajustar una coordenada a una calle en OSMnx?

OSMnx proporciona una solución para calcular la ruta más corta entre dos nodos, pero me gustaría lo mismo con puntos en las calles (tengo coordenadas GPS registradas desde los vehículos). Sé que también hay un método para obtener el nodo más cercano, pero tengo dos preguntas para este problema mío.

i) ¿Cuando se calcula el nodo más cercano es la calle donde también se toma en cuenta el punto? (Supongo que no) ii) Si quisiera implementar algo como esto, me gustaría saber cómo se representa una calle (borde) como una curva (¿curva de Bézier, tal vez?). ¿Es posible obtener la curva (o la ecuación de la curva) de un borde?

Hice esta pregunta aquí, porque las pautas para la contribución de OSMnx lo hicieron.

Las calles y el nodo en OSMnx son shapely.geometry.LineString , y shapely.geometry.Point objetos, por lo que no hay una curva, solo una secuencia de coordenadas. El término técnico para lo que describió es Map Matching . Existen diferentes formas de correlación de mapas, la más simple es la correspondencia geométrica en la que se encuentra la geometría más cercana (nodo o borde) al punto GPS. point to point coincidencia de mapa point to point se puede lograr fácilmente mediante la función ox.get_nearest_node() incorporada ox.get_nearest_node() . Si tiene un lujo de pistas GPS densas, este enfoque podría funcionar razonablemente bien. Para la coincidencia de mapa de point to line debe usar funciones bien proporcionadas. El problema con este enfoque es que es muy lento. puede acelerar el algoritmo usando un índice espacial, pero aún así, no será lo suficientemente rápido para la mayoría de los propósitos. Tenga en cuenta que la correspondencia geométrica del mapa es menos precisa entre todos los enfoques. Escribí una función hace unas semanas que hace una simple correlación de mapa punto a línea usando GeoDataFrame de borde y GeoDataFrame de nodo que puede obtener de OSMnx. Abandoné esta idea y ahora estoy trabajando en un nuevo algoritmo (con suerte mucho más rápido), que publicaré en GitHub al finalizar. Mientras tanto, esto puede ser de alguna ayuda para usted u otra persona, así que lo publico aquí. Esta es una versión anterior del código abandonado, no se ha probado lo suficiente y no se ha optimizado. Pruébalo y hazme saber si funciona para ti.

 def GeoMM(traj, gdfn, gdfe): """ performs map matching on a given sequence of points Parameters ---------- Returns ------- list of tuples each containing timestamp, projected point to the line, the edge to which GPS point has been projected, the geometry of the edge)) """ traj = pd.DataFrame(traj, columns=['timestamp', 'xy']) traj['geom'] = traj.apply(lambda row: Point(row.xy), axis=1) traj = gpd.GeoDataFrame(traj, geometry=traj['geom'], crs=EPSG3740) traj.drop('geom', axis=1, inplace=True) n_sindex = gdfn.sindex res = [] for gps in traj.itertuples(): tm = gps[1] p = gps[3] circle = p.buffer(150) possible_matches_index = list(n_sindex.intersection(circle.bounds)) possible_matches = gdfn.iloc[possible_matches_index] precise_matches = possible_matches[possible_matches.intersects(circle)] candidate_nodes = list(precise_matches.index) candidate_edges = [] for nid in candidate_nodes: candidate_edges.append(G.in_edges(nid)) candidate_edges.append(G.out_edges(nid)) candidate_edges = [item for sublist in candidate_edges for item in sublist] dist = [] for edge in candidate_edges: # get the geometry ls = gdfe[(gdfe.u == edge[0]) & (gdfe.v == edge[1])].geometry dist.append([ls.distance(p), edge, ls]) dist.sort() true_edge = dist[0][1] true_edge_geom = dist[0][2].item() pp = true_edge_geom.interpolate(true_edge_geom.project(p)) # projected point res.append((tm, pp, true_edge, true_edge_geom)) return res