Free Electron
Barycenter.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __math_Barycenter_h__
8 #define __math_Barycenter_h__
9 
10 namespace fe
11 {
12 
13 /**************************************************************************//**
14  @brief Barycentric coordinates for a triangle
15 
16  @ingroup math
17 
18  b2 is not stored, but implied as (1 - b0 - b1)
19 
20  Usually, b0 >= 0, b1 >= 0, and b0 + b1 <= 1,
21  but this is not a restriction.
22 
23  coincident point = vert0 * b0 + vert1 * b1 + vert2 * b2
24 *//***************************************************************************/
25 template <typename T>
26 class Barycenter: public Vector<2,T>
27 {
28  public:
29  Barycenter(void) {}
30 
31  Barycenter(T a_b0, T a_b1)
32  { set(*this,a_b0,a_b1); }
33 
34  Barycenter(T a_b0, T a_b1, T a_b2)
35  { set(*this,a_b0,a_b1,a_b2); }
36 
37  Barycenter(const Barycenter<T>& a_rOther):
38  Vector<2,T>()
39  { Vector<2,T>::operator=(a_rOther); }
40 
41  Barycenter(const Vector<3,T>& a_rOther):
42  Vector<2,T>()
43  { set(*this,a_rOther[0],a_rOther[1]); }
44 
45  Barycenter& operator=(const Barycenter<T>& a_rOther)
46  { Vector<2,T>::operator=(a_rOther);
47  return *this; }
48 
49  Barycenter& operator=(const Vector<3,T>& a_rOther)
50  { Vector<2,T>::operator=(a_rOther);
51  return *this; }
52 
53  //* TODO verify using RayTriangleIntersect
54  //* I think their U and V are normalized weights
55  //* toward vert1 and vert2 from vert0.
56  Barycenter& setUV(T a_u,T a_v)
57  { set(*this,T(1)-a_u-a_v,a_u);
58  return *this; }
59 
60  operator Vector<3,T>(void) const
61  { return Vector<3,T>((*this)[0],(*this)[1],
62  T(1)-(*this)[0]-(*this)[1]); }
63 
64  void solve(
65  const Vector<3,T>& a_vert0,
66  const Vector<3,T>& a_vert1,
67  const Vector<3,T>& a_vert2,
68  const Vector<3,T>& a_point);
69 
70  //* clamp to triangle
71  void clamp(
72  const Vector<3,T>& a_vert0,
73  const Vector<3,T>& a_vert1,
74  const Vector<3,T>& a_vert2);
75 
76  private:
77 
78 static T along( const Vector<3,T>& start,
79  const Vector<3,T>& end,
80  const Vector<3,T>& point);
81 };
82 
83 template<class T, typename U, typename V, typename W>
84 inline Barycenter<T>& set(Barycenter<T> &a_lhs, U a_b0, V a_b1, W a_b2)
85 {
86  FEASSERT(fabs(a_b0+a_b1+a_b2-T(1))<T(0.001));
87  set(a_lhs,a_b0,a_b1);
88  return a_lhs;
89 }
90 
91 template<int N,class T, typename U, typename V, typename W>
92 inline Vector<N,T> location(const Barycenter<T>& a_barycenter,
93  const Vector<N,U>& a_vert0,
94  const Vector<N,V>& a_vert1,
95  const Vector<N,W>& a_vert2)
96 {
97  return a_vert0*a_barycenter[0]+a_vert1*a_barycenter[1]+
98  a_vert2*(T(1)-a_barycenter[0]-a_barycenter[1]);
99 }
100 
101 template<class T, typename U>
102 inline U blend(const Barycenter<T>& a_barycenter,
103  U a_value0, U a_value1, U a_value2)
104 {
105  return a_value0*a_barycenter[0]+a_value1*a_barycenter[1]+
106  a_value2*(T(1)-a_barycenter[0]-a_barycenter[1]);
107 }
108 
109 template <typename T>
110 inline void Barycenter<T>::solve(
111  const Vector<3,T>& a_vert0,
112  const Vector<3,T>& a_vert1,
113  const Vector<3,T>& a_vert2,
114  const Vector<3,T>& a_point)
115 {
116  const T A=a_vert0[0]-a_vert2[0];
117  const T B=a_vert1[0]-a_vert2[0];
118  const T C=a_vert2[0]-a_point[0];
119 
120  const T D=a_vert0[1]-a_vert2[1];
121  const T E=a_vert1[1]-a_vert2[1];
122  const T F=a_vert2[1]-a_point[1];
123 
124  const T G=a_vert0[2]-a_vert2[2];
125  const T H=a_vert1[2]-a_vert2[2];
126  const T I=a_vert2[2]-a_point[2];
127 
128  const T d0=(A*(E+H)-B*(D+G));
129  const T d1=(B*(D+G)-A*(E+H));
130 
131  const T b0=(d0==0.0)? 0.0: (B*(F+I)-C*(E+H))/d0;
132  const T b1=(d1==0.0)? 0.0: (A*(F+I)-C*(D+G))/d1;
133 
134  set(*this,b0,b1);
135 }
136 
137 //* TODO can this be done without verts simply in unit space?
138 template <typename T>
139 inline void Barycenter<T>::clamp(
140  const Vector<3,T>& a_vert0,
141  const Vector<3,T>& a_vert1,
142  const Vector<3,T>& a_vert2)
143 {
144  const Vector<3,T> point=location(*this,a_vert0,a_vert1,a_vert2);
145 
146  if((*this)[0]<T(0))
147  {
148  (*this)[0]=T(0);
149  (*this)[1]=along(a_vert2,a_vert1,point);
150  }
151  else if((*this)[1]<T(0))
152  {
153  (*this)[0]=along(a_vert2,a_vert0,point);
154  (*this)[1]=T(0);
155  }
156  else
157  {
158  const T sum=(*this)[0]+(*this)[1];
159  if(sum>T(1))
160  {
161  (*this)[0]=along(a_vert1,a_vert0,point);
162  (*this)[1]=T(1)-(*this)[0];
163  }
164  }
165 }
166 
167 template <typename T>
168 inline T Barycenter<T>::along(const Vector<3,T>& start,
169  const Vector<3,T>& end,
170  const Vector<3,T>& point)
171 {
172  const Vector<3,T> edge=end-start;
173  const T mag2=magnitudeSquared(edge);
174  if(mag2==T(0))
175  {
176  return T(0);
177  }
178 
179  T result=dot(edge,point-start)/mag2;
180  if(result<T(0))
181  {
182  return T(0);
183  }
184  if(result>T(1))
185  {
186  return T(1);
187  }
188  return result;
189 }
190 
192 
193 } /* namespace */
194 
195 #endif /* __math_Barycenter_h__ */
196 
kernel
Definition: namespace.dox:3
Barycentric coordinates for a triangle.
Definition: Barycenter.h:26
Dense vector - size fixed by template.
Definition: Vector.h:19
T dot(const Vector< N, T > &lhs, const Vector< N, T > &rhs)
Dot (inner) product.
Definition: Vector.h:768
T magnitudeSquared(const Vector< N, T > &rhs)
Square of the length.
Definition: Vector.h:794