使用经度和纬度提升凸包

问题描述

我正在尝试对经度/纬度坐标使用 boost 的 convex_hull 算法。

从这里:https://archive.fosdem.org/2017/schedule/event/geo_boost_geography/attachments/slides/1748/export/events/attachments/geo_boost_geography/slides/1748/FOSDEM17_vissarion.pdf

我可以看到我们可以计算两点之间的距离,甚至可以使用经纬度坐标找到区域(请参阅 PDF 文档的第 19 页和第 22 页)。

结合 https://www.boost.org/doc/libs/1_75_0/libs/geometry/doc/html/geometry/reference/algorithms/convex_hull.html

我想出了这个:https://wandbox.org/permlink/2AGPUtHPWrlGFMTf,但它不能编译,为了方便起见,代码在这里:

#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>

namespace bg = boost::geometry;

int main()
{
    typedef bg::model::point<double,2,bg::cs::geographic<bg::degree>> point;
    typedef boost::geometry::model::polygon<point> polygon;
    polygon poly;
    bg::read_wkt(" POLYGON ((4.346693 50.858306,4.367945 50.852455,4.366227 50.840809,4.344961 50.833264,4.338074 50.848677,4.346693 50.858306))",poly );
    
    polygon hull;
    boost::geometry::convex_hull(poly,hull);

    using boost::geometry::dsv;
    std::cout << "polygon: " << dsv(poly) << std::endl << "hull: " << dsv(hull) << std::endl;
}

非常感谢任何帮助。

解决方法

是的,虽然您认为/可以/制定策略是对的,但并未实施。

一个小的并排测试器清楚地表明该策略没有针对地理坐标系实施:

top: 0

它还证明了一些其他策略正在实施(例如距离)。

看到它Live On Coliru

template <typename cs> void test() {
    using point   = bg::model::point<double,2,cs>;
    using polygon = bg::model::polygon<point>;
    polygon poly;
    bg::read_wkt("POLYGON((4.346693 50.858306,4.367945 50.852455,4.366227 "
                 "50.840809,4.344961 50.833264,4.338074 50.848677,4.346693 "
                 "50.858306))",poly);

    std::cout << std::fixed;
    std::cout << "Polygon:   " << bg::dsv(poly)       << std::endl;
    std::cout << "Perimeter: " << bg::perimeter(poly) << std::endl;
    std::cout << "Area:      " << bg::area(poly)      << std::endl;

    using Strategy = typename bg::strategy_convex_hull<polygon,point>::type;
    std::cout << "Strategy " << boost::core::demangle(typeid(Strategy).name()) << "\n";

    if constexpr (not std::is_same_v<Strategy,bg::strategy::not_implemented>) {
        polygon hull;
        bg::convex_hull(poly,hull);
        std::cout << "Hull: " << bg::dsv(hull) << std::endl;
    }
}

简化输出中的类型名称:

int main() {
    std::cout << "Cartesian:\n";
    std::cout << "----------\n";
    test<bg::cs::cartesian>();

    std::cout << "\nGeographic:\n";
    std::cout <<   "-----------\n";
    test<bg::cs::geographic<bg::degree>>();
}

查看 documented strategies 表明 Cartesian: ---------- Polygon: (((4.346693,50.858306),(4.367945,50.852455),(4.366227,50.840809),(4.344961,50.833264),(4.338074,50.848677),(4.346693,50.858306))) Perimeter: 0.086184 Area: 0.000488 Strategy bg::strategy::convex_hull::graham_andrew<polygon,point> Hull: (((4.338074,50.848677))) Geographic: ----------- Polygon: (((4.346693,50.858306))) Perimeter: 7663.398262 Area: 3848183.734567 Strategy bg::strategy::not_implemented 实际上是唯一可用的。

您可能应该了解需要进行哪些调整才能使工作正常进行。从技术上讲,强制 graham_andrew 使用 Graham/Andrew 策略是可能的,但这似乎是不明智的,因为该特征意味着该策略是专门根据坐标系取消选择的: >

convex_hull

深入了解战略的实施,这是一个充满希望的提示:

/*!
    \brief Traits class binding a convex hull calculation strategy to a coordinate system
    \ingroup convex_hull
    \tparam Tag tag of coordinate system
    \tparam Geometry the geometry type (hull operates internally per hull over geometry)
    \tparam Point point-type of output points
*/
template
<
    typename Geometry1,typename Point,typename CsTag = typename cs_tag<Point>::type
>
struct strategy_convex_hull
{
    typedef strategy::not_implemented type;
};

也许我们可以“完成”“只”为您的坐标系专门化 Side Strategy?更有趣的是:a strategy::side::geographic 存在。我对参数的理解不够深入(例如大地测量解决策略的含义?),但也许您自己可以从那里得到它?

我相信,如果您知道需要做什么,邮件列表中的有用开发人员将非常愿意指导有关如何将其放入库中的技术问题。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...