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