Oracle SQL query or function to cluster geographic data - sql

I have a table containing geographic data and I want to group rows on the proximity of the X and Y coordinates. So, given an offset, n, and a table with columns X and Y, I want to group rows where ABS(row1.X - row2.X) < n, with a count of the number of rows in the group. Is this possible with SQL or do I need a function?

How big is your spatial range ? How big is your data set ? How accurate do you need ?
This is relevant because, if they are close, you don't have to worry about the curvature of the Earth.
Degrees of latitude are parallel so the distance between each degree remains almost constant but since degrees of longitude are farthest apart at the equator and converge at the poles, their distance varies greatly.
Each degree of latitude is approximately 69 miles (111 kilometers) apart. The range varies (due to the earth's slightly ellipsoid shape) from 68.703 miles (110.567 km) at the equator to 69.407 (111.699 km) at the poles. This is convenient because each minute (1/60th of a degree) is approximately one mile.
A degree of longitude is widest at the equator at 69.172 miles (111.321) and gradually shrinks to zero at the poles. At 40° north or south the distance between a degree of longitude is 53 miles (85 km).
The other aspect is, if Fred is 4 miles from Bill and Bill is 4 miles from Tom, the distance between Fred and Tom might be 8 miles. If your proximity threshold is 5 miles, Bill and Fred are in the same group, Bill and Tom are in the same group, but Fred and Tom aren't.
The following query might give you a useful start though:
select abs(abs(a.lat) - abs(b.lat)),abs(abs(a.lon) - abs(b.lon)),
sdo_geom.sdo_distance(a.geom, b.geom, 0.005,'unit=kilometer') dist_km
from
(select sdo_geometry(2001,8314,sdo_point_type(33,151, null), null,null) geom, 33 lat, 151 lon from dual) a,
(select sdo_geometry(2001,8314,sdo_point_type(34,151, null), null,null) geom, 34 lat, 151 lon from dual) b

Do you have oracle spatial? If so there are a number of built in functions to handle this for you. If not - you'll need a function to determine catographic distances (and then group off of that). I recall seing a SO question on how to write such a function last week. (There are actually a few along these lines)
How to limit a MySQL Distance Query
Best bet. Use the spatial extensions. They'll perform much better.

Related

Optimizong billboard placement

I have a table of a 18,000 billboards with an ID, latitude, longitude, Impacts(the amount of people that see the billboard in a month).
ID
Latitude
Longitude
Impacts
1
107.45
92.45
200,000
2
102.67
96.67
180,000
3
105.12
94.23
160,000
4
106.42
91.87
220,000
5
109.89
93.56
240,000
The idea is I want to build a model that optimizes for a maximum amount of impacts, keeping a minimum distance between each billboard, for an amount of billboards chosen by the user.
I can build a matrix with the linear distances of each billboard to all the others, so basically I have the value that I want to maximize which are the impacts, a distance matrix which has linear distances between each billboard which is a constraint and the amount of billboards to select which is another constraint.
does anyone know a sort of linear programming model that I could implement for this specific case?

Accuracy for points within distance of 5km

What are the precision characteristics of Google S2 for let’s say two indexed points which are within a radius of 5km? What kind of precision can I expect in mm for a query for these points?
It depends on the S2 level on which you've indexed these points. Not all cells on a given level are the same size, but on average they'll all be close.
For example, a level 30 cell (smallest level) is on average 74 mm^2, so it's very precise.
You can see a reference here.

GIS buffer value degree to meters with spatiallite

I am new to Spatialite. I have following query:
select A.*
from linka as A, pointa as B
where Contains(Buffer(B.Geometry, 100), A.Geometry)
I actually want to create 100 meters buffer and get to know which are the link's are contained by it.
I can able to find the inserted '100' is actually degree value and it's giving me output which are coming in this range.
I can put the degree value also in my query but the transformation from degree to meters/kilometers is not same all around the world.
I gone through many sites and able to know 1 degree = 110 KM approx.
but from GIS expert and some reference sites also get to know at each pole on earth it's different.
For instance, the difference at Alta/Norway between metrical x and y for planar approximation is 34 km in x direction equal 111 km in y direction. The buffer looks similar to this while using geographic coordinates:
http://extremelysatisfactorytotalitarianism.com/blog/wp-content/uploads/2010/08/tissot_indicatrix_equirectangular_proj.png
I build software which convert geographical data to geometrical (X, Y -coordinate format) data and make transformation where Spatiallite can understand.
I also trying to read regarding SRID things but not able to understand how to insert it into my query.
temporary transform your geometry to a metric projection (eg UTM)
if i assume your current projection is WGS84 try the following statment
transform (buffer (transform (B.geometry, #projection), #dist), 4326))
-in #projection: your new projection, eg: 32631 for WGS 84 / UTM zone 31N (choose the projection that fits your Zone)
-in #dist: distance in meters
(4326 for WGS84)
If You are using SQL server 2008 or later, You should be able to use spatial types
lets assume linka contains geography column, and its name is geo, and it contains Points
dont forget to create spatial index !
try this
DECLARE #buffer geography = geography::Point( 1.234, 5.678, 4326 );
DECLARE #distance float = 100.0;
SELECT * from linka
WHERE linka.geo.STDistance(#buffer) < #distance

CoreLocation - what do the latitude and longitude numbers actually represent

I have :
+37.785834 (lat)
-122.406417 (long)
The LAT positive means North of the equator
The LONG negative means to the West of 0
So far so good.
But what does the number represent exactly ? For example suppose I added 0.000001 to the LAT what would this actually represent ? That I have moved in some Northerly direction by 1 metre, for example or....
If I understand what these numbers actually represent then I can use them intelligently.
Longitude and latitude are measured in degrees. The latitude ranges from -90° (south pole) to +90° (north pole). The longitude ranges from -180° to +180°.

How can I create SQL Server Geography polygons that are of a specific size?

I want to create a group of polygons for a city that are 80km x 80km. Given a starting Lat and Long, my thought is I can add 80km to that point so that I get 4 points to create the polygon.
(x,y) -> (x+80km, y) -> (x+80km, y+80km) -> (x, y+80km) -> (x,y)
Where I'm having difficulty is finding a way to calculate the point +80km. I've found the SQL Server Spatial Tools and there is a function
SqlGeography LocateAlongGeog(SqlGeography g, double distance)
But so far I haven't been able to figure out how to use it. I will continue to play with this but if there are any other approaches I can take, or if anyone knows how to properly use this function, I'd be grateful.
Longitude is a "great circle" measure, i.e. if you draw a circle representing a particular longitude round the Earth, it's always a circle whose centre is the centre of the Earth - so to circumnavigate the Earth at a constant longitude, you always travel the same distance:
2 * PI * 6378 /* 6378 is the radius of the Earth in km */
So, moving North (i.e travelling along the same longitude) 80 km will increase your latitude by:
360 * 80 / (2 * PI * 6378)
Latitude is trickier cos the distance travelled when you circumnavigate the Earth at the same latitude changes depending on the latitude at which you're travelling: however, the formula is simple and I looked it up at: http://www.newton.dep.anl.gov/askasci/env99/env086.htm
2 * PI * 6378 * COS(LAT) /* where LAT is your Latitude */
So, if you are at latitude LAT, and move 80km East, you will increase your longitude by:
360 * 80 / (2 * PI * 6378 * COS(LAT))
Couple of things to note:
a) 6378 is only accurate to the nearest km
b) The East/West between your two Northerly points will not be precisely 80km - not significantly different for Latitudes between about 80 degrees North and 80 degrees South - as long as you're not looking for high-precision pinpoint accuracy (which I'm guessing with base measurements of 80 km you're not) it'll do just nicely (and point nicelt at Bing or Google, say)
c) SQL calculates trigonometry functions using radians not degrees - so in SQL your cosine will need to be:
COS(PI * LAT / 180)
HTH and makes some sort of sense