Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possibility to save gpx #6

Closed
bartsaintgermain opened this issue Jan 27, 2021 · 15 comments
Closed

Possibility to save gpx #6

bartsaintgermain opened this issue Jan 27, 2021 · 15 comments

Comments

@bartsaintgermain
Copy link

No description provided.

@matejker
Copy link
Owner

Hi bartsaintgermain!,

Thanks for raising an issue! The file is in XML format so all you need to do is to hit Ctrl + S as save it as e.g. .gpx.

I tried to add download flied to do <a> as is recommended. Unfortunately, it is not working and I assume because the GPX file isn't on the same domain 👇

[path] that resolves to an URL on the same origin. That means the page and the file must share the same domain, subdomain, protocol (HTTP vs. HTTPS), and port (if specified). Exceptions are blob: and data: (which always work), and file: (which never works). (https://stackoverflow.com/a/18678698)

In the next release, I will try to take deeper look into :)

Matej

@bartsaintgermain
Copy link
Author

Is this also possible when running locally. I did succeed in generating the png files but could not find the gpx/xml file.

@matejker
Copy link
Owner

matejker commented Feb 5, 2021

Hmm, interesting. It is created as XML file so when you download it, you should get XML and not png.

@devoteappdevelopment
Copy link

I have the same question. If I download the python code and run the program locally I can generate the .png's given in the example of "The Grange". However, the code as given does not generate a .gpx file. The website generates a .gpx file so it must be possible to generate one. How can we generate a .gpx in the vein of the code example you provide. Thanks.

@matejker
Copy link
Owner

matejker commented Feb 7, 2021

I think that understand your question now. Sure, the jupyter notebook / the Grange example doesn't have the .gpx output.
You can do it simply by converting networkx nodes into geo coordinates, e.g. using this function convert_final_path_to_coordinates(org_graph, final_path) and using a newly added gpx_formatter.py. Putting all together, you can try something like:

from libs.tools import *
from libs.gpx_formatter import TEMPLATE, TRACE_POINT

... 

# List all edges of the extended graph including original edges and edges from minimal matching
single_edges = [(u, v) for u, v, k in graph.edges]
added_edges = get_shortest_paths(graph, matched_edges_with_weights)
edges = map_osmnx_edges2integers(graph, single_edges + added_edges)

# Finds the Eulerian path
network = Network(len(graph.nodes), edges, weighted=True)
eulerian_path = hierholzer(network)
converted_eulerian_path = convert_integer_path2osmnx_nodes(eulerian_path, graph.nodes())
double_edge_heap = get_double_edge_heap(org_graph)

# Finds the final path with edge IDs
final_path = convert_path(graph, converted_eulerian_path, double_edge_heap)
coordinates_path = convert_final_path_to_coordinates(org_graph, final_path)

# Route statistics from OSMnx 
ex = ox.extended_stats(org_graph, ecc=True)
center_node = org_graph.nodes[ex["center"][0]]

trace_points = "\n\t\t\t".join([TRACE_POINT.format(
    lat=lat, lon=lon, id=i, timestamp=datetime.now().isoformat()
) for i, (lat, lon) in enumerate(coordinates_path)])

gpx_payload = TEMPLATE.format(
    name="Name your everystreet route",
    trace_points=trace_points,
    center_lat=center_node["y"],
    center_lon=center_node["x"]
)

with open("gpx_output.gpx", "w") as f:
    f.write(gpx_payload)

I believe this could work 😄

@devoteappdevelopment
Copy link

Thank you so much! That works great. The .xml format doesn't play nice with the mapping software I am using, but plugging it into this website : https://mygeodata.cloud/converter/mapfactor-to-gpx generates a .gpx file that works.
I also had to use datetime.now() -> datetime.datetime.now().

@matejker
Copy link
Owner

matejker commented Feb 7, 2021

Glad to hear that! Oh yeah, I could name it open("gpx_output.gpx", "w") and it would work.
BTW, did you know that you can generate the GPX file on http://www.everystreetchallenge.com?

@bartsaintgermain
Copy link
Author

Thx.
Would be great to generate from site but quickly hit on 3km2 limit.

@matejker
Copy link
Owner

matejker commented Feb 7, 2021

I agree that the 3km^2 limit is annoying, on the other hand I think you will understand it is a webserver and the algorithm is a bit "heavy" 😄

Maybe different question, I guess you have tried to find a route on larger area and you saw that it takes a while, it is basically undoable to generate larger areas such as whole cities. I tired to generate Edinburgh and after an hour I had to kill it. I believe that some optimisation (such as multiprocessing) could help. What would be a decent area size for you as a user? Or what is the area that you are trying to generate?

@bartsaintgermain
Copy link
Author

sure, I fully understand the limit.

my area is about 50m2 but mostly rural area. I guess the number of streets and intersections are also determining the complexity.

@matejker
Copy link
Owner

matejker commented Feb 8, 2021

Yeah, the area it self isn't a problem, even the number of nodes / edges, but the issue are odd-degree nodes. I thought, it might be simpler to and easier to understand to restrict it based on the area size than based on the number of odd-degree nodes.

@1J2B
Copy link

1J2B commented Dec 19, 2021

Hello @matejker,
Your job on that CPP is great, thanks a lot ! However, I've tried many things to save the route as GPX on www.everystreetchallenge.com (ctrl+s, save as, source code display, both on PC & MAC, etc.), but I cannot get anything else than HTML or TXT. Did I miss something ? Because that wold be SO useful !
JB

@joostschouppe
Copy link

did you know that you can generate the GPX file on http://www.everystreetchallenge.com?

I think that functionality might be broken? At least just like @1J2B I can't seem to find a way to export the result.

@PierreSerpe
Copy link

I think that understand your question now. Sure, the jupyter notebook / the Grange example doesn't have the .gpx output. You can do it simply by converting networkx nodes into geo coordinates, e.g. using this function convert_final_path_to_coordinates(org_graph, final_path) and using a newly added gpx_formatter.py. Putting all together, you can try something like:

from libs.tools import *
from libs.gpx_formatter import TEMPLATE, TRACE_POINT

... 

# List all edges of the extended graph including original edges and edges from minimal matching
single_edges = [(u, v) for u, v, k in graph.edges]
added_edges = get_shortest_paths(graph, matched_edges_with_weights)
edges = map_osmnx_edges2integers(graph, single_edges + added_edges)

# Finds the Eulerian path
network = Network(len(graph.nodes), edges, weighted=True)
eulerian_path = hierholzer(network)
converted_eulerian_path = convert_integer_path2osmnx_nodes(eulerian_path, graph.nodes())
double_edge_heap = get_double_edge_heap(org_graph)

# Finds the final path with edge IDs
final_path = convert_path(graph, converted_eulerian_path, double_edge_heap)
coordinates_path = convert_final_path_to_coordinates(org_graph, final_path)

# Route statistics from OSMnx 
ex = ox.extended_stats(org_graph, ecc=True)
center_node = org_graph.nodes[ex["center"][0]]

trace_points = "\n\t\t\t".join([TRACE_POINT.format(
    lat=lat, lon=lon, id=i, timestamp=datetime.now().isoformat()
) for i, (lat, lon) in enumerate(coordinates_path)])

gpx_payload = TEMPLATE.format(
    name="Name your everystreet route",
    trace_points=trace_points,
    center_lat=center_node["y"],
    center_lon=center_node["x"]
)

with open("gpx_output.gpx", "w") as f:
    f.write(gpx_payload)

I believe this could work 😄

Hi Thanks for this fun tool.
In order to get this GPX output i had to (in addition to install scipy):

  1. add "import datetime"
  2. add an extra "datetime." to get the following:
    lat=lat, lon=lon, id=i, timestamp=datetime.datetime.now().isoformat()

find an example (replace .txt by .ipynb)
example.txt

@Sasni
Copy link

Sasni commented May 12, 2024

Function extended_stats was deprecated for a while before it was eventually removed.

use NetworkX :

from libs.gpx_formatter import TEMPLATE, TRACE_POINT
from datetime import datetime
...
# List all edges of the extended graph including original edges and edges from minimal matching
single_edges = [(u, v) for u, v, k in graph.edges]
added_edges = get_shortest_paths(graph, matched_edges_with_weights)
edges = map_osmnx_edges2integers(graph, single_edges + added_edges)

# Finds the Eulerian path
network = Network(len(graph.nodes), edges, weighted=True)
eulerian_path = hierholzer(network)
converted_eulerian_path = convert_integer_path2osmnx_nodes(eulerian_path, graph.nodes())
double_edge_heap = get_double_edge_heap(org_graph)

# Finds the final path with edge IDs
final_path = convert_path(graph, converted_eulerian_path, double_edge_heap)
coordinates_path = convert_final_path_to_coordinates(org_graph, final_path)

eccentricity = nx.eccentricity(graph)
center = nx.center(graph)
center_node = graph.nodes[center[0]]

trace_points = "\n\t\t\t".join([TRACE_POINT.format(
    lat=lat, lon=lon, id=i, timestamp=datetime.now().isoformat()
) for i, (lat, lon) in enumerate(coordinates_path)])

gpx_payload = TEMPLATE.format(
    name="Name your everystreet route",
    trace_points=trace_points,
    center_lat=center_node["y"],
    center_lon=center_node["x"]
)

with open("gpx_output.gpx", "w") as f:
    f.write(gpx_payload)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants