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 /*=========================================================================
19  *
20  *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
21  *
22  *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
23  *
24  *  For complete copyright, license and disclaimer of warranty information
25  *  please refer to the NOTICE file at the top of the ITK source tree.
26  *
27  *=========================================================================*/
28 #ifndef itkLabelMap_hxx
29 #define itkLabelMap_hxx
30 
31 #include "itkLabelMap.h"
32 #include "itkProcessObject.h"
33 
34 #include <algorithm>
35 
36 namespace itk
37 {
38 
39 template< typename TLabelObject >
40 LabelMap< TLabelObject >
LabelMap()41 ::LabelMap()
42 {
43   m_BackgroundValue = NumericTraits< LabelType >::ZeroValue();
44   this->Initialize();
45 }
46 
47 
48 template< typename TLabelObject >
49 void
50 LabelMap< TLabelObject >
PrintSelf(std::ostream & os,Indent indent) const51 ::PrintSelf(std::ostream & os, Indent indent) const
52 {
53   Superclass::PrintSelf(os, indent);
54 
55   os << indent << "BackgroundValue: "
56      << static_cast< typename NumericTraits< LabelType >::PrintType >( m_BackgroundValue ) << std::endl;
57   os << indent << "LabelObjectContainer: " << &m_LabelObjectContainer << std::endl;
58 }
59 
60 
61 template< typename TLabelObject >
62 void
63 LabelMap< TLabelObject >
Initialize()64 ::Initialize()
65 {
66   this->ClearLabels();
67 }
68 
69 
70 template< typename TLabelObject >
71 void
72 LabelMap< TLabelObject >
Allocate(bool)73 ::Allocate(bool)
74 {
75   this->Initialize();
76 }
77 
78 
79 template< typename TLabelObject >
80 void
81 LabelMap< TLabelObject >
Graft(const Self * imgData)82 ::Graft(const Self *imgData)
83 {
84   if(imgData == nullptr)
85     {
86     return; // nothing to do
87     }
88   // call the superclass' implementation
89   Superclass::Graft(imgData);
90 
91   // Now copy anything remaining that is needed
92   if( &m_LabelObjectContainer != &(imgData->m_LabelObjectContainer) )
93     {
94     m_LabelObjectContainer.clear();
95     LabelObjectContainerType newLabelObjectContainer( imgData->m_LabelObjectContainer );
96     std::swap( m_LabelObjectContainer, newLabelObjectContainer );
97     }
98   m_BackgroundValue = imgData->m_BackgroundValue;
99 }
100 
101 template< typename TLabelObject >
102 void
103 LabelMap< TLabelObject >
Graft(const DataObject * data)104 ::Graft(const DataObject *data)
105 {
106   if(data == nullptr)
107     {
108     return; // nothing to do
109     }
110 
111   // Attempt to cast data to an Image
112   const auto * imgData = dynamic_cast< const Self * >( data );
113 
114   if ( imgData == nullptr )
115     {
116     // pointer could not be cast back down
117     itkExceptionMacro( << "itk::LabelMap::Graft() cannot cast "
118                        << typeid( data ).name() << " to "
119                        << typeid( const Self * ).name() );
120     }
121   this->Graft(imgData);
122 }
123 
124 
125 template< typename TLabelObject >
126 typename LabelMap< TLabelObject >::LabelObjectType *
127 LabelMap< TLabelObject >
GetLabelObject(const LabelType & label)128 ::GetLabelObject(const LabelType & label)
129 {
130   if ( m_BackgroundValue == label )
131     {
132     itkExceptionMacro(<< "Label "
133                       << static_cast< typename NumericTraits< LabelType >::PrintType >( label )
134                       << " is the background label.");
135     }
136   auto it = m_LabelObjectContainer.find( label );
137   if ( it == m_LabelObjectContainer.end() )
138     {
139     itkExceptionMacro(<< "No label object with label "
140                       << static_cast< typename NumericTraits< LabelType >::PrintType >( label )
141                       << ".");
142     }
143 
144   return it->second;
145 }
146 
147 
148 template< typename TLabelObject >
149 const typename LabelMap< TLabelObject >::LabelObjectType *
150 LabelMap< TLabelObject >
GetLabelObject(const LabelType & label) const151 ::GetLabelObject(const LabelType & label) const
152 {
153   if ( m_BackgroundValue == label )
154     {
155     itkExceptionMacro(<< "Label "
156                       << static_cast< typename NumericTraits< LabelType >::PrintType >( label )
157                       << " is the background label.");
158     }
159   auto it = m_LabelObjectContainer.find( label );
160   if ( it == m_LabelObjectContainer.end() )
161     {
162     itkExceptionMacro(<< "No label object with label "
163                       << static_cast< typename NumericTraits< LabelType >::PrintType >( label )
164                       << ".");
165     }
166 
167   return it->second;
168 }
169 
170 
171 template< typename TLabelObject >
172 bool
173 LabelMap< TLabelObject >
HasLabel(const LabelType label) const174 ::HasLabel(const LabelType label) const
175 {
176   return m_LabelObjectContainer.find(label) != m_LabelObjectContainer.end();
177 }
178 
179 
180 template< typename TLabelObject >
181 const typename LabelMap< TLabelObject >::LabelType &
182 LabelMap< TLabelObject >
GetPixel(const IndexType & idx) const183 ::GetPixel(const IndexType & idx) const
184 {
185   auto end = m_LabelObjectContainer.end();
186 
187   for ( auto it = m_LabelObjectContainer.begin();
188         it != end;
189         ++it )
190     {
191     if ( it->second->HasIndex(idx) )
192       {
193       return it->second->GetLabel();
194       }
195     }
196   return m_BackgroundValue;
197 }
198 
199 
200 template< typename TLabelObject >
201 typename LabelMap< TLabelObject >::LabelObjectType *
202 LabelMap< TLabelObject >
GetNthLabelObject(const SizeValueType & pos)203 ::GetNthLabelObject(const SizeValueType & pos)
204 {
205   SizeValueType i = 0;
206 
207   for ( auto it = m_LabelObjectContainer.begin();
208         it != m_LabelObjectContainer.end();
209         it++ )
210     {
211     if ( i == pos )
212       {
213       return it->second;
214       }
215     i++;
216     }
217   itkExceptionMacro(<< "Can't access to label object at position "
218                     << pos
219                     << ". The label map has only "
220                     << this->GetNumberOfLabelObjects()
221                     << " label objects registered.");
222 }
223 
224 
225 template< typename TLabelObject >
226 const typename LabelMap< TLabelObject >::LabelObjectType *
227 LabelMap< TLabelObject >
GetNthLabelObject(const SizeValueType & pos) const228 ::GetNthLabelObject(const SizeValueType & pos) const
229 {
230   SizeValueType i = 0;
231 
232   for ( LabelObjectContainerConstIterator it = m_LabelObjectContainer.begin();
233         it != m_LabelObjectContainer.end();
234         it++ )
235     {
236     if ( i == pos )
237       {
238       return it->second;
239       }
240     i++;
241     }
242   itkExceptionMacro(<< "Can't access to label object at position "
243                     << pos
244                     << ". The label map has only "
245                     << this->GetNumberOfLabelObjects()
246                     << " label objects registered.");
247 }
248 
249 
250 template< typename TLabelObject >
251 void
252 LabelMap< TLabelObject >
SetPixel(const IndexType & idx,const LabelType & iLabel)253 ::SetPixel(const IndexType & idx, const LabelType & iLabel )
254 {
255   bool newLabel = true; // or can be initialized by ( iLabel == m_BackgroundValue )
256 
257   auto it = m_LabelObjectContainer.begin();
258 
259   while( it != m_LabelObjectContainer.end() )
260     {
261     // increment the iterator before removing the pixel because
262     // RemovePixel() can remove the object and thus invalidate the
263     // iterator
264       if( it->first != iLabel )
265         {
266         auto tempIt = it;
267         ++it;
268         bool emitModifiedEvent = ( iLabel == m_BackgroundValue );
269         this->RemovePixel( tempIt, idx, emitModifiedEvent );
270         }
271       else
272         {
273         newLabel = false;
274         this->AddPixel( it, idx, iLabel );
275         ++it;
276         }
277     }
278   if( newLabel )
279     {
280     this->AddPixel( m_LabelObjectContainer.end(), idx, iLabel );
281     }
282 }
283 
284 
285 template< typename TLabelObject >
286 void
287 LabelMap< TLabelObject >
AddPixel(const IndexType & idx,const LabelType & label)288 ::AddPixel(const IndexType & idx, const LabelType & label)
289 {
290   if ( label == m_BackgroundValue )
291     {
292     // just do nothing
293     return;
294     }
295 
296   LabelObjectContainerIterator it = m_LabelObjectContainer.find(label);
297 
298   this->AddPixel( it, idx, label );
299 }
300 
301 
302 template< typename TLabelObject >
303 void
304 LabelMap< TLabelObject >
AddPixel(const LabelObjectContainerIterator & it,const IndexType & idx,const LabelType & label)305 ::AddPixel(const LabelObjectContainerIterator & it,
306            const IndexType & idx,
307            const LabelType & label )
308 {
309   if ( label == m_BackgroundValue )
310     {
311     // just do nothing
312     return;
313     }
314 
315   if ( it != m_LabelObjectContainer.end() )
316     {
317     // the label already exist - add the pixel to it
318     ( *it ).second->AddIndex(idx);
319     this->Modified();
320     }
321   else
322     {
323     // the label does not exist yet - create a new one
324     LabelObjectPointerType labelObject = LabelObjectType::New();
325     labelObject->SetLabel(label);
326     labelObject->AddIndex(idx);
327     // Modified() is called in AddLabelObject()
328     this->AddLabelObject(labelObject);
329     }
330 }
331 
332 
333 template< typename TLabelObject >
334 void
335 LabelMap< TLabelObject >
RemovePixel(const LabelObjectContainerIterator & it,const IndexType & idx,bool iEmitModifiedEvent)336 ::RemovePixel(const LabelObjectContainerIterator & it,
337               const IndexType & idx,
338               bool iEmitModifiedEvent )
339 {
340   if ( it != m_LabelObjectContainer.end() )
341     {
342     // the label already exist - add the pixel to it
343     if( it->second->RemoveIndex(idx) )
344       {
345       if( it->second->Empty() )
346         {
347         this->RemoveLabelObject(it->second);
348         }
349       if( iEmitModifiedEvent )
350         {
351         this->Modified();
352         }
353       }
354     }
355 }
356 
357 
358 template< typename TLabelObject >
359 void
360 LabelMap< TLabelObject >
RemovePixel(const IndexType & idx,const LabelType & label)361 ::RemovePixel(const IndexType & idx, const LabelType & label)
362 {
363   if ( label == m_BackgroundValue )
364     {
365     // just do nothing
366     return;
367     }
368 
369   LabelObjectContainerIterator it = m_LabelObjectContainer.find(label);
370 
371   bool emitModifiedEvent = true;
372   RemovePixel( it, idx, emitModifiedEvent );
373 }
374 
375 
376 template< typename TLabelObject >
377 void
378 LabelMap< TLabelObject >
SetLine(const IndexType & idx,const LengthType & length,const LabelType & label)379 ::SetLine(const IndexType & idx, const LengthType & length, const LabelType & label)
380 {
381   if ( label == m_BackgroundValue )
382     {
383     // just do nothing
384     return;
385     }
386 
387   auto it = m_LabelObjectContainer.find(label);
388 
389   if ( it != m_LabelObjectContainer.end() )
390     {
391     // the label already exist - add the pixel to it
392     ( *it ).second->AddLine(idx, length);
393     this->Modified();
394     }
395   else
396     {
397     // the label does not exist yet - create a new one
398     LabelObjectPointerType labelObject = LabelObjectType::New();
399     labelObject->SetLabel(label);
400     labelObject->AddLine(idx, length);
401     // Modified() is called in AddLabelObject()
402     this->AddLabelObject(labelObject);
403     }
404 }
405 
406 
407 template< typename TLabelObject >
408 typename LabelMap< TLabelObject >::LabelObjectType *
409 LabelMap< TLabelObject >
GetLabelObject(const IndexType & idx) const410 ::GetLabelObject(const IndexType & idx) const
411 {
412   for ( auto it = m_LabelObjectContainer.begin();
413         it != m_LabelObjectContainer.end();
414         it++ )
415     {
416     if ( it->second->HasIndex(idx) )
417       {
418       return it->second.GetPointer();
419       }
420     }
421   itkExceptionMacro(<< "No label object at index " << idx << ".");
422 //   return nullptr;
423 }
424 
425 
426 template< typename TLabelObject >
427 void
428 LabelMap< TLabelObject >
AddLabelObject(LabelObjectType * labelObject)429 ::AddLabelObject(LabelObjectType *labelObject)
430 {
431   itkAssertOrThrowMacro( ( labelObject != nullptr ), "Input LabelObject can't be Null" );
432 
433   m_LabelObjectContainer[labelObject->GetLabel()] = labelObject;
434   this->Modified();
435 }
436 
437 
438 template< typename TLabelObject >
439 void
440 LabelMap< TLabelObject >
PushLabelObject(LabelObjectType * labelObject)441 ::PushLabelObject(LabelObjectType *labelObject)
442 {
443   itkAssertOrThrowMacro( ( labelObject != nullptr ), "Input LabelObject can't be Null" );
444 
445   if ( m_LabelObjectContainer.empty() )
446     {
447     if ( m_BackgroundValue == 0 )
448       {
449       labelObject->SetLabel(1);
450       }
451     else
452       {
453       labelObject->SetLabel(0);
454       }
455     }
456   else
457     {
458     LabelType lastLabel = m_LabelObjectContainer.rbegin()->first;
459     LabelType firstLabel = m_LabelObjectContainer.begin()->first;
460     if ( lastLabel != NumericTraits< LabelType >::max() && lastLabel + 1 != m_BackgroundValue )
461       {
462       labelObject->SetLabel(lastLabel + 1);
463       }
464     else if ( lastLabel != NumericTraits< LabelType >::max() && lastLabel + 1 != NumericTraits< LabelType >::max()
465               && lastLabel + 2 != m_BackgroundValue )
466       {
467       labelObject->SetLabel(lastLabel + 2);
468       }
469     else if ( firstLabel != NumericTraits< LabelType >::NonpositiveMin() && firstLabel - 1 != m_BackgroundValue )
470       {
471       labelObject->SetLabel(firstLabel - 1);
472       }
473     else
474       {
475       // search for an unused label
476       LabelType label = firstLabel;
477       LabelObjectContainerConstIterator it;
478       for ( it = m_LabelObjectContainer.begin();
479             it != m_LabelObjectContainer.end();
480             it++, label++ )
481         {
482         assert( ( it->second.IsNotNull() ) );
483         if ( label == m_BackgroundValue )
484           {
485           label++;
486           }
487         if ( label != it->first )
488           {
489           labelObject->SetLabel(label);
490           break;
491           }
492         }
493       if ( label == lastLabel )
494         {
495         itkExceptionMacro(<< "Can't push the label object: the label map is full.");
496         }
497       }
498     }
499   // modified is called in AddLabelObject()
500   this->AddLabelObject(labelObject);
501 }
502 
503 
504 template< typename TLabelObject >
505 void
506 LabelMap< TLabelObject >
RemoveLabelObject(LabelObjectType * labelObject)507 ::RemoveLabelObject(LabelObjectType *labelObject)
508 {
509   itkAssertOrThrowMacro( ( labelObject != nullptr ), "Input LabelObject can't be Null" );
510   // modified is called in RemoveLabel()
511   this->RemoveLabel( labelObject->GetLabel() );
512 }
513 
514 
515 template< typename TLabelObject >
516 void
517 LabelMap< TLabelObject >
RemoveLabel(const LabelType & label)518 ::RemoveLabel(const LabelType & label)
519 {
520   if ( m_BackgroundValue == label )
521     {
522     itkExceptionMacro(<< "Label "
523                       << static_cast< typename NumericTraits< LabelType >::PrintType >( label )
524                       << " is the background label.");
525     }
526   m_LabelObjectContainer.erase(label);
527   this->Modified();
528 }
529 
530 
531 template< typename TLabelObject >
532 void
533 LabelMap< TLabelObject >
ClearLabels()534 ::ClearLabels()
535 {
536   if ( !m_LabelObjectContainer.empty() )
537     {
538     m_LabelObjectContainer.clear();
539     this->Modified();
540     }
541 }
542 
543 
544 template< typename TLabelObject >
545 typename LabelMap< TLabelObject >::SizeValueType
546 LabelMap< TLabelObject >
GetNumberOfLabelObjects() const547 ::GetNumberOfLabelObjects() const
548 {
549   return static_cast<typename LabelMap< TLabelObject >::SizeValueType>( m_LabelObjectContainer.size() );
550 }
551 
552 
553 template< typename TLabelObject >
554 typename LabelMap< TLabelObject >::LabelVectorType
555 LabelMap< TLabelObject >
GetLabels() const556 ::GetLabels() const
557 {
558   LabelVectorType res;
559 
560   res.reserve( this->GetNumberOfLabelObjects() );
561   for ( auto it = m_LabelObjectContainer.begin();
562         it != m_LabelObjectContainer.end();
563         it++ )
564     {
565     res.push_back(it->first);
566     }
567   return res;
568 }
569 
570 
571 template< typename TLabelObject >
572 typename LabelMap< TLabelObject >::LabelObjectVectorType
573 LabelMap< TLabelObject >
GetLabelObjects() const574 ::GetLabelObjects() const
575 {
576   LabelObjectVectorType res;
577 
578   res.reserve( this->GetNumberOfLabelObjects() );
579   for ( auto it = m_LabelObjectContainer.begin();
580         it != m_LabelObjectContainer.end();
581         it++ )
582     {
583     res.push_back(it->second);
584     }
585   return res;
586 }
587 
588 
589 template< typename TLabelObject >
590 void
591 LabelMap< TLabelObject >
PrintLabelObjects(std::ostream & os) const592 ::PrintLabelObjects(std::ostream & os) const
593 {
594   for ( auto it = m_LabelObjectContainer.begin();
595         it != m_LabelObjectContainer.end();
596         it++ )
597     {
598     assert( ( it->second.IsNotNull() ) );
599     it->second->Print(os);
600     os << std::endl;
601     }
602 }
603 
604 
605 template< typename TLabelObject >
606 void
607 LabelMap< TLabelObject >
Optimize()608 ::Optimize()
609 {
610   for ( LabelObjectContainerConstIterator it = m_LabelObjectContainer.begin();
611         it != m_LabelObjectContainer.end();
612         it++ )
613     {
614     assert( ( it->second.IsNotNull() ) );
615     it->second->Optimize();
616     }
617   this->Modified();
618 }
619 
620 } // end namespace itk
621 
622 #endif
623