Find points where a polygon and the road network intersect - networkx

I want to find the intersecting points between a polygon and the road network and add them to the network as nodes.
import osmnx as ox
import folium
from shapely.geometry import Polygon
G = ox.graph_from_place('Lebanon, NH, USA', network_type='drive')
m1 = ox.plot_graph_folium(G, edge_color = "red")
polygon = Polygon([(-72.2460023,43.6225941), (-72.2547570,43.6063131),(-72.2329560,43.6007194),(-72.2272912,43.6136463),(-72.2460023,43.6225941)])
folium.GeoJson(data=polygon).add_to(m1)
The second part of what I seek to do can be accomplished in a pretty straightforward fashion - has previously been answered on Stack Overflow here.
I'm presuming I would have to get both the polygon and the road network as linestrings (perhaps by rounding the points in the line string to a number of significant digits) to find the common latitude and longitude points.
Here is an image of the points (encircled in black) I'd like to add to the network, as a minimalistic example.
The folium map is reproducible from the code above.
An alternative method that could also be useful in my case, is if I am able to say that there are two unconnected road network segments (in orange) within the polygon (might be more "unconnected" segments in some other road networks).
Thank you for your help in advance!

Related

Create circle around user inputted point and plot on map with custom latlon points

I have a question about if something is possible using Tableau.
I already have a coastline plotted on one map using custom LatLon coordinates and I would like to take a user inputted Lat and Lon and plot a circle around it with let's say radius 10 and display it on the same map.
I was using this tutorial before to plot a circle:
https://www.crowdanalytix.com/communityBlog/customers-within-n-miles-radius-analysis-using-tableau
But I don't think the same approach can work with user-inputted fields because then it would require restructuring the data..
Okay, a (much smarter LOL) coworker helped me figure this out....
So my goal was to graph distance band (like a distance of 5 miles around a coast) . In order to do this we can use the distance between two coastline points since they are connected by a line, not a curve...From there we can find the perpendicular point a certain distance away and connect those points. Much easier than my circle idea...

Extract constrained polygon using OSMnx

I'm playing around with OSMnx package in order to solve the following task:
- there is a point X on the map defined by latitude and longitude
- we need to detect a polygon that contains that point X and is constrained by the neighboring roads
- so basically the point X is inside the polygon and the neighboring roads will be borders of that polygon.
So far I've managed only to plot the visualization of the graph on the map and find the closest edge/node to point X.
In the attached image I've highlighted the area I want to extract in red.
As you are trying to find a polygon containing your point, you first need to generate polygons out of multilinestring geometry. As you did not provide your data I am downloading a sample from OSM using OSMnx.
import osmnx as ox
import geopandas as gpd
import shapely
point = (40.742623, -73.977857)
streets_graph = ox.graph_from_point(point, distance=500, network_type='drive')
streets_graph = ox.project_graph(streets_graph)
I have reprojected it as it is way more convenient than working with degrees, especially if you want to measure anything.
You then have to convert OSMnx graph to geopandas GeoDataFrame.
streets = ox.save_load.graph_to_gdfs(streets_graph, nodes=False, edges=True,
node_geometry=False, fill_edge_geometry=True)
To get some point I can work with, I'll just use the one in the centre of this geodataframe.
point = streets.unary_union.centroid
This is what it looks like.
Next you need to get polygons of your blocks defined by streets, using shapely.ops.polygonize as I suggested in the comment above and store them as GeoSeries.
polygons = shapely.ops.polygonize(streets.geometry)
polygons = gpd.GeoSeries(polygons)
The only thing you have to do next is to find which polygon contains your point.
target = polygons.loc[polygons.contains(point)]
Plotting it again:
ax = target.plot()
gpd.GeoSeries([point]).plot(ax=ax, color='r')
If you want to know which streets are forming the boundary of this polygon, just intersect it with the original network. I am filtering for MultiLineString to exclude streets which intersects the polygon only in one point.
target_streets = streets.loc[streets.intersection(target.iloc[0]).type == 'MultiLineString']
This is how the result of that looks like.
ax = target_streets2.plot()
gpd.GeoSeries([point]).plot(ax=ax, color='r')
Hope it helps.

Separating points/clusters with a line

Context: I want to create an interactive heatmap with areas separated by a ZIP code. I've found no way of displaying it directly (i.e. using Google Maps or OSM), so I want to create curves or lines that are separating those areas, and visualize it in maps.
I have a set of points, represented by their coordinates and their according class (ZIP code). I want to get a curve separating them. The problem is that these points are not linearly separable.
I tried to use softmax regression, but that doesn't work well with non-linearly separable classes. The only methods I know which are able to separate non-linearly are nearest neighbors and neural networks. But such classifiers only classify, they don't tell me the borders between classes.
Is there a way to get the borders somehow?
If you have a dense cloud of known points within each Zip code with coordinates [latitude. longitude, zip code], using machine learning to find the boundary enclosing those points sounds like overkill.
You could probably get a good approximation of the boundary by using computational geometry, e.g finding the 2D convex hull of each Zip code's set of points using the Matlab convhull function
K = convhull(X,Y)
The result K would be a vector of points enclosing the input X, Y vector of points, that could be used to draw a polygon.
The only complication would be what coordinate system to work in, you might need to do a bit of work going between (lat, lon) and map (x,y) coordinates. If you do not have the Matlab Mapping Toolbox, you could look at the third party library M_Map M_Map home page, which offers some of the same functionality.
Edit: If the cloud of points for Zip codes has a bounding region that is non convex, you may need a more general computational geometry technique to find a better approximation to the bounding region. Performing a Voronoi tesselation of the region, as suggested in the comments, is one such possibility.

Qgis how to distribute points inside a polygon

I´m new to QGIS, lately I got 2 Shapefiles one showing the polygons for some areas that represent street blocks, and another shapefile with the points that represent the number of comercial stores in the area, so sometimes we have one and others we have 90, depending on which street the survey was done.
The problem is that the points layer shows only one point where there should be more than one, that is because all points corresponding to a certain street or block are asigned the centroid of that polygon as coordinates. Is there a way to distribute all points automatically inside the polygons so if there is only one the points stays in the centroid and if there are more the points shift position in order to show how many points are exactly? Added a screencap for references

How to find closest points between two convex hull in MATLAB?

In part of an Artificial Neural Network matlab code, I want to find nearest points of two convex polygons.
I saw
dsearchn(X,T,XI)
command's description here, but that finds closest points between two sets of points, and polygons (like convexs) have infinites points.
So can you suggest any way/idea?
Notice: I'm using MATLAB 2014a. I have the coordinate of each convex's vertex point.
If you are not happy with what is provided by dsearchn, then, If I were you, I would do one of two following:
Find Nearest Neighbours on the vertices (for example which vertex of
polygon A is the NN of a given vertex of polygon B).
Pick a random point inside polygon A (you may want to compute the
convex hull of A, but you may skip that and take into account only
the vertices you know already). That random point is the query. Find
an NN of that point from the vertices of polygon B.
You may want to ask in Software recommendations for more.
Edit:
Another approach is this:
Create a representative dataset of polygon A. Set the size of the dataset yourself and fill it with samples of points that lie inside the polygon. Choose them uniformly randomly inside the polygon.
Then take a point of polygon B (either a vertex or a random point inside polygon B) and that's the query point, for which you will seek Nearest Neighbour(s) inside the representative dataset of polygon A.
Of course that's just an approximation, but I can't think of something else now.
Notice that you can of course do the same for polygon B.
With This File in File Exchange, I've find the solution.
With a little code modification, I have drawn a perpendicular bisector which I wanted. Of course, this way is time consuming.