mysql空间扩展,使用MySQL空间扩展在圆内选择点

I have a table called flags that contains a column called coordinates that is full of MySQL 'points'. I need to perform a query where I get all the flags within a circle based on a latitude and longitude position with 100m radius.

From a usage point of view this is based around the user's position. For example, the mobile phone would give the user's latitude and longitude position and then pass it to this part of the API. It's then up to the API to create an invisible circle around the user with a radius of 100 metres and then return the flags that are in this circle.

It's this part of the API I'm not sure how to create as I'm unsure how to use SQL to create this invisible circle and select points only within this radius.

Is this possible? Is there a MySQL spatial function that will help me do this?

I believe the Buffer() function can do this but I can't find any documentation as to how to use it (eg example SQL). Ideally I need an answer that shows me how to use this function or the closest to it. Where I'm storing these coordinates as geospatial points I should be using a geospatial function to do what I'm asking to maximize efficiency.

Flags table:

id

coordinates

name

Example row:

1 | [GEOMETRY - 25B] | Tenacy AB

For the flags table I have latitude, longitude positions and easting and northing (UTM)

The user's location is just standard latitude/longitude but I have a library that can conver this position to UTM

解决方案

There are no geospatial extension functions in MySQL supporting latitude / longitude distance computations. There is as of MySQL 5.7.

You're asking for proximity circles on the surface of the earth. You mention in your question that you have lat/long values for each row in your flags table, and also universal transverse Mercator (UTM) projected values in one of several different UTM zones. If I remember my UK Ordnance Survey maps correctly, UTM is useful for locating items on those maps.

It's a simple matter to compute the distance between two points in the same zone in UTM: the Cartesian distance does the trick. But, when points are in different zones, that computation doesn't work.

Accordingly, for the application described in your question, it's necessary to use the Great Circle Distance, which is computed using the haversine or another suitable formula.

MySQL, augmented with geospatial extensions, supports a way to represent various planar shapes (points, polylines, polygons, and so forth) as geometrical primitives. MySQL 5.6 implements an undocumented distance function st_distance(p1, p2). However, this function returns Cartesian distances. So it's entirely unsuitable for latitude and longitude based computations. At temperate latitudes a degree of latitude subtends almost twice as much surface distance (north-south) as a degree of longitude(east-west), because the latitude lines grow closer together nearer the poles.

So, a circular proximity formula needs to use genuine latitude and longitude.

In your application, you can find all the flags points within ten statute miles of a given latpoint,longpoint with a query like this:

SELECT id, coordinates, name, r,

units * DEGREES( ACOS(

COS(RADIANS(latpoint))

* COS(RADIANS(X(coordinates)))

* COS(RADIANS(longpoint) - RADIANS(Y(coordinates)))

+ SIN(RADIANS(latpoint))

* SIN(RADIANS(X(coordinates))))) AS distance

FROM flags

JOIN (

SELECT 42.81 AS latpoint, -70.81 AS longpoint,

10.0 AS r, 69.0 AS units

) AS p ON (1=1)

WHERE MbrContains(GeomFromText (

CONCAT('LINESTRING(',

latpoint-(r/units),' ',

longpoint-(r /(units* COS(RADIANS(latpoint)))),

',',

latpoint+(r/units) ,' ',

longpoint+(r /(units * COS(RADIANS(latpoint)))),

')')), coordinates)

If you want to search for points within 20 km, change this line of the query

20.0 AS r, 69.0 AS units

to this, for example

20.0 AS r, 111.045 AS units

r is the radius in which you want to search. units are the distance units (miles, km, furlongs, whatever you want) per degree of latitude on the surface of the earth.

This query uses a bounding lat/long along with MbrContains to exclude points that are definitely too far from your starting point, then uses the great circle distance formula to generate the distances for the remaining points. An explanation of all this can be found here. If your table uses the MyISAM access method and has a spatial index, MbrContains will exploit that index to get you fast searching.

Finally, the query above selects all the points within the rectangle. To narrow that down to only the points in the circle, and order them by proximity, wrap the query up like this:

SELECT id, coordinates, name

FROM (

/* the query above, paste it in here */

) AS d

WHERE d.distance <= d.r

ORDER BY d.distance ASC

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值