构造多边形的轮廓(特别是三角剖分)

时间:2009-01-25 16:30:01

标签: algorithm contour triangulation polygons

如何构建仅由三角形组成的二维多边形轮廓,它可以有孔,外部轮廓可以是凹/凸,孔也可以是凹/凸。

I'm reading over here看来,这正是三角测量问题的反面。 你知道任何处理这类问题的文章吗?

八叉树/四叉树是否与此相关?

3 个答案:

答案 0 :(得分:4)

我猜你有三个点的形式的数据,它们构成一个“填充的”三角形,这些三角形沿着边连接,并且所有将成为完整形状的角的顶点也是触及这一点的所有三角形。然后你必须找到所有没有加倍的边,即不属于两个相邻的三角形。

答案 1 :(得分:1)

我认为您可以通过创建拓扑数据结构来表示您的三角形集合,然后使用该结构按顺序迭代位于边界上的三角形边缘来解决您的问题。

例如:您可以创建halfedge数据结构。假设你甚至在边界(正确)上插入半边,迭代边界轮廓就像在边界上找到一个半边然后迭代它的“下一个”指针一样简单,直到你回到你开始的半边。

与halfedges类似,您可以使用其他拓扑结构,如翼边等,但概念是相同的。

答案 2 :(得分:0)

这是在三角形网格上运行的实现,如this answer中所述,查找并连接所有非双边缘。

#include <list>
#include <map>
#include <set>
#include <vector>
#include <iostream>

typedef int Vertex;

class Triangle {
public:
    const Vertex& operator [] (size_t i) const {
        return p[i];
    }
    Vertex p[3];
};

std::list<std::list<Vertex>> find_contours(const std::vector<Triangle>& triangles) {

    std::set<std::pair<Vertex, Vertex>> edges;
    std::map<Vertex, Vertex> neighbors;
    for(const auto& t : triangles) {
        edges.insert(std::make_pair(t[0], t[1]));
        edges.insert(std::make_pair(t[1], t[2]));
        edges.insert(std::make_pair(t[2], t[0]));
    }
    for(const auto& t : triangles) {
        edges.erase(std::make_pair(t[1], t[0]));
        edges.erase(std::make_pair(t[2], t[1]));
        edges.erase(std::make_pair(t[0], t[2]));
    }
    for(const auto& t : triangles) {
        if (edges.find(std::make_pair(t[0], t[1])) != edges.end()) {
            neighbors[t[0]] = t[1];
        }
        if (edges.find(std::make_pair(t[1], t[2])) != edges.end()) {
            neighbors[t[1]] = t[2];
        }
        if (edges.find(std::make_pair(t[2], t[0])) != edges.end()) {
            neighbors[t[2]] = t[0];
        }
    }
    std::list<std::list<Vertex>> result;
    while(!neighbors.empty()) {
        std::list<Vertex> contour;
        auto v0 = neighbors.begin()->first;
        auto v = v0;
        while(neighbors.find(v) != neighbors.end()) {
            contour.push_back(v);
            auto old_v = v;
            v = neighbors.at(v);
            neighbors.erase(old_v);
        }
        if (v != v0) {
            throw std::runtime_error("Contour is not closed");
        }
        neighbors.erase(v);
        result.push_back(contour);
    }
    return result;
}

int main() {
    int v00 = 0;
    int v10 = 1;
    int v01 = 2;
    int v11 = 3;
    std::vector<Triangle> v{
        {v00, v10, v11},
        {v00, v11, v01}};
    for(const auto& c : find_contours(v)) {
        for(const auto& v : c) {
            std::cerr << v << " | ";
        }
        std::cerr << std::endl;
    }
    std::cerr << std::endl;
    return 0;
}