4

How would I go about constructing the contour of 2d polygon which is formed of only triangles and it can have holes and the external contour can be concave/convex and the holes can also be concave/convex.

From what I'm reading over here it seems that It's exactly the inverse of the triangulation problem. Do you know any articles treating this type of problem?

Are octrees/quadtrees relevant to this?

Community
  • 1
  • 1
xxxxxxx
  • 4,601
  • 6
  • 26
  • 26

3 Answers3

4

I guess that you have data in the form of sets of three points, which constitute a "filled" triangle, that these triangles are adjoined along edges, and that all vertices that will be corners of the complete shape are also vertices of all the triangles that touch this point. You would then just have to find all edges that are not doubled, i.e. do not belong to two adjoined triangles.

Svante
  • 46,788
  • 11
  • 77
  • 118
  • 1
    ok,and we're left with a set of points.connecting them to find out the result of the problem is nontrivial,or is it ? – xxxxxxx Feb 24 '09 at 16:35
  • I am not sure if I understand you, spx2, but after eliminating all doubled edges, you are left with the ones that constitute the contour. – Svante Feb 24 '09 at 17:02
  • I think he wants to know how to get the points of the contour in order instead of start-end pairs. Also, consider inputs which may result in multiple contours? – Agnel Kurian Apr 20 '10 at 05:41
1

I think you can solve your problem by creating a topological data structure to represent your set of triangles, and then using that structure to iterate in order over the triangle edges that lie on the boundary.

For example: you can create a halfedge data structure. Assuming you insert halfedges even on the boundary (correctly), iterating over the boundary contour is as simple as locating one halfedge on the boundary and then iterating over it's "next" pointer until you get back to the halfedge you started from.

Similarly to halfedges, you can use other topological structures like winged-edge, etc., but the concept is the same.

0

Here is an implementation operating on a triangle-mesh, finding and connecting all non-doubled edges as explained also in 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;
}
klaus se
  • 2,173
  • 18
  • 15