LightOSM and OpenStreetMapX assigning inconsistent nearest node

100 randomly chosen real coordinates:
pts = collect(zip(df.cLat, df.cLng))[rand(1:size(df, 1), 100)]

Conversion of points to appropriate package types:
losm_pts = [GeoLocation(pts[i][1], pts[i][2]) for i in 1:length(pts)]
osmx_pts = [LLA(pts[i][1], pts[i][2]) for i in 1:length(pts)]

Using appropiate API on self-same OSM map
losmNodes = LightOSM.nearest_node(g, losm_pts)[1]
osmxNodes = [OpenStreetMapX.point_to_nodes(pt, m) for pt in osmx_pts]

sum(losmNodes .== osmxNodes) => 26

Is this expected behavior?
Setup:

using LightOSM
using OpenStreetMapX

sol = GeoLocation(40.416775, -3.703790)
radius = 30 # km (you might wanna choose smaller radius)
data_file = joinpath(@__DIR__, "assets", "sol_30km.osm")

g_losm = LightOSM.graph_from_download(
                                    :point,
                                    point=sol,
                                    radius=radius,
                                    weight_type=:distance,
                                    download_format=:osm,
                                    save_to_file_location=data_file
                                    )

@time g = graph_from_file(
                        data_file, 
                        weight_type=:distance, 
                        precompute_dijkstra_states=false, 
                        largest_connected_component=true
                        )


@time m = get_map_data(
                    data_file,
                    use_cache=true,
                    trim_to_connected_graph=true
                    )
pts = [(40.45977619, -3.64972306), (40.4123686, -3.7043242), (40.4788906, -3.7418347), (40.4323104, -3.6872047), (40.4073795, -3.632668), (40.42164902, -3.69933352), (40.49180334, -3.65343723), (40.36011003, -3.68639991), (40.4440244, -3.6841504), (40.41666095, -3.71297909), (40.44113437, -3.68297474), (40.4263387, -3.70946389), (40.42662246, -3.68903793), (40.41527178, -3.68852225), (40.4328848, -3.6379967), (40.4286787, -3.7179097), (40.40717241, -3.68853017), (40.45314175, -3.62145994), (40.45770264, -3.68642494), (40.521698, -3.88468782), (40.449005, -3.7000483), (40.42022393, -3.70619079), (40.4469191, -3.6699378), (40.4134544, -3.6634627), (40.3987967, -3.6952302), (40.40771914, -3.61503991), (40.42921736, -3.70259969), (40.47553255, -3.67525063), (40.406528, -3.689373), (40.41838565, -3.70101392), (40.40617412, -3.69181302), (40.42593384, -3.69835465), (40.4267856, -3.6967374), (40.44563293, -3.60773659), (40.41691594, -3.69437511), (40.4320605, -3.6421621), (40.43600464, -3.68548169), (40.4031125, -3.6946819), (40.4269148, -3.6997695), (40.4510321, -3.5948981), (40.42525794, -3.6860182), (40.43395038, -3.69468391), (40.4327477, -3.5399445), (40.4399234, -3.7125539), (40.56665056, -3.61032285), (40.4399745, -3.7087431), (40.40122644, -3.59628875), (40.3778614, -3.7169789), (40.42983471, -3.69981565), (40.387983, -3.711779), (40.3755017, -3.6999926), (40.45898894, -3.67791139), (40.4313791, -3.6906561), (40.45213973, -3.6890672), (40.43873464, -3.70953597), (40.4072328, -3.6884097), (40.47051018, -3.67605186), (40.4334051, -3.6863526), (40.40317734, -3.6059012), (40.42540329, -3.66637956), (40.425744, -3.690308), (40.455769, -3.6976891), (40.3663398, -3.60001869), (40.3818695, -3.7172834), (40.4280238, -3.6966277), (40.4485723, -3.64852737), (40.44565562, -3.67175571), (40.4337923, -3.6844133), (40.41444787, -3.70027769), (40.43379095, -3.69128813), (40.42207866, -3.69764734), (40.40631031, -3.68845833), (40.3554854, -3.7784936), (40.49862671, -3.612889), (40.4166774, -3.7078537), (40.4102642, -3.6650068), (40.42832514, -3.67511261), (40.45329126, -3.69509295), (40.52252818, -3.63474827), (40.4488398, -3.6785424), (40.485591, -3.6346916), (40.42609397, -3.68794536), (40.4106581, -3.6644704), (40.52603672, -3.63684484), (40.4291194, -3.63469), (40.442856, -3.6401386), (40.4224859, -3.6825111), (40.41159154, -3.69779295), (40.42269689, -3.70753555), (40.46801, -3.57002), (40.43342104, -3.67312995), (40.46787479, -3.6951587), (40.4223607, -3.6938232), (40.491255, -3.594576), (40.44849247, -3.67053363), (40.39638871, -3.66900964), (40.4713565, -3.689335), (40.44038766, -3.69751196), (40.491111, -3.7010693), (40.3880102, -3.6889842)]

Comparisons along shortest paths between

strtPoints = [(40.40647374, -3.68861037), (40.4766087, -3.6876792), (40.423677, -3.6848885), (40.4429993, -3.67984459), (40.42625779, -3.69331498), (40.4170684, -3.6756673), (40.40042329, -3.61914136), (40.43208461, -3.68719853), (40.4431324, -3.6743115), (40.43723621, -3.66986241), (40.42985589, -3.69983482), (40.45574495, -3.68120812), (40.46254312, -3.67447646), (40.4379108, -3.8133623), (40.45347052, -3.69908986), (40.4012675, -3.5959367), (40.4637, -3.69354), (40.445051, -3.6868186), (40.52329745, -3.64814346), (40.42510453, -3.69224084), (40.46183075, -3.61775375), (40.5245128, -3.6421908), (40.47213, -3.73097), (40.43765982, -3.67690099), (40.4387251, -3.7935788), (40.44726613, -3.71879801), (40.43875567, -3.70335088), (40.4272168, -3.6941936), (40.43246741, -3.6846149), (40.4407972, -3.6560046), (40.48782021, -3.66446623), (40.43177402, -3.66691533), (40.45591005, -3.62149045), (40.43174292, -3.63298388), (40.48045716, -3.73669503), (40.46261203, -3.63156298), (40.42038172, -3.66242632), (40.4212875, -3.6746451), (40.4746587, -3.687773), (40.49027882, -3.6936422), (40.4845639, -3.7083036), (40.4499374, -3.6902337), (40.4496493, -3.6521805), (40.38325532, -3.7222768), (40.47642543, -3.63367572), (40.43369235, -3.69091547), (40.4261263, -3.6937435), (40.45233301, -3.67935441), (40.43818865, -3.69490725), (40.42890061, -3.67798448), (40.3898206, -3.7338412), (40.44515845, -3.63430437), (40.41638686, -3.68894669), (40.45800858, -3.69776577), (40.43452635, -3.70414138), (40.4087793, -3.6775419), (40.4984586, -3.6648577), (40.43783826, -3.69816423), (40.44177, -3.60804), (40.45812988, -3.71165466), (40.42070512, -3.72034594), (40.4272239, -3.6712037), (40.4452947, -3.6505415), (40.53185151, -3.63782066), (40.45851048, -3.67653007), (40.40761908, -3.68874793), (40.43407628, -3.68945539), (40.42286611, -3.68409065), (40.40729, -3.68812), (40.46720414, -3.81536923), (40.46278293, -3.6365346), (40.4343269, -3.6130739), (40.4476545, -3.6379286), (40.42884574, -3.71579692), (40.42950364, -3.68171499), (40.420539, -3.7040679), (40.43768199, -3.67672745), (40.4622958, -3.6162491), (40.4494742, -3.6678332), (40.43677637, -3.68522845), (40.45838766, -3.68166916), (40.4268809, -3.6536716), (40.43562835, -3.70148394), (40.44312908, -3.66818877), (40.43232727, -3.67701244), (40.4208559, -3.7061332), (40.43115412, -3.69265373), (40.4468401, -3.5953674), (40.44838244, -3.66544615), (40.47057237, -3.8209613), (40.42170849, -3.71839765), (40.42623004, -3.68971361), (40.42941808, -3.70031473), (40.4179008, -3.6984637), (40.4242752, -3.6662009), (40.47017751, -3.66643433), (40.49916614, -3.65650778), (40.44308108, -3.67445754), (40.39655069, -3.87176226), (40.4551661, -3.69450574)]
endPoints = [(40.40035, -3.70306), (40.47780807, -3.69849334), (40.4377299, -3.6800531), (40.4211153, -3.6879227), (40.41384654, -3.69493838), (40.471597, -3.682403), (40.48230943, -3.67061352), (40.4239884, -3.6864495), (40.406806, -3.691947), (40.44236981, -3.65546398), (40.4262522, -3.7068227), (40.4468401, -3.69488566), (40.447563, -3.656106), (40.4396692, -3.8073816), (40.43474505, -3.66857059), (40.42054213, -3.57832935), (40.491255, -3.594576), (40.4696799, -3.6698), (40.46801, -3.57002), (40.4296166, -3.6876464), (40.42423842, -3.68000284), (40.491255, -3.594576), (40.471597, -3.682403), (40.4358823, -3.6421008), (40.4354445, -3.7334977), (40.4585917, -3.6945422), (40.406806, -3.691947), (40.4730513, -3.6868434), (40.43313179, -3.73357988), (40.4227419, -3.6964978), (40.4256262, -3.6844591), (40.491255, -3.594576), (40.46801, -3.57002), (40.4806616, -3.6862549), (40.406806, -3.691947), (40.467844, -3.626451), (40.4637403, -3.6139041), (40.4431511, -3.6823055), (40.41807399, -3.68979726), (40.4867882, -3.6658943), (40.447689, -3.657577), (40.48837, -3.6959), (40.4295441, -3.6835559), (40.45766912, -3.66049308), (40.46682955, -3.65845665), (40.41458, -3.69028), (40.446625, -3.695867), (40.4466221, -3.6924595), (40.42212769, -3.69565118), (40.422233, -3.6923577), (40.432579, -3.7076952), (40.438277, -3.637089), (40.4465975, -3.6975215), (40.4277378, -3.7295722), (40.39943841, -3.68889302), (40.420281, -3.690747), (40.491255, -3.594576), (40.4167081, -3.6910361), (40.46575663, -3.61401077), (40.42791748, -3.71710682), (40.4427623, -3.7871334), (40.46801, -3.57002), (40.4349325, -3.6799566), (40.471754, -3.849293), (40.50185837, -3.66879389), (40.4348437, -3.6968111), (40.448043, -3.624555), (40.43067, -3.6822437), (40.4339336, -3.6924939), (40.44618, -3.71253), (40.4236729, -3.7072785), (40.4445497, -3.6543204), (40.4634108, -3.6967773), (40.4517406, -3.69269371), (40.4125946, -3.6937105), (40.465511, -3.616573), (40.385241, -3.717764), (40.422343, -3.686257), (40.472916, -3.6636556), (40.41819319, -3.68981805), (40.4235863, -3.6684468), (40.375187, -3.6470258), (40.446773, -3.6936392), (40.46801, -3.57002), (40.44898857, -3.6904071), (40.406806, -3.691947), (40.47537293, -3.68825234), (40.4063306, -3.6900896), (40.500982, -3.867037), (40.4481, -3.78518), (40.4209713, -3.7080051), (40.4489254, -3.6708406), (40.4556463, -3.6800522), (40.44954419, -3.69145327), (40.428623, -3.6951358), (40.44696788, -3.69304122), (40.42867831, -3.69419441), (40.406806, -3.691947), (40.45108855, -3.69518925), (40.471597, -3.682403)]

losm_oPoints = [GeoLocation(strtPoints[i][1], strtPoints[i][2]) for i in 1:length(strtPoints)]
losm_dPoints = [GeoLocation(endPoints[i][1], endPoints[i][2]) for i in 1:length(endPoints)]

osmx_oPoints = [LLA(strtPoints[i][1], strtPoints[i][2]) for i in 1:length(strtPoints)]
osmx_dPoints = [LLA(endPoints[i][1], endPoints[i][2]) for i in 1:length(endPoints)]

losm_oNodes = LightOSM.nearest_node(g, losm_oPoints)[1]
losm_dNodes = LightOSM.nearest_node(g, losm_dPoints)[1]

osmx_oNodes = [OpenStreetMapX.point_to_nodes(pt, m) for pt in osmx_oPoints]
osmx_dNodes = [OpenStreetMapX.point_to_nodes(pt, m) for pt in osmx_dPoints]

losm_paths = [LightOSM.shortest_path(g, losm_oNodes[i], losm_dNodes[i]) for i in 1:length(losm_oNodes)]
osmx_paths = [OpenStreetMapX.shortest_route(m, osmx_oNodes[i], osmx_dNodes[i], routing=:astar) for i in 1:length(osmx_oNodes)]

numLosmNodesInPath = [length(losm_paths[i]) for i in 1:length(losm_paths)]
numOsmxNodesInPath = [length(osmx_paths[i][1]) for i in 1:length(osmx_paths)]

diff_in_numOfNodes = numLosmNodesInPath .- numOsmxNodesInPath

osmxRouteDist = [osmx_paths[i][2] for i in 1:length(osmx_paths)] ./ 1000
losmRouteDist = [cumsum(weights_from_path(g, losm_paths[i]))[end] for i in 1:length(losm_paths)]

diff_in_distances = losmRouteDist .- osmxRouteDist

results = DataFrame(
    numLosmNodesInPath = numOfLosmNodes,
    numOsmxNodesInPath = numOfOsmxNodes,
    diff_in_numOfNodes = diff_in_numOfNodes,
    losmRouteDist = losmRouteDist,
    osmxRouteDist = osmxRouteDist,
    diff_in_distances = diff_in_distances
)

mean(diff_in_distances) = 0.123
median(diff_in_distances) = 0.015

histogram(losmRouteDist)
histogram(osmxRouteDist)

Routes from OpenStreetMapX

Routes from LightOSM

They do seem to match up pretty well, after all. But it is just still strange, I mean, check out the difference in the number of nodes between the two paths shown. There must be something wrong about my intuition about the underlying graphs. For instance, how can OpenStreetMapX draw such twisty path with only three nodes between them? There must be a fieldname in its graph that it’s using.

Anyways, would appreciate any insight you have about these if you do.

1 Like

Perhaps paths in one package are comprised of sub-paths and lengths calculated by aerial distance between nodes, and the other package polygonizes the path and thus gets a more accurate distance. According to this Losm polygonizes and Osmx has sub-paths. And also, Losm has longer distances accordingly. This fits with the table in the post.

HI @Dan, you mean like haversine or euclidean measures of distance? I’m pretty sure OpenStreetMapX implements euclidean in this case, I’m not quite as sure for LightOSM. I could measure the distance from each original point to its associated node and see who gets nearest but I wouldn’t put too much faith on the results, it would be interesting to see though.

I meant distances from point A to B directly or along a path. Haversine vs. Euclidean should make negligible difference here.