【问题标题】:Determine if two coordinates are within desired radius确定两个坐标是否在所需的半径内
【发布时间】:2019-07-04 02:14:44
【问题描述】:

我正在将我所在城市的主要大十字路口与我所在城市的碰撞数据汇总在一起。我试图完成的是确定在 20 米半径内的交叉路口及其周围发生的事故数量。

幸运的是,我的项目已经很遥远了,我的数据库中有两个表 intersectionscollisions

我的intersections表:

 --------------------------------------------
 |  id  |  city  |  Latitude  |  Longitude  |
 --------------------------------------------
 |  1   |   1    |   34.44444 |   84.3434   |
 --------------------------------------------
 |  2   |   1    | 42.4666667 | 1.4666667   |
 --------------------------------------------
 |  3   |   1    |  32.534167 | 66.078056   |
 --------------------------------------------
 |  4   |   1    |  36.948889 | 66.328611   |
 --------------------------------------------
 |  5   |   1    |  35.088056 | 69.046389   |
 --------------------------------------------
 |  6   |   1    |  36.083056 |   69.0525   |
 --------------------------------------------
 |  7   |   1    |  31.015833 | 61.860278   |
 --------------------------------------------

我的collisions表:

--------------------------------------------
 |  id  |  cause |  Latitude  |  Longitude  |
 --------------------------------------------
 |  1   |   1    |   44.44444 |   81.3434   |
 --------------------------------------------
 |  2   |   1    | 32.4666667 | 1.4666667   |
 --------------------------------------------
 |  3   |   1    |  42.534167 | 63.078056   |
 --------------------------------------------
 |  4   |   1    |  46.948889 | 62.328611   |
 --------------------------------------------
 |  5   |   1    |  45.088056 | 61.046389   |
 --------------------------------------------
 |  6   |   1    |  46.083056 |   63.0525   |
 --------------------------------------------
 |  7   |   1    |  41.015833 | 69.860278   |
 --------------------------------------------

注意:为简单起见省略了一些字段

如您所见,两个表都拥有latitudelongitude 字段。现在要确定 intersectioncollision 坐标是否接近,我想到了使用带有 id 的 MySQL 查询intersection,然后查询 collisions 表以获取 intersection 20 米内的所有碰撞。

这个查询是什么(在 MySQL 或 Sequelize 中)?

这是我现在拥有的(它在 Sequelize 中使用 MySQL 数据库)

// api/collisions/{intersection_id}/count

exports.intersection_accident_count = (req, res) => {
    intersection.findOne({where: {equipement: req.params.intersection_id}}).then(intersection => {

        let intersectionLongitude = intersection.longitude;
        let intersectionLatitude = intersection.latitude;

        collision.count({where: {
            longitude: {
                $gt: intersectionLongitude
            },
            latitude: {
                $gt: intersectionLatitude
            },
        }}).then(count => {
            res.status(200).json({'number_of_accidents': count});
        });
    });
};

【问题讨论】:

    标签: javascript mysql node.js express sequelize.js


    【解决方案1】:

    你应该从直接的方式开始:

    SELECT
        i.*
    FROM
        intersections AS i
        INNER JOIN collisions AS c ON (
            ST_Distance_Sphere(POINT(i.Longitude, i.Latitude), POINT(c.Longitude, c.Latitude)) < @dist
        )
    

    这应该会给你结果,但是查询根本不会使用任何索引,如果你有很多记录,它会很慢。

    您应该考虑在表中添加几何数据类型:

    ALTER TABLE `collisions` ADD COLUMN `Location` POINT;
    UPDATE `collisions` SET Location = POINT(Longitude, Latitude);
    ALTER TABLE `intersections` ADD COLUMN `Location` POINT;
    UPDATE `intersections` SET Location = POINT(Longitude, Latitude);
    

    您可以添加触发器,以便在更新经度/纬度时自动填充位置。

    然后:

    SELECT
        i.*
    FROM
        intersections AS i
        INNER JOIN collisions AS c ON (
            ST_Distance_Sphere(i.Location, c.Location) < @dist
        )
    

    这样会快一点。

    如果您想让它更快,您可以将另一个几何 poligon Area 列添加到您的交叉表和“预构建”区域(可以是圆形以提高准确性或方形以提高速度)。 之后,您将能够执行以下操作:

    SELECT
        i.*
    FROM
        intersections AS i
        INNER JOIN collisions AS c ON (
            ST_WITHIN(c.Location, i.Area)
        )
    

    【讨论】:

    • 非常感谢!但是您认为创建一个聚合两个模型的新表并使用 javascript 方法来确定碰撞是否在半径范围内会更好吗?我刚刚教过这个
    • 不。交叉点和碰撞是不同的东西,它们会有不同的属性。所以你不应该仅仅因为它们都有位置坐标就将它们合并到一个表中。另外,我认为这个计算应该由服务器完成。但是,这取决于您的申请和一个或多个记录。
    • 我不是说合并,而是一个映射表,两个表的id都有,如果id在一行,说明碰撞发生在路口
    • 对不起,我不太明白为什么如果 ids 在一行中,这意味着碰撞发生在路口。
    • 当然可以。 ST_Distance_Sphere/ST_Distance 完全相同——它们计算两点之间的距离。由于所有数据都在数据库中,我也会在数据库级别处理它(它会更快,可以通过插入/更新触发器进行更新)。您想将结果“缓存”在单独的表中吗?不同的故事。我不会像几乎任何其他过早的优化一样从一开始就这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    相关资源
    最近更新 更多