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 itkTetrahedronCell_hxx
19 #define itkTetrahedronCell_hxx
20 #include "itkTetrahedronCell.h"
21 #include "vnl/algo/vnl_determinant.h"
22
23 namespace itk
24 {
25 /**
26 * Standard CellInterface:
27 */
28 template< typename TCellInterface >
29 void
30 TetrahedronCell< TCellInterface >
MakeCopy(CellAutoPointer & cellPointer) const31 ::MakeCopy(CellAutoPointer & cellPointer) const
32 {
33 cellPointer.TakeOwnership(new Self);
34 cellPointer->SetPointIds( this->GetPointIds() );
35 }
36
37 /**
38 * Standard CellInterface:
39 * Get the topological dimension of this cell.
40 */
41 template< typename TCellInterface >
42 unsigned int
43 TetrahedronCell< TCellInterface >
GetDimension() const44 ::GetDimension() const
45 {
46 return Self::CellDimension;
47 }
48
49 /**
50 * Standard CellInterface:
51 * Get the number of points required to define the cell.
52 */
53 template< typename TCellInterface >
54 unsigned int
55 TetrahedronCell< TCellInterface >
GetNumberOfPoints() const56 ::GetNumberOfPoints() const
57 {
58 return Self::NumberOfPoints;
59 }
60
61 /**
62 * Standard CellInterface:
63 * Get the number of boundary features of the given dimension.
64 */
65 template< typename TCellInterface >
66 typename TetrahedronCell< TCellInterface >::CellFeatureCount
67 TetrahedronCell< TCellInterface >
GetNumberOfBoundaryFeatures(int dimension) const68 ::GetNumberOfBoundaryFeatures(int dimension) const
69 {
70 switch ( dimension )
71 {
72 case 0:
73 return GetNumberOfVertices();
74 case 1:
75 return GetNumberOfEdges();
76 case 2:
77 return GetNumberOfFaces();
78 default:
79 return 0;
80 }
81 }
82
83 template< typename TCellInterface >
84 bool
85 TetrahedronCell< TCellInterface >
EvaluatePosition(CoordRepType * x,PointsContainer * points,CoordRepType * closestPoint,CoordRepType pcoord[3],double * minDist2,InterpolationWeightType * weights)86 ::EvaluatePosition(CoordRepType *x,
87 PointsContainer *points,
88 CoordRepType *closestPoint,
89 CoordRepType pcoord[3],
90 double *minDist2,
91 InterpolationWeightType *weights)
92 {
93 unsigned int i;
94 double rhs[PointDimension];
95 double c1[PointDimension];
96 double c2[PointDimension];
97 double c3[PointDimension];
98 double det;
99 double p4;
100
101 CoordRepType pcoords[3];
102
103 pcoords[0] = pcoords[1] = pcoords[2] = 0.0;
104
105 if ( !points )
106 {
107 return false;
108 }
109
110 PointType pt1 = points->GetElement(m_PointIds[0]);
111 PointType pt2 = points->GetElement(m_PointIds[1]);
112 PointType pt3 = points->GetElement(m_PointIds[2]);
113 PointType pt4 = points->GetElement(m_PointIds[3]);
114
115 for ( i = 0; i < PointDimension; i++ )
116 {
117 rhs[i] = x[i] - pt4[i];
118 c1[i] = pt1[i] - pt4[i];
119 c2[i] = pt2[i] - pt4[i];
120 c3[i] = pt3[i] - pt4[i];
121 }
122
123 // Create a vnl_matrix so that the determinant can be computed
124 // for any PointDimension
125 vnl_matrix_fixed< CoordRepType, 3, PointDimension > mat;
126 for ( i = 0; i < PointDimension; i++ )
127 {
128 mat.put(0, i, c1[i]);
129 mat.put(1, i, c2[i]);
130 mat.put(2, i, c3[i]);
131 }
132
133 if ( ( det = vnl_determinant(mat) ) == 0.0 )
134 {
135 return false;
136 }
137
138 for ( i = 0; i < PointDimension; i++ )
139 {
140 mat.put(0, i, rhs[i]);
141 mat.put(1, i, c2[i]);
142 mat.put(2, i, c3[i]);
143 }
144
145 pcoords[0] = vnl_determinant(mat) / det;
146
147 for ( i = 0; i < PointDimension; i++ )
148 {
149 mat.put(0, i, c1[i]);
150 mat.put(1, i, rhs[i]);
151 mat.put(2, i, c3[i]);
152 }
153
154 pcoords[1] = vnl_determinant(mat) / det;
155
156 for ( i = 0; i < PointDimension; i++ )
157 {
158 mat.put(0, i, c1[i]);
159 mat.put(1, i, c2[i]);
160 mat.put(2, i, rhs[i]);
161 }
162
163 pcoords[2] = vnl_determinant(mat) / det;
164
165 p4 = 1.0 - pcoords[0] - pcoords[1] - pcoords[2];
166
167 if ( weights )
168 {
169 weights[0] = p4;
170 weights[1] = pcoords[0];
171 weights[2] = pcoords[1];
172 weights[3] = pcoords[2];
173 }
174
175 if ( pcoord )
176 {
177 pcoord[0] = pcoords[0];
178 pcoord[1] = pcoords[1];
179 pcoord[2] = pcoords[2];
180 }
181
182 if ( pcoords[0] >= -0.001 && pcoords[0] <= 1.001
183 && pcoords[1] >= -0.001 && pcoords[1] <= 1.001
184 && pcoords[2] >= -0.001 && pcoords[2] <= 1.001 && p4 >= -0.001 && p4 <= 1.001 )
185 {
186 if ( closestPoint )
187 {
188 for ( unsigned int ii = 0; ii < PointDimension; ii++ )
189 {
190 closestPoint[ii] = x[ii];
191 }
192 if ( minDist2 )
193 {
194 *minDist2 = 0.0; //inside tetra
195 }
196 }
197 return true;
198 }
199 else
200 { //could easily be sped up using parametric localization - next release
201 double dist2;
202 CoordRepType closest[PointDimension], pc[3];
203
204 if ( closestPoint )
205 {
206 FaceAutoPointer triangle;
207 *minDist2 = NumericTraits< double >::max();
208 for ( i = 0; i < 4; i++ )
209 {
210 this->GetFace (i, triangle);
211 triangle->EvaluatePosition(x, points, closest, pc, &dist2, nullptr);
212
213 if ( dist2 < *minDist2 )
214 {
215 for( unsigned int dim = 0; dim < PointDimension; dim++ )
216 {
217 closestPoint[dim] = closest[dim];
218 }
219 *minDist2 = dist2;
220 }
221 }
222 }
223 //Just fall through to default return false;
224 }
225 return false;
226 }
227
228 /**
229 * Standard CellInterface:
230 * Get the boundary feature of the given dimension specified by the given
231 * cell feature Id.
232 * The Id can range from 0 to GetNumberOfBoundaryFeatures(dimension)-1.
233 */
234 template< typename TCellInterface >
235 bool
236 TetrahedronCell< TCellInterface >
GetBoundaryFeature(int dimension,CellFeatureIdentifier featureId,CellAutoPointer & cellPointer)237 ::GetBoundaryFeature(int dimension, CellFeatureIdentifier featureId,
238 CellAutoPointer & cellPointer)
239 {
240 switch ( dimension )
241 {
242 case 0:
243 {
244 VertexAutoPointer vertexPointer;
245 if ( this->GetVertex(featureId, vertexPointer) )
246 {
247 TransferAutoPointer(cellPointer, vertexPointer);
248 return true;
249 }
250 break;
251 }
252 case 1:
253 {
254 EdgeAutoPointer edgePointer;
255 if ( this->GetEdge(featureId, edgePointer) )
256 {
257 TransferAutoPointer(cellPointer, edgePointer);
258 return true;
259 }
260 break;
261 }
262 case 2:
263 {
264 FaceAutoPointer facePointer;
265 if ( this->GetFace(featureId, facePointer) )
266 {
267 TransferAutoPointer(cellPointer, facePointer);
268 return true;
269 }
270 break;
271 }
272 default:
273 break; //just fall through
274 }
275 cellPointer.Reset();
276 return false;
277 }
278
279 /**
280 * Standard CellInterface:
281 * Set the point id list used by the cell. It is assumed that the given
282 * iterator can be incremented and safely de-referenced enough times to
283 * get all the point ids needed by the cell.
284 */
285 template< typename TCellInterface >
286 void
287 TetrahedronCell< TCellInterface >
SetPointIds(PointIdConstIterator first)288 ::SetPointIds(PointIdConstIterator first)
289 {
290 PointIdConstIterator ii(first);
291
292 for ( unsigned int i = 0; i < Self::NumberOfPoints; ++i )
293 {
294 m_PointIds[i] = *ii++;
295 }
296 }
297
298 /**
299 * Standard CellInterface:
300 * Set the point id list used by the cell. It is assumed that the range
301 * of iterators [first, last) contains the correct number of points needed to
302 * define the cell. The position *last is NOT referenced, so it can safely
303 * be one beyond the end of an array or other container.
304 */
305 template< typename TCellInterface >
306 void
307 TetrahedronCell< TCellInterface >
SetPointIds(PointIdConstIterator first,PointIdConstIterator last)308 ::SetPointIds(PointIdConstIterator first, PointIdConstIterator last)
309 {
310 int localId = 0;
311 PointIdConstIterator ii(first);
312
313 while ( ii != last )
314 {
315 m_PointIds[localId++] = *ii++;
316 }
317 }
318
319 /**
320 * Standard CellInterface:
321 * Set an individual point identifier in the cell.
322 */
323 template< typename TCellInterface >
324 void
325 TetrahedronCell< TCellInterface >
SetPointId(int localId,PointIdentifier ptId)326 ::SetPointId(int localId, PointIdentifier ptId)
327 {
328 m_PointIds[localId] = ptId;
329 }
330
331 /**
332 * Standard CellInterface:
333 * Get a begin iterator to the list of point identifiers used by the cell.
334 */
335 template< typename TCellInterface >
336 typename TetrahedronCell< TCellInterface >::PointIdIterator
337 TetrahedronCell< TCellInterface >
PointIdsBegin()338 ::PointIdsBegin()
339 {
340 return &m_PointIds[0];
341 }
342
343 /**
344 * Standard CellInterface:
345 * Get a const begin iterator to the list of point identifiers used
346 * by the cell.
347 */
348 template< typename TCellInterface >
349 typename TetrahedronCell< TCellInterface >::PointIdConstIterator
350 TetrahedronCell< TCellInterface >
PointIdsBegin() const351 ::PointIdsBegin() const
352 {
353 return &m_PointIds[0];
354 }
355
356 /**
357 * Standard CellInterface:
358 * Get an end iterator to the list of point identifiers used by the cell.
359 */
360 template< typename TCellInterface >
361 typename TetrahedronCell< TCellInterface >::PointIdIterator
362 TetrahedronCell< TCellInterface >
PointIdsEnd()363 ::PointIdsEnd()
364 {
365 return &m_PointIds[Self::NumberOfPoints - 1] + 1;
366 }
367
368 /**
369 * Standard CellInterface:
370 * Get a const end iterator to the list of point identifiers used
371 * by the cell.
372 */
373 template< typename TCellInterface >
374 typename TetrahedronCell< TCellInterface >::PointIdConstIterator
375 TetrahedronCell< TCellInterface >
PointIdsEnd() const376 ::PointIdsEnd() const
377 {
378 return &m_PointIds[Self::NumberOfPoints - 1] + 1;
379 }
380
381 /**
382 * Tetrahedron-specific:
383 * Get the number of vertices defining the tetrahedron.
384 */
385 template< typename TCellInterface >
386 typename TetrahedronCell< TCellInterface >::CellFeatureCount
387 TetrahedronCell< TCellInterface >
GetNumberOfVertices() const388 ::GetNumberOfVertices() const
389 {
390 return Self::NumberOfVertices;
391 }
392
393 /**
394 * Tetrahedron-specific:
395 * Get the number of edges defined for the tetrahedron.
396 */
397 template< typename TCellInterface >
398 typename TetrahedronCell< TCellInterface >::CellFeatureCount
399 TetrahedronCell< TCellInterface >
GetNumberOfEdges() const400 ::GetNumberOfEdges() const
401 {
402 return Self::NumberOfEdges;
403 }
404
405 /**
406 * Tetrahedron-specific:
407 * Get the number of faces defined for the tetrahedron.
408 */
409 template< typename TCellInterface >
410 typename TetrahedronCell< TCellInterface >::CellFeatureCount
411 TetrahedronCell< TCellInterface >
GetNumberOfFaces() const412 ::GetNumberOfFaces() const
413 {
414 return Self::NumberOfFaces;
415 }
416
417 /**
418 * Tetrahedron-specific:
419 * Get the vertex specified by the given cell feature Id.
420 * The Id can range from 0 to GetNumberOfVertices()-1.
421 */
422 template< typename TCellInterface >
423 bool
424 TetrahedronCell< TCellInterface >
GetVertex(CellFeatureIdentifier vertexId,VertexAutoPointer & vertexPointer)425 ::GetVertex(CellFeatureIdentifier vertexId, VertexAutoPointer & vertexPointer)
426 {
427 auto * vert = new VertexType;
428
429 vert->SetPointId(0, m_PointIds[vertexId]);
430 vertexPointer.TakeOwnership(vert);
431 return true;
432 }
433
434 /**
435 * Tetrahedron-specific:
436 * Get the edge specified by the given cell feature Id.
437 * The Id can range from 0 to GetNumberOfEdges()-1.
438 */
439 template< typename TCellInterface >
440 bool
441 TetrahedronCell< TCellInterface >
GetEdge(CellFeatureIdentifier edgeId,EdgeAutoPointer & edgePointer)442 ::GetEdge(CellFeatureIdentifier edgeId, EdgeAutoPointer & edgePointer)
443 {
444 auto * edge = new EdgeType;
445
446 for ( unsigned int i = 0; i < EdgeType::NumberOfPoints; ++i )
447 {
448 edge->SetPointId(i, m_PointIds[m_Edges[edgeId][i]]);
449 }
450 edgePointer.TakeOwnership(edge);
451 return true;
452 }
453
454 /**
455 * Tetrahedron-specific:
456 * Get the face specified by the given cell feature Id.
457 * The Id can range from 0 to GetNumberOfFaces()-1.
458 */
459 template< typename TCellInterface >
460 bool
461 TetrahedronCell< TCellInterface >
GetFace(CellFeatureIdentifier faceId,FaceAutoPointer & facePointer)462 ::GetFace(CellFeatureIdentifier faceId, FaceAutoPointer & facePointer)
463 {
464 auto * face = new FaceType;
465
466 for ( unsigned int i = 0; i < FaceType::NumberOfPoints; ++i )
467 {
468 face->SetPointId(i, m_PointIds[m_Faces[faceId][i]]);
469 }
470 facePointer.TakeOwnership(face);
471 return true;
472 }
473 } // end namespace itk
474
475 #endif
476