0

I already have the theory behind the algorithm but since I have no formal education I am having trouble translating it into code. More information about the theory is below. Any help is appreciated.

make_shape

You are given x vertices and their coordinates relative to a corner (let it be relative to the bottom left corner for simplicity's sake) as an argument to a function.

using vertices_t = std::vector< std::pair< double,
                                           double > >;

make_shape( vertices_t const & vertices );
// doesnt need to be a vector of a pair of doubles.
// use anything else, like a valarray of ints if you so choose

In return, you are to construct a an object who describes the shape in triangles (primitives)

using triangles_t = std::vector< std::tuple< std::size_t,
                                             std::size_t,
                                             std::size_t > >;

triangles_t make_shape( vertices_t vertices );
// once again, it does not need to be a vector of a 3 tuple of size_t

The theory: any shape can be composed of triangles. The number of triangles required is equal to the number of vertices minus two.

auto && triangles = vertices.size( ) - 2;

The algorithm is simple: you take a vertex and two adjacent vertices and connect them. Then, alternatingly increment the vertices and store the last incremented vertex as your three next vertices. This will result in a series of triangles that composes any shape. The issue arises with concave shapes, where picking the vertex matters.

The following are some images of how the algorithm looks in action

enter image description here

nowi
  • 437
  • 4
  • 13
  • Why don't you just use one of the dozens existing opensource libraries that implem this? – ALX23z Apr 11 '20 at 06:45
  • 1
    So, what have you tried so far and what is the problem? Aside from that, can't you simply use Delaunay triangulation? – Aziuth Apr 11 '20 at 06:46
  • @ALX23z I'm not aware of any and I also enjoy the challenge of making stuff myself. Once I've made something and I've made it well, I allow myself to use the open source options :) – nowi Apr 11 '20 at 06:46
  • @Aziuth I'm not familiar with "Delaunay triangulation". Could you tell me more? So far I've tried just doing exactly what I've done in the screenshots where I alternate which I increment/decrement and store that as an index. It gets hairy with concave and more complex shapes. It seems like this might not be the way to compose a shape of the minimum number of triangles – nowi Apr 11 '20 at 06:47
  • @nowi poor stance. There is way too much stuff and life is finite. Avoid reinventing the wheel. – ALX23z Apr 11 '20 at 06:48
  • That's the standard way of tesselating something like that. Produces triangles with wide angles preferably and is dual to the Voronoi diagram. In any case, start with wikipedia: https://en.wikipedia.org/wiki/Delaunay_triangulation – Aziuth Apr 11 '20 at 06:49
  • For concave hulls you actually need something like constrained Delaunay triangulation. You might want to look at [this post](https://stackoverflow.com/questions/42075386/a-brute-force-constrained-delaunay-triangulation). – G.M. Apr 11 '20 at 06:50
  • @Aziuth Very interesting! I'll look into trying to implement this. – nowi Apr 11 '20 at 06:54
  • @G.M. I'll investigate further, hopefully I'll learn how to implement this. – nowi Apr 11 '20 at 06:55
  • @Aziuth Delaunay is not the correct tessellation to use for these cases. Only the cases that the polygon is itself the convex hull. Ear clipping is preffered, and also supports holes/internal loops which requires extra processing if using delaunay. – lfgtm Apr 11 '20 at 08:34

1 Answers1

1

The part you're missing is the "ear clipping algorithm" which selects an "ear" of the polygon which is a vertex that's ok to cut off in the manner you describe. It's guaranteed that any polygon (with at least 4 vertices) has at least 2 ears; the so-called "two ears theorem".

If you search for "ear clipping algorithm", you'll get a bunch of links on how to implement it more or less efficiently.

For example, this is some very clear code that identifies an ear (although in go, so you'd have to translate it): https://github.com/fogleman/triangulate/blob/master/ring.go

Paul Hankin
  • 54,811
  • 11
  • 92
  • 118