import%20marimo%0A%0A__generated_with%20%3D%20%220.23.13%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Create%20a%20Dual%20Graph%0A%0A%20%20%20%20Create%20a%20dual%20graph%20representation%20from%20a%20primal%20graph.%0A%0A%20%20%20%20For%20purposes%20of%20visualisation%20and%20intuition%2C%20it%20is%20preferable%20to%20work%20with%20the%20network%20in%20its%20dual%20representation.%20Metrics%20such%20as%20centrality%20and%20accessibility%20are%20then%20calculated%20relative%20to%20streets%20instead%20of%20intersections%2C%20and%20the%20results%20can%20be%20visualised%20on%20the%20street%20geometries%20themselves.%20Angular%20(simplest-path)%20analysis%20requires%20the%20dual%20graph%2C%20since%20angular%20distances%20are%20tracked%20from%20street%20to%20street.%20Metric%20(shortest-path)%20analysis%20can%20also%20be%20run%20on%20the%20primal%20graph%20if%20preferred.%0A%0A%20%20%20%20%3E%20**Note%3A**%0A%20%20%20%20%3E%20The%20high-level%20%5B%60CityNetwork%60%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Fapi%2Fnetwork)%20class%20builds%20the%20dual%20graph%20automatically.%20The%20manual%20conversion%20shown%20here%20applies%20when%20working%20with%20the%20lower-level%20%60networkx%60%20based%20API.%0A%0A%20%20%20%20Network%20data%20%C2%A9%20%5BOpenStreetMap%5D(https%3A%2F%2Fwww.openstreetmap.org%2Fcopyright)%20contributors%2C%20available%20under%20the%20Open%20Database%20Licence.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20from%20cityseer.tools%20import%20graphs%2C%20io%2C%20plot%0A%0A%20%20%20%20return%20graphs%2C%20io%2C%20plot%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20First%2C%20create%20a%20primal%20graph%20as%20before.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(io%2C%20plot)%3A%0A%20%20%20%20lng%2C%20lat%20%3D%20-0.13396079424572427%2C%2051.51371088849723%0A%20%20%20%20buffer%20%3D%20500%0A%20%20%20%20poly_wgs%2C%20epsg_code%20%3D%20io.buffered_point_poly(lng%2C%20lat%2C%20buffer)%0A%20%20%20%20G%20%3D%20io.osm_graph_from_poly(poly_wgs)%0A%20%20%20%20print(G)%0A%20%20%20%20plot.plot_nx(G%2C%20plot_geoms%3DTrue)%0A%20%20%20%20return%20(G%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20A%20dual%20graph%20representation%20can%20then%20be%20created%20using%20the%20%5B%60nx_to_dual%60%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Ftools%2Fgraphs%23nx-to-dual)%20function%20available%20from%20the%20%60cityseer%60%20package's%20%60graphs%60%20module.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(G%2C%20graphs)%3A%0A%20%20%20%20G_dual%20%3D%20graphs.nx_to_dual(G)%0A%20%20%20%20print(G_dual)%0A%20%20%20%20return%20(G_dual%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Notice%20that%20the%20dual%20graph%20will%20have%20the%20same%20number%20of%20nodes%20as%20the%20primal%20graph's%20number%20of%20edges%2C%20since%20the%20edges%20have%20been%20converted%20to%20nodes.%20The%20new%20edges%20are%20created%20by%20splitting%20the%20original%20edges%20at%20their%20midpoints%2C%20and%20then%20welding%20corresponding%20segments%20together%20across%20intersections.%20True%20representations%20of%20street%20geometries%20are%20therefore%20preserved%20in%20the%20dual%20graph%2C%20allowing%20for%20accurate%20calculations%20of%20metric%20distances%20and%20angular%20deviation.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(G_dual%2C%20plot)%3A%0A%20%20%20%20plot.plot_nx(G_dual%2C%20plot_geoms%3DTrue)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Conclusion%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20This%20notebook%20demonstrated%20how%20to%20convert%20a%20primal%20street%20network%20graph%20into%20its%20dual%20representation%20using%20%60nx_to_dual%60.%20In%20the%20dual%20graph%2C%20edges%20become%20nodes%20and%20new%20edges%20are%20formed%20by%20splitting%20and%20welding%20geometries%20across%20intersections%2C%20preserving%20accurate%20street%20geometries%20for%20metric%20and%20angular%20distance%20calculations.%20The%20dual%20representation%20is%20especially%20useful%20for%20visualising%20street-level%20centrality%20results.%0A%0A%20%20%20%20To%20continue%20into%20analysis%2C%20hand%20the%20*primal*%20graph%20to%20the%20high-level%20API%20with%20%5B%60CityNetwork.from_nx%60%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Fapi%2Fnetwork%23from_nx)%3A%20it%20performs%20this%20dual%20conversion%20automatically%20and%20exposes%20the%20centrality%20and%20land-use%20methods.%0A%0A%20%20%20%20**Next%20steps%3A**%20The%20dual%20representation%20is%20recommended%20for%20centrality%20analysis%3B%20see%20%5BMetric%20Centrality%5D(https%3A%2F%2Fcityseer.benchmarkurbanism.com%2Fexamples%2Fcentrality%2Fgpd-metric-centrality).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
b4c1d7182daa2ccbd2350a16c251a088