Points&Forces (core)
Software tools facilitating the task of surveying architecture
a_triangle.cxx
Go to the documentation of this file.
1 /*
2  Copyright 2000-19 Pierre SMARS (smars@yuntech.edu.tw)
3  This program is free software: you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation, either version 2 of the License, or
6  (at your option) any later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 #include "a_triangle.h"
17 #include "a_plane.h"
18 #include "a_segment.h"
19 
20 #include "a_debug.h"
21 #include <sstream>
22 
23 //---------------------------------------------------------------------------
24 const std::string a_triangle::help()
25 {
26  std::ostringstream o;
27  o << "***********" << std::endl;
28  o << "a_triangle:" << std::endl;
29  o << "***********" << std::endl;
30  o << "This is a 'triangle' class" << std::endl;
31  o << std::endl;
32  o << "Create a triangle:" << std::endl;
33  o << " a_triangle a" << std::endl;
34  o << " a_triangle a _p1 _p2 _p3" << std::endl;
35  o << std::endl;
36  o << "Commands:" << std::endl;
37  o << "p1, p2, p3: get or set apices" << std::endl;
38  o << "s1, s2, s3: returns sides of triangle as segments" << std::endl;
39  o << "s _ref: returns sides of triangle as segments" << std::endl;
40  o << "c: get centre" << std::endl;
41  o << "translate _x _y _z: translate." << std::endl;
42  o << "rotate _xaxis _yaxis _zaxis: rotate." << std::endl;
43  o << "invert: inverts orientation (p2 and p3)." << std::endl;
44  o << "normal: get normal vector" << std::endl;
45  o << "contains _pt: check whether contains point" << std::endl;
46  o << "closest _pt: triangle point closest to p" << std::endl;
47  o << "closestp _pt: point of plane defined by triangle closest to p" << std::endl;
48  o << "dist _pt: distance between p and triangle" << std::endl;
49  o << "distp _pt: distance between p and plane defined by triangle" << std::endl;
50  o << "intersect _seg: intersection of triangle with a segment" << std::endl;
51  o << "min_edge: length of shortest edge" << std::endl;
52  o << "max_edge: length of longest edge" << std::endl;
53  o << "quality: ratio between the shortest and longest edge" << std::endl;
54  o << a_geom_base::help();
55  return o.str();
56 }
57 //---------------------------------------------------------------------------
59 {
60  return ((p1_ == p.p1())&&(p2_ == p.p2())&&(p3_ == p.p3()));
61 }
62 //---------------------------------------------------------------------------
64 {
65  p1_ = p.p1();
66  p2_ = p.p2();
67  p3_ = p.p3();
68  return *this;
69 }
70 //---------------------------------------------------------------------------
71 a_segment a_triangle::s(const int ref) const
72 {
73  if (ref==0) return this->s1();
74  else if (ref==1) return this->s2();
75  return this->s3();
76 }
77 //-rotate--------------------------------------------------------------------
78 a_triangle& a_triangle::translate(double x, double y, double z)
79 {
80  p1_.translate(x,y,z);
81  p2_.translate(x,y,z);
82  p3_.translate(x,y,z);
83  return *this;
84 }
85 //-rotate--------------------------------------------------------------------
86 a_triangle& a_triangle::rotate(const a_point& x_axis, const a_point& y_axis, const a_point& z_axis)
87 {
88  p1_.rotate(x_axis, y_axis, z_axis);
89  p2_.rotate(x_axis, y_axis, z_axis);
90  p2_.rotate(x_axis, y_axis, z_axis);
91  return *this;
92 }
93 //---------------------------------------------------------------------------
95 {
96  a_point v = p2_;
97  p2_ = p3_;
98  p3_ = v;
99  return *this;
100 }
101 //---------------------------------------------------------------------------
103 {
104  return cross(p2_-p1_,p3_-p1_).normalise();
105 }
106 //---------------------------------------------------------------------------
107 double a_triangle::S() const
108 {
109  return cross(p2_-p1_,p3_-p1_).norm()/2.;
110 }
111 //---------------------------------------------------------------------------
113 {
114  a_point c = this->c();
115  return a_triangle(p1_-c,p2_-c,p3_-c);
116 }
117 //---------------------------------------------------------------------------
119 {
120  a_mat_sq a(3);
121  for (short i = 0; i<3; i++)
122  {
123  a_point p = this->p(i);
124  for (short j = 0; j<3; j++)
125  a(i,j) = p[j];
126  }
127  return a;
128 }
129 //---------------------------------------------------------------------------
131 {
132  a_mat_sq a(3);
133  a_triangle tri = this->shape();
134  a_point c = this->c();
135  double S = this->S();
136  //matrix of inertia of unit triangle: [(-1/3,-1/3) (2/3,-1/3) (-1/3,2/3)]
137  a_mat_sq s(3);
138  for (short i = 0; i<2; i++)
139  {
140  s(i,i) = 1./36.;
141  s(i,(i+1)%2) = -1./72.;
142  }
143  //matrix of transformation
144  a_mat_sq v(3);
145  a_point p1 = tri.p1();
146  a_point p2 = tri.p2();
147  for (short i = 0; i<2; i++)
148  {
149  v(i,0) = -2.*p1[i]-p2[i];
150  v(i,1) = -p1[i]+p2[i];
151  v(i,2) = 0.;
152  }
153  //its transpose
154  a_mat_sq vt(3);
155  vt = v.transpose();
156  a_mat_sq cm(3);
157  cm = v*s;
158  cm *= vt;
159  cm *= 2.*S;
160  //translation
161  a_mat_sq im(3);
162  im = c.inertia();
163  im *= S;
164  a = im+cm;
165  return a;
166 }
167 //---------------------------------------------------------------------------
168 bool a_triangle::contains(const a_point& p) const
169 {
171  if (this->distp(p)>verysmall_)
172  return false;
174  a_point v1 = this->p3()-this->p1();
175  a_point v2 = this->p2()-this->p1();
176  a_point vp = p-this->p1();
177  double a11 = v1*v1;
178  double a12 = v1*v2;
179  double a22 = v2*v2;
180  double p1 = vp*v1;
181  double p2 = vp*v2;
182  double det = a11*a22-a12*a12;
184  double u = (a22*p1-a12*p2)/det;
185  double v = (-a12*p1+a11*p2)/det;
186  if (u<0.)
187  return false;
188  if (v<0.)
189  return false;
190  if (u+v>1.)
191  return false;
192  return true;
193 }
194 //---------------------------------------------------------------------------
196 {
197  a_plane a(this->p1(),this->p2(),this->p3());
198  return a.closest(p);
199 }
200 //---------------------------------------------------------------------------
202 {
203  a_point pt = this->closestp(p);
204  if (this->contains(pt))
205  return pt;
206  a_segment s1(this->p1(),this->p2());
207  a_segment s2(this->p2(),this->p3());
208  a_segment s3(this->p3(),this->p1());
209  a_point p1 = s1.closest(p);
210  a_point p2 = s2.closest(p);
211  a_point p3 = s3.closest(p);
212  double d1 = (p-p1).norm();
213  double d2 = (p-p2).norm();
214  double d3 = (p-p3).norm();
215  if ((d1<d2)&&(d1<d3))
216  return p1;
217  if ((d2<d1)&&(d2<d3))
218  return p2;
219  return p3;
220 }
221 //---------------------------------------------------------------------------
222 double a_triangle::dist(const a_point& p) const
223 {
224  return (p-this->closest(p)).norm();
225 }
226 //---------------------------------------------------------------------------
227 double a_triangle::distp(const a_point& p) const
228 {
229  return (p-this->closestp(p)).norm();
230 }
231 //---------------------------------------------------------------------------
233 {
234  a_point p1 = s.p1();
235  a_point p2 = s.p2();
237  double d1 = this->distp(p1);
238  double d2 = this->distp(p2);
239  if ((d1>verysmall_)||(d2>verysmall_))
240  {
244  }
245  bool t1 = this->contains(p1);
246  bool t2 = this->contains(p2);
248  if (t1&&t2)
249  return s;
250  std::vector<a_point> list;
251  a_segment s1(p1_,p2_);
252  a_segment s2(p2_,p3_);
253  a_segment s3(p3_,p1_);
254  double m1,m2;
255  a_segment i1 = s1.shortest(s,m1,m2);
256  a_segment i2 = s2.shortest(s,m1,m2);
257  a_segment i3 = s3.shortest(s,m1,m2);
258  if (i1.length()<verysmall_)
259  list.push_back(i1.c());
260  if (i2.length()<verysmall_)
261  list.push_back(i2.c());
262  if (i3.length()<verysmall_)
263  list.push_back(i3.c());
265  if (!t1&&!t2)
266  {
267  if (list.size()==2)
268  return a_segment(list[0],list[1]);
269  else
270  throw a_segment::null_segment_error();//no intersection
271  }
273  if (t1)
274  return a_segment(p1,list[0]);
275  else
276  return a_segment(p2,list[0]);
277 }
278 //---------------------------------------------------------------------------
279 double a_triangle::min_edge() const
280 {
281  double m = this->s1().length();
282  double d2 = this->s2().length();
283  double d3 = this->s3().length();
284  if (d2<m)
285  m = d2;
286  if (d3<m)
287  m = d3;
288  return m;
289 }
290 //---------------------------------------------------------------------------
291 double a_triangle::max_edge() const
292 {
293  double M = this->s1().length();
294  double d2 = this->s2().length();
295  double d3 = this->s3().length();
296  if (d2>M)
297  M = d2;
298  if (d3>M)
299  M = d3;
300  return M;
301 }
302 //---------------------------------------------------------------------------
303 double a_triangle::quality() const
304 {
305  double m = this->s1().length();
306  double d2 = this->s2().length();
307  double d3 = this->s3().length();
308  double M = m;
309  if (d2<m)
310  m = d2;
311  else
312  M = d2;
313  if (d3<m)
314  m = d3;
315  if (d3>M)
316  M = d3;
317  if (M==0)
318  return 0.;
319  else
320  return m/M;
321 }
322 //***************************************************************************
323 //---------------------------------------------------------------------------
324 void a_triangle::read(std::istream &in)
325 {
326  in >> p1_;
327  in >> p2_;
328  in >> p3_;
329 }
330 //---------------------------------------------------------------------------
331 void a_triangle::write(std::ostream &o) const
332 {
333  o << this->p1() << " ";
334  o << this->p2() << " ";
335  o << this->p3() << " ";
336 }
a_point cross(const a_point &a, const a_point &b)
Definition: a_point.cxx:284
double verysmall_
Definition: a_base.h:62
static const std::string help()
Definition: a_geom_base.cxx:21
a square matrix unit
Definition: a_mat_sq.h:29
a_mat transpose()
Definition: a_mat.cxx:127
a plane
Definition: a_plane.h:32
a_point closest(const a_point &p) const
point on the plane closest to p
Definition: a_plane.cxx:71
a_point & rotate(const a_point &x_axis, const a_point &y_axis, const a_point &z_axis)
Definition: a_point.cxx:225
a_point & normalise()
Definition: a_point.cxx:190
a_point & translate(double x, double y, double z)
Definition: a_point.h:70
a_mat_sq inertia() const
Definition: a_point.cxx:197
double norm() const
Definition: a_point.cxx:168
a segment
Definition: a_segment.h:29
a_segment shortest(const a_segment &s, double &m1, double &m2) const
intersection between two segments, returns a segment between the closest point between the two segmen...
Definition: a_segment.cxx:177
a_point c() const
center of segment
Definition: a_segment.h:46
double length() const
Definition: a_segment.h:57
a_point p2() const
get second apex of segment
Definition: a_segment.h:40
a_point closest(const a_point &p) const
point closest to p inside segment
Definition: a_segment.cxx:117
a_point p1() const
get first apex of segment
Definition: a_segment.h:38
a triangle
Definition: a_triangle.h:31
a_triangle & invert()
Definition: a_triangle.cxx:94
a_point p3_
Definition: a_triangle.h:101
a_point p1_
Definition: a_triangle.h:99
a_triangle & rotate(const a_point &x_axis, const a_point &y_axis, const a_point &z_axis)
Definition: a_triangle.cxx:86
double max_edge() const
length of longest segment
Definition: a_triangle.cxx:291
static const std::string help()
Definition: a_triangle.cxx:24
a_point p(const int i) const
Definition: a_triangle.h:44
virtual void read(std::istream &i)
Definition: a_triangle.cxx:324
bool operator==(const a_triangle &p)
Definition: a_triangle.cxx:58
virtual void write(std::ostream &o) const
Definition: a_triangle.cxx:331
a_point p1() const
Definition: a_triangle.h:40
a_triangle & operator=(const a_triangle &p)
Definition: a_triangle.cxx:63
bool contains(const a_point &p) const
check whether point lies inside triangle
Definition: a_triangle.cxx:168
a_segment s(const int ref) const
get segment i (0-2) of triangle
Definition: a_triangle.cxx:71
a_triangle shape() const
triangle with same shape but with centre of gravity at origin
Definition: a_triangle.cxx:112
a_point closest(const a_point &p) const
triangle point closest to p
Definition: a_triangle.cxx:201
a_segment s2() const
get second segment of triangle
Definition: a_triangle.h:55
double S() const
Definition: a_triangle.cxx:107
a_segment s1() const
get first segment of triangle
Definition: a_triangle.h:53
a_point p3() const
Definition: a_triangle.h:42
a_mat_sq inertia() const
inertia of the triangle 3x3 matrix
Definition: a_triangle.cxx:130
double quality() const
quality: ratio between smaller and bigger segment
Definition: a_triangle.cxx:303
a_point c() const
get centre of gravity
Definition: a_triangle.h:61
a_point normal() const
Definition: a_triangle.cxx:102
double min_edge() const
length of smallest segment
Definition: a_triangle.cxx:279
a_segment s3() const
get third segment of triangle
Definition: a_triangle.h:57
a_segment intersect(const a_segment &s) const
intersection of triangle with a segment
Definition: a_triangle.cxx:232
a_triangle & translate(double x, double y, double z)
Definition: a_triangle.cxx:78
double distp(const a_point &p) const
distance between p and plane defined by triangle
Definition: a_triangle.cxx:227
a_point p2() const
Definition: a_triangle.h:41
a_point p2_
Definition: a_triangle.h:100
a_mat_sq coord() const
cordinates of the triangle as a 3x3 matrix
Definition: a_triangle.cxx:118
double dist(const a_point &p) const
distance between p and triangle
Definition: a_triangle.cxx:222
a_point closestp(const a_point &p) const
point of plane defined by triangle closest to p
Definition: a_triangle.cxx:195