I need to calculate the amount of two oval intersects in a python program.
I know in shaply there is a function that return true if two object has intersects. As like as this:
from shapely.geometry import Polygon
p1=Polygon([(0,0),(1,1),(1,0)])
p2=Polygon([(0,1),(1,0),(1,1)])
print p1.intersects(p2)
is there any library or function That help me?
Thanks.
Is this what you are looking for? (the polygon that results from the intersection)
x = p1.intersection(p2)
x.area
Find more information in the documentation here
Related
There is a boundary inside China, which divide the region as North-South. I have drawn this boundary as a polyline format shapefile Download link.
I want to divide those points in the following figures into "North" and "South". Is there any useful function in Python can achieve this.
fiona has point.within function to test points within/out a polygon, but I have not searched a suitable function to divide multiple points by polyline.
Any advices or tips would be appreciated!
updated
According to the valuable suggestion made by Prune, I worked it out. The codes are provided as follows:
from shapely.geometry import shape
from shapely.geometry import LineString
# loading the boundary layer
import fiona
fname = './N-S_boundary.shp'
line1 = fiona.open(fname)
line1 = shape(line1.next()['geometry'])
# set a end point which is the southernmost for all stations.
end_point = (dy[dy['lat']==dy['lat'].min()]['lon'].values[0],dy[dy['lat']==dy['lat'].min()]['lat'].values[0])
# loop all monitoring stations for classification
dy['NS']= np.nan
for i in range(0,len(dy),1):
start_point = (dy['lon'].iloc[i],dy['lat'].iloc[i])
line2 = LineString([start_point, end_point])
if line1.intersection(line2).is_empty:
dy["NS"].iloc[i]='S'
else:
dy["NS"].iloc[i]='N'
color_dict= {'N':'steelblue','S':'r'}
dy['site_color']=dy['NS'].map(color_dict)
You can apply a simple property from topology.
First, make sure that your boundary partitions the universe (all available points you're dealing with). You may need to extend the boundary through the ocean to finish this.
Now, pick any reference point that is labeled as to the region -- to define "North" and "South", you must have at least one such point. w.l.o.g. assume it's a "South" point called Z.
Now, for each point A you want to classify, draw a continuous path (a straight one is usually easiest, but not required) from A to Z. Find the intersections of this path with the boundary. If you have an even quantity of intersections, then A is in the same class ("South") as Z; other wise, it's in the other class ("North").
Note that this requires a topological property of "partition" -- there are no tangents to the boundary line: if your path touches the boundary, it must cross completely.
I want to detect if given Geo coordinates fall into the route I will be tracing.
I am using shapely for this but that doesn't seems to be working correcly with Geo Coordinates.
Can you please explain what am I doing wrong here
Using snap_to_road google maps API I snap the route to get multiple GPS points along the route, then I create the LineString(coordinates) from it and used LineString.contains method to check if given point falls in the line
>>> from shapely.geometry import *
>>> coords = [(18.541658213425041,73.802487036668737),(18.541715999999997,73.8024635),(18.5417578,73.8024447),(18.5417578,73.8024447),(18.5417748,73.802437),(18.541841700000003,73.8023838),(18.541933099999998,73.8022613),(18.542033699999998,73.8021515),(18.542150000000003,73.802104)]
>>> line = LineString(coords)
>>> line.contains(Point(18.541933099999998,73.8022613))
True
>>> line.contains(Point(18.542077799999994,73.8021211))
False
Code to get multiple points across the route:
import urllib,json,requests
request = "https://roads.googleapis.com/v1/snapToRoads?path=18.5416582,73.802487|18.5462013,73.8025098|18.5536253,73.80331540000002\
&interpolate=true&key=<API KEY>"
response = urllib.urlopen(request).read()
print response
As per google maps this (18.542077799999994,73.8021211) point is a part of route these co-ordinates are following.
Then why does shapely failed to detect it ?
Does it has to do something with 2D and 3D geometry.
Edit:
Following two sites will help you to measure buffer value in meteres
http://www.longitudestore.com/how-big-is-one-gps-degree.html
https://www.rapidtables.com/convert/number/degrees-to-degrees-minutes-seconds.html
Use buffer method to dialate little bit. Increase the number 0.01 if you can allow more tolerance.
line.buffer(0.01).contains(Point(18.541933099999998,73.8022613))
I have a set of coordinates (x,y) and im trying to write a function that generates the centroid of them, so far I keep getting errors, here is the code I have so far:
def get_centroid(x,y):
centroid = (sum(x)/len(x),sum(y)/len(y))
x=[3,1,5,7,4,-2]
y=[0,-3,-3,1,5,2]
thank you for any help or suggestions.
Your approach will work, but just remember to return your result and be careful of dividing by zero with empty lists.
I have a a line segment AB (2d) from point A to point B. For the representation of a coastline (closed polygon, 3*10^3 vertices), I have a NumPy array (2d) of points which start and end at the same point. I want to know, if the connection between point A and B intersects the coastline.
My first approach was to iterate over each line segment of the closed polygon and check if it intersects with AB. Here is the underlying method.
Even if I do this working with NumPy arrays or translating the function with cython, it is not fast enough, because I have to do it a lot of times for different As and Bs.
I thought, this may be a conceptual problem and I was wondering, if there is a smarter way to check only, if at least one intersection exists (True/False)?
I tried to use shapely as well. But this was kind of slow.
from shapely.geometry import LineString
import numpy as np
coastline = LineString(np.dstack(x_values,y_values))
def intersection(A,B,Coastline):
AB = LineString([(A[0], A[1]), (B[0], B[1])])
if AB.intersection(coastline).is_empty:
return False
return True
This is a collision detection problem.
So in your case the best is to put your coastline inside one spatial datastrcture such as bsp-tree, quad-tree, aabb-tree, etc.
Then perform intersection between your line segment and the tree-structure.
See for instance CGAL AABB_tree:
https://doc.cgal.org/latest/AABB_tree/index.html
That library is for 3D but the same idea works for 2D. You can embedd almost any geometry inside aabbtree and query line intersection very fast
I have made a three way venn diagram. I have three issues with it that I can't seem to solve.
What is the code to move the circle labels (i.e."Set1","Set2","Set3") because right now one is too far away from the circle.
What is the code to make the circles be three equal sizes/change the circle size?
What is the code to move the circles around the plot. Right now, set2 is within set3 (but coloured differently), I would like the diagram to look more like the "standard" way of showing a venn diagram (i.e. 3 separate circles with some overlap in the middle).
On another note, I found it difficult to find what the commands such as "set_x", "set_alpha" should be; if anyone knew of a manual that would answer by above questions I would appreciate it, I couldn't seem to find one place with all the information I needed.
import sys
import numpy
import scipy
from matplotlib_venn import venn3,venn3_circles
from matplotlib import pyplot as plt
#Build three lists to make 3 way venn diagram with
list_line = lambda x: set([line.strip() for line in open(sys.argv[x])])
set1,set2,set3 = list_line(1),list_line(2),list_line(3)
#Make venn diagram
vd = venn3([set1,set2,set3],set_labels=("Set1","Set2","Set3"))
#Colours: get the HTML codes from the net
vd.get_patch_by_id("100").set_color("#FF8000")
vd.get_patch_by_id("001").set_color("#5858FA")
vd.get_patch_by_id("011").set_color("#01DF3A")
#Move the numbers in the circles
vd.get_label_by_id("100").set_x(-0.55)
vd.get_label_by_id("011").set_x(0.1)
#Strength of color, 2.0 is very strong.
vd.get_patch_by_id("100").set_alpha(0.8)
vd.get_patch_by_id("001").set_alpha(0.6)
vd.get_patch_by_id("011").set_alpha(0.8)
plt.title("Venn Diagram",fontsize=14)
plt.savefig("output",format="pdf")
What is the code to move the circle labels (i.e."Set1","Set2","Set3") because right now one is too far away from the circle.
Something like that:
lbl = vd.get_label_by_id("A")
x, y = lbl.get_position()
lbl.set_position((x+0.1, y-0.2)) # Or whatever
The "A", "B", and "C" are predefined identifiers, denoting the three sets.
What is the code to make the circles be three equal sizes/change the circle size?
If you do not want the circle/region sizes to correspond to your data (not necessarily a good idea), you can get an unweighted ("classical") Venn diagram using the function venn3_unweighted:
from matplotlib_venn import venn3_unweighted
venn3_unweighted(...same parameters you used in venn3...)
You can further cheat and tune the result by providing a subset_areas parameter to venn3_unweighted - this is a seven-element vector specifying the desired relative size of each region. In this case the diagram will be drawn as if the region areas were subset_areas, yet the numbers will be shown from the actual subsets. Try, for example:
venn3_unweighted(...., subset_areas=(10,1,1,1,1,1,1))
What is the code to move the circles around the plot.
The need to "move the circles around" is somewhat unusual - normally you would either want the circles to be positioned so that their intersection sizes correspond to your data, or use the "default" positioning. The functions venn3 and venn3_unweighted cater to those two requirements. Moving circles around arbitrarily is possible, but would require some lower-level coding and I'd advice against that.
I found it difficult to find what the commands such as "set_x", "set_alpha" should be
The object you get when you call v.get_label_by_id is a Matplotlib Text object. You can read about its methods and properties here. The object returned by v.get_patch_by_id is a PathPatch, look here and here for reference.