KWStyle - itkMesh.txx
 
Matrix View
Description

1 /*=========================================================================
2
3   Program:   Insight Segmentation & Registration Toolkit
4   Module:    $RCSfile: itkMesh.txx.html,v $
5   Language:  C++
6   Date:      $Date: 2006/01/17 19:15:41 $
7   Version:   $Revision: 1.4 $
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   Portions of this code are covered under the VTK copyright.
13   See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.
14
15      This software is distributed WITHOUT ANY WARRANTY; without even 
16      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
17 IND *****PURPOSE.  See the above copyright notices for more information.
18
19 =========================================================================*/
20 DEF #ifndef _itkMesh_txx
21 DEF #define _itkMesh_txx
22
23 #include "itkMesh.h"
24 #include "itkObjectFactory.h"
25 #include "itkProcessObject.h"
26 #include <algorithm>
27
28 namespace itk
29 {
30   
31 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
32 void
33 Mesh<TPixelType, VDimension, TMeshTraits>
34 ::PrintSelf(std::ostream& os, Indent indent) const
35 {
36   Superclass::PrintSelf(os, indent);
37   os << indent << "Number Of Points: " 
38 LEN      << ((this->m_PointsContainer.GetPointer()) ?  this->m_PointsContainer->Size() : 0) << std::endl;
39   os << indent << "Number Of Cell Links: " 
40 LEN      << ((m_CellLinksContainer) ?  m_CellLinksContainer->Size() : 0) << std::endl;
41   os << indent << "Number Of Cells: " 
42      << ((m_CellsContainer) ?  m_CellsContainer->Size() : 0) << std::endl;
43   os << indent << "Size of Cell Data Container: " 
44      << ((m_CellDataContainer) ?  m_CellDataContainer->Size() : 0) << std::endl;
45   os << indent << "Number of explicit cell boundary assignments: " 
46 LEN      << static_cast<unsigned long>( m_BoundaryAssignmentsContainers.size() ) << std::endl;
47   
48   os << indent << "CellsAllocationMethod: " 
49      << m_CellsAllocationMethod << std::endl;
50
51 }
52
53
54 /**
55  * Access routine to set the cell links container.
56  */
57 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
58 void
59 Mesh<TPixelType, VDimension, TMeshTraits>
60 ::SetCellLinks(CellLinksContainer* cellLinks)
61 {
62   itkDebugMacro("setting CellLinks container to " << cellLinks);
63   if(m_CellLinksContainer != cellLinks)
64     {
65     m_CellLinksContainer = cellLinks;
66     this->Modified();
67     }
68 }
69
70 /**
71  * Access routines to get the cell links container.
72  */
73 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
74 typename Mesh<TPixelType, VDimension, TMeshTraits>::CellLinksContainerPointer
75 Mesh<TPixelType, VDimension, TMeshTraits>
76 ::GetCellLinks()
77 {
78   itkDebugMacro("returning CellLinks container of "
79                 << m_CellLinksContainer );
80   return m_CellLinksContainer;
81 }
82 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
83 LEN const typename Mesh<TPixelType, VDimension, TMeshTraits>::CellLinksContainerPointer
84 Mesh<TPixelType, VDimension, TMeshTraits>
85 ::GetCellLinks() const
86 {
87   itkDebugMacro("returning CellLinks container of "
88                 << m_CellLinksContainer );
89   return m_CellLinksContainer;
90 }
91
92
93 /**
94  * Access routine to set the cells container.
95  */
96 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
97 void
98 Mesh<TPixelType, VDimension, TMeshTraits>
99 ::SetCells(CellsContainer* cells)
100 {
101   itkDebugMacro("setting Cells container to " << cells);
102   if(m_CellsContainer != cells)
103     {
104     this->ReleaseCellsMemory();
105     m_CellsContainer = cells;
106     this->Modified();
107     }
108 }
109
110
111 /**
112  * Access routines to get the cells container.
113  */
114 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
115 typename Mesh<TPixelType, VDimension, TMeshTraits>::CellsContainerPointer
116 Mesh<TPixelType, VDimension, TMeshTraits>
117 ::GetCells()
118 {
119   itkDebugMacro("returning Cells container of " << m_CellsContainer );
120   return m_CellsContainer;
121 }
122 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
123 const typename Mesh<TPixelType, VDimension, TMeshTraits>::CellsContainerPointer
124 Mesh<TPixelType, VDimension, TMeshTraits>
125 ::GetCells() const 
126 {
127   itkDebugMacro("returning Cells container of " << m_CellsContainer );
128   return m_CellsContainer;
129 }
130
131
132 /**
133  * Access routine to set the cell data container.
134  */
135 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
136 void
137 Mesh<TPixelType, VDimension, TMeshTraits>
138 ::SetCellData(CellDataContainer* cellData)
139 {
140   itkDebugMacro("setting CellData container to " << cellData);
141   if(m_CellDataContainer != cellData)
142     {
143     m_CellDataContainer = cellData;
144     this->Modified();
145     }
146 }
147
148
149 /**
150  * Access routines to get the cell data container.
151  */
152 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
153 typename Mesh<TPixelType, VDimension, TMeshTraits>::CellDataContainerPointer
154 Mesh<TPixelType, VDimension, TMeshTraits>
155 ::GetCellData()
156 {
157   itkDebugMacro("returning CellData container of "
158                 << m_CellDataContainer );
159   return m_CellDataContainer;
160 }
161 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
162 LEN const typename Mesh<TPixelType, VDimension, TMeshTraits>::CellDataContainerPointer
163 Mesh<TPixelType, VDimension, TMeshTraits>
164 ::GetCellData() const 
165 {
166   itkDebugMacro("returning CellData container of "
167                 << m_CellDataContainer );
168   return m_CellDataContainer;
169 }
170
171 /**
172  * Access routine to set the boundary assignment container for a given
173  * dimension.
174  */
175 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
176 void
177 Mesh<TPixelType, VDimension, TMeshTraits>
178 ::SetBoundaryAssignments(
179   int dimension,
180   BoundaryAssignmentsContainer* boundaryAssignments)
181 {
182   itkDebugMacro("setting BoundaryAssignments[" << dimension
183                 << "] container to " << boundaryAssignments);
184   if(m_BoundaryAssignmentsContainers[dimension] != boundaryAssignments)
185     {
186     m_BoundaryAssignmentsContainers[dimension] = boundaryAssignments;
187     this->Modified();
188     }
189 }
190
191
192 /**
193  * Access routines to get the boundary assignment container for a given
194  * dimension.
195  */
196 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
197 LEN typename Mesh<TPixelType, VDimension, TMeshTraits>::BoundaryAssignmentsContainerPointer
198 Mesh<TPixelType, VDimension, TMeshTraits>
199 ::GetBoundaryAssignments(int dimension)
200 {
201   itkDebugMacro("returning BoundaryAssignments[" << dimension
202                 << "] container of "
203                 << m_BoundaryAssignmentsContainers[dimension]);
204   return m_BoundaryAssignmentsContainers[dimension];
205 }
206 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
207 const typename Mesh<TPixelType, VDimension, TMeshTraits>
208 ::BoundaryAssignmentsContainerPointer
209 Mesh<TPixelType, VDimension, TMeshTraits>
210 ::GetBoundaryAssignments(int dimension) const
211 {
212   itkDebugMacro("returning BoundaryAssignments[" << dimension
213                 << "] container of "
214                 << m_BoundaryAssignmentsContainers[dimension]);
215   return m_BoundaryAssignmentsContainers[dimension];
216 }
217
218
219 /**
220  * Assign a cell to a cell identifier.  If a spot for the cell identifier
221  * does not exist, it will be created automatically.
222  */
223 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
224 void
225 Mesh<TPixelType, VDimension, TMeshTraits>
226 ::SetCell(CellIdentifier cellId, CellAutoPointer & cellPointer )
227 {
228   /**
229    * Make sure a cells container exists.
230    */
231   if( !m_CellsContainer )
232     {
233     this->SetCells(CellsContainer::New());
234     }
235   
236   /**
237    * Insert the cell into the container with the given identifier.
238    */
239   m_CellsContainer->InsertElement(cellId, cellPointer.ReleaseOwnership() ); 
240 }
241
242
243 /**
244  * Check if a cell exists for a given cell identifier.  If a spot for
245  * the cell identifier exists, "cell" is set, and true is returned.
246  * Otherwise, false is returned, and "cell" is not modified.
247  * If "cell" is NULL, then it is never set, but the existence of the cell
248  * is still returned.
249  */
250 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
251 bool
252 Mesh<TPixelType, VDimension, TMeshTraits>
253 ::GetCell(CellIdentifier cellId, CellAutoPointer & cellPointer ) const
254 {
255   /**
256    * If the cells container doesn't exist, then the cell doesn't exist.
257    */
258   if( m_CellsContainer.IsNull() )
259     {
260     cellPointer.Reset();
261     return false;
262     }
263   
264   /**
265    * Ask the container if the cell identifier exists.
266    */
267   CellType * cellptr;
268 LEN   const bool found = m_CellsContainer->GetElementIfIndexExists(cellId, &cellptr);
269   if( found )
270     {
271     cellPointer.TakeNoOwnership( cellptr );
272     }
273   else
274     {
275     cellPointer.Reset();
276     }
277
278   return found; 
279 }
280
281
282 /**
283  * Assign data to a cell identifier.  If a spot for the cell identifier
284  * does not exist, it will be created automatically.  There is no check if
285  * a cell with the same identifier exists.
286  */
287 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
288 void
289 Mesh<TPixelType, VDimension, TMeshTraits>
290 ::SetCellData(CellIdentifier cellId, CellPixelType data)
291 {
292   /**
293    * Make sure a cell data container exists.
294    */
295   if( !m_CellDataContainer )
296     {
297     this->SetCellData(CellDataContainer::New());
298     }
299
300   /**
301    * Insert the cell data into the container with the given identifier.
302    */
303   m_CellDataContainer->InsertElement(cellId, data);
304 }
305
306
307 /**
308  * Check if cell data exists for a given cell identifier.  If a spot for
309  * the cell identifier exists, "data" is set, and true is returned.
310  * Otherwise, false is returned, and "data" is not modified.
311  * If "data" is NULL, then it is never set, but the existence of the cell
312  * data is still returned.
313  */
314 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
315 bool
316 Mesh<TPixelType, VDimension, TMeshTraits>
317 ::GetCellData(CellIdentifier cellId, CellPixelType* data) const
318 {
319   /**
320    * If the cell data container doesn't exist, then the cell data doesn't
321    * either.
322    */
323   if( !m_CellDataContainer )
324 IND ****return false;
325   
326   /**
327    * Ask the container if the cell identifier exists.
328    */
329   return m_CellDataContainer->GetElementIfIndexExists(cellId, data);
330 }
331
332
333 /** 
334  * Explicitly assign boundaryId as a part of the boundary of cellId.
335  * The identifiers boundaryId and cellId must identify cell objects
336  * already in the mesh.  The dimension of boundaryId must be specified
337  * by 'dimension', and a unique CellFeatureIdentifier featureId must be
338  * assigned for each distinct boundary feature of a given dimension.
339  * CellFeatureIdentifier is equivalent to unsigned long by default,
340  * and will not typically need to be changed.  The UsingCells list of
341  * boundaryId is automatically updated to include cellId.
342  */
343 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
344 void
345 Mesh<TPixelType, VDimension, TMeshTraits>
346 ::SetBoundaryAssignment(int dimension, CellIdentifier cellId,
347                         CellFeatureIdentifier featureId,
348                         CellIdentifier boundaryId)
349 {
350   BoundaryAssignmentIdentifier assignId( cellId, featureId );
351     
352   /**
353    * Make sure a boundary assignment container exists for the given dimension.
354    */
355   if( !m_BoundaryAssignmentsContainers[dimension] )
356     {
357     this->SetBoundaryAssignments(
358       dimension, BoundaryAssignmentsContainer::New() );
359     }
360
361   /**
362    * Insert the boundary assignment into the container with the given
363    * assignment identifier in the given dimension.
364    */
365 LEN   m_BoundaryAssignmentsContainers[dimension]->InsertElement( assignId, boundaryId );
366
367   /**
368    * Add cellId to the UsingCells list of boundaryId.
369    */
370   CellAutoPointer boundaryCell;
371   this->GetCell( boundaryId, boundaryCell );
372   boundaryCell->AddUsingCell( cellId );
373
374 }
375
376
377 /**
378  * Check if an explicit boundary assignment exists.
379  */
380 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
381 bool
382 Mesh<TPixelType, VDimension, TMeshTraits>
383 ::GetBoundaryAssignment(int dimension, CellIdentifier cellId,
384                         CellFeatureIdentifier featureId,
385                         CellIdentifier* boundaryId) const
386 {
387   BoundaryAssignmentIdentifier assignId(cellId, featureId);  
388
389   /**
390    * If the boundary assignments container for the given dimension doesn't
391    * exist, then the boundary assignment doesn't either.
392    */
393   if( !m_BoundaryAssignmentsContainers[dimension] )
394 IND ****return false;
395   
396   /**
397    * Ask the container if the boundary assignment exists.
398    */
399   return m_BoundaryAssignmentsContainers[dimension]->
400 IND ****GetElementIfIndexExists(assignId, boundaryId);
401 }
402
403
404 /**
405  * Remove an explicit boundary assignment if it exists.
406  * Returns whether the assignment was found at all.
407  */
408 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
409 bool
410 Mesh<TPixelType, VDimension, TMeshTraits>
411 ::RemoveBoundaryAssignment(int dimension, CellIdentifier cellId,
412                            CellFeatureIdentifier featureId)
413 {
414   BoundaryAssignmentIdentifier assignId(cellId, featureId);
415
416   /**
417    * If the boundary assignments container for the given dimension doesn't
418    * exist, then the boundary assignment doesn't either.
419    */
420   if( !m_BoundaryAssignmentsContainers[dimension] )
421 IND ****return false;
422   
423   /**
424    * Ask the container if the boundary assignment exists, and delete it if
425    * so.
426    */
427   if(m_BoundaryAssignmentsContainers[dimension]->IndexExists(assignId))
428     {
429     m_BoundaryAssignmentsContainers[dimension]->DeleteIndex(assignId);
430     return true;
431     }
432   else return false;  
433 }
434
435
436 /**
437  * Get the number of cell boundary features of the given topological dimension
438  * on the cell with the given identifier.
439  */
440 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
441 typename Mesh<TPixelType, VDimension, TMeshTraits>::CellFeatureCount 
442 Mesh<TPixelType, VDimension, TMeshTraits>
443 ::GetNumberOfCellBoundaryFeatures(int dimension, CellIdentifier cellId) const
444 {
445   /**
446    * Make sure the cell container exists and contains the given cell Id.
447    */
448   if( !m_CellsContainer ) return 0;
449   if(!m_CellsContainer->IndexExists(cellId)) return 0;
450   
451   /**
452    * Ask the cell for its boundary count of the given dimension.
453    */
454   return m_CellsContainer->GetElement(cellId)->
455 IND ****GetNumberOfBoundaryFeatures(dimension);
456 }
457
458
459 /**
460  * Copy the geometric and topological structure of the given input mesh.
461  * The copying is done via reference counting.
462  */
463 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
464 void
465 Mesh<TPixelType, VDimension, TMeshTraits>
466 ::PassStructure(Self*)
467 {
468   // IMPLEMENT ME
469 }
470
471
472 /**
473  * Get the number of cells in the CellsContainer.
474  */
475 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
476 unsigned long
477 Mesh<TPixelType, VDimension, TMeshTraits>
478 ::GetNumberOfCells() const
479 {  
480   if ( ! m_CellsContainer )
481     {
482     return 0;
483     }
484   else
485     {
486     return m_CellsContainer->Size();
487     }
488 }
489
490
491 /**
492  * Get the bounding box of the cell with the given identifier.
493  */
494 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
495 typename Mesh<TPixelType, VDimension, TMeshTraits>::BoundingBoxPointer 
496 Mesh<TPixelType, VDimension, TMeshTraits>
497 ::GetCellBoundingBox(CellIdentifier cellId, BoundingBoxPointer bbox)
498 {
499   bbox->SetPoints(this->GetPoints());
500   return bbox;
501 }
502
503
504 /**
505  * Given the geometric coordinates of a point and a squared tolerance,
506  * locate .....COMMENT ME.....
507  */
508 #if 0
509 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
510 bool
511 Mesh<TPixelType, VDimension, TMeshTraits>
512 ::FindCell(CoordRep coords[PointDimension], ..FINISH ME..)
513 #endif
514
515 /**
516  * Restore the Mesh to its initial state.  Useful for data pipeline updates
517  * without memory re-allocation.
518  */
519 IND **template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
520 void
521 Mesh<TPixelType, VDimension, TMeshTraits>
522 ::Initialize()
523 {
524   itkDebugMacro("Mesh Initialize method ");
525   Superclass::Initialize();
526
527   this->ReleaseCellsMemory();
528
529   m_CellsContainer = 0;
530   m_CellDataContainer = 0;
531   m_CellLinksContainer = 0;
532   
533 }
534   
535   
536 /**
537  * Get the boundary feature of the given dimension of the given cell
538  * corresponding to the given feature identifier.  If the boundary
539  * feature has been explicitly assigned, then \a boundary will be left
540  * pointing to the appropriate cell in the mesh.  If the boundary has
541  * not been explicitly assigned, then a boundary cell will be
542  * constructed and placed in \a boundary.  The constructed cell will
543  * not be added to the mesh or somehow cached.
544  */
545 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
546 bool
547 Mesh<TPixelType, VDimension, TMeshTraits>
548 ::GetCellBoundaryFeature(int dimension, CellIdentifier cellId,
549                          CellFeatureIdentifier featureId,
550                          CellAutoPointer& boundary) const
551 {
552   /**
553    * First check if the boundary has been explicitly assigned.
554    */
555   if(GetAssignedCellBoundaryIfOneExists(dimension, cellId, featureId, boundary))
556     {
557     return true;
558     }
559   
560   /**
561    * It was not explicitly assigned, so ask the cell to construct it.
562    * This will be a geometric copy of the actual boundary feature, not
563    * a pointer to an actual cell in the mesh.  
564    */
565   if(( !m_CellsContainer.IsNull() ) && m_CellsContainer->IndexExists(cellId))
566     {
567     // Don't take ownership
568     CellType * thecell = m_CellsContainer->GetElement(cellId);
569     if( thecell->GetBoundaryFeature(dimension, featureId, boundary ) )
570       {
571       return true;
572       }
573     else
574       {
575       boundary.Reset();
576       return false;
577       }
578     }
579   
580   /**
581    * The cell did not exist, so just give up.
582    */
583   boundary.Reset();
584
585   return false;
586
587 }
588
589
590 /**
591  * Get the set of cells neighboring the given cell across the given boundary
592  * feature.  Returns the number of neighbors found.  If cellSet is not
593  * NULL, the set of cell pointers is filled in with identifiers of the
594  * neighboring cells.
595  *
596  * NOTE: We would like to change this to use an "output iterator"
597  * (in STL fashion) instead of an actual container to return the neighbor
598  * identifiers.  This requires templated member support by the compiler,
599  * though, and we are not sure how wide-spread this support is.
600  */
601 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
602 unsigned long
603 Mesh<TPixelType, VDimension, TMeshTraits>
604 ::GetCellBoundaryFeatureNeighbors(int dimension, CellIdentifier cellId,
605                                   CellFeatureIdentifier featureId,
606                                   std::set<CellIdentifier>* cellSet)
607 {
608   /**
609    * Sanity check on mesh status.
610    */
611   if( !this->m_PointsContainer || !m_CellsContainer ||
612       (!m_CellsContainer->IndexExists(cellId)) )
613     {
614     /**
615      * TODO: Throw EXCEPTION here?
616      */
617     return 0;
618     }
619   
620   /**
621    * First check if the boundary has been explicitly assigned.
622    */
623   CellAutoPointer boundary;
624   if( this->GetAssignedCellBoundaryIfOneExists(
625         dimension, cellId, featureId, boundary) )
626     {
627     /**
628      * Explicitly assigned boundary found.  Loop through its UsingCells,
629      * and put them in the output set except for the cell through which the
630      * request was made.  First we empty the output set.
631      */
632     if(cellSet != 0)
633       {
634       cellSet->erase(cellSet->begin(), cellSet->end());
635
636       typename CellType::UsingCellsContainerIterator usingCell;
637 SEM       for(usingCell = boundary->UsingCellsBegin() ;
638 SEM,IND **********usingCell != boundary->UsingCellsEnd() ; ++usingCell)
639         {
640         if((*usingCell) != cellId)
641           {
642           cellSet->insert(*usingCell);
643           }
644         }
645       }
646     /**
647      * The number of neighboring cells is the number of cells using the
648      * boundary less one for the cell through which the request was made.
649      */
650     return (boundary->GetNumberOfUsingCells()-1);
651     }
652
653
654   /**
655    * An explicit assignment for the boundary was not found.  We use set
656    * operations through point neighboring information to get the neighbors.
657    * This requires that the CellLinks be built.
658    */
659   if( !m_CellLinksContainer )
660     {
661     this->BuildCellLinks();
662     }
663 LEN   else if((this->m_PointsContainer->GetMTime() > m_CellLinksContainer->GetMTime()) ||
664 IND **********(m_CellsContainer->GetMTime()  > m_CellLinksContainer->GetMTime()))
665     {
666     this->BuildCellLinks();
667     }
668   
669   /**
670    * Cell links are up to date. We can proceed with the set operations.
671    * We need to intersect the CellLinks sets for each point on the boundary
672    * feature.
673    */
674   
675   /**
676    * First, ask the cell to construct the boundary feature so we can look
677    * at its points.
678    */
679   m_CellsContainer->GetElement(cellId)
680 IND ****->GetBoundaryFeature(dimension, featureId, boundary);
681   
682
683   /**
684    * Now get the cell links for the first point.  Also allocate a second set
685    * for temporary storage during set intersections below.
686    */
687   typename CellType::PointIdConstIterator pointId = boundary->PointIdsBegin();
688   PointCellLinksContainer*  currentCells =
689 IND ****new PointCellLinksContainer(m_CellLinksContainer->GetElement(*pointId++));
690   PointCellLinksContainer*  tempCells = new PointCellLinksContainer();
691   
692   /**
693    * Next, loop over the other points, and intersect their cell links with
694    * the current result.  We maintain "currentCells" as a pointer to the
695    * current cell set instead of a set itself to prevent an extra copy of
696    * the temporary set after each intersection.
697    */
698   while(pointId != boundary->PointIdsEnd())
699     {
700     /**
701      * Clean out temporary cell set from previous iteration.
702      */
703     tempCells->erase(tempCells->begin(), tempCells->end());
704     
705     /**
706      * Perform the intersection.
707      */
708 LEN     std::set_intersection(m_CellLinksContainer->CreateElementAt(*pointId).begin(),
709 IND **************************m_CellLinksContainer->CreateElementAt(*pointId).end(),
710 IND **************************currentCells->begin(),
711 IND **************************currentCells->end(),
712 IND **************************std::inserter(*tempCells, tempCells->begin()));
713     
714     /**
715      * Switch the cell set pointers to make the intersection result the
716      * current set.
717      */
718     std::swap(currentCells, tempCells);
719     
720     /**
721      * Move on to the next point.
722      */
723     ++pointId;
724     }
725   
726   /**
727    * Don't need the second set anymore.
728    */
729   delete tempCells;
730   
731   /** delete the boundary feature added as a temporary auxiliar object,
732 IND ******being an AutoPointer it will release memory when going out of scope */
733
734   /**
735    * Now we have a set of all the cells which share all the points on the
736    * boundary feature.  We simply need to copy this set to the output cell
737    * set, less the cell through which the request was made.
738    */
739   currentCells->erase(cellId);
740   unsigned long numberOfNeighboringCells = currentCells->size();
741   if(cellSet != 0)
742     {
743     *cellSet = *currentCells;    
744     }
745   
746   /**
747    * Don't need the cell set anymore.
748    */
749   delete currentCells;
750   
751   /**
752    * Return the number of neighboring cells that were put into the set.
753    */
754   return numberOfNeighboringCells;
755 }
756
757 /**
758  * Get the set of cells having the given cell as part of their
759  * boundary.  Returns the number of neighbors found.  If cellSet is not
760  * NULL, the set of cell pointers is filled in with identifiers of the
761  * neighboring cells.
762  *
763  * NOTE: We would like to change this to use an "output iterator"
764  * (in STL fashion) instead of an actual container to return the neighbor
765  * identifiers.  This requires templated member support by the compiler,
766  * though, and we are not sure how wide-spread this support is.
767  */
768 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
769 unsigned long
770 Mesh<TPixelType, VDimension, TMeshTraits>
771 ::GetCellNeighbors( CellIdentifier cellId, std::set<CellIdentifier>* cellSet )
772 {
773   /**
774    * Sanity check on mesh status.
775    */
776   if( !this->m_PointsContainer || !m_CellsContainer ||
777       (!m_CellsContainer->IndexExists(cellId)) )
778     {
779     /**
780      * TODO: Throw EXCEPTION here?
781      */
782     return 0;
783     }
784   
785   /**
786    * Get the cell itself.  IndexExists call above should ensure that
787    * GetCell() returns true, but be safe anyway.
788    */
789   CellAutoPointer cell;
790   if( !this->GetCell( cellId, cell ) )
791     {
792     return 0;
793     }
794
795   /**
796    * If the cell's UsingCells list is nonempty, then use it.
797    */
798   if( cell->GetNumberOfUsingCells() != 0 )
799     {
800
801     /**
802      * Loop through UsingCells and put them in the output set.  First
803      * we empty the output set.
804      */
805     if(cellSet != 0)
806       {
807       cellSet->erase(cellSet->begin(), cellSet->end());
808
809       typename CellType::UsingCellsContainerIterator usingCell;
810 SEM       for(usingCell = cell->UsingCellsBegin() ;
811 SEM,IND **********usingCell != cell->UsingCellsEnd() ; ++usingCell)
812         {
813         cellSet->insert(*usingCell);
814         }
815       }
816     return cell->GetNumberOfUsingCells();
817     }
818
819
820   /**
821    * The cell's UsingCells list was empy.  We use set operations
822    * through point neighboring information to get the neighbors.  This
823    * requires that the CellLinks be built.
824    */
825   if( !m_CellLinksContainer ||
826 LEN       (this->m_PointsContainer->GetMTime() > m_CellLinksContainer->GetMTime()) ||
827 IND ******(m_CellsContainer->GetMTime()  > m_CellLinksContainer->GetMTime()) )
828     {
829     this->BuildCellLinks();
830     }
831   
832   /**
833    * Cell links are up to date. We can proceed with the set operations.
834    * We need to intersect the CellLinks sets for each point on the
835    * given cell.
836    */
837
838   /**
839    * Now get the cell links for the first point.  Also allocate a second set
840    * for temporary storage during set intersections below.
841    */
842   typename CellType::PointIdConstIterator pointId = cell->PointIdsBegin();
843   PointCellLinksContainer*  currentCells =
844 IND ****new PointCellLinksContainer(m_CellLinksContainer->GetElement(*pointId++));
845   PointCellLinksContainer*  tempCells = new PointCellLinksContainer();
846   
847   /**
848    * Next, loop over the other points, and intersect their cell links with
849    * the current result.  We maintain "currentCells" as a pointer to the
850    * current cell set instead of a set itself to prevent an extra copy of
851    * the temporary set after each intersection.
852    */
853   while(pointId != cell->PointIdsEnd())
854     {
855     /**
856      * Clean out temporary cell set from previous iteration.
857      */
858     tempCells->erase(tempCells->begin(), tempCells->end());
859     
860     /**
861      * Perform the intersection.
862      */
863 LEN     std::set_intersection(m_CellLinksContainer->CreateElementAt(*pointId).begin(),
864 IND **************************m_CellLinksContainer->CreateElementAt(*pointId).end(),
865 IND **************************currentCells->begin(),
866 IND **************************currentCells->end(),
867 IND **************************std::inserter(*tempCells, tempCells->begin()));
868     
869     /**
870      * Switch the cell set pointers to make the intersection result the
871      * current set.
872      */
873     std::swap(currentCells, tempCells);
874     
875     /**
876      * Move on to the next point.
877      */
878     ++pointId;
879     }
880   
881   /**
882    * Don't need the second set anymore.
883    */
884   delete tempCells;
885   
886   /**
887    * Now we have a set of all the cells which share all the points on
888    * the original cell determined by cellId.  We simply need to copy
889    * this set to the output cell set.
890    */
891   unsigned long numberOfNeighboringCells = currentCells->size();
892   if(cellSet != 0)
893     {
894     *cellSet = *currentCells;    
895     }
896   
897   /**
898    * Don't need the cell set anymore.
899    */
900   delete currentCells;
901   
902   /**
903    * Return the number of neighboring cells that were put into the set.
904    */
905   return numberOfNeighboringCells;
906 }
907
908
909 /**
910  * Check if there is an explicitly assigned boundary feature for the
911  * given dimension and cell- and cell-feature-identifiers.  If there is,
912  * a pointer to it is given back through "boundary" (if it isn't 0) and
913  * true is returned.  Otherwise, false is returned.
914  * 
915  * This version is new.  It does not treat boundaries as a separate
916  * type.  A boundary (boundary component, really) is just a cell that
917  * is part of the boundary of another cell.  As this conversion is
918  * completed, the parts that use the boundary types will be removed.
919  */
920 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
921 bool
922 Mesh<TPixelType, VDimension, TMeshTraits>
923 ::GetAssignedCellBoundaryIfOneExists( int dimension, CellIdentifier cellId,
924                                       CellFeatureIdentifier featureId,
925                                       CellAutoPointer& boundary ) const
926 {
927   if( m_BoundaryAssignmentsContainers[dimension].IsNotNull() )
928     {
929     BoundaryAssignmentIdentifier assignId(cellId, featureId);
930     CellIdentifier boundaryId;
931     
932     if( m_BoundaryAssignmentsContainers[dimension]->
933         GetElementIfIndexExists( assignId, &boundaryId ) )
934       {
935       CellType* boundaryptr;
936       const bool found = m_CellsContainer->
937 IND ********GetElementIfIndexExists( boundaryId, &boundaryptr );
938       boundary.TakeNoOwnership( boundaryptr );
939       return found;
940       }
941     }
942   
943   /** An explicitly assigned boundary was not found. */
944   boundary.Reset();
945   return false;
946 }
947
948 /**
949  * Dynamically build the links from points back to their using cells.  This
950  * information is stored in the cell links container, not in the points.
951  */
952 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
953 void
954 Mesh<TPixelType, VDimension, TMeshTraits>
955 ::Accept(CellMultiVisitorType* mv)
956 {
957   if(!m_CellsContainer)
958     {
959     return;
960     }
961   for(CellsContainerIterator i = m_CellsContainer->Begin();
962 IND ******i != m_CellsContainer->End(); ++i)
963     {
964     if( i->Value() )
965       {
966       i->Value()->Accept(i->Index(), mv);
967       }
968     else
969       {
970       itkDebugMacro("Null cell at " << i->Index());
971       }
972     }
973 }
974
975
976 /**
977  * Dynamically build the links from points back to their using cells.  This
978  * information is stored in the cell links container, not in the points.
979  */
980 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
981 void
982 Mesh<TPixelType, VDimension, TMeshTraits>
983 ::BuildCellLinks()
984 {
985   /**
986    * Make sure we have a cells and a points container.
987    */
988   if( !this->m_PointsContainer || !m_CellsContainer )
989     {
990     /**
991      * TODO: Throw EXCEPTION here?
992      */
993     return;
994     }
995       
996   /**
997    * Make sure the cell links container exists.
998    */
999   if( !m_CellLinksContainer )
1000     {
1001     this->SetCellLinks(CellLinksContainer::New());
1002     }
1003
1004   /**
1005    * Loop through each cell, and add its identifier to the CellLinks of each
1006    * of its points.
1007    */
1008 SEM   for(CellsContainerIterator cellItr = m_CellsContainer->Begin() ;
1009 SEM,IND ******cellItr != m_CellsContainer->End() ; ++cellItr)
1010     {
1011     CellIdentifier cellId  = cellItr->Index();
1012     CellType *     cellptr = cellItr->Value();
1013     
1014     /**
1015      * For each point, make sure the cell links container has its index,
1016      * and then insert the cell ID into the point's set.
1017      */
1018 LEN,SEM     for(typename CellType::PointIdConstIterator pointId = cellptr->PointIdsBegin() ;
1019 SEM,IND ********pointId != cellptr->PointIdsEnd() ; ++pointId)
1020       {
1021       (m_CellLinksContainer->CreateElementAt(*pointId)).insert(cellId);
1022       }
1023     }
1024 }
1025
1026
1027 /******************************************************************************
1028  * PROTECTED METHOD DEFINITIONS
1029  *****************************************************************************/
1030
1031 /**
1032  * A protected default constructor allows the New() routine to create an
1033  * instance of Mesh.  All the containers are initialized to empty
1034  * containers.
1035  */
1036 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
1037 Mesh<TPixelType, VDimension, TMeshTraits>
1038 ::Mesh()
1039 {
1040   m_CellsContainer = CellsContainer::New();
1041   m_CellDataContainer =  CellDataContainer::New();
1042   m_CellLinksContainer = CellLinksContainer::New();
1043 LEN   m_BoundaryAssignmentsContainers = BoundaryAssignmentsContainerVector( MaxTopologicalDimension );
1044   m_CellsAllocationMethod = CellsAllocatedDynamicallyCellByCell;
1045 }
1046
1047
1048 /**
1049  * Mesh Destructor takes care of releasing the memory of Cells
1050  * and CellBoundaries objects for which normal pointers are
1051  * stored.
1052  */
1053 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
1054 Mesh<TPixelType, VDimension, TMeshTraits>
1055 ::~Mesh()
1056 {
1057   itkDebugMacro("Mesh Destructor ");
1058   this->ReleaseCellsMemory();
1059 }
1060
1061
1062 EML
1063 /**
1064  * Releasing the memory of Cells aobjects for which normal pointers 
1065  * are stored. The method used for memory release is based on information 
1066  * provided by the user who is the only who know how the memory was allocated.
1067  */
1068 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
1069 void
1070 Mesh<TPixelType, VDimension, TMeshTraits>
1071 ::ReleaseCellsMemory()
1072 {
1073   itkDebugMacro("Mesh  ReleaseCellsMemory method ");
1074   // Cells are stored as normal pointers in the CellContainer.
1075   //
1076   // The following cases are assumed here: 
1077   //
1078   // 0) The user forgot to tell the mesh how he allocated  the memory.
1079   //    In this case an exception is thrown. There is now way the mesh
1080   //    can guess how to correctly release the memory. 
1081   // 1) The user allocated the cells as an static array and then 
1082   //    passed pointers to the mesh. The mesh doesn't have to release
1083   //    any memory in this case. The user however has to be careful
1084   //    in making sure that the mesh is not used out of the scope in
1085   //    which the static array of cells is valid.(e.g. the pointer
1086   //    of the mesh should not be passed as a return parameter...)
1087   // 2) the user allocated the Cells as a big array so the 
1088   //    memory has to be released by getting the pointer to
1089   //    the first cell in the array and calling "delete [] cells"
1090   // 3) the user allocated the Cells on a cell-by-cell basis
1091   //    so every cell has to be deleted using   "delete cell"
1092   //
1093   if( !m_CellsContainer )
1094     {
1095     itkDebugMacro("m_CellsContainer is null");
1096     return;
1097     }
1098         
1099 LEN   itkDebugMacro("m_CellsContainer->GetReferenceCount()= " << m_CellsContainer->GetReferenceCount() );
1100
1101   if( m_CellsContainer->GetReferenceCount()==1 ) 
1102     {
1103     switch( m_CellsAllocationMethod )
1104       {
1105       case CellsAllocationMethodUndefined:
1106 IND ******{
1107 IND ******// The user forgot to tell the mesh about how he allocated 
1108 IND ******// the cells. No responsible guess can be made here. Call for help.
1109 LEN,IND ******itkGenericExceptionMacro(<<"Cells Allocation Method was not specified. See SetCellsAllocationMethod()");
1110       break;
1111       }
1112       case CellsAllocatedAsStaticArray:
1113       {
1114       // The cells will be naturally destroyed when
1115       // the original array goes out of scope.
1116       itkDebugMacro("CellsAllocatedAsStaticArray ");
1117       break;
1118       }
1119       case CellsAllocatedAsADynamicArray:
1120       {
1121       // the pointer to the first Cell is assumed to be the 
1122       // base pointer of the array
1123       CellsContainerIterator first = m_CellsContainer->Begin();
1124 IND ******CellType * baseOfCellsArray = first->Value();
1125 IND ******delete [] baseOfCellsArray;
1126 IND ******m_CellsContainer->Initialize();
1127 IND ******itkDebugMacro("CellsAllocatedAsADynamicArray");
1128 IND ******break;
1129 IND ******}
1130       case CellsAllocatedDynamicallyCellByCell:
1131 IND ******{
1132 IND ******itkDebugMacro("CellsAllocatedDynamicallyCellByCell start");
1133 IND ******// It is assumed that every cell was allocated independently.
1134 IND ******// A Cell iterator is created for going through the cells 
1135 IND ******// deleting one by one.
1136 IND ******CellsContainerIterator cell  = m_CellsContainer->Begin();
1137 IND ******CellsContainerIterator end   = m_CellsContainer->End();
1138 IND ******while( cell != end )
1139 IND ********{
1140 IND ********const CellType * cellToBeDeleted = cell->Value();
1141 LEN,IND ********itkDebugMacro( << "Mesh destructor deleting cell = " << cellToBeDeleted );
1142         delete cellToBeDeleted;
1143         ++cell; 
1144         }
1145       m_CellsContainer->Initialize();
1146 IND ******itkDebugMacro("CellsAllocatedDynamicallyCellByCell end");
1147 IND ******break;
1148 IND ******}
1149       }
1150     }
1151 }
1152
1153
1154 EML
1155 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
1156 void
1157 Mesh<TPixelType, VDimension, TMeshTraits>
1158 ::CopyInformation(const DataObject *data)
1159 {
1160   this->Superclass::CopyInformation( data );
1161
1162   const Self * mesh = NULL;
1163   
1164   try
1165     {
1166     mesh = dynamic_cast<const Self*>(data);
1167     }
1168   catch( ... )
1169     {
1170     // mesh could not be cast back down
1171     itkExceptionMacro(<< "itk::Mesh::CopyInformation() cannot cast "
1172                       << typeid(data).name() << " to "
1173                       << typeid(Self*).name() );
1174     }
1175
1176   if ( !mesh )
1177     {
1178     // pointer could not be cast back down
1179     itkExceptionMacro(<< "itk::Mesh::CopyInformation() cannot cast "
1180                       << typeid(data).name() << " to "
1181                       << typeid(Self*).name() );
1182     }
1183
1184
1185   // Copy here specific elements of the Mesh
1186 }
1187
1188
1189 template <typename TPixelType, unsigned int VDimension, typename TMeshTraits>
1190 void
1191 Mesh<TPixelType, VDimension, TMeshTraits>
1192 ::Graft(const DataObject *data)
1193 {
1194   this->Superclass::Graft( data );
1195
1196   const Self * mesh = NULL;
1197   
1198   try
1199     {
1200     mesh = dynamic_cast<const Self*>(data);
1201     }
1202   catch( ... )
1203     {
1204     // mesh could not be cast back down
1205     itkExceptionMacro(<< "itk::Mesh::CopyInformation() cannot cast "
1206                       << typeid(data).name() << " to "
1207                       << typeid(Self*).name() );
1208     }
1209
1210   if ( !mesh )
1211     {
1212     // pointer could not be cast back down
1213     itkExceptionMacro(<< "itk::Mesh::CopyInformation() cannot cast "
1214                       << typeid(data).name() << " to "
1215                       << typeid(Self*).name() );
1216     }
1217
1218
1219   this->m_CellsContainer     = mesh->m_CellsContainer;
1220   this->m_CellDataContainer  = mesh->m_CellDataContainer;
1221   this->m_CellLinksContainer = mesh->m_CellLinksContainer;
1222   this->m_BoundaryAssignmentsContainers = mesh->m_BoundaryAssignmentsContainers;
1223
1224   // Transfer the responsibility for releasing cells memory
1225   this->m_CellsAllocationMethod = mesh->m_CellsAllocationMethod;
1226
1227
1228   // Tell the original mesh that the cells were allocated statically 
1229   // in order to prevent it from trying to delete the cells.
1230   //
1231   // Casting away constness here is ugly but necessary...
1232   Self * nonConstMesh = const_cast< Self *>( mesh );
1233   nonConstMesh->m_CellsAllocationMethod = CellsAllocatedAsStaticArray; 
1234
1235 }
1236
1237
1238 // end namespace itk
1239
1240 #endif
1241

Generated by KWStyle 1.0b on Tuesday January,17 at 02:14:22PM
© Kitware Inc.