DeSiGNAR  0.5a
Data Structures General Library
triangle.H
Go to the documentation of this file.
1 /*
2  This file is part of Designar.
3  Copyright (C) 2017 by Alejandro J. Mujica
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  Any user request of this software, write to
19 
20  Alejandro Mujica
21 
22  aledrums@gmail.com
23 */
24 
25 # ifndef DSGTRIANGLE_H
26 # define DSGTRIANGLE_H
27 
28 # include <segment.H>
29 
30 namespace Designar
31 {
32 
33  template <class PointT>
35  {
36  PointT p1;
37  PointT p2;
38  PointT p3;
39 
40  public:
41  using PointType = PointT;
43 
44  GenTriangle(const PointT & _p1, const PointT & _p2, const PointT & _p3)
45  : p1(_p1), p2(_p2), p3(_p3)
46  {
47  if (p1.is_collinear_with(p2, p3))
48  throw std::logic_error("Points are collinear");
49  }
50 
52  : p1(t.p1), p2(t.p2), p3(t.p3)
53  {
54  // Empty
55  }
56 
58  {
59  swap(t);
60  }
61 
63  {
64  if (this == &t)
65  return *this;
66 
67  p1 = t.p1;
68  p2 = t.p2;
69  p3 = t.p3;
70 
71  return *this;
72  }
73 
75  {
76  swap(t);
77  return *this;
78  }
79 
80  void swap(GenTriangle & t)
81  {
82  std::swap(p1, t.p1);
83  std::swap(p2, t.p2);
84  std::swap(p3, t.p3);
85  }
86 
87  const PointT & get_p1() const
88  {
89  return p1;
90  }
91 
92  const PointT & get_p2() const
93  {
94  return p2;
95  }
96 
97  const PointT & get_p3() const
98  {
99  return p3;
100  }
101 
102  void set_p1(const PointT & _p1)
103  {
104  if (_p1.is_collinear_with(p2, p3))
105  throw std::domain_error("The new point is collinear with the others");
106 
107  p1 = _p1;
108  }
109 
110  void set_p1(PointT && _p1)
111  {
112  if (_p1.is_collinear_with(p2, p3))
113  throw std::domain_error("The new point is collinear with the others");
114 
115  p1 = std::move(_p1);
116  }
117 
118  void set_p2(const PointT & _p2)
119  {
120  if (p1.is_collinear_with(_p2, p3))
121  throw std::domain_error("The new point is collinear with the others");
122 
123  p2 = _p2;
124  }
125 
126  void set_p2(PointT && _p2)
127  {
128  if (p1.is_collinear_with(_p2, p3))
129  throw std::domain_error("The new point is collinear with the others");
130 
131  p2 = std::move(_p2);
132  }
133 
134  void set_p3(const PointT & _p3)
135  {
136  if (p1.is_collinear_with(p2, _p3))
137  throw std::domain_error("The new point is collinear with the others");
138 
139  p3 = _p3;
140  }
141 
142  void set_p3(PointT && _p3)
143  {
144  if (p1.is_collinear_with(p2, _p3))
145  throw std::domain_error("The new point is collinear with the others");
146 
147  p3 = std::move(_p3);
148  }
149 
150  real_t area() const
151  {
152  return Designar::abs(area_of_parallelogram(p1, p2, p3)) / 2.;
153  }
154 
155  bool is_clockwise() const
156  {
157  return p3.is_to_right_from(p1, p2);
158  }
159 
160  bool is_counterclockwise() const
161  {
162  return p3.is_to_left_from(p1, p2);
163  }
164 
165  bool contains_to(const PointT & p) const
166  {
167  if (p.is_between(p1, p2) or p.is_between(p2, p3) or p.is_between(p3, p1))
168  return true;
169 
170  bool test = p.is_to_left_from(p1, p2);
171 
172  if (p.is_to_left_from(p2, p3) != test)
173  return false;
174 
175  if (p.is_to_left_from(p3, p1) != test)
176  return false;
177 
178  return true;
179  }
180 
181  bool contains_to(const SegmentType & s) const
182  {
183  return contains_to(s.get_src_point()) and contains_to(s.get_tgt_point());
184  }
185 
186  bool intersects_properly_with(const SegmentType & s) const
187  {
188  return s.intersects_properly_with(SegmentType(p1, p2)) or
191  }
192 
193  bool intersects_with(const SegmentType & s) const
194  {
195  return s.intersects_with(SegmentType(p1, p2)) or
196  s.intersects_with(SegmentType(p2, p3)) or
197  s.intersects_with(SegmentType(p3, p1));
198  }
199 
201  {
202  PointT p[2];
203 
204  int i = 0;
205 
206  try
207  {
208  p[i] = s.intersection_with(SegmentType(p1, p2));
209 
210  if (p[i].is_between(p1, p2))
211  ++i;
212  }
213  catch(const std::domain_error &)
214  {
215  // Nothing to do
216  }
217 
218  try
219  {
220  p[i] = s.intersection_with(SegmentType(p2, p3));
221 
222  if (p[i].is_between(p2, p3))
223  ++i;
224  }
225  catch(const std::domain_error &)
226  {
227  // Nothing to do
228  }
229 
230  if (i == 2)
231  return SegmentType (p[0], p[1]);
232 
233  try
234  {
235  p[i] = s.intersection_with(SegmentType(p3, p1));
236 
237  if (p[i].is_between(p3, p1))
238  ++i;
239  }
240  catch(const std::domain_error &)
241  {
242  // Nothing to do
243  }
244 
245  if (i == 0)
246  throw std::domain_error("Triangle does not intersects with segment");
247 
248  return (i == 2) ? SegmentType(p[0], p[1]) : SegmentType(p[0], p[0]);
249  }
250 
251  bool operator == (const GenTriangle & t) const
252  {
253  return p1 == t.p1 and p2 == t.p2 and p3 == t.p3;
254  }
255 
256  bool operator != (const GenTriangle & t) const
257  {
258  return not (*this == t);
259  }
260  };
261 
262  class TriangleInt : public GenTriangle<PointInt2D>
263  {
265  using Base::Base;
266  };
267 
268  class Triangle : public GenTriangle<Point2D>
269  {
270  using Base = GenTriangle<Point2D>;
271  using Base::Base;
272  };
273 
274 } // end namespace Designar
275 
276 # endif // DSGTRIANGLE_H
bool intersects_with(const GenSegment &s) const
Definition: segment.H:189
PointT intersection_with(const GenSegment &s) const
Definition: segment.H:271
bool intersects_properly_with(const SegmentType &s) const
Definition: triangle.H:186
const PointT & get_src_point() const
Definition: segment.H:107
bool is_clockwise() const
Definition: triangle.H:155
double real_t
Definition: types.H:51
bool operator==(const GenTriangle &t) const
Definition: triangle.H:251
bool operator!=(const GenTriangle &t) const
Definition: triangle.H:256
void set_p2(const PointT &_p2)
Definition: triangle.H:118
bool is_counterclockwise() const
Definition: triangle.H:160
void swap(GenTriangle &t)
Definition: triangle.H:80
const PointT & get_p3() const
Definition: triangle.H:97
bool intersects_properly_with(const GenSegment &s) const
Definition: segment.H:177
Definition: triangle.H:262
SegmentType intersection_with(const SegmentType &s)
Definition: triangle.H:200
GenTriangle & operator=(const GenTriangle &t)
Definition: triangle.H:62
real_t area() const
Definition: triangle.H:150
void set_p3(PointT &&_p3)
Definition: triangle.H:142
const PointT & get_p1() const
Definition: triangle.H:87
GenTriangle(const PointT &_p1, const PointT &_p2, const PointT &_p3)
Definition: triangle.H:44
Definition: point2D.H:241
void set_p2(PointT &&_p2)
Definition: triangle.H:126
void set_p1(const PointT &_p1)
Definition: triangle.H:102
const PointT & get_tgt_point() const
Definition: segment.H:112
const PointT & get_p2() const
Definition: triangle.H:92
Definition: array.H:32
GenTriangle(GenTriangle &&t)
Definition: triangle.H:57
GenSegment< PointT > SegmentType
Definition: triangle.H:42
GenTriangle(const GenTriangle &t)
Definition: triangle.H:51
bool intersects_with(const SegmentType &s) const
Definition: triangle.H:193
void set_p1(PointT &&_p1)
Definition: triangle.H:110
Definition: triangle.H:34
T abs(T)
Definition: math.H:83
void set_p3(const PointT &_p3)
Definition: triangle.H:134
real_t area_of_parallelogram(const GenPoint2D< NumberType > &, const GenPoint2D< NumberType > &, const GenPoint2D< NumberType > &)
Definition: math.H:129
bool contains_to(const PointT &p) const
Definition: triangle.H:165
bool contains_to(const SegmentType &s) const
Definition: triangle.H:181
Definition: triangle.H:268