Všimněte si, že při použití lon-lat, jsou vaše čehož vyplývá, zeměkoule nějakého druhu, a že množina bodů popisuje dva možné sférické mnohoúhelníky na povrchu spehre. Tady předpokládám, že chceš menší. Pokud si objednáte bodů ve směru hodinových ručiček, pak můžete použít postup popsaný zde pomocí lineární algebry.
Toto vezme v úvahu podmínky, kde jste obeplutí tyč nebo antimeridian, a vypadá to na velké kruhy spojující body (úsečka spojující (000, 45) a (100, 45) ano ne následovat 45 ° paralelní. Takže, myslím, že pečlivě o tom, co máte na mysli tím, že na náměstí jako čtverce (tak, jak jsme normálně přemýšlet o nich) nemají závěs na kouli.
V závislosti na aplikaci, Jeremyho odpověď by mohla být dostačující, ale v některých případech to nemusí být.
Přístup naznačuji níže, je založen na odpověď na otázku, na kterou jsem se ptal tady, který vysvětluje matematiku, co jsem prováděcích zde.
Nejprve budete muset převést své body na vektory (můžete použít koule jednotky)
import numpy as np
def deg2rad(theta):
return(theta * np.pi / 180)
def get_xyz(p):
lon = deg2rad(p[0])
lat = deg2rad(p[1])
return(np.array([np.cos(lat) * np.cos(lon),
np.cos(lat) * np.sin(lon),
np.sin(lat)]))
Takže pro vaše čtyři body vytvořit čtyři vektory popisující umístění v kartézských souřadnicích. Například,
p1 = [ 170, -10]
p2 = [-170, -10]
p3 = [-170, 10]
p4 = [ 170, 10]
v1 = get_xyz(p1)
v2 = get_xyz(p2)
v3 = get_xyz(p3)
v4 = get_xyz(p4)
Každá strana mnohoúhelník je část velké kružnice a vektor kolmý k rovině, je n1 = np.cross(v1, v2)
atd.:
n1 = np.cross(v1, v2)
n2 = np.cross(v2, v3)
n3 = np.cross(v3, v4)
n4 = np.cross(v4, v1)
Pokud nějaký bod v5 je uvnitř polygonu popsal v1, v2, v3, v4, pak skalární součin v5 s každou n-vektory bude větší než 1. (Pokud je na okraji jedné ze stran, pak se to bude rovnat 1.)
p5 = [180, 0]
v5 = get_xyz(p5)
in_poly = (np.dot(v5, n1)) > 0 and \
(np.dot(v5, n2)) > 0 and \
(np.dot(v5, n3)) > 0 and \
(np.dot(v5, n4)) > 0
print(in_poly) # True
p5 = [180, 20]
v5 = get_xyz(p5)
in_poly = (np.dot(v5, n1)) > 0 and \
(np.dot(v5, n2)) > 0 and \
(np.dot(v5, n3)) > 0 and \
(np.dot(v5, n4)) > 0
print(in_poly) # False
EDIT:
Dnes ráno mi došlo, že jsem nevysvětlil, jak na bin data. Dávám si to ve slovníku, ale tady si můžete vytvořit sloupce v datovém udělat něco podobného. Také, není to můj grid boxy musí být konvexní (ne pacman tvary) a rohy vašeho bodu mřížky musí být poskytnuty v proti-směru hodinových ručiček.
def in_poly(poly, point):
v_vec = [get_xyz(p) for p in poly]
n_vec = [np.cross(v_vec[i], v_vec[(i+1)%len(v_vec)]) for i in range(len(v_vec))]
v_p = get_xyz(point)
dot_prod = [np.dot(n, v_p) for n in n_vec]
if all(d > 0 for d in dot_prod):
return True
else:
return False
p1 = [ 170, -10]
p2 = [-170, -10]
p3 = [-170, 10]
p4 = [ 170, 10]
p5 = [ 150, -10]
p6 = [ 150, 10]
P = {1: [p1, p2, p3, p4],
2: [p1, p4, p6, p5]}
InBox = {1: 0, 2: 0}
Npts = 100
lonlim = [150, 190]
latlim = [-20, 20]
points = np.stack([np.random.randint(lonlim[0], lonlim[1], Npts),
np.random.randint(latlim[0], latlim[1], Npts)])
for i in range(Npts):
for key in InBox.keys():
if in_poly(P[key], points[:,i]):
InBox[key] += 1
print(InBox)
#{1: 25, 2: 22}