【问题标题】:Incorrect subtract result using Boost Polygon使用 Boost Polygon 的减法结果不正确
【发布时间】:2017-11-09 13:13:26
【问题描述】:

我有以下两个输入多边形,我想为其计算减去的多边形:

答:

               * (0, 8)
              / \
             /   \
            /     \
   (-3, 0) *-------* (3, 0)

乙:

      (-1, 2) *-----* (1, 2)
              |     |
      (-1, 1) *-----* (1, 1)

因此,我想计算A - B,这应该会产生一个带有方形切口的三角形。使用 Boost Polygon 进行计算会导致不正确的带有切口的部分三角形。很难画;结果三角形的缺失部分由三角形(3, 0) => (0, 8) => (1, 2) 表示。我正在使用以下代码来计算减法:

#include <boost/polygon/polygon.hpp>

namespace bp = boost::polygon;

int main()
{
  using Polygon = bp::polygon_data<int>;
  using Point = bp::point_data<int>;
  using PolygonSet = bp::polygon_set_data<int>;
  using SimplePolygons = std::vector<bp::polygon_data<int>>;

  using namespace boost::polygon::operators;

  Polygon A;
  {
    std::vector<Point> points{{-3, 0}, {3, 0}, {0, 8}};
    bp::set_points(A, points.begin(), points.end());
  }

  Polygon B;
  {
    std::vector<Point> points{{-1, 1}, {1, 1}, {1, 2}, {-1, 2}};
    bp::set_points(B, points.begin(), points.end());
  }

  PolygonSet result{A - B};

  SimplePolygons simplePolygons;
  result.get<SimplePolygons>(simplePolygons);
  for (const auto& polygon : simplePolygons)
  {
    for (const Point& p : polygon)
    {
      std::cout << '(' << std::to_string(p.x()) << ", " << std::to_string(p.y()) << ")\n";
    }
  }

  return 0;
}

这将打印构成剪切三角形的以下后续点:

(3, 0)
(1, 2)
(1, 1)
(-1, 1)
(-1, 2)
(1, 2)
(0, 8)
(-3, 0)
(3, 0)

因此,结果中缺少边缘 (1, 2) =&gt; (3, 0)(3, 0) =&gt; (0, 8)。结果中缺少输入三角形的右上部分。

正确的输出可能如下所示:

(3, 0)
(1, 2)
(1, 1)
(-1, 1)
(-1, 2)
(1, 2)
(3, 0)
(0, 8)
(-3, 0)
(3, 0)

这是 Boost Polygon 中的一个错误,我是否以某种方式错误地使用了该库,还是我缺少其他东西?

一些附加信息:

  • 我使用的是 GCC 7.2.0,Boost 1.60.0。 Boost Polygon 此后一直没有更新,因此升级 Boost 很可能无济于事。
  • 使用double 而不是int 参数化点类型和所有其他几何类型不能解决问题。
  • 例如,使用轴对齐的矩形计算切口没有问题。
  • 对于我的应用程序,我想使用 Boost Polygon 而不是 Boost Geometry,因为它提供了多边形锁孔压裂支持。

【问题讨论】:

  • 对于圣诞节,我希望关于 SO 的每个问题都像这个问题一样得到充分研究和呈现。模范。
  • @sehe,谢谢你的好话!

标签: c++ boost boost-polygon


【解决方案1】:

回答我自己的问题...

Boost Polygon 在编写时考虑了整数数据类型。来自文档:

一般而言,数据类型应定义 std::numeric_limits 并类似于整数。并非所有算法都支持浮点坐标类型,目前一般不适合与库一起使用(http://www.boost.org/doc/libs/1_60_0/libs/polygon/doc/gtl_coordinate_concept.htm

我怀疑这是我不完全理解的某种精度问题。实际上,例如,将所有输入坐标缩放1000 确实会产生正确的多边形:

(3000, 0)
(1000, 5333)
(1000, 2000)
(1000, 1000)
(-1000, 1000)
(-1000, 2000)
(1000, 2000)
(1000, 5333)
(0, 8000)
(-3000, 0)
(3000, 0)

所以对于原始输入,钥匙孔破裂算法似乎打算在边缘(3, 0) -&gt; (0, 8) 上添加一个新顶点,从中输入“钥匙孔多边形”。它可以为此创建的整数网格位置上的最佳可能顶点位于(0, 8)。所以结果代表一个近似值。

确实,为算法提供相似的输入,在三角形边上存在一个好的候选顶点确实会导致正确的输出。例如,一个这样的输入三角形是(-4, 0) - (4, 0) - (0, 8)

我认为这是钥匙孔压裂算法的限制。

【讨论】:

  • 仅出于我个人的兴趣:在您的结果数据中,您如何识别轮廓的结束位置和孔的开始位置?它只是一个二维坐标数组,如何找到不同部分的结束位置?
  • 你不应该把有洞的多边形看成是两个独立的多边形,它是单一的、结构良好的多边形。
  • @Elmi,轮廓和孔真的没有区别。它确实是一个二维坐标数组,描述了单个多边形的轮廓,其中多边形包含一个洞。如果您想以某种方式检测构成孔的顶点;有一条重复的边,方向相反。也就是可以认为是连接外部轮廓和孔轮廓的线的边缘。可以说,这两条边将多边形轮廓和孔轮廓分开。用一张纸和一支笔来解释会容易得多。
猜你喜欢
  • 2016-05-02
  • 1970-01-01
  • 2016-08-22
  • 1970-01-01
  • 2013-06-25
  • 2014-01-28
  • 1970-01-01
  • 2012-02-02
  • 1970-01-01
相关资源
最近更新 更多