这可能会也可能不会很清楚,如果我不在基础上,或者您需要更多信息,请给我留言。也许已经有了解决方案,我已经想要用PHP了。
我正在寻找一个能够增加或减去经度OR纬度值的距离的函数。
原因:我有一个包含所有纬度和经度的数据库,并希望形成一个查询来提取X公里(或英里)内的所有城市。我的查询看起来像这样......
Select * From Cities Where (Longitude > X1 and Longitude < X2) And (Latitude > Y1 and Latitude < Y2)
Where X1 = Longitude - (distance)
Where X2 = Longitude + (distance)
Where Y1 = Latitude - (distance)
Where Y2 = Latitude + (distance)
我在PHP中工作,使用MySql数据库。
也可以打开任何建议! :)
答案 0 :(得分:17)
这是一个MySQL查询,可以完全按照您的意愿执行。请记住这样的事情一般是近似值,因为地球不是完美的球形,也不考虑山脉,山丘,山谷等。我们在AcademicHomes.com上使用PHP和MySQL的代码,它返回记录在$ latitude里面,$纬度,$经度。
$res = mysql_query("SELECT
*
FROM
your_table
WHERE
(
(69.1 * (latitude - " . $latitude . ")) *
(69.1 * (latitude - " . $latitude . "))
) + (
(69.1 * (longitude - " . $longitude . ") * COS(" . $latitude . " / 57.3)) *
(69.1 * (longitude - " . $longitude . ") * COS(" . $latitude . " / 57.3))
) < " . pow($radius, 2) . "
ORDER BY
(
(69.1 * (latitude - " . $latitude . ")) *
(69.1 * (latitude - " . $latitude . "))
) + (
(69.1 * (longitude - " . $longitude . ") * COS(" . $latitude . " / 57.3)) *
(69.1 * (longitude - " . $longitude . ") * COS(" . $latitude . " / 57.3))
) ASC");
答案 1 :(得分:3)
编辑:如果你在某个地方有一张世界上所有城市的列表以及他们的lat。而且很长。值,你可以做一个查找。在这种情况下,请参阅下面的第一个链接,了解在纬度计算一个纵向度的宽度的公式:
老实说,这个问题背后的复杂性使得您使用Google Maps等服务来获取数据要好得多。具体来说,地球不是一个完美的球体,两度之间的距离随着距离赤道越来越近而变化。
请参阅http://en.wikipedia.org/wiki/Geographic_coordinate_system了解我的意思,并查看the Google Maps API。
答案 2 :(得分:1)
根据您所包含的城市数量,您可以预先计算列表。我们这里为内部应用程序执行此操作,其中+ 100m的不准确度对我们的设置来说太多了。它通过具有location1,location2,distance的两个关键表来工作。然后我们可以非常快速地从位置1拉回位置x距离。
此外,由于计算可以离线完成,因此不会影响系统的运行。用户也可以获得更快的结果。
答案 3 :(得分:1)
我尝试使用上面的代码,当点之间的距离在20-30英里的范围内时,答案太多了,而且我没有几英里的错误。与我的一个测绘伙伴交谈,我们想出了这个。代码是python,但你可以很容易地翻译它。为了避免不断转换为弧度,我重新编写了数据库,将lat / lng点从度数转换为Radians。关于这一点的好处是,数学的最大部分大部分都是完成一次。
ra = 3963.1906 # radius @ equator in miles, change to km if you want distance in km
rb = 3949.90275 # radius @ poles in miles, change to km if you want distance in km
ra2 = ra * ra
rb2 = rb * rb
phi = self.lat
big_ol_constant = (math.pow(ra2*math.cos(phi), 2) + pow(rb2*math.sin(phi), 2))/ (pow(ra*math.cos(phi), 2) + pow(rb*math.sin(phi), 2))
sqlWhere = "%(distance)g > sqrt((power(lat - %(lat)g,2) + power(lng-%(lng)g,2)) * %(big_ol_constant)g)" % {
'big_ol_constant': big_ol_constant, 'lat': self.lat, 'lng': self.lng, 'distance': distance}
# This is the Django portion of it, where the ORM kicks in. sqlWhere is what you would put after the WHERE part of your SQL Query.
qs = ZipData.objects.extra(where=[sqlWhere]);
当距离很小时似乎非常准确,并且距离增加到200英里之内10英里左右(当然,到那时,你会遇到“像乌鸦飞行”和“铺砌道路”的问题)
以上是我在上面提到的模型ZipData。
class ZipData(models.Model):
zipcode = ZipCodeField(null=False, blank=False, verbose_name="ZipCode", primary_key=True)
city = models.CharField(max_length=32, null=False, blank=False)
state = models.CharField(max_length=2)
lat = models.FloatField(null=False, blank=False)
lng = models.FloatField(null=False, blank=False)
另外需要注意的是,您可以在GeoNames.org获得大量与邮政编码相关的地理数据,他们甚至还可以使用一些网络服务API。
答案 4 :(得分:0)
有很多(糟糕的选择)
使用数学公式(处理X1-X2和Y1-Y2)作为向量计算距离。
使用所有组合预先创建查找表并保持距离。
考虑使用MySQL的特定于GIS的扩展。这是one article我发现了这个。
答案 5 :(得分:0)
lessthandot.com实际上有3种不同的方法来做到这一点。你必须滚动浏览博客,但他们在那里。 http://blogs.lessthandot.com/
答案 6 :(得分:0)
以下函数来自nerddinner(ASP.NET MVC示例应用程序available on codeplex)数据库(MSSQL)。
ALTER FUNCTION [dbo].[DistanceBetween] (@Lat1 as real,
@Long1 as real, @Lat2 as real, @Long2 as real)
RETURNS real
AS
BEGIN
DECLARE @dLat1InRad as float(53);
SET @dLat1InRad = @Lat1 * (PI()/180.0);
DECLARE @dLong1InRad as float(53);
SET @dLong1InRad = @Long1 * (PI()/180.0);
DECLARE @dLat2InRad as float(53);
SET @dLat2InRad = @Lat2 * (PI()/180.0);
DECLARE @dLong2InRad as float(53);
SET @dLong2InRad = @Long2 * (PI()/180.0);
DECLARE @dLongitude as float(53);
SET @dLongitude = @dLong2InRad - @dLong1InRad;
DECLARE @dLatitude as float(53);
SET @dLatitude = @dLat2InRad - @dLat1InRad;
/* Intermediate result a. */
DECLARE @a as float(53);
SET @a = SQUARE (SIN (@dLatitude / 2.0)) + COS (@dLat1InRad)
* COS (@dLat2InRad)
* SQUARE(SIN (@dLongitude / 2.0));
/* Intermediate result c (great circle distance in Radians). */
DECLARE @c as real;
SET @c = 2.0 * ATN2 (SQRT (@a), SQRT (1.0 - @a));
DECLARE @kEarthRadius as real;
/* SET kEarthRadius = 3956.0 miles */
SET @kEarthRadius = 6376.5; /* kms */
DECLARE @dDistance as real;
SET @dDistance = @kEarthRadius * @c;
return (@dDistance);
END
我猜这可能会有所帮助。
答案 7 :(得分:0)
你可以使用毕达哥拉斯定理来计算两对纬度/经度点的接近程度。
如果您有两个位置(Alpha和Beta),您可以通过以下方式计算它们之间的距离:
SQRT( POW(Alpha_lat - Beta_lat,2) + POW(Alpha_lon - Beta_lon,2) )
答案 8 :(得分:0)
使用以下网址中的设置,我在下面构建了查询。 (请注意我使用codeIgnitor查询数据库)
http://howto-use-mysql-spatial-ext.blogspot.com/2007/11/using-circular-area-selection.html
function getRadius($point="POINT(-29.8368 30.9096)", $radius=2)
{
$km = 0.009;
$center = "GeomFromText('$point')";
$radius = $radius*$km;
$bbox = "CONCAT('POLYGON((',
X($center) - $radius, ' ', Y($center) - $radius, ',',
X($center) + $radius, ' ', Y($center) - $radius, ',',
X($center) + $radius, ' ', Y($center) + $radius, ',',
X($center) - $radius, ' ', Y($center) + $radius, ',',
X($center) - $radius, ' ', Y($center) - $radius, '
))')";
$query = $this->db->query("
SELECT id, AsText(latLng) AS latLng, (SQRT(POW( ABS( X(latLng) - X({$center})), 2) + POW( ABS(Y(latLng) - Y({$center})), 2 )))/0.009 AS distance
FROM crime_listing
WHERE Intersects( latLng, GeomFromText($bbox) )
AND SQRT(POW( ABS( X(latLng) - X({$center})), 2) + POW( ABS(Y(latLng) - Y({$center})), 2 )) < $radius
ORDER BY distance
");
if($query->num_rows()>0){
return($query->result());
}else{
return false;
}
}
答案 9 :(得分:0)
不要重新发明轮子。这是一个空间查询。使用MySQL's built-in spatial extensions将纬度 - 经度坐标数据存储在native MySQL geometry column type中。然后使用Distance函数查询彼此指定距离内的点。
免责声明:这是基于阅读文档,我自己没有尝试过。