1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkPoint_hxx
19 #define itkPoint_hxx
20 #include "itkPoint.h"
21 #include "itkNumericTraitsPointPixel.h"
22 #include "itkMath.h"
23 #include "itkObject.h"
24 
25 namespace itk
26 {
27 /**
28  * Assignment from a plain array
29  */
30 template< typename T, unsigned int TPointDimension >
31 Point< T, TPointDimension > &
32 Point< T, TPointDimension >
operator =(const ValueType r[TPointDimension])33 ::operator=(const ValueType r[TPointDimension])
34 {
35   BaseArray::operator=(r);
36   return *this;
37 }
38 
39 /**
40  * In place increment by a vector
41  */
42 template< typename T, unsigned int TPointDimension >
43 const Point< T, TPointDimension > &
44 Point< T, TPointDimension >
operator +=(const VectorType & vec)45 ::operator+=(const VectorType & vec)
46 {
47   for ( unsigned int i = 0; i < TPointDimension; i++ )
48     {
49     ( *this )[i] += vec[i];
50     }
51   return *this;
52 }
53 
54 /**
55  * In place subtract a vector
56  */
57 template< typename T, unsigned int TPointDimension >
58 const Point< T, TPointDimension > &
59 Point< T, TPointDimension >
operator -=(const VectorType & vec)60 ::operator-=(const VectorType & vec)
61 {
62   for ( unsigned int i = 0; i < TPointDimension; i++ )
63     {
64     ( *this )[i] -= vec[i];
65     }
66   return *this;
67 }
68 
69 /*
70  * Add operator with a vector
71  */
72 template< typename T, unsigned int TPointDimension >
73 Point< T, TPointDimension >
74 Point< T, TPointDimension >
operator +(const VectorType & vec) const75 ::operator+(const VectorType & vec) const
76 {
77   Self result;
78 
79   for ( unsigned int i = 0; i < TPointDimension; i++ )
80     {
81     result[i] = ( *this )[i] + vec[i];
82     }
83   return result;
84 }
85 
86 /*
87  * Subtract a vector, return a point
88  */
89 template< typename T, unsigned int TPointDimension >
90 Point< T, TPointDimension >
91 Point< T, TPointDimension >
operator -(const VectorType & vec) const92 ::operator-(const VectorType & vec)  const
93 {
94   Self result;
95 
96   for ( unsigned int i = 0; i < TPointDimension; i++ )
97     {
98     result[i] = ( *this )[i] - vec[i];
99     }
100   return result;
101 }
102 
103 /*
104  * Difference between two points
105  */
106 template< typename T, unsigned int TPointDimension >
107 Vector< T, TPointDimension >
108 Point< T, TPointDimension >
operator -(const Self & pnt) const109 ::operator-(const Self & pnt)  const
110 {
111   VectorType result;
112 
113   for ( unsigned int i = 0; i < TPointDimension; i++ )
114     {
115     result[i] = ( *this )[i] - pnt[i];
116     }
117   return result;
118 }
119 
120 /*
121  * Return a vnl_vector_ref
122  */
123 template< typename T, unsigned int TPointDimension >
124 vnl_vector_ref< T >
125 Point< T, TPointDimension >
GetVnlVector()126 ::GetVnlVector()
127 {
128   return vnl_vector_ref< T >( TPointDimension, this->GetDataPointer() );
129 }
130 
131 /**
132  * Return a vnl_vector const
133  */
134 template< typename T, unsigned int TPointDimension >
135 vnl_vector< T >
136 Point< T, TPointDimension >
GetVnlVector() const137 ::GetVnlVector() const
138 {
139   // Return a vector_ref<>.  This will be automatically converted to a
140   // vnl_vector<>.  We have to use a const_cast<> which would normally
141   // be prohibited in a const method, but it is safe to do here
142   // because the cast to vnl_vector<> will ultimately copy the data.
143   return vnl_vector_ref< T >( TPointDimension,
144                               const_cast< T * >( this->GetDataPointer() ) );
145 }
146 
147 template< typename T, unsigned int TPointDimension >
148 typename Point< T, TPointDimension >::VectorType
149 Point< T, TPointDimension >
GetVectorFromOrigin() const150 ::GetVectorFromOrigin() const
151 {
152   // VectorType knows how to construct from ValueType*.
153   return &( *this )[0];
154 }
155 
156 /**
157  * Set the point to the median point of the two arguments
158  */
159 template< typename T, unsigned int TPointDimension >
160 void
161 Point< T, TPointDimension >
SetToMidPoint(const Self & A,const Self & B)162 ::SetToMidPoint(const Self & A, const Self & B)
163 {
164   for ( unsigned int i = 0; i < TPointDimension; i++ )
165     {
166     ( *this )[i] = ( A[i] + B[i] ) / 2.0;
167     }
168 }
169 
170 /**
171  * Set the point to the barycentric combination of two points
172  */
173 template< typename T, unsigned int TPointDimension >
174 void
175 Point< T, TPointDimension >
SetToBarycentricCombination(const Self & A,const Self & B,double alpha)176 ::SetToBarycentricCombination(const Self & A,
177                               const Self & B,
178                               double alpha)
179 {
180   const double wa = alpha;
181   const double wb = 1.0 - alpha;
182 
183   for ( unsigned int i = 0; i < TPointDimension; i++ )
184     {
185     ( *this )[i] =  wa * A[i] + wb * B[i];
186     }
187 }
188 
189 /**
190  * Set the point to the barycentric combination of three points
191  */
192 template< typename T, unsigned int TPointDimension >
193 void
194 Point< T, TPointDimension >
SetToBarycentricCombination(const Self & A,const Self & B,const Self & C,double weightForA,double weightForB)195 ::SetToBarycentricCombination(const Self & A,
196                               const Self & B,
197                               const Self & C,
198                               double weightForA,
199                               double weightForB)
200 {
201   const double weightForC = 1.0 - weightForA - weightForB;
202 
203   for ( unsigned int i = 0; i < TPointDimension; i++ )
204     {
205     ( *this )[i] =  weightForA * A[i] + weightForB * B[i] + weightForC * C[i];
206     }
207 }
208 
209 /**
210  * Set the point to the barycentric combination of N points
211  */
212 template< typename T, unsigned int TPointDimension >
213 void
214 Point< T, TPointDimension >
SetToBarycentricCombination(const Self * P,const double * weights,unsigned int N)215 ::SetToBarycentricCombination(const Self *P,
216                               const double *weights, unsigned int N)
217 {
218   this->Fill(NumericTraits< T >::ZeroValue()); // put this point to null
219   double weightSum = 0.0;
220   for ( unsigned int j = 0; j < N - 1; j++ )
221     {
222     const double weight = weights[j];
223     weightSum += weight;
224     for ( unsigned int i = 0; i < TPointDimension; i++ )
225       {
226       ( *this )[i] += weight * P[j][i];
227       }
228     }
229   const double weight = ( 1.0 - weightSum );
230   for ( unsigned int i = 0; i < TPointDimension; i++ )
231     {
232     ( *this )[i] += weight * P[N - 1][i];
233     }
234 }
235 
236 /**
237  * Set the point to the barycentric combination of N points in a Container
238  */
239 template< typename TPointContainer, typename TWeightContainer >
240 typename BarycentricCombination< TPointContainer, TWeightContainer >
241 ::PointType
242 BarycentricCombination< TPointContainer, TWeightContainer >
Evaluate(const PointContainerPointer & points,const WeightContainerType & weights)243 ::Evaluate(
244   const PointContainerPointer & points,
245   const WeightContainerType & weights)
246 {
247   using ValueType = typename PointType::ValueType;
248   PointType barycentre;
249   barycentre.Fill(NumericTraits< ValueType >::ZeroValue());   // set to null
250 
251   typename TPointContainer::Iterator point = points->Begin();
252   typename TPointContainer::Iterator final = points->End();
253   typename TPointContainer::Iterator last  = final;
254   --last; // move to the (N)th point
255 
256   double weightSum = 0.0;
257 
258   const unsigned int PointDimension = PointType::PointDimension;
259   unsigned int       j = 0;
260 
261   while ( point != last )
262     {
263     const double weight = weights[j++];
264     weightSum += weight;
265     for ( unsigned int i = 0; i < PointDimension; i++ )
266       {
267       barycentre[i] += weight * ( point->Value() )[i];
268       }
269     ++point;
270     }
271 
272   // Compute directly the last one
273   // to make sure that the weights sum 1
274   const double weight = ( 1.0 - weightSum );
275   for ( unsigned int i = 0; i < PointDimension; i++ )
276     {
277     barycentre[i] += weight * ( last->Value() )[i];
278     }
279 
280   return barycentre;
281 }
282 
283 /**
284  * Print content to an ostream
285  */
286 template< typename T, unsigned int TPointDimension >
287 std::ostream &
operator <<(std::ostream & os,const Point<T,TPointDimension> & vct)288 operator<<(std::ostream & os, const Point< T, TPointDimension > & vct)
289 {
290   os << "[";
291   if ( TPointDimension == 1 )
292     {
293     os << vct[0];
294     }
295   else
296     {
297     for ( unsigned int i = 0; i + 1 < TPointDimension; i++ )
298       {
299       os <<  vct[i] << ", ";
300       }
301     os <<  vct[TPointDimension - 1];
302     }
303   os << "]";
304   return os;
305 }
306 
307 /**
308  * Read content from an istream
309  */
310 template< typename T, unsigned int TPointDimension >
311 std::istream &
operator >>(std::istream & is,Point<T,TPointDimension> & vct)312 operator>>(std::istream & is, Point< T, TPointDimension > & vct)
313 {
314   for ( unsigned int i = 0; i < TPointDimension; i++ )
315     {
316     is >>  vct[i];
317     }
318   return is;
319 }
320 
321 } // end namespace itk
322 
323 #endif
324