Im using the following to get all points from my hive datbase that are within 200m of my center.
SELECT * FROM mytable
WHERE ST_GeodesicLengthWGS84(ST_SetSRID(ST_LineString(array(ST_Point(longitude_of_center,
latitude_of_center),
ST_Point(longitude_of_point, latitude_of_point))), 4326)) <= 200;
Please, I need also is to get the distance between the choosen points and the center as part of my query result as a new colum DIST.
You can make a LineString from each chosen point paired with the center, then call GeodesicLengthWGS84 on each such LineString. It would be the same Length call as you have in the where clause, but also added to the column projections (so something like select *, ST_GeodesicLengthWGS834(...) from ....
(disclosure: collaborator on Esri Spatial Framework for Hadoop)
Related
I am trying to find all locations within a one mile radius of a specified point. I have longitude and latitude data for each point,
multi polygon geometry (Example :
MULTIPOLYGON(((2147312.63139525 161631.130590368,2147298.94808962 164286.665686698,2147623.79332922 164287.328517173,2149920.27996486 164292.162599235,2149944.29540875 161654.921437815,2147312.63139525 161631.130590368)))
and the_geom data
Example:
0106000020DA08000001000000010300000001000000060000003F8FD150F86140417EF6720BF9BA03412C005B79F16140412A8C5353F50D0441D7CF8BE593624041929CCDA0FA0D044177E3D52310674041E5D3004D210E044134F4CF251C67404106CA1A5FB7BB03413F8FD150F86140417EF6720BF9BA0341
I'm just not sure of the best way to approach finding all distances within one mile.
To query geometries within a given radius you have to use ST_DWithin:
SELECT * FROM t
WHERE
ST_DWithin(
the_geom::geography,
ST_MakePoint(longitude,latitude),1609.344); -- 1609.34 metres = 1 mile;
The geography cast enables you to search using metres as unit, which can be easily converted to miles.
Related post: Getting all Buildings in range of 5 miles from specified coordinates
I wanted to stop by and thank Jim Jones for your help! I wasn't able to end up to get the_geom to work, although this was probably user error. The link you shared did help me to come up with the fix below.
SELECT * FROM t where ST_DWithin('POINT($long $lat)'::geography, ST_MakePoint(longitude,latitude)::GEOGRAPHY, 1609.344);
I am creating a report that uses a Map. I have database of every city, their longitude, and latitude, and I use that to create a Spatial Location which I map onto a SSRS map.
99% of the data points seem right, but there are a few that appear to be in the ocean. Is there any way to get rid of these points? They cause my map to become small.
Maybe the best way is to just select the top 100 spatial points, instead of all.
Is that possible?
Can I change this expression to have it so it does top 100 spatial points by another field (customer value) or since my query is already sorted, should I just select the top 100? Does anyone know how to do that?
I downloaded the file italy.osm and import to postgresql with postgis.
So i try to extract latitude and longitude from the field "way" (geometry) of the table planet_osm_point, using the functions ST_X(), ST_Y() and these are the coordinates that I get as a result by querying a point in center of Milan City.
X: 1025988.29850153
Y: 5709056.87437553
I'm doing something wrong?
The data need to be projected to WGS84:
SELECT ST_Y(ST_Transform(way, 4326)) AS lat, ST_X(ST_Transform(way, 4326)) AS long
FROM planet_osm_point;
Don't install the spatial reference from spatialreference.org (which is srid=94326), as you should already have this when you spatially enabled the database. If srid=4326 wasn't already there, then there was a problem or skipped step when you spatially enabled the database.
I have an Oracle table 12K records/gyms, and the query below takes approximately ~0.3s:
SELECT (acos(sin(41.922682*0.017453293) *
sin(to_number(LATITUDE)*0.017453293) + cos(41.922682*0.017453293) *
cos(to_number(LATITUDE)*0.017453293) * cos(to_number(LONGITUDE)*0.017453293 -
(-87.65432*0.017453293)))*3959) as distance
FROM gym
However, I would like to return all of the records where distance <= 10, and as soon as I run the following query, my query execution time jumps up to ~5.0s:
SELECT * from (SELECT (acos(sin(41.922682*0.017453293) *
sin(to_number(LATITUDE)*0.017453293) + cos(41.922682*0.017453293) *
cos(to_number(LATITUDE)*0.017453293) * cos(to_number(LONGITUDE)*0.017453293 -
(-87.65432*0.017453293)))*3959)
as distance FROM gym)
WHERE distance <= 10
ORDER BY distance asc
Any idea how I can optimize this in Oracle?
Most important:
use a where clause to exclude all longitudes and latitudes that will be more than 10 km/miles (?) away from your point. So you only need to make your calculation for the window within a 10km/miles block.
as an and very rough approximation you could use 0.1 degree as a rule, this is 11km at the equator,and less elsewhere
so add
WHERE (longitude - -87.65)<0.1 and (latitude - 41.922)<0.1
(If you use nested queries, add this to the deepest level)
Since your distance is smaller than 10 km or mile, you can consider the length of one unit latitude/longitude as constant, and calculate them once using your formula. Than you can use pythagoras rule to calculate the distance (after adding the bounding box). This is basically why people usually use projected data for calculations.
Other things:
order by is always slow if you don't have an index. Do you need to order?
save your longitude and latitude as numbers in your table. Why would you store them different in a database?
With money. Specifically, Oracle Spatial.
1) How are you measuring 0.3 seconds for the first query? I'll wager that you are measuring the time required to fetch the first row rather than the time required to fetch the last row. Most client tools will start displaying results long before the database has finished producing them if that is possible (which it almost certainly is if there is no ORDER BY). So you're probably measuring the time required by the first query to calculate the distance to the first 50 or 500 gyms against the time required by the last query to calculate the distance to all 12,000 gyms.
2) Oracle Locator is a feature that comes with all editions of the Oracle database that includes the ability to use spatial indexes and that provides built-in methods for computing distance. It's not nearly as powerful as Oracle Spatial but it should be more than sufficient for what you're discussing here.
3) If you want to roll your own, I'd second johanvdw's suggestion of using a bounding box.
I have a table where each row is part of a New Zealand map. What I really want to know is is a point within the map (ie the country data) or is it in the water.
I understand how StIntersects works but all examples are for a single Polygon or LineString but I have a table of LineStrings - 130 rows that define the country border.
Lots of rows like this
LINESTRING (6252032.7308424888 -3161950.9615992079, 6252033.7275789445 -3161929.3581238855, 6252011.5227283547 -3161906.1086780191, 6251992.0438580718 -3161880.6299652755)
So I think I need to sort of put all the line strings together to make my country border a single polygon or something like that, but I do not know how to do that.
Can someone give me an example of how I could do this?
The original data was from a ShapeFile from www.koordinates.com called New Zealand Coastlines. I then used Shape2Sql to import to SQL Server using Planer Geometry.
Geometry (spheric) in Shape2File said "Data projects or extent is outside the bounds of what is supported by the SqlGeography type)
Hope I have provided enough information?
Cheers Chris
You have most likely moved on from this but I am posting for future use.
If I understand you correctly, you need to create one polygon from a table of LINESTRINGs that make up the boundary of the polygon?
First, combine all of the LINESTRINGs in your table into one geometry like this:
DECLARE #g geometry
SELECT TOP 1 #g = geom from #geom_tmp
SELECT
#g = #g.STUnion(geom)
FROM
#geom_tmp
SELECT #g
Then you want to create a polygon from your single-line boundary. There are only two things that differ between your single-line boundary string and a polygon, first we replace "LINESTRING" with "POLYGON". Then we add a set of parentheses since a polygon's WKT string separates multiple polygons with parentheses like this:
DECLARE #str NVARCHAR(max)
SET #str = REPLACE(REPLACE(#g.STAsText(),'(','((') + ')','LINESTRING','POLYGON')
SET #g = GEOMETRY::STGeomFromText(#str,0)
SELECT #g
Which will give you your polygon of the country.
Then you simply see if your point intersects the polygon (#p is the point geometry):
SELECT #p.STIntersects(#g)
-- OUTPUT is 1 if it intersects and 0 if it does not.
OR if your points are in a table, you could select the list of points that intersect the country as shown below if the point table geometry column is called "point".
SELECT *
FROM point_table
WHERE point.STIntersects(#g) = 1
Since there are many of us who cannot move to SQL server 2012 any time soon, this comes in handy. Hope it helps.
The classic approach to determine whether two points are on the same side (inside or outside) of a polygon, is to calculate the number of intersections between a line connecting the two and borders of the polygon. Even number (incl. 0) is same side, odd is different sides.
So define one (any) point which is inside New Zealand for sure (preferably near geometric middle), then a line that connects it with the point you want to check, then calculate the number of lines it intersects. If it's 0 or even, the other point is on the same side (that is in New Zealand.) If it's odd, the point is outside the country borders. You don't need to worry about ordering or connecting the border lines.
It becomes more tricky if the line crosses exactly through a joint point between two border lines, but StIntersects won't save you against that, and besides if you work on real values with 17 significant places, the likehood for this to occur is minimal.
The algorithm is good here in that it works for multiple disjoint polygons (isles) just as well as for single irregular polygon. The only requirement is all the lines are closed.
Of course to get that to work you'd have to transform linestrings into a set of single lines and store these, because you need to find number of intersections, not just fact: line intersects polygon (n times) vs 0 times.
Let me see if I understand your problem.
You wish to determine if a pre-determined point is either INSIDE NZ or OUTSIDE. Now, you have the coastline of NZ, right? This coastline is around 130 rows ... but we need to make this one single row .. and THEN see if the point lies inside this boundary or outside.
If this is correct, then the first thing you'll need to do is to join all the linestrings into a single massive polygon .. and we need this final single row as a Sql Server 2008 GEOGRAPHY type.
So - first some help. Jump over to Codeplex and grab this library - sql spatial tools. In this library, there is a method to JOIN all the linestrings. I think it's called GeographyUnionAggregate . Figure out how to run this stored proc which will join all the linestrings together (assuming none of them are messed up).
Once this task is done, you will have a single GEOGRAPHY row which repesents the entire coastline of NZ.
Now, it's a simple sql statement to see if the point exists/intersects the boundary (the country of NZ) or not :-
DECLARE #SomePoint GEOGRAPHY
SET #SomePoint = geography::STGeomFromText('POINT(-122.358 47.653)', 4326);
SELECT CountryId, Name
FROM Countries a
INNER JOIN a.AdministrativeBoundary.STIntersects(#SomePoint) = 1
And that should return you one result :)