C++ Boost.Geometry 中的多边形变换:围绕直线的平移、旋转、反射
Polygon transformation in Boost.Geometry in C++: Translation, Rotation, Reflection around a line
我有三种类型的多边形查询要使用 boost 几何体来实现:
- 将多边形平移到给定点
- 围绕参考点(不一定是原点)旋转多边形
- 反映一条线周围的多边形
由于我是 Boost Geomtry 的新手,我在理解语法方面遇到了问题。我搜索了满足我的查询但没有完全找到的示例,或者找到了一些我难以理解的示例。
能否请您提供任何实现查询的示例代码,无需过多解释?
我知道库中最通用的变换是矩阵变换,这是一种可以与 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);
}
}
结果:
直线镜像
我不认为该转换涵盖了这些内容(尽管您可以用合适的翻译来表达其中的任何一个,然后是旋转和另一个翻译?)。
我会通过逐点变换来解决这个问题,您可以在其中将一个点投影到一条线上(参见例如 ,但不那么复杂,因为您可以假设无限线,而不是线段) , 并在另一侧延伸相同的距离。
完整的演示代码
#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 几何体来实现:
- 将多边形平移到给定点
- 围绕参考点(不一定是原点)旋转多边形
- 反映一条线周围的多边形
由于我是 Boost Geomtry 的新手,我在理解语法方面遇到了问题。我搜索了满足我的查询但没有完全找到的示例,或者找到了一些我难以理解的示例。 能否请您提供任何实现查询的示例代码,无需过多解释?
我知道库中最通用的变换是矩阵变换,这是一种可以与 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);
}
}
结果:
直线镜像
我不认为该转换涵盖了这些内容(尽管您可以用合适的翻译来表达其中的任何一个,然后是旋转和另一个翻译?)。
我会通过逐点变换来解决这个问题,您可以在其中将一个点投影到一条线上(参见例如
完整的演示代码
#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);
}