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