Php 使用mysql查找矩形或圆形中的点

Php 使用mysql查找矩形或圆形中的点,php,mysql,geometry,cartesian,Php,Mysql,Geometry,Cartesian,我有一个mysql数据库表,其中列出了坐标(x,y)的点 我想找到矩形内的点列表。如果矩形的任何一侧平行或垂直于任何轴对齐,这将非常简单。但事实并非如此。这意味着矩形是旋转的。 我还要找到圆内的点 矩形的已知数据 -所有四个点的坐标 圆的已知数据 -中心和半径的坐标 如何查询mysql表以查找矩形和圆形中的点 如果有关系,那么我使用的前端是PHP。一个矩形可以由两个表示对角的点定义,例如:A(x,y)和B(x,y)。如果要测试点C(x,y)是否位于矩形内,则: IF( (Cx BETWEEN A

我有一个mysql数据库表,其中列出了坐标(x,y)的点

我想找到矩形内的点列表。如果矩形的任何一侧平行或垂直于任何轴对齐,这将非常简单。但事实并非如此。这意味着矩形是旋转的。 我还要找到圆内的点

矩形的已知数据 -所有四个点的坐标 圆的已知数据 -中心和半径的坐标

如何查询mysql表以查找矩形和圆形中的点


如果有关系,那么我使用的前端是PHP。

一个矩形可以由两个表示对角的点定义,例如:A(x,y)和B(x,y)。如果要测试点C(x,y)是否位于矩形内,则:

IF( (Cx BETWEEN Ax AND Bx) AND (Cy BETWEEN Ay AND By) ) THEN
  point C is in the rectangle defined by points A and B
ELSE
  nope
ENDIF
圆可以由单个点C(x,y)和半径R定义。如果中心和点p(x,y)之间的距离D小于半径R,则它位于圆内:

当然你还记得毕达哥拉斯的理论,对吧

C² = A² + B² SO C = SQRT(A² + B²)
因此:

假设包含x和y值的列被编入索引,这可能比简单地进行数学运算少占用几个CPU周期,但这是有争议的,我倾向于称之为wash

至于循环,你不可能比

WHERE
  SQRT( POW(ABS($Cx - x),2) + POW(ABS($Cy - y),2) ) < $radius
在哪里
SQRT(功率(ABS($Cx-x),2)+功率(ABS($Cy-y),2))<$radius

你太关心这些计算的感知成本了,只需编写代码并使其工作即可。这不是执行这种琐碎优化的阶段。

要补充@Sammitch的答案的一点是,如果你在世界地图上查看纬度和经度,计算哈弗斯线距离(在球面上计算距离,因为地球是球体;)

下面是一个用于计算的普通Javascript示例:

          function calculateHaversineDistance(lat1x, lon1, lat2x, lon2) {
            var R = 6371; // km
            var dLat = toRad(lat2x-lat1x);
            var dLon = toRad(lon2-lon1);
            var lat1 = toRad(lat1x);
            var lat2 = toRad(lat2x);
            var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                    Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
            var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
            return R * c;
          }
          function toRad(x) {
             return x * Math.PI / 180;
          }
编辑->

以下是我编写的php版本:

function toRad($x) {
 return $x * pi() / 180;
}

function calculateHaversineDistance($lat1, $lon1, $lat2, $lon2) {

    $R = 6371; // km
    $dLat = $this->toRad($lat2-$lat1);

    $dLon = $this->toRad($lon2-$lon1);

    $lat1 = $this->toRad($lat1);

    $lat2 = $this->toRad($lat2);


    $a = sin($dLat/2) * sin($dLat/2) +
            sin($dLon/2) * sin($dLon/2) * cos($lat1) * cos($lat2);

    $c = 2 * atan2(sqrt($a), sqrt(1-$a));

    return $R * $c;
}

我知道这些公式,但我需要知道的是,我可以编写一个存储过程或一个查询,通过它我可以传递已知的参数,并得到该区域内的点列表。这是否可能使用php+mysql。他的矩形显然是旋转的,因此您的inRectangle代码无法工作。必须旋转它,使其与Y轴垂直,这将是非常痛苦的。我不想调用所有点并分析每个点,因为点列表非常广泛。@Vishak,除非你想到的圆和矩形总是相同的,你可以预先计算并存储结果,否则,就没有可能的方法只是神奇地知道。您可能可以通过过滤掉距离任何测试点超过X个单位的点来减少实际处理的点数,其中X足够大,但这可能需要与实际处理它们一样多的数学运算,而这并不多。数学是计算机的全部工作,他们很擅长数学。谢谢。编辑有帮助。我的想法是一样的。我计划从矩形顶点获取max x、max y、min x和min y,以创建另一个围绕所需矩形的矩形,并获取主矩形内的所有点,然后仅在这些返回点上运行函数,消除其余点。通过具有四个条件的查询(max x、min x、min y和maxy),获取主矩形中的点将非常简单。对于一个圆,我想用同样的方法在它周围创建一个正方形。我不想调用所有的点并分析每个点,因为点的列表很广泛,可以用其他方法吗?
          function calculateHaversineDistance(lat1x, lon1, lat2x, lon2) {
            var R = 6371; // km
            var dLat = toRad(lat2x-lat1x);
            var dLon = toRad(lon2-lon1);
            var lat1 = toRad(lat1x);
            var lat2 = toRad(lat2x);
            var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                    Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
            var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
            return R * c;
          }
          function toRad(x) {
             return x * Math.PI / 180;
          }
function toRad($x) {
 return $x * pi() / 180;
}

function calculateHaversineDistance($lat1, $lon1, $lat2, $lon2) {

    $R = 6371; // km
    $dLat = $this->toRad($lat2-$lat1);

    $dLon = $this->toRad($lon2-$lon1);

    $lat1 = $this->toRad($lat1);

    $lat2 = $this->toRad($lat2);


    $a = sin($dLat/2) * sin($dLat/2) +
            sin($dLon/2) * sin($dLon/2) * cos($lat1) * cos($lat2);

    $c = 2 * atan2(sqrt($a), sqrt(1-$a));

    return $R * $c;
}