GRALE
triangle2d.h
Go to the documentation of this file.
1 /*
2 
3  This file is a part of GRALE, a library to facilitate the simulation
4  and inversion of gravitational lenses.
5 
6  Copyright (C) 2008-2012 Jori Liesenborgs
7 
8  Contact: jori.liesenborgs@gmail.com
9 
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 
24 */
25 
30 #ifndef GRALE_TRIANGLE2D_H
31 
32 #define GRALE_TRIANGLE2D_H
33 
34 #include "graleconfig.h"
35 #include "line2d.h"
36 #include "pointsort.h"
37 #include "Wm5IntrTriangle2Triangle2.h"
38 #include <algorithm>
39 #include <vector>
40 
41 namespace grale
42 {
43 
45 template<class T>
47 {
48 public:
49  Triangle2D() { }
50  Triangle2D(Vector2D<T> point1, Vector2D<T> point2, Vector2D<T> point3) { m_points[0] = point1; m_points[1] = point2; m_points[2] = point3; m_points[3] = point1; }
51  Triangle2D(Vector2D<T> p[3]) { m_points[0] = p[0]; m_points[1] = p[1]; m_points[2] = p[2]; m_points[3] = p[0]; }
52  T getArea() const;
53  T getOverlapArea(const Triangle2D<T> &t) const;
54  bool isInside(Vector2D<T> point) const;
55  const Vector2D<T> *getPoints() const { return m_points; }
56  Vector2D<T> getCentroid() const;
57 protected:
58  Vector2D<T> m_points[4]; // last one is same as first one
59 };
60 
61 template<class T>
62 inline T Triangle2D<T>::getArea() const
63 {
64  // Easy to calculate using cross product
65 
66  Vector2D<T> vec1 = m_points[1] - m_points[0];
67  Vector2D<T> vec2 = m_points[2] - m_points[0];
68 
69  return ((T)0.5)*ABS(vec1.getX()*vec2.getY() - vec1.getY()*vec2.getX());
70 }
71 
72 template<class T>
73 bool Triangle2D<T>::isInside(Vector2D<T> point) const
74 {
75  int posCount = 0;
76  int negCount = 0;
77 
78  for (int i = 0 ; i < 3 ; i++)
79  {
80  Vector2D<T> v = m_points[i+1] - m_points[i];
81  Vector2D<T> w = point - m_points[i];
82  T value = v.getX()*w.getY() - v.getY()*w.getX();
83  if (value > 0)
84  posCount++;
85  else if (value < 0)
86  negCount++;
87  else
88  {
89  posCount++;
90  negCount++;
91  }
92  }
93  if (posCount == 3 || negCount == 3)
94  return true;
95  return false;
96 }
97 
98 template<class T>
99 inline T Triangle2D<T>::getOverlapArea(const Triangle2D<T> &t) const
100 {
101  Wm5::Triangle2<T> t1;
102  Wm5::Triangle2<T> t2;
103 
104  Vector2D<T> A = m_points[1]-m_points[0];
105  Vector2D<T> B = m_points[2]-m_points[0];
106 
107  if (A.getX()*B.getY() - A.getY()*B.getX() > 0)
108  {
109  t1 = Wm5::Triangle2<T>(Wm5::Vector2<T>(m_points[0].getX(), m_points[0].getY()),
110  Wm5::Vector2<T>(m_points[1].getX(), m_points[1].getY()),
111  Wm5::Vector2<T>(m_points[2].getX(), m_points[2].getY()));
112  }
113  else
114  {
115  t1 = Wm5::Triangle2<T>(Wm5::Vector2<T>(m_points[1].getX(), m_points[1].getY()),
116  Wm5::Vector2<T>(m_points[0].getX(), m_points[0].getY()),
117  Wm5::Vector2<T>(m_points[2].getX(), m_points[2].getY()));
118  }
119 
120  A = t.m_points[1]-t.m_points[0];
121  B = t.m_points[2]-t.m_points[0];
122 
123  if (A.getX()*B.getY() - A.getY()*B.getX() > 0)
124  {
125  t2 = Wm5::Triangle2<T>(Wm5::Vector2<T>(t.m_points[0].getX(), t.m_points[0].getY()),
126  Wm5::Vector2<T>(t.m_points[1].getX(), t.m_points[1].getY()),
127  Wm5::Vector2<T>(t.m_points[2].getX(), t.m_points[2].getY()));
128  }
129  else
130  {
131  t2 = Wm5::Triangle2<T>(Wm5::Vector2<T>(t.m_points[1].getX(), t.m_points[1].getY()),
132  Wm5::Vector2<T>(t.m_points[0].getX(), t.m_points[0].getY()),
133  Wm5::Vector2<T>(t.m_points[2].getX(), t.m_points[2].getY()));
134  }
135 
136  Wm5::IntrTriangle2Triangle2<T> intersection(t1, t2);
137 
138  //for (int i = 0 ; i < 4 ; i++)
139  //std::cout << m_points[i].getX() << " " << m_points[i].getY() << std::endl;
140 
141  //std::cout << std::endl;
142  //std::cout << std::endl;
143 
144  //for (int i = 0 ; i < 4 ; i++)
145  //std::cout << t.m_points[i].getX() << " " << t.m_points[i].getY() << std::endl;
146 
147  //std::cout << std::endl;
148  //std::cout << std::endl;
149 
150  if (!intersection.Test())
151  return 0;
152 
153  if (!intersection.Find())
154  return 0;
155 
156  int numIntersectionPoints = intersection.GetQuantity();
157 
158  //for (int i = 0 ; i < numIntersectionPoints ; i++)
159  //std::cout << intersection.GetPoint(i).X() << " " << intersection.GetPoint(i).Y() << std::endl;
160  //std::cout << intersection.GetPoint(0).X() << " " << intersection.GetPoint(0).Y() << std::endl;
161 
162  if (numIntersectionPoints < 3)
163  return 0;
164 
165  int num = numIntersectionPoints - 2;
166  T totalArea = 0;
167  Vector2D<T> v1(intersection.GetPoint(0).X(), intersection.GetPoint(0).Y());
168 
169  for (int i = 0 ; i < num ; i++)
170  {
171  Vector2D<T> v2(intersection.GetPoint(i+1).X(),intersection.GetPoint(i+1).Y());
172  Vector2D<T> v3(intersection.GetPoint(i+2).X(),intersection.GetPoint(i+2).Y());
173 
174  Triangle2D<T> t2(v1, v2, v3);
175 
176  totalArea += t2.getArea();
177  }
178 
179  return totalArea;
180 }
181 
182 template<class T>
183 Vector2D<T> Triangle2D<T>::getCentroid() const
184 {
185  return (m_points[0] + m_points[1] + m_points[2])/((T)3);
186 }
187 
188 template<class T>
189 class Triangle2DPlus : public Triangle2D<T>
190 {
191 public:
192  Triangle2DPlus(Vector2D<T> point1, Vector2D<T> point2, Vector2D<T> point3, T height1, T height2, T height3) : Triangle2D<T>(point1, point2, point3)
193  {
194  m_heights[0] = height1;
195  m_heights[1] = height2;
196  m_heights[2] = height3;
197  m_heights[3] = height1;
198  m_diff1 = Triangle2D<T>::m_points[1] - Triangle2D<T>::m_points[0];
199  m_diff2 = Triangle2D<T>::m_points[2] - Triangle2D<T>::m_points[0];
200  m_hdiff1 = m_heights[1] - m_heights[0];
201  m_hdiff2 = m_heights[2] - m_heights[0];
202  m_denom = m_diff1.getX()*m_diff2.getY() - m_diff1.getY()*m_diff2.getX();
203  }
204 
205  bool isInside(Vector2D<T> point, T &height)
206  {
207  if (!Triangle2D<T>::isInside(point))
208  return false;
209 
210  Vector2D<T> pdiff = point - Triangle2D<T>::m_points[0];
211  T alpha = (m_diff2.getY()*pdiff.getX() - m_diff2.getX()*pdiff.getY())/m_denom;
212  T beta = (-m_diff1.getY()*pdiff.getX() + m_diff1.getX()*pdiff.getY())/m_denom;
213 
214  height = m_heights[0] + alpha*m_hdiff1 + beta*m_hdiff2;
215 
216  return true;
217  }
218 
219  const double *getHeights() const { return m_heights; }
220 private:
221  T m_heights[4];
222  T m_denom, m_hdiff1, m_hdiff2;
223  Vector2D<T> m_diff1, m_diff2;
224 };
225 
226 }
227 
228 #endif // GRALE_TRIANGLE2D_H
229