[英]Intersection of boost::geometry::model::linestring with boost::geometry::model::polygon
[英]How to get a polygon from boost::geometry::model::polygon?
我正在嘗試使用boost::geometry::difference
計算兩個多邊形的boost::geometry::difference
其中boost::geometry::model::polygon
表示我的多邊形。
如果第一個多邊形包含第二個操作的結果是單個boost::geometry::model::polygon
,其內環和外環填充了源多邊形的坐標。
如何從boost::geometry::model::polygon
獲得多邊形(在基本幾何意義上)?
澄清:
在初等幾何中,多邊形是一個平面圖形,它以有限的直線段鏈為界,在環中閉合以形成閉合的鏈或回路。
boost::geometry::model::polygon
的外環是多邊形,內環也是多邊形。 總的來說boost::geometry::model::polygon
不是多邊形。
所以,我要問的是:如何將boost::geometry::model::polygon
轉換為普通多邊形(具有單個直線段鏈),它表示平面上的相同區域。
這是我想要實現的目標:
polygon1 = (0,0), (0,8), (8,8), (8,0), (0,0)
polygon2 = (2,2), (2,6), (6,6), (6,2), (2,2)
多邊形 1 和 2 為綠色 / oker:
difference = (0,0), (0,4), (2,4), (2,2), (6,2), (6,6), (2,6), (2,4), (0,4), (0,8), (8,8), (8,0), (0,0)
灰色的預期差異:
我知道具有內環的相同boost::geometry::model::polygon
可以由無限多個不同的法線多邊形表示。 我不在乎我得到哪一個。
您可以輕松構建一個環來模擬您預期的弱簡單多邊形。 第一的:
請注意,結果對於進一步使用 Boost Geometry 庫的算法無效。
以你的文字為例:
std::string reason;
poly expected;
bg::read_wkt("POLYGON((0 0, 0 4, 2 4, 2 2, 6 2, 6 6, 2 6, 2 4, 0 4, 0 8, 8 8, 8 0, 0 0))", expected);
bool ok = bg::is_valid(expected, reason);
std::cout << "Expected: " << bg::dsv(expected) << (ok?" valid":" invalid: '" + reason + "'") << "\n";
印刷
預期:(((0, 0), (0, 4), (2, 4), (2, 2), (6, 2), (6, 6), (2, 6), (2, 4) ), (0, 4), (0, 8), (8, 8), (8, 0), (0, 0))) invalid: 'Geometry has invalid self-intersections. 在 (0, 4) 處發現了一個自交點; 方法:t; 操作:x/u; 段 ID {source、multi、ring、segment}:{0, -1, -1, 0}/{0, -1, -1, 7}'
有了這個,這里有一個簡單的算法來從給定的多邊形構造簡單的弱多邊形:
ring weak_simple_ring(poly& p) {
ring r = p.outer();
for (auto& i: p.inners()) {
auto last = r.back();
r.insert(r.end(), i.rbegin(), i.rend());
r.insert(r.end(), last);
}
return r;
}
唯一更微妙的一點是反轉內圈的方向 (CW/CCW) 以匹配外圈的方向。
該算法並沒有試圖巧妙地找到內環的切點,這可能也意味着它不適用於具有多個內環的通用情況。
這是一個完整的現場演示
輸入在哪里
bg::read_wkt("POLYGON((0 0,0 10,10 10,10 0,0 0))", a);
bg::read_wkt("POLYGON((2 2, 2 6, 6 6, 6 2, 2 2))", b);
變換是
std::vector<poly> output;
bg::difference(a, b, output);
for (auto& p : output) {
ring r = weak_simple_ring(p);
bg::convert(r, p);
}
結果變成了
考慮當b
有一個洞時:
bg::read_wkt("POLYGON((0 0,0 10,10 10,10 0,0 0))", a);
bg::read_wkt("POLYGON((2 2, 2 6, 6 6, 6 2, 2 2)(3 3, 5 3, 5 5, 3 5, 3 3))", b);
相同代碼的輸出變成
這是舊答案。 對問題進行編輯后,我發布了一個適合給定示例的算法的簡單實現
已經是了。
如果您的意思是“簡單”的無孔多邊形,那么外環就是您想要的。 只需丟棄內環。
但是,在最通用的情況下,您最終會得到多個完全分離的多邊形,這就是為什么輸出是多邊形集合的原因。 您也必須考慮這種可能性(可以選擇將不同的結果多邊形合並為一個,並在功能上根據您的需要丟棄內環)。
一個樣品:
bg::read_wkt("POLYGON((0 0,0 10,10 10,10 0,0 0))", a);
bg::read_wkt("POLYGON((2 -2,2 12,5 12,5 -2,2 -2))", b);
這里, b
將a
切成兩個單獨的部分。 因此,您必須准備好處理多個分離的輸出多邊形:
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/io/io.hpp>
#include <iostream>
#include <fstream>
namespace bg = boost::geometry;
using pt = bg::model::d2::point_xy<int>;
using poly = bg::model::polygon<pt>;
int main() {
poly a, b;
bg::read_wkt("POLYGON((0 0,0 10,10 10,10 0,0 0))", a);
bg::read_wkt("POLYGON((2 -2,2 12,5 12,5 -2,2 -2))", b);
std::cout << bg::dsv(a) << "\n";
std::cout << bg::dsv(b) << "\n";
{
std::ofstream svg("/tmp/input.svg");
boost::geometry::svg_mapper<pt> mapper(svg, 400, 400);
mapper.add(a);
mapper.add(b);
mapper.map(a, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2");
mapper.map(b, "fill-opacity:0.5;fill:rgb(204,153,0);stroke:rgb(202,153,0);stroke-width:2");
}
std::vector<poly> output;
bg::difference(a, b, output);
for (auto& p : output)
std::cout << "\n\t" << bg::dsv(p);
{
std::ofstream svg("/tmp/output.svg");
boost::geometry::svg_mapper<pt> mapper(svg, 400, 400);
assert(output.size() == 2);
mapper.add(output[0]);
mapper.add(output[1]);
mapper.add(b);
mapper.map(output[0], "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2");
mapper.map(output[1], "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2");
mapper.map(b, "fill-opacity:0.15;fill:rgb(153,153,153);stroke-width:0");
}
}
印刷:
(((0, 0), (0, 10), (10, 10), (10, 0), (0, 0)))
(((2, -2), (2, 12), (5, 12), (5, -2), (2, -2)))
(((5, 10), (10, 10), (10, 0), (5, 0), (5, 10)))
(((2, 10), (2, 0), (0, 0), (0, 10), (2, 10)))
渲染的 SVG:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.