获得点矢量的边界框?

时间:2012-01-30 21:04:36

标签: c++ boost std bounding-box

我有一个存储在std::vector实例中的点矢量。我想计算这些点的边界框。我试过这段代码:

bool _compare1(ofPoint const &p1, ofPoint const &p2) {
    return p1.x < p2.x && p1.y < p2.y;
}
bool _compare4(ofPoint const &p1, ofPoint const &p2) {
    return p1.x > p2.x && p1.y > p2.y;
}
vector<ofPoint> points;

// ...
if(points.size()>1) {
    ofPoint p_min = *std::min_element(points.begin(), points.end(), &_compare1);
    ofPoint p_max = *std::min_element(points.begin(), points.end(), &_compare4);
}

但是这段代码产生了奇怪的结果。实际上,我只对我的边界框的第一点和最后一点感兴趣:

1------2
|\     |
| \    |
|  \   |
|   \  |
|    \ |
|     \|
3------4

如果我的点代表对角线,我只对第1点和第4点感兴趣。

是否有通过标准库或Boost获得此功能的智能方法?


当前解决方案:

bool _compare_min_x(ofPoint const &p1, ofPoint const &p2) { return p1.x < p2.x; }
bool _compare_min_y(ofPoint const &p1, ofPoint const &p2) { return p1.y < p2.y; }

// ....

    if(points.size()>1) {
        min_x = (*std::min_element(points.begin(), points.end(), &_compare_min_x)).x;
        min_y = (*std::min_element(points.begin(), points.end(), &_compare_min_y)).y;

        max_x = (*std::max_element(points.begin(), points.end(), &_compare_min_x)).x;
        max_y = (*std::max_element(points.begin(), points.end(), &_compare_min_y)).y;
    }

3 个答案:

答案 0 :(得分:14)

我认为问题在于您的比较函数对边界框的形状做出了过于强烈的假设。考虑以下两点:

          1
         /
        /
       /
      2

正确的边界框是

      +---1
      |  /|
      | / |
      |/  |
      2---+

请注意,边界框角实际上不是矢量中的点。相反,它们是通过组合矢量中不同点的坐标而形成的点。此外,如果你看看你的两个比较函数,你会发现给定这两个点,这两个点都不会比另一个点小于或大于另一个点,因为每个点都有一个高于另一个的坐标和一个低于另一个的坐标。比另一个。

要获取边界框,您应该执行以下操作:

  1. 找到最小x值的点。
  2. 找到最大x值的点。
  3. 找到最小值的点。
  4. 找到最大y值的点。
  5. 将点的x和y与min x和y值组合成一个角点。
  6. 将具有最大x和y值的点中的x和y组合成一个角点。
  7. 您可以使用新的C ++ 11 std::minmax_element算法以及lambdas执行此操作:

    auto xExtremes = std::minmax_element(v.begin(), v.end(),
                                         [](const ofPoint& lhs, const ofPoint& rhs) {
                                            return lhs.x < rhs.x;
                                         });
    
    auto yExtremes = std::minmax_element(v.begin(), v.end(),
                                         [](const ofPoint& lhs, const ofPoint& rhs) {
                                            return lhs.y < rhs.y;
                                         });
    
    ofPoint upperLeft(xExtremes.first->x, yExtremes.first->y);
    ofPoint lowerRight(xExtremes.second->x, yExtremes.second->y);
    

    希望这有帮助!

答案 1 :(得分:3)

简单地遍历所有元素并跟踪当前的最小值/最大值。您可以使用boost::minmax同时更新两者。真的不需要在数据集上迭代两次。

答案 2 :(得分:2)

如果你没有c ++ 11,你可以使用boost :: algorithm :: minmax_element。

#include <boost/algorithm/minmax_element.hpp>
bool compareX(ofPoint lhs, ofPoint rhs) { return lhs.x < rhs.x; };
bool compareY(ofPoint lhs, ofPoint rhs) { return lhs.y < rhs.y; };

// ....
    pair<vector<ofPoint>::iterator, vector<ofPoint>::iterator> xExtremes, yExtremes;
    xExtremes = boost::minmax_element(overlap_point.begin(), overlap_point.end(), compareX);
    yExtremes = boost::minmax_element(overlap_point.begin(), overlap_point.end(), compareY);
    ofPoint upperLeft(xExtremes.first->x, yExtremes.first->y);
    ofPoint lowerRight(xExtremes.second->x, yExtremes.second->y);