Orfeo Toolbox  3.16
itkHexahedronCell.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkHexahedronCell.txx,v $
5  Language: C++
6  Date: $Date: 2008-10-17 01:21:45 $
7  Version: $Revision: 1.38 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 #ifndef __itkHexahedronCell_txx
18 #define __itkHexahedronCell_txx
19 #include "itkHexahedronCell.h"
20 #include "vnl/vnl_matrix_fixed.h"
21 #include "vnl/algo/vnl_determinant.h"
22 
23 namespace itk
24 {
25 
29 template <typename TCellInterface >
30 void
32 ::MakeCopy(CellAutoPointer & cellPointer) const
33 {
34  cellPointer.TakeOwnership( new Self );
35  cellPointer->SetPointIds(this->GetPointIds());
36 }
37 
42 template <typename TCellInterface>
43 unsigned int
45 ::GetDimension(void) const
46 {
47  return Self::CellDimension;
48 }
49 
54 template <typename TCellInterface>
55 unsigned int
58 {
59  return Self::NumberOfPoints;
60 }
61 
66 template <typename TCellInterface>
69 ::GetNumberOfBoundaryFeatures(int dimension) const
70 {
71  switch (dimension)
72  {
73  case 0: return GetNumberOfVertices();
74  case 1: return GetNumberOfEdges();
75  case 2: return GetNumberOfFaces();
76  default: return 0;
77  }
78 }
79 
86 template <typename TCellInterface>
87 bool
89 ::GetBoundaryFeature(int dimension, CellFeatureIdentifier featureId,
90  CellAutoPointer & cellPointer )
91 {
92  switch (dimension)
93  {
94  case 0:
95  {
96  VertexAutoPointer vertexPointer;
97  if( this->GetVertex(featureId,vertexPointer) )
98  {
99  TransferAutoPointer(cellPointer,vertexPointer);
100  return true;
101  }
102  else
103  {
104  cellPointer.Reset();
105  return false;
106  }
107  break;
108  }
109  case 1:
110  {
111  EdgeAutoPointer edgePointer;
112  if( this->GetEdge(featureId,edgePointer) )
113  {
114  TransferAutoPointer(cellPointer,edgePointer);
115  return true;
116  }
117  else
118  {
119  cellPointer.Reset();
120  return false;
121  }
122  break;
123  }
124  case 2:
125  {
126  FaceAutoPointer facePointer;
127  if( this->GetFace(featureId,facePointer) )
128  {
129  TransferAutoPointer(cellPointer,facePointer);
130  return true;
131  }
132  else
133  {
134  cellPointer.Reset();
135  return false;
136  }
137  break;
138  }
139  default:
140  {
141  cellPointer.Reset();
142  return false;
143  }
144  }
145  return false;
146 }
147 
154 template <typename TCellInterface>
155 void
157 ::SetPointIds(PointIdConstIterator first)
158 {
159  PointIdConstIterator ii(first);
160  for( int i=0; i < Self::NumberOfPoints; ++i )
161  {
162  m_PointIds[i] = *ii++;
163  }
164 }
165 
173 template <typename TCellInterface>
174 void
176 ::SetPointIds(PointIdConstIterator first, PointIdConstIterator last)
177 {
178  int localId=0;
179  PointIdConstIterator ii(first);
180 
181  while(ii != last)
182  {
183  m_PointIds[localId++] = *ii++;
184  }
185 }
186 
191 template <typename TCellInterface>
192 void
194 ::SetPointId(int localId, PointIdentifier ptId)
195 {
196  m_PointIds[localId] = ptId;
197 }
198 
203 template <typename TCellInterface>
207 {
208  return &m_PointIds[0];
209 }
210 
216 template <typename TCellInterface>
219 ::PointIdsBegin(void) const
220 {
221  return &m_PointIds[0];
222 }
223 
228 template <typename TCellInterface>
232 {
233  return &m_PointIds[Self::NumberOfPoints-1] + 1;
234 }
235 
241 template <typename TCellInterface>
244 ::PointIdsEnd(void) const
245 {
246  return &m_PointIds[Self::NumberOfPoints-1] + 1;
247 }
248 
253 template <typename TCellInterface>
257 {
258  return Self::NumberOfVertices;
259 }
260 
265 template <typename TCellInterface>
269 {
270  return Self::NumberOfEdges;
271 }
272 
277 template <typename TCellInterface>
281 {
282  return Self::NumberOfFaces;
283 }
284 
290 template <typename TCellInterface>
291 bool
293 ::GetVertex(CellFeatureIdentifier vertexId,VertexAutoPointer & vertexPointer )
294 {
295  VertexType * vert = new VertexType;
296  vert->SetPointId(0, m_PointIds[vertexId]);
297  vertexPointer.TakeOwnership( vert );
298  return true;
299 }
300 
306 template <typename TCellInterface>
307 bool
309 ::GetEdge(CellFeatureIdentifier edgeId, EdgeAutoPointer & edgePointer )
310 {
311  EdgeType * edge = new EdgeType;
312  for(int i=0; i < EdgeType::NumberOfPoints; ++i)
313  {
314  edge->SetPointId(i, m_PointIds[ m_Edges[edgeId][i] ]);
315  }
316  edgePointer.TakeOwnership( edge );
317  return true;
318 }
319 
320 
326 template <typename TCellInterface>
327 bool
329 ::GetFace(CellFeatureIdentifier faceId, FaceAutoPointer & facePointer )
330 {
331  FaceType * face = new FaceType;
332  for(unsigned int i=0; i < FaceType::NumberOfPoints; ++i)
333  {
334  face->SetPointId(i, m_PointIds[ m_Faces[faceId][i] ]);
335  }
336  facePointer.TakeOwnership( face );
337  return true;
338 }
339 
341 template <typename TCellInterface>
342 bool
344 ::EvaluatePosition(CoordRepType* x,
345  PointsContainer* points,
346  CoordRepType* closestPoint,
347  CoordRepType pcoord[3],
348  double* dist2,
349  InterpolationWeightType* weight)
350 {
351  static const int ITK_HEX_MAX_ITERATION=10;
352  static const double ITK_HEX_CONVERGED=1.e-03;
353  static const double ITK_DIVERGED = 1.e6;
354 
355  int iteration, converged;
356  double params[3];
357  double fcol[3], rcol[3], scol[3], tcol[3];
358  double d;
359  PointType pt;
360  CoordRepType derivs[24];
361  InterpolationWeightType weights[8];
362 
363  // set initial position for Newton's method
364  int subId = 0;
365  CoordRepType pcoords[3];
366  pcoords[0] = pcoords[1] = pcoords[2] = params[0] = params[1] = params[2]=0.5;
367 
368  // enter iteration loop
369  for (iteration=converged=0;
370  !converged && (iteration < ITK_HEX_MAX_ITERATION); iteration++)
371  {
372  // calculate element interpolation functions and derivatives
373  this->InterpolationFunctions(pcoords, weights);
374  this->InterpolationDerivs(pcoords, derivs);
375 
376  // calculate newton functions
377  for (unsigned int i=0; i<3; i++)
378  {
379  fcol[i] = rcol[i] = scol[i] = tcol[i] = 0.0;
380  }
381  for (unsigned int i=0; i<8; i++)
382  {
383  pt = points->GetElement( m_PointIds[i] );
384  for (unsigned int j=0; j<3; j++)
385  {
386  fcol[j] += pt[j] * weights[i];
387  rcol[j] += pt[j] * derivs[i];
388  scol[j] += pt[j] * derivs[i+8];
389  tcol[j] += pt[j] * derivs[i+16];
390  }
391  }
392 
393  for (unsigned int i=0; i<3; i++)
394  {
395  fcol[i] -= x[i];
396  }
397 
398  // compute determinants and generate improvements
399  vnl_matrix_fixed<CoordRepType,3,PointDimension> mat;
400  for(unsigned int i=0;i<PointDimension;i++)
401  {
402  mat.put(0,i,rcol[i]);
403  mat.put(1,i,scol[i]);
404  mat.put(2,i,tcol[i]);
405  }
406 
407  d = vnl_determinant(mat);
408  //d=vtkMath::Determinant3x3(rcol,scol,tcol);
409  if ( vcl_abs(d) < 1.e-20)
410  {
411  return false;
412  }
413 
414  vnl_matrix_fixed<CoordRepType,3,PointDimension> mat1;
415  for(unsigned int i=0;i<PointDimension;i++)
416  {
417  mat1.put(0,i,fcol[i]);
418  mat1.put(1,i,scol[i]);
419  mat1.put(2,i,tcol[i]);
420  }
421 
422  vnl_matrix_fixed<CoordRepType,3,PointDimension> mat2;
423  for(unsigned int i=0;i<PointDimension;i++)
424  {
425  mat2.put(0,i,rcol[i]);
426  mat2.put(1,i,fcol[i]);
427  mat2.put(2,i,tcol[i]);
428  }
429 
430  vnl_matrix_fixed<CoordRepType,3,PointDimension> mat3;
431  for(unsigned int i=0;i<PointDimension;i++)
432  {
433  mat3.put(0,i,rcol[i]);
434  mat3.put(1,i,scol[i]);
435  mat3.put(2,i,fcol[i]);
436  }
437 
438  pcoords[0] = params[0] - vnl_determinant(mat1) / d;
439  pcoords[1] = params[1] - vnl_determinant(mat2) / d;
440  pcoords[2] = params[2] - vnl_determinant(mat3) / d;
441 
442  if(pcoord)
443  {
444  pcoord[0] = pcoords[0];
445  pcoord[1] = pcoords[1];
446  pcoord[2] = pcoords[2];
447  }
448 
449  // check for convergence
450  if ( ((vcl_abs(pcoords[0]-params[0])) < ITK_HEX_CONVERGED) &&
451  ((vcl_abs(pcoords[1]-params[1])) < ITK_HEX_CONVERGED) &&
452  ((vcl_abs(pcoords[2]-params[2])) < ITK_HEX_CONVERGED) )
453  {
454  converged = 1;
455  }
456 
457  // Test for bad divergence (S.Hirschberg 11.12.2001)
458  else if ((vcl_abs(pcoords[0]) > ITK_DIVERGED) ||
459  (vcl_abs(pcoords[1]) > ITK_DIVERGED) ||
460  (vcl_abs(pcoords[2]) > ITK_DIVERGED))
461  {
462  return -1;
463  }
464 
465  // if not converged, repeat
466  else
467  {
468  params[0] = pcoords[0];
469  params[1] = pcoords[1];
470  params[2] = pcoords[2];
471  }
472  }
473 
474  // if not converged, set the parametric coordinates to arbitrary values
475  // outside of element
476  if ( !converged )
477  {
478  return false;
479  }
480 
481  this->InterpolationFunctions(pcoords, weights);
482 
483  if(weight)
484  {
485  for(unsigned int i=0;i<8;i++)
486  {
487  weight[i] = weights[i];
488  }
489  }
490 
491  if ( pcoords[0] >= -0.001 && pcoords[0] <= 1.001 &&
492  pcoords[1] >= -0.001 && pcoords[1] <= 1.001 &&
493  pcoords[2] >= -0.001 && pcoords[2] <= 1.001 )
494  {
495  if (closestPoint)
496  {
497  closestPoint[0] = x[0]; closestPoint[1] = x[1]; closestPoint[2] = x[2];
498  *dist2 = 0.0; //inside hexahedron
499  }
500  return true;
501  }
502  else
503  {
504  CoordRepType pc[3], w[8];
505  if (closestPoint)
506  {
507  for (unsigned int i=0; i<3; i++) //only approximate, not really true for warped hexa
508  {
509  if (pcoords[i] < 0.0)
510  {
511  pc[i] = 0.0;
512  }
513  else if (pcoords[i] > 1.0)
514  {
515  pc[i] = 1.0;
516  }
517  else
518  {
519  pc[i] = pcoords[i];
520  }
521  }
522  this->EvaluateLocation(subId, points, pc, closestPoint, (InterpolationWeightType *)w);
523 
524  *dist2 = 0;
525  for(unsigned int i=0;i<3;i++)
526  {
527  *dist2 += (closestPoint[i]-x[i])*(closestPoint[i]-x[i]);
528  }
529  }
530  return false;
531  }
532 }
533 
535 template <typename TCellInterface>
536 void
538 ::InterpolationFunctions(CoordRepType pcoords[3], InterpolationWeightType sf[8])
539 {
540  const double rm = 1. - pcoords[0];
541  const double sm = 1. - pcoords[1];
542  const double tm = 1. - pcoords[2];
543 
544  sf[0] = rm*sm*tm;
545  sf[1] = pcoords[0]*sm*tm;
546  sf[2] = pcoords[0]*pcoords[1]*tm;
547  sf[3] = rm*pcoords[1]*tm;
548  sf[4] = rm*sm*pcoords[2];
549  sf[5] = pcoords[0]*sm*pcoords[2];
550  sf[6] = pcoords[0]*pcoords[1]*pcoords[2];
551  sf[7] = rm*pcoords[1]*pcoords[2];
552 }
553 
555 template <typename TCellInterface>
556 void
558 ::InterpolationDerivs(CoordRepType pcoords[3], CoordRepType derivs[24])
559 {
560  const double rm = 1. - pcoords[0];
561  const double sm = 1. - pcoords[1];
562  const double tm = 1. - pcoords[2];
563 
564  // r-derivatives
565  derivs[0] = -sm*tm;
566  derivs[1] = sm*tm;
567  derivs[2] = pcoords[1]*tm;
568  derivs[3] = -pcoords[1]*tm;
569  derivs[4] = -sm*pcoords[2];
570  derivs[5] = sm*pcoords[2];
571  derivs[6] = pcoords[1]*pcoords[2];
572  derivs[7] = -pcoords[1]*pcoords[2];
573 
574  // s-derivatives
575  derivs[8] = -rm*tm;
576  derivs[9] = -pcoords[0]*tm;
577  derivs[10] = pcoords[0]*tm;
578  derivs[11] = rm*tm;
579  derivs[12] = -rm*pcoords[2];
580  derivs[13] = -pcoords[0]*pcoords[2];
581  derivs[14] = pcoords[0]*pcoords[2];
582  derivs[15] = rm*pcoords[2];
583 
584  // t-derivatives
585  derivs[16] = -rm*sm;
586  derivs[17] = -pcoords[0]*sm;
587  derivs[18] = -pcoords[0]*pcoords[1];
588  derivs[19] = -rm*pcoords[1];
589  derivs[20] = rm*sm;
590  derivs[21] = pcoords[0]*sm;
591  derivs[22] = pcoords[0]*pcoords[1];
592  derivs[23] = rm*pcoords[1];
593 }
594 
596 template <typename TCellInterface>
597 void
599 ::EvaluateLocation(int& itkNotUsed(subId),PointsContainer* points, CoordRepType pcoords[3],
600  CoordRepType x[3], InterpolationWeightType *weights)
601 {
602  PointType pt;
603  this->InterpolationFunctions(pcoords, weights);
604  x[0] = x[1] = x[2] = 0.0;
605  for (unsigned int i=0; i<8; i++)
606  {
607  pt = points->GetElement( m_PointIds[i] );
608 
609  for (unsigned int j=0; j<3; j++)
610  {
611  x[j] += pt[j] * weights[i];
612  }
613  }
614 }
615 
616 
617 } // end namespace itk
618 
619 #endif

Generated at Sat Feb 2 2013 23:41:24 for Orfeo Toolbox with doxygen 1.8.1.1