c++ अंक के एक सदिश का बाउंडिंग बॉक्स प्राप्त करना?




boost std (3)

मेरे पास std::vector instance में संग्रहीत अंकों की एक सदिश है। मैं इन बिंदुओं के बाउंडिंग बॉक्स की गणना करना चाहता हूं मैंने इस कोड के साथ कोशिश की है:

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 में दिलचस्पी है I

क्या मानक पुस्तकालयों या बूस्ट के साथ इसे प्राप्त करने के लिए स्मार्ट तरीके हैं?

वर्तमान समाधान:

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;
    }

यदि आपके पास सी ++ नहीं है, तो आप 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);

बस सभी तत्वों पर पुनरावृत्त करें और वर्तमान न्यूनतम / अधिकतम का ट्रैक रखें आप एक ही समय में दोनों को अपडेट करने के लिए boost::minmax का उपयोग कर सकते हैं। वास्तव में आपके डेटासेट पर दो बार दोबारा पुनरावृति करने की आवश्यकता नहीं है।


मुझे लगता है कि समस्या यह है कि आपके तुलनात्मक कार्य बाउंडिंग बॉक्स के आकार के बारे में एक दृढ़ संकल्प बना रहे हैं इन दो बिंदुओं पर विचार करें:

          1
         /
        /
       /
      2

सही बाउंडिंग बॉक्स है

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

ध्यान दें कि सीमावर्ती बॉक्स के कोने वास्तव में आपके सदिश में नहीं हैं इसके बजाय, वे वेक्टर में विभिन्न बिंदुओं से संयोजन निर्देशों के संयोजन के आधार पर बना रहे हैं। इसके अलावा, यदि आप अपने दो तुलनात्मक कार्यों को देखते हैं, तो आप पाएंगे कि ये दो बिंदु दिए गए हैं, न तो बिंदु दूसरे बिंदु से कम या उससे अधिक की तुलना करता है, क्योंकि प्रत्येक के पास एक समन्वय होता है जो दूसरे से अधिक होता है और जो कम है इसके अलावा।

अपने बाउंडिंग बॉक्स प्राप्त करने के लिए, आपको निम्न कार्य करना चाहिए:

  1. न्यूनतम एक्स मान के साथ बिंदु खोजें
  2. अधिकतम x मान के साथ बिंदु खोजें
  3. न्यूनतम वाई मूल्य के साथ बिंदु खोजें।
  4. अधिकतम वाई मान के साथ बिंदु खोजें
  5. X और y को एक कोने बिन्दु में न्यूनतम एक्स और वाई मान के साथ अंक से जोड़ते हैं।
  6. अधिकतम x और y मान के साथ एक कोने बिन्दु में अंकों से एक्स और वाई का संयोजन करें।

आप इसे std::minmax_element साथ नए C ++ 11 std::minmax_element एल्गोरिथ्म का उपयोग कर सकते हैं:

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);

उम्मीद है की यह मदद करेगा!







bounding-box