IntelliPhoto  0.6
IntelliTriangulation.cpp
Go to the documentation of this file.
1 #include "IntelliTriangulation.h"
2 #include <algorithm>
3 #include <queue>
4 #include <cmath>
5 #define pi 3.1415926535897932384626433832795
6 
7 std::vector<Triangle> IntelliTriangulation::calculateTriangles(std::vector<QPoint> polyPoints){
8  // helper for managing the triangle vertices and their state
9  struct TriangleHelper {
10  QPoint vertex;
11  float interiorAngle;
12  int idx;
13  bool isTip;
14  };
15 
16  // calculates the inner angle of 'point'
17  auto calculateInner = [] (QPoint& point, QPoint& prev, QPoint& post) {
18  QPoint AP(point.x() - prev.x(), point.y() - prev.y());
19  QPoint BP(point.x() - post.x(), point.y() - post.y());
20 
21  float topSclar = AP.x() * BP.x() + AP.y() * BP.y();
22  float absolute = static_cast<float>(sqrt(pow(AP.x(),2.) + pow(AP.y(),2.)) * sqrt(pow(BP.x(),2.) + pow(BP.y(),2.)));
23  return acos(topSclar / absolute);
24  };
25 
26  // gets the first element of vec for which element.isTip == true holds
27  auto getTip = [] (const std::vector<TriangleHelper>& vec) {
28  size_t min = 0;
29  for(size_t i = 0; i<vec.size(); i++) {
30  if(vec[i].interiorAngle<vec[min].interiorAngle) {
31  min = i;
32  }
33  }
34  return vec[min];
35  };
36 
37  // get the vertex idx bevor idx in relation to the container length
38  auto getPrev = [] (int idx, int length) {
39  return (idx - 1)>=0 ? (idx - 1) : (length - 1);
40  };
41 
42  // get the vertex idx after idx in relation to the container lenght
43  auto getPost = [] (int idx, int length) {
44  return (idx + 1) % length;
45  };
46 
47  // return if the vertex is a tip
48  auto isTip = [] (float angle) {
49  return static_cast<double>(angle)<(pi / 2.);
50  };
51 
52  std::vector<TriangleHelper> Vertices;
53  std::vector<Triangle> Triangles;
54 
55  // set up all vertices and calculate intirior angle
56  for(int i = 0; i<static_cast<int>(polyPoints.size()); i++) {
57  TriangleHelper helper;
58  int prev = getPrev(i, static_cast<int>(polyPoints.size()));
59  int post = getPost(i, static_cast<int>(polyPoints.size()));
60 
61  helper.vertex = polyPoints[static_cast<size_t>(i)];
62  helper.idx = i;
63 
64  helper.interiorAngle = calculateInner(polyPoints[static_cast<size_t>(i)],
65  polyPoints[static_cast<size_t>(prev)],
66  polyPoints[static_cast<size_t>(post)]);
67  helper.isTip = isTip(helper.interiorAngle);
68  Vertices.push_back(helper);
69  }
70 
71  // search triangles based on the intirior angles of each vertey
72  while(Triangles.size() != polyPoints.size() - 2) {
73  Triangle tri;
74  TriangleHelper smallest = getTip(Vertices);
75  int prev = getPrev(smallest.idx, static_cast<int>(Vertices.size()));
76  int post = getPost(smallest.idx, static_cast<int>(Vertices.size()));
77 
78  // set triangle and push it
79  tri.A = Vertices[static_cast<size_t>(prev)].vertex;
80  tri.B = Vertices[static_cast<size_t>(smallest.idx)].vertex;
81  tri.C = Vertices[static_cast<size_t>(post)].vertex;
82  Triangles.push_back(tri);
83 
84  // update Vertice array
85  Vertices.erase(Vertices.begin() + smallest.idx);
86  for(size_t i = static_cast<size_t>(smallest.idx); i<Vertices.size(); i++) {
87  Vertices[i].idx -= 1;
88  }
89 
90  // update post und prev idx
91  post = getPrev(post, Vertices.size());
92  prev = prev<smallest.idx ? prev : (prev - 1);
93 
94  // calcultae neighboors of prev and post to calculate new interior angles
95  int prevOfPrev = getPrev(prev, static_cast<int>(Vertices.size()));
96  int postOfPrev = getPost(prev, static_cast<int>(Vertices.size()));
97 
98  int prevOfPost = getPrev(post, static_cast<int>(Vertices.size()));
99  int postOfPost = getPost(post, static_cast<int>(Vertices.size()));
100 
101  // update vertices with interior angles
102  // updtae prev
103  Vertices[static_cast<size_t>(prev)].interiorAngle = calculateInner(Vertices[static_cast<size_t>(prev)].vertex,
104  Vertices[static_cast<size_t>(prevOfPrev)].vertex,
105  Vertices[static_cast<size_t>(postOfPrev)].vertex);
106  Vertices[static_cast<size_t>(prev)].isTip = isTip(Vertices[static_cast<size_t>(prev)].interiorAngle);
107  // update post
108  Vertices[static_cast<size_t>(post)].interiorAngle = calculateInner(Vertices[static_cast<size_t>(post)].vertex,
109  Vertices[static_cast<size_t>(prevOfPost)].vertex,
110  Vertices[static_cast<size_t>(postOfPost)].vertex);
111  Vertices[static_cast<size_t>(post)].isTip = isTip(Vertices[static_cast<size_t>(post)].interiorAngle);
112  }
113  return Triangles;
114 }
115 
116 bool IntelliTriangulation::isInPolygon(const std::vector<Triangle> &triangles, QPoint &point){
117  for(auto triangle : triangles) {
118  if(IntelliTriangulation::isInTriangle(triangle, point)) {
119  return true;
120  }
121  }
122  return false;
123 }
IntelliTriangulation::isInTriangle
bool isInTriangle(Triangle &tri, QPoint &P)
A function to check if a given point is in a triangle.
Definition: IntelliTriangulation.h:36
IntelliTriangulation::calculateTriangles
std::vector< Triangle > calculateTriangles(std::vector< QPoint > polyPoints)
A function to split a polygon in its spanning traingles by using Meisters Theorem of graph theory by ...
Definition: IntelliTriangulation.cpp:7
Triangle::B
QPoint B
Definition: IntelliTriangulation.h:14
pi
#define pi
Definition: IntelliTriangulation.cpp:5
Triangle::C
QPoint C
Definition: IntelliTriangulation.h:14
Triangle
The Triangle struct holds the 3 vertices of a triangle.
Definition: IntelliTriangulation.h:13
Triangle::A
QPoint A
Definition: IntelliTriangulation.h:14
IntelliTriangulation::isInPolygon
bool isInPolygon(const std::vector< Triangle > &triangles, QPoint &point)
A function to check if a point lies in a polygon by checking its spanning triangles.
Definition: IntelliTriangulation.cpp:116
IntelliTriangulation.h