C++中Boost.Geometry中的多边形变换:平移、旋转、绕线反射

Posted

技术标签:

【中文标题】C++中Boost.Geometry中的多边形变换:平移、旋转、绕线反射【英文标题】:Polygon transformation in Boost.Geometry in C++: Translation, Rotation, Reflection around a line 【发布时间】:2020-07-04 14:24:42 【问题描述】:

我有三种类型的多边形查询要使用 boost 几何实现:

    将多边形平移到给定点 围绕参考点旋转多边形(不一定围绕原点) 围绕一条线反射多边形

由于我是 Boost Geomtry 的新手,我在理解语法方面遇到了问题。我搜索了满足我的查询的示例,但没有找到一个或发现一些对我来说难以理解的东西。 您能否提供任何实现查询的示例代码,几乎没有解释?

【问题讨论】:

【参考方案1】:

我所知道的库中最通用的变换是矩阵变换,这是一种可以与transform 一起使用的策略。

让我们生成一些随机矩形,按随机角度旋转,平移 (-500..500, -500..500) 并在 1..3 之间缩放:

polygon gen_rectangle() 
    using box = bgm::box<point_xy>;
    polygon raw, result;
    box initial  0, 0,  rand(1, 1'000), rand(1, 1'000)  ;
    bg::correct(raw);
    bg::assign(raw, initial);

    using namespace bg::strategy::transform;
    auto rot   = rand(-M_PI, +M_PI);
    auto scale = rand(1.0, 3.0);
    auto x     = rand(-500.0, 500.0),
         y     = rand(-500.0, 500.0);

    matrix_transformer<double, 2, 2> xfrm(
            scale* cos(rot), scale*sin(rot), x,
            scale*-sin(rot), scale*cos(rot), y,
            0,              0, 1);

    boost::geometry::transform(raw, result, xfrm);
    return result;

写一些帧:

int main(int argc, char** argv) 
    auto const seed = argc>1? std::stoul(argv[1]) : std::random_device();
    prng.seed(seed);

    // generate shapes
    for (int frame = 0; frame < 30; ++frame) 
        multi_polygon shapes, merged;
        std::generate_n(back_inserter(shapes), 10, gen_rectangle);
        save_frame(shapes, frame);
    

结果:

在一行中镜像

我不认为该变换涵盖了这一点(尽管您可能能够通过适当的平移、旋转和另一个平移来表达这些中的任何一个?)。

我会通过逐点变换来解决这个问题,您可以在一条线上投影一个点(参见例如How to find two points that form closest distance between two rectangles?,但不太复杂,因为您可以假设无限线,而不是线段),并扩展另一边的距离相同。

完整的演示代码

Live On Coliru

#include <boost/geometry.hpp>
#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <random>

namespace bg  = boost::geometry;
namespace bgm = bg::model;

using point_xy      = bgm::d2::point_xy<double>;
using polygon       = bgm::polygon<point_xy>;
using multi_polygon = bgm::multi_polygon<polygon>;

static std::mt19937 prng;
void save_frame(multi_polygon const& p, int frameno);
polygon gen_rectangle();

int main(int argc, char** argv) 
    auto const seed = argc>1? std::stoul(argv[1]) : std::random_device();
    prng.seed(seed);

    // generate shapes
    for (int frame = 0; frame < 30; ++frame) 
        multi_polygon shapes, merged;
        std::generate_n(back_inserter(shapes), 10, gen_rectangle);
        save_frame(shapes, frame);
    


static inline double rand(double b, double e)  return std::uniform_real_distribution<double>(b, e)(prng); 

// generate rectangle shape with varying sizes, positions and rotations
polygon gen_rectangle() 
    using box = bgm::box<point_xy>;
    polygon raw, result;
    box initial  0, 0,  rand(1, 1'000), rand(1, 1'000)  ;
    bg::assign(raw, initial);

    using namespace bg::strategy::transform;
    double rot   = rand(-M_PI, +M_PI);
    double scale = rand(1.0, 3.0);
    double x     = rand(-500.0, 500.0),
           y     = rand(-500.0, 500.0);

    matrix_transformer<double, 2, 2> xfrm(
            scale* cos(rot), scale*sin(rot), x,
            scale*-sin(rot), scale*cos(rot), y,
            0,              0, 1);

    boost::geometry::transform(raw, result, xfrm);
    return result;


void save_frame(multi_polygon const& p, int frameno) 
    std::ostringstream name;
    name << "frame" << std::setw(4) << std::setfill('0') << frameno << ".svg";
    std::ofstream ofs(name.str());
    bg::svg_mapper<point_xy> mapper(ofs, 400, 400);

    mapper.add(p);
    mapper.map(p, "fill-opacity:0.5;fill:rgb(204,153,0);stroke:rgb(204,153,0);stroke-width:1", 5);


【讨论】:

感谢您的回答。但我想知道是否有任何内置库方法 Boost.Geometry 用于反射点/多边形? 那不是但是。那是你最初的问题。如果我认为有,我会提前告诉你。当然,如果其他人知道,他们也会回答:) 您能否推荐一些好的资源来学习从基础到高级的 Boost.Geometry 库? 很遗憾,没有。他们有一个高于平均水平的邮件列表,您可能会觉得有趣。他们的作者很有帮助,但很少在Stack Overflow 上活跃

以上是关于C++中Boost.Geometry中的多边形变换:平移、旋转、绕线反射的主要内容,如果未能解决你的问题,请参考以下文章

Boost::geometry::intersection 与 C++

C++ 上不正确的工作 boost::geometry::union_

如何通过 Boost C++ 库与 3D 多边形相交?

boost::geometry 中无效几何的数据集

用 boost::geometry 扩展多边形?

boost几何中的环和多边形有什么区别?