簡體   English   中英

獲取凸包指數

[英]Get convex hull indices

我想計算一組點的凸包。 我在網上找到的大多數算法都會返回一個點列表,但我需要一個點索引列表。

為此,我采用了一些計算點的現有代碼,並嘗試將其更改為返回點索引。

原來function返回一個凸包點向量

#include <iostream>
#include <vector>
#include <tuple>

using namespace std;

typedef std::tuple<int, int> point;

// returns true if the three points make a counter-clockwise turn
bool ccw(const point &a, const point &b, const point &c) {
    return ((std::get<0>(b) - std::get<0>(a)) * (std::get<1>(c) - std::get<1>(a)))
           > ((std::get<1>(b) - std::get<1>(a)) * (std::get<0>(c) - std::get<0>(a)));
}

std::vector<point> convexHull(std::vector<point> p) {
    if (p.size() == 0) return std::vector<point>();
    std::sort(p.begin(), p.end(), [](point &a, point &b) {
        if (std::get<0>(a) < std::get<0>(b)) return true;
        return false;
    });

    std::vector<point> h;

    // lower hull
    for (const auto &pt: p) {
        while (h.size() >= 2 && !ccw(h.at(h.size() - 2), h.at(h.size() - 1), pt)) {
            h.pop_back();
        }
        h.push_back(pt);
    }

    // upper hull
    auto t = h.size() + 1;
    for (auto it = p.crbegin(); it != p.crend(); it = std::next(it)) {
        auto pt = *it;
        while (h.size() >= t && !ccw(h.at(h.size() - 2), h.at(h.size() - 1), pt)) {
            h.pop_back();
        }
        h.push_back(pt);
    }

    h.pop_back();
    return h;
}

int main() {
    using namespace std;

    vector<point> points = {
            make_pair(16, 3), make_pair(12, 17), make_pair(0, 6), make_pair(-4, -6), make_pair(16, 6),
            make_pair(16, -7), make_pair(16, -3), make_pair(17, -4), make_pair(5, 19), make_pair(19, -8),
            make_pair(3, 16), make_pair(12, 13), make_pair(3, -4), make_pair(17, 5), make_pair(-3, 15),
            make_pair(-3, -9), make_pair(0, 11), make_pair(-9, -3), make_pair(-4, -2), make_pair(12, 10)
    };

    auto hull = convexHull(points);

    for (const auto &point: hull) {
        std::cout << get<0>(point) << ", " << get<1>(point) << std::endl;
    }

    return 0;
} 

結果

-9, -3
-3, -9
19, -8
17, 5
12, 17
5, 19
-3, 15

我采用了這段代碼並添加了一個indices向量。 然后我嘗試將每個循環中的當前索引添加到此向量以返回基於傳遞到 function 的點的索引。

新的 function 更改為返回點的索引

#include <iostream>
#include <vector>
#include <tuple>

using namespace std;

typedef std::tuple<int, int> point;

// returns true if the three points make a counter-clockwise turn
bool ccw(const point &a, const point &b, const point &c) {
    return ((std::get<0>(b) - std::get<0>(a)) * (std::get<1>(c) - std::get<1>(a)))
           > ((std::get<1>(b) - std::get<1>(a)) * (std::get<0>(c) - std::get<0>(a)));
}

std::vector<int> convexHull(std::vector<point> p) {

    if (p.size() == 0) return {};
    std::sort(p.begin(), p.end(), [](point &a, point &b) {
        if (std::get<0>(a) < std::get<0>(b)) return true;
        return false;
    });

    std::vector<point> h;
    std::vector<int> indices;

    // lower hull
    for (int i = 0; i < p.size(); i++) {

        auto pt = p[i];
        while (h.size() >= 2 && !ccw(h.at(h.size() - 2), h.at(h.size() - 1), pt)) {
            h.pop_back();
            indices.pop_back();
        }
        h.push_back(pt);
        indices.push_back(i);
    }

    // upper hull
    auto t = h.size() + 1;


    for (int i = p.size() - 1; i >= 0; i--) {
        auto pt = p[i];
        while (h.size() >= t && !ccw(h.at(h.size() - 2), h.at(h.size() - 1), pt)) {
            h.pop_back();
            indices.pop_back();
        }
        h.push_back(pt);
        indices.push_back(i);
    }


    h.pop_back();
    indices.pop_back();
    return indices;
}

int main() {
    using namespace std;

    vector<point> points = {
            make_pair(16, 3), make_pair(12, 17), make_pair(0, 6), make_pair(-4, -6), make_pair(16, 6),
            make_pair(16, -7), make_pair(16, -3), make_pair(17, -4), make_pair(5, 19), make_pair(19, -8),
            make_pair(3, 16), make_pair(12, 13), make_pair(3, -4), make_pair(17, 5), make_pair(-3, 15),
            make_pair(-3, -9), make_pair(0, 11), make_pair(-9, -3), make_pair(-4, -2), make_pair(12, 10)
    };

    auto hull = convexHull(points);

    for (const auto &index: hull) {
        std::cout << get<0>(points[index]) << ", " << get<1>(points[index]) << std::endl;
    }

    return 0;
}

結果

16, 3
-4, -6
12, 10
-9, -3
3, -4
19, -8
16, 6

我希望看到相同的結果。

我錯過了什么?

在您的程序/函數中,您正在對點進行排序,然后計算索引和船體。 然后您返回索引(基於排序的向量)。 然后將索引應用於未排序的向量。

請記住,C++ 可以通過引用或值/副本傳遞(我可能有點含糊,但我希望你能理解;如果你不知道我在說什么,那么這是你必須了解的主題)。

您可以在第二個程序中做的是:在打印之前對矢量進行排序。 也許這會給你預期的結果。

更好的解決方案需要更多的努力:通過引用傳遞

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM