如何在Boost几何中使用多个线串创建盒子?
Posted
技术标签:
【中文标题】如何在Boost几何中使用多个线串创建盒子?【英文标题】:How to create box using multiple linestrings in Boost geometry? 【发布时间】:2021-08-11 20:32:02 【问题描述】:我正在尝试使用多个线串创建一个框。当然这些线串是相互连接的,可以组成一个盒子。 boost中是否有任何功能可以做到这一点?谢谢!
【问题讨论】:
【参考方案1】:我不确定您到底在寻找什么。所以,让我双向走吧。
单向
如果你有一个盒子,你可以使用分段迭代器来获取分段:
Live On Coliru
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <iostream>
namespace bg = boost::geometry;
namespace bgm = bg::model;
using Point = bgm::d2::point_xy<int>;
using Box = bgm::box<Point>;
using Poly = bgm::polygon<Point>;
int main()
Box const box Point 0,1, 1,2 ;
std::cout << "box: " << bg::wkt(box) << "\n";
// now get the segments:
Poly p;
bg::assign(p, box);
for (auto f = bg::segments_begin(p), l = bg::segments_end(p); f != l; ++f)
std::cout << bg::wkt(*f) << "\n";
打印
box: POLYGON((0 1,0 2,1 2,1 1,0 1))
LINESTRING(0 1,0 2)
LINESTRING(0 2,1 2)
LINESTRING(1 2,1 1)
LINESTRING(1 1,0 1)
另一种方式
最灵活的是使用envelope
算法得到一个盒子:
Live On Coliru
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <iostream>
namespace bg = boost::geometry;
namespace bgm = bg::model;
using Point = bgm::d2::point_xy<int>;
using Box = bgm::box<Point>;
using LineString = bgm::linestring<Point>;
int main()
LineString const ls1, 1, 1, 2, 0, 2, 0, 1;
std::cout << "ls: " << bg::wkt(ls) << "\n";
Box box;
bg::envelope(ls, box);
std::cout << "box: " << bg::wkt(box) << "\n";
打印
ls: LINESTRING(1 1,1 2,0 2,0 1)
box: POLYGON((0 1,0 2,1 2,1 1,0 1))
(请注意,点顺序已更正以生成有效的环)
有验证吗?
为了减少灵活性,换句话说,对输入进行更多验证,我会从点手动创建一个多边形。
验证后,您可以通过 WKT 创建一个框...这并不理想,但可能比编写自己的逻辑要好。然而,从 WKT 读取 Box 似乎只在没有任何实际验证的点上应用最小/最大算法 - 因此实际上与获取 bg::envelope
相同。
因此,IMO 解决此问题的最佳方法是将生成的框与手动多边形进行比较,以检查输入是否已经是一个框。
bool is_box(Poly const& p)
Box env;
bg::envelope(p, env);
return bg::equals(p, env);
例如使用一些输入进行测试:
LineString1, 1, 0, 1, 0, 2, 1, 2, 1, 1,
LineString1, 1, 1, 2, 0, 2, 0, 1,
LineString1, 1, 1, 2, 0, 2, 0, 1, 1, 1,
LineString1, 1, 0, 2, 0, 1, 1, 1, // triangle
is_box
将为最后一个返回 false
(即使在更正多边形之后)
Live On Coliru
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <iostream>
namespace bg = boost::geometry;
namespace bgm = bg::model;
using Point = bgm::d2::point_xy<int>;
using Box = bgm::box<Point>;
using Poly = bgm::polygon<Point>;
using LineString = bgm::linestring<Point>;
bool is_box(Poly const& p)
Box env;
bg::envelope(p, env);
return bg::equals(p, env);
int main()
for (auto& ls :
LineString1, 1, 0, 1, 0, 2, 1, 2, 1, 1,
LineString1, 1, 1, 2, 0, 2, 0, 1,
LineString1, 1, 1, 2, 0, 2, 0, 1, 1, 1,
LineString1, 1, 0, 2, 0, 1, 1, 1, // triangle
)
std::cout << " --\nls: " << bg::wkt(ls) << "\n";
Poly p;
bg::assign_points(p, ls);
if (std::string reason; !bg::is_valid(p, reason))
std::cout << "Trying to correct...: " << reason << "\n";
bg::correct(p);
if (!bg::is_valid(p))
continue;
std::cout << "poly: " << bg::wkt(p) << "\n";
std::cout << "is a box? " << (is_box(p) ? "yes" : "no") << "\n";
打印
--
ls: LINESTRING(1 1,0 1,0 2,1 2,1 1)
poly: POLYGON((1 1,0 1,0 2,1 2,1 1))
is a box? yes
--
ls: LINESTRING(1 1,1 2,0 2,0 1)
Trying to correct...: Geometry is defined as closed but is open
poly: POLYGON((1 1,0 1,0 2,1 2,1 1))
is a box? yes
--
ls: LINESTRING(1 1,1 2,0 2,0 1,1 1)
Trying to correct...: Geometry has wrong orientation
poly: POLYGON((1 1,0 1,0 2,1 2,1 1))
is a box? yes
--
ls: LINESTRING(1 1,0 2,0 1,1 1)
Trying to correct...: Geometry has wrong orientation
poly: POLYGON((1 1,0 1,0 2,1 1))
is a box? no
【讨论】:
以上是关于如何在Boost几何中使用多个线串创建盒子?的主要内容,如果未能解决你的问题,请参考以下文章