好的 - 我已经花了大约3个月的时间,在这期间一直在努力解决问题。由于我已经尽可能使用了各种地理接近度公式,但仍然没有得到正确的结果,因此我认为是时候寻求帮助了。
目标
我正在设置一个相当基本的店铺定位实现。用户输入他们的邮政编码并从预定义的搜索半径列表中进行选择。gmaps API 为此地址生成纬度/经度坐标,并将它们传递给php脚本。在这个脚本中,用户坐标被查询与mysql数据库表(结构如下)进行比较。
post_id int(11)
post_type varchar(20)
lat float(10,6)
lng float(10,6)
这个查询的结果(文章id)被输入到一个WordPress查询中,生成包含地图标记数据的XML。(WordPress查询使用post__in和posts_per_page -1来显示由查询生成的所有ID的信息)
问题在于,我找到的Haversine公式的每个实现似乎都会导致缺少标记,特别是任何距离用户输入坐标非常接近的标记(不确定但我认为在大约500米内)。这是一个很大的问题,因为如果用户输入他们的邮政编码,并且有一家商店非常靠近他们的位置,它将不会显示出来。
我尝试了各种不同的公式排列组合,从各种教程中挖掘出来,但结果都相同。下面是我目前在网站上使用的公式,它提供了除那些非常接近用户输入位置的标记之外的所有标记:
$center_lat = $_GET["lat"];
$center_lng = $_GET["lng"];
$radius = $_GET["radius"];
// Calculate square radius search
$lat1 = (float) $center_lat - ( (int) $radius / 69 );
$lat2 = (float) $center_lat + ( (int) $radius / 69 );
$lng1 = (float) $center_lng - (int) $radius / abs( cos( deg2rad( (float) $center_lat ) ) * 69 );
$lng2 = (float) $center_lng + (int) $radius / abs( cos( deg2rad( (float) $center_lat ) ) * 69 );
$sqlsquareradius = "
SELECT
post_id, lat, lng
FROM
wp_geodatastore
WHERE
lat BETWEEN ".$lat1." AND ".$lat2."
AND
lng BETWEEN ".$lng1." AND ".$lng2."
"; // End $sqlsquareradius
// Create sql for circle radius check
$sqlcircleradius = "
SELECT
t.post_id,
3956 * 2 * ASIN(
SQRT(
POWER(
SIN(
( ".(float) $center_lat." - abs(t.lat) ) * pi() / 180 / 2
), 2
) + COS(
".(float) $center_lat." * pi() / 180
) * COS(
abs(t.lat) * pi() / 180
) * POWER(
SIN(
( ".(float) $center_lng." - t.lng ) * pi() / 180 / 2
), 2
)
)
) AS distance
FROM
(".$sqlsquareradius.") AS t
HAVING
distance <= ".(int) $radius."
ORDER BY distance
"; // End $sqlcircleradius
$result = mysql_query($sqlcircleradius);
$row = mysql_fetch_array( $result );
while($row = mysql_fetch_array( $result )) {
// the contents of each row
$post_ids[] = $row['post_id'];
}
我尝试了Mike Pelley在这里建议的1个公式:Geolocation SQL query not finding exact location
这个公式似乎显示了非常接近用户输入位置的标记,但错过了其他应该在给定半径内显示的标记。为了消除任何困惑,这是我使用的代码:
$center_lat = $_GET["lat"];
$center_lng = $_GET["lng"];
$radius = $_GET["radius"];
$sql = "
SELECT post_id, lat, lng,
truncate((degrees(acos( sin(radians(lat))
* sin(radians(".$center_lat."))
+ cos(radians(lat))
* cos(radians(".$center_lat."))
* cos(radians(".$center_lng." - lng) ) ) )
* 69.09*1.6),1) as distance
FROM wp_geodatastore HAVING distance <= ".$radius." ORDER BY distance desc
"; // End $sqlcircleradius
$result = mysql_query($sql);
$row = mysql_fetch_array( $result );
while($row = mysql_fetch_array( $result )) {
// Print out the contents of each row
$post_ids[] = $row['post_id'];
}
请求内容
基本上,我想知道为什么这些代码块都没有显示正确的标记。如果有人能提出对代码的改进意见或指向我可能错过的资源,那就太好了。
编辑
虽然我认为我的伪答案可以工作,但事实证明它仍然存在问题。现在我采用了非常不同的方法,使用一个非常好的jQuery商店定位器,可以在这里找到:http://www.bjornblog.com/web/jquery-store-locator-plugin
这并不适用于所有项目,但对于我的需求来说,它是完美的(而且有效!)
HAVING
(而不是WHERE
)似乎都会出现。int
这些东西可能不需要,但是我变得很沮丧,开始将可以从我找到的公式中剥离的东西留下来(无论如何都没有对结果产生任何影响)。我尝试了你的BETWEEN
/WHERE
建议,但恐怕它破坏了查询——请参见我下一个评论中所尝试的内容: - FourStacks