我正在与谷歌地图,确定输入的地址是一个预定义的服务区域的一部分,一个小应用程序。
用户输入一个地址,一个PHP脚本获取纬度/长从地理编码API和适用与一群坐标的组成区域(将KML文件中的地图生成拍摄)的顶点光线投射。
问题是这样的:它工作的大部分时间,但服务区域外的一些地址错误地报告为合格,而另一些区域内部是没有资格。 起初我以为这是一个精密的问题与谷歌地图,而是从地理编码服务的地址生成的坐标点上准确的。 它可能有一些做的公式。
这里是(它是基于关闭的代码,我在别处找到):
// $points is an array full of Point objects (the vertices), which contain lat/long variables
// $ctr is simply a counter that we will test to see if it's even/odd
for ($i = 0, $j = sizeof($points) - 1; $i < sizeof($points); $j = $i++) {
$p1 = $points[$i];
$p2 = $points[$j];
// $test_point is the lat/long pair of the user's address
if ($p1->lat < $test_point->lat && $p2->lat >= $test_point->lat || $p2->lat < $test_point->lat && $p1->lat >= $test_point->lat) {
if ($p1->long + ($test_point->lat - $p1->lat)/($p2->lat - $p1->lat)*($p2->long - $p1->long) < $test_point->long)
$ctr++;
}
}
有什么事,我在这里失踪? 我试图得出关于我自己的一个公式,我明白这背后的数学到一定程度,但它是确定使用GPS从谷歌地图的坐标与此?
似乎没有成为一个真正的模式,什么是错误报告:我测试的东西像接近服务区的角落边界或那些地址,但没有运气。 另外一些值得关注的是,该服务区仅在一个城市一个相对较小的区域,没有像国家或国家范围内的地区。
嗯....你的第二个,如果()不补偿的事实,任何删减的可能会导致一个负数; 如果坐标严格下令只会工作。
更新:在http://rosettacode.org/wiki/Ray-casting_algorithmn有在描述的过程进行了详细各种语言算法一大堆(不幸的是,没有任何版本的PHP)。 什么似乎是从您的解决方案缺少的是采摘有保证是多边形的某个点; 因为你所面对的经度/ lattitude这应该很容易。 二,请确保您的多边形被关闭(即从最后一个点回到第一,如果谷歌地图已经不这样做)
假设$points
阵列包含描述顺时针(或逆时针顺序)的覆盖区域的多边形的角落,你的代码看起来正确的给我。 基本上,它的票相交从给定的点到180度经线拉正东线多边形的边数。
我也许把它改写这个样子,只是为了清晰:
$p0 = end($points);
foreach ( $points as $p1 ) {
// ignore edges of constant latitude (yes, this is correct!)
if ( $p0->lat != $p1->lat ) {
// scale latitude of $test_point so that $p0 maps to 0 and $p1 to 1:
$interp = ($test_point->lat - $p0->lat) / ($p1->lat - $p0->lat);
// does the edge intersect the latitude of $test_point?
// (note: use >= and < to avoid double-counting exact endpoint hits)
if ( $interp >= 0 && $interp < 1 ) {
// longitude of the edge at the latitude of the test point:
// (could use fancy spherical interpolation here, but for small
// regions linear interpolation should be fine)
$long = $interp * $p1->long + (1 - $interp) * $p0->long;
// is the intersection east of the test point?
if ( $long < $test_point->long ) {
// if so, count it:
$ctr++;
}
}
}
$p0 = $p1;
}
请注意,此代码将在各种有趣的方式,如果区域边界穿过180度经线断,所以请您在太平洋中部有任何服务区不使用它。
如果您还有问题,请尝试绘制所描述的多边形$points
在地图上阵列; 你可能会发现,它并不像你想的那样,例如,如果一些点在错误的顺序列出。
没有与此算法,当光线相切形状的错误。 只是一个小量添加到测试点的纬度时,它可能会发生(的ILMARI的代码3号线):
if ($test_point->lat == $p0->lat)
$test_point->lat += 0.0000000001;
另见http://rosettacode.org/wiki/Ray-casting_algorithm (更正URL)。
谢谢。