Alvin1359
Alvin1359

Reputation: 19

Creating a list of nearby locations within a rectangular region around the selected location

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

Answers (1)

cards
cards

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 floatcasting 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

Related Questions