Reputation: 19
I am trying to create a list of locations around a selected point within a rectangular boundary. The dimensions of the boundary are provided by d1 and d2, where d1 extends the rectangle in the East-West direction and d2 extends the region in the North-South direction. For example, if the latitude and longitude of a location point L83 are given as (x,y), the search space will create a rectangle region where the coordinate of the North-East (NE), North-West (NW), South-West (SW), and SouthEast (SE) corners will be
NE = (x+d1, y+d2)
NW = (x-d1, y+d2)
SW = (x-d1, y-d2)
SE = (x+d1, y-d2)
Below is a snippet of the CSV data file:
LocId,Latitude,Longitude,Category
L1,4.5692,2.747,P
L2,2.2551,16.7944,H
L3,15.761,15.1464,R
L4,15.6516,5.1249,C
L5,6.0939,9.8601,S
L18,17.2331,18.7218,R
L47,16.3438,18.5479,H
L53,16.7774,17.4848,R
L83,16.9767,17.0477,R
L91,16.4508,18.9552,P
I have tried
querylocid = "L83"
d1=1.5
d2=2.2
infile = open(<CSV FILE NAME>, "r")
infile.readline()
for line in infile:
line = line.strip().split(",")
if line[0] == querylocid:
ne = (float(line[1])+d1, float(line[2])+d2)
nw = (float(line[1])-d1, float(line[2])+d2)
sw = (float(line[1])-d1, float(line[2])-d2)
se = (float(line[1])+d1, float(line[2])-d2)
# checking if location is within rectangle boundary
if float(line[1]) >= nw[0] and float(line[1]) <= ne[0] and float(line[2]) >= sw[1] and float(line[2]) <= nw[1]:
list.append(line[0])
print(list)
which only gives me
['L83']
The output I am looking for is
['L3', 'L18', 'L47', 'L53', 'L91']
I can probably guess that the problem is if line[0] == querylocid:, but I'm unsure as to how to specify the rectangle boundaries around the selected location if I don't have this line.
Upvotes: 0
Views: 397
Reputation: 4986
To find all locations with an overlapping rectangle you can compute the difference of them and check if it smaller than twice the distance [along the same direction (longitudinal/latitudinal)], i.e. abs(long1 -long2) < 2*d2
.
I used itertools.combinations
to find all possible pairings.
Warning: the string
to float
casting is based a cheap check: '.' in string
import itertools as it
geo = """L1,4.5692,2.747,P
L2,2.2551,16.7944,H
L3,15.761,15.1464,R
L4,15.6516,5.1249,C
L5,6.0939,9.8601,S
L18,17.2331,18.7218,R
L47,16.3438,18.5479,H
L53,16.7774,17.4848,R
L91,16.4508,18.9552,P"""
# data from string to dictionary + casting numbers to float!
geo_data = {}
attrs = ['LocId', 'Latitude', 'Longitude' ,'Category']
for line in geo.split('\n'):
attrs_values = [float(g) if '.' in g else g for g in line.split(',')]
geo_data[attrs_values[0]] = dict(zip(attrs[1:], attrs_values[1:]))
def is_in_interval(c1, c2, r):
"""c1, c2 are center of an interval with radius r, to have an intersection the maximum distance allowed is 2r"""
return abs(c2-c1) <= 2*r
# size of a single box
d1 = 1.5
d2 = 2.2
pairwise_overlapping_locations = []
for id1, id2 in it.combinations(geo_data, 2):
lat1 = geo_data[id1]['Latitude']
lat2 = geo_data[id2]['Latitude']
is_in_lat = is_in_interval(lat1, lat2, d1)
long1 = geo_data[id1]['Longitude']
long2 = geo_data[id2]['Longitude']
is_in_long = is_in_interval(long2, long1, d2)
if is_in_lat and is_in_long:
pairwise_overlapping_locations += [(id1, id2)]
print(pairwise_overlapping_locations)
print(set(it.chain(*pairwise_overlapping_locations)))
Output
[('L3', 'L18'), ('L3', 'L47'), ('L3', 'L53'), ('L3', 'L91'), ('L18', 'L47'), ('L18', 'L53'), ('L18', 'L91'), ('L47', 'L53'), ('L47', 'L91'), ('L53', 'L91')]
{'L91', 'L18', 'L47', 'L53', 'L3'}
Upvotes: 2