Reputation: 2352
I have some locations I want to store on a database, the locations are defined by 4 coordinates p1(lat,long), p2(lat,long), p3(lat,long) and p4(lat,long)
, the only characteristic is that they always form a rectangle.
Once a few locations are stored in the DB I want to be able to query it, giving it a point(lat, long) and check if this point is inside any of the boxes in the DB.
My first question is what's the best way to design this table to make it easier and efficient to query it later. My first guess is something like this:
| id | lat1 | lon1 | lat2 | lon2 | lat3 | lon3 | lat4 | lon4 |
--------------------------------------------------------------
But I'm not sure what the best query to get all the locations or single location that another point is inside. for example the database contains 2 locations (rows)
| id | lat1 | lon1 | lat2 | lon2 | lat3 | lon3 | lat4 | lon4 |
--------------------------------------------------------------
| 1 | 0 | 0 | 0 | 10 | 10 | 10 | 10 | 0 |
| 2 | 50 | 50 | 50 | 60 | 60 | 60 | 60 | 50 |
If I have the point (5,5) how can I query the DB to get row 1?
Upvotes: 0
Views: 2158
Reputation: 3669
Question 1: Are the rectangles horizontally aligned like your examples?
If they are, then it's enough to consider lat/long 1 and 3, for example, because you know that:
minLat = lat1
minLong = long1
maxLat = lat3
maxLong = long3
Question 2: Are lat and long 1 minor than lat and long 3 (are they ordered)?
If yes:
// You simply need to check that:
(lat1 <= latX <= lat3)
&& (long1 <= longX <= long3)
If not, you can previously check that lat1 <= lat3 and long1 <= long2 and switch them if needed.
Finally: If the answer to the question 1 was "not", then you can use the same principle, but first you need to apply some additional math. But, attending provided examples I suppose that it is not the case.
...anyway, If you are planning to check more complex cases (such as real -not only integers- coordinates) you probably should try using PostGIS...
Upvotes: 1
Reputation: 4503
You can use the least()
and greatest()
functions to get the min/max values for the x,y values (and maybe use these to construct two points and an enclosing rectangle)
CREATE TABLE latlon
( id INTEGER NOT NULL PRIMARY KEY
, lat1 INTEGER NOT NULL , lon1 INTEGER NOT NULL
, lat2 INTEGER NOT NULL , lon2 INTEGER NOT NULL
, lat3 INTEGER NOT NULL , lon3 INTEGER NOT NULL
, lat4 INTEGER NOT NULL , lon4 INTEGER NOT NULL
);
INSERT into LATLON ( id,lat1,lon1,lat2,lon2,lat3,lon3,lat4,lon4) VALUES
( 1 ,0 ,0 ,0 ,10 ,10 ,10 ,10 ,0 ),
( 2 ,50 ,50 ,50 ,60 ,60 ,60 ,60 ,50 );
SELECT id
, LEAST(lat1,lat2,lat3,lat4) AS MINLAT
, LEAST(lon1,lon2,lon3,lon4) AS MINLON
, GREATEST(lat1,lat2,lat3,lat4) AS MAXLAT
, GREATEST(lon1,lon2,lon3,lon4) AS MAXLON
FROM latlon;
Result:
CREATE TABLE
INSERT 0 2
id | minlat | minlon | maxlat | maxlon
----+--------+--------+--------+--------
1 | 0 | 0 | 10 | 10
2 | 50 | 50 | 60 | 60
(2 rows)
finding the (5,5) point:
SELECT * FROM (
SELECT id
, LEAST(lat1,lat2,lat3,lat4) AS minlat
, LEAST(lon1,lon2,lon3,lon4) AS minlon
, GREATEST(lat1,lat2,lat3,lat4) AS maxlat
, GREATEST(lon1,lon2,lon3,lon4) AS maxlon
FROM latlon
) rect
WHERE 5 >= rect.minlat AND 5 < rect.maxlat
AND 5 >= minlon AND 5 < rect.maxlon
;
Upvotes: 1