我有一个复杂的折线处理使用boost::geometry,我需要做布尔运算与他们。我得到了一个奇怪的情况,当boost::geometry不能看到3点都在一条线上,并未能减去线串与3点是共线(根据boost::geometry本身)从线串与2个相同的端点(没有中间的一个)。
如果两个线串一个在另一个之上,那么它们相减的结果不应该是空的吗?
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <iostream>
namespace bg = boost::geometry;
using Number = double;
typedef bg::model::d2::point_xy<Number> point_type;
typedef bg::model::linestring<point_type> linestring_type;
typedef bg::model::multi_linestring<linestring_type> multilinestring_type;
typedef bg::model::segment<point_type> segment_type;
int main() {
std::cout << std::setprecision(17);
point_type p1{ 41.746999534390177, 58.355029632348561 };
point_type pc{ 41.803915890274112, 58.454652240833830 };
point_type p2{ 41.856075653483821, 58.54593925181792 };
linestring_type ls1{ p1, p2 };
linestring_type ls2{ p1, pc, p2 }; // same as ls1 endpoints with a center point which is slightly off
auto d1 = bg::distance(pc, ls1);
std::cout << "Distance between Point pc " << bg::wkt(pc) << "and line ls1 " << bg::wkt(ls1) << " is " << d1 << std::endl;
// now project pc onto ls1
bg::model::segment<point_type> sout;
bg::closest_points(pc, ls1, sout);
point_type pc_proj = sout.second;
// check if pc_proj is on ls1 (expect zero distance since it is the result of the projection)
auto d2 = bg::distance(pc_proj, ls1); // should be 0
std::cout << "Distance between Point pc_proj " << bg::wkt(pc_proj) << "and line ls1 " << bg::wkt(ls1) << " is " << d2 << std::endl;
//now, create another linestring where all three points should be in line and aligned with ls1
linestring_type ls2_proj{ p1, pc_proj, p2 }; // same as ls2 with the aligned with ls1 center point
// the idea is that since all the points of ls2_proj lie on ls1, the difference should be empty
multilinestring_type output1;
boost::geometry::difference(ls1, ls2_proj, output1);
// oops, non-empty difference
std::cout << "Difference ls1 - ls2_proj: " << std::endl;
for (auto& p : output1)
std::cout << bg::wkt(p) << "\n";
// and if we ask whether pc_proj is covered by ls1, it is not. But why?
if (!bg::covered_by(pc_proj, ls1))
{
std::cout << "Point " << bg::wkt(pc_proj) << " is not on ls1, but distance is: " << d2 << std::endl;
}
}
输出为
Distance between Point pc POINT(41.803915890274112 58.45465224083383)and line ls1 LINESTRING(41.746999534390177 58.355029632348561,41.856075653483821 58.54593925181792) is 2.5817835214104254e-06
Distance between Point pc_proj POINT(41.803918131966284 58.454650960044091)and line ls1 LINESTRING(41.746999534390177 58.355029632348561,41.856075653483821 58.54593925181792) is 0
Difference ls1 - ls2_proj:
LINESTRING(41.746999534390177 58.355029632348561,41.856075653483821 58.54593925181792)
Point POINT(41.803918131966284 58.454650960044091) is not on ls1, but distance is: 0
1条答案
按热度按时间mctunoxg1#
文件规定行为定义为:
现在,稍微摆弄一下代码让我怀疑浮点数不准确:**一个
这让我想到了其他的方法,最简单的是
simplify
,它似乎工作得很好,至少对于一些坐标类型是这样:一个月一次
图纸
另一种方法是在查询
covered_by
关系之前应用buffer
,从而允许一个容差“区域”,我不确定哪种方法更优,但我怀疑simplify
方法会更优。注意,根据文档,
simplify
可能会导致自相交。您可能会发现first listing中的check
助手非常方便: