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 #ifndef itkFastMarchingQuadEdgeMeshFilterBase_hxx
20 #define itkFastMarchingQuadEdgeMeshFilterBase_hxx
21 
22 #include "itkFastMarchingQuadEdgeMeshFilterBase.h"
23 
24 #include "itkMath.h"
25 #include "itkVector.h"
26 #include "itkMatrix.h"
27 
28 namespace itk
29 {
30 template< typename TInput, typename TOutput >
31 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
FastMarchingQuadEdgeMeshFilterBase()32 ::FastMarchingQuadEdgeMeshFilterBase() : Superclass()
33 {
34   this->m_InputMesh = nullptr;
35 }
36 
37 template< typename TInput, typename TOutput >
38 IdentifierType
39 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
GetTotalNumberOfNodes() const40 ::GetTotalNumberOfNodes() const
41 {
42   return this->GetInput()->GetNumberOfPoints();
43 }
44 
45 template< typename TInput, typename TOutput >
46 void
47 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
SetOutputValue(OutputMeshType * oMesh,const NodeType & iNode,const OutputPixelType & iValue)48 ::SetOutputValue( OutputMeshType* oMesh,
49                   const NodeType& iNode,
50                   const OutputPixelType& iValue )
51 {
52   oMesh->SetPointData( iNode, iValue );
53 }
54 
55 template< typename TInput, typename TOutput >
56 const typename
57 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
58 ::OutputPixelType
59 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
GetOutputValue(OutputMeshType * oMesh,const NodeType & iNode) const60 ::GetOutputValue( OutputMeshType* oMesh, const NodeType& iNode ) const
61 {
62   OutputPixelType outputValue = NumericTraits< OutputPixelType >::ZeroValue();
63   oMesh->GetPointData( iNode, &outputValue );
64   return outputValue;
65 }
66 
67 
68 template< typename TInput, typename TOutput >
69 unsigned char
70 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
GetLabelValueForGivenNode(const NodeType & iNode) const71 ::GetLabelValueForGivenNode( const NodeType& iNode ) const
72 {
73   auto it = m_Label.find( iNode );
74 
75   if( it != m_Label.end() )
76     {
77     return it->second;
78     }
79   else
80     {
81     return Traits::Far;
82     }
83 }
84 
85 template< typename TInput, typename TOutput >
86 void
87 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
SetLabelValueForGivenNode(const NodeType & iNode,const LabelType & iLabel)88 ::SetLabelValueForGivenNode( const NodeType& iNode,
89                              const LabelType& iLabel )
90 {
91    m_Label[iNode] = iLabel;
92 }
93 
94 template< typename TInput, typename TOutput >
95 void
96 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
UpdateNeighbors(OutputMeshType * oMesh,const NodeType & iNode)97 ::UpdateNeighbors( OutputMeshType* oMesh,
98                    const NodeType& iNode )
99 {
100   OutputPointType p;
101   oMesh->GetPoint( iNode, &p );
102 
103   OutputQEType* qe = p.GetEdge();
104 
105   if( qe )
106     {
107     OutputQEType *qe_it = qe;
108     this->m_InputMesh = this->GetInput();
109     do
110       {
111       if( qe_it )
112         {
113         OutputPointIdentifierType neigh_id = qe_it->GetDestination();
114 
115         const char label = this->GetLabelValueForGivenNode( neigh_id );
116 
117         if ( ( label != Traits::Alive ) &&
118              ( label != Traits::InitialTrial ) &&
119              ( label != Traits::Forbidden ) )
120           {
121           this->UpdateValue( oMesh, neigh_id );
122           }
123         }
124       else
125         {
126         itkGenericExceptionMacro( <<"qe_it is nullptr" );
127         }
128       qe_it = qe_it->GetOnext();
129       }
130     while( qe_it != qe );
131     }
132   else
133     {
134     itkGenericExceptionMacro( <<"qe is nullptr" );
135     }
136 }
137 
138 template< typename TInput, typename TOutput >
139 void
140 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
UpdateValue(OutputMeshType * oMesh,const NodeType & iNode)141 ::UpdateValue( OutputMeshType* oMesh,
142                const NodeType& iNode )
143   {
144   OutputPointType p;
145   oMesh->GetPoint( iNode, &p );
146 
147   InputPixelType F = NumericTraits< InputPixelType >::ZeroValue();
148   this->m_InputMesh->GetPointData( iNode, &F );
149 
150   if( F < 0. )
151     {
152     itkGenericExceptionMacro( << "F < 0." );
153     }
154 
155   OutputQEType* qe = p.GetEdge();
156 
157   OutputPixelType outputPixel = this->m_LargeValue;
158 
159   if( qe )
160     {
161     OutputQEType *qe_it = qe;
162     qe_it = qe_it->GetOnext();
163 
164     do
165       {
166       OutputQEType *qe_it2 = qe_it->GetOnext();
167 
168       if( qe_it2 )
169         {
170         if( qe_it->GetLeft() != OutputMeshType::m_NoFace )
171           {
172           OutputPointIdentifierType id1 = qe_it->GetDestination();
173           OutputPointIdentifierType id2 = qe_it2->GetDestination();
174 
175           const auto label1 = static_cast< LabelType >( this->GetLabelValueForGivenNode( id1 ) );
176           const auto label2 = static_cast< LabelType >( this->GetLabelValueForGivenNode( id2 ) );
177 
178           bool IsFar1 = ( label1 != Traits::Far );
179           bool IsFar2 = ( label2 != Traits::Far );
180 
181           if( IsFar1 || IsFar2 )
182             {
183             OutputPointType q1 = oMesh->GetPoint( id1 );
184             OutputPointType q2 = oMesh->GetPoint( id2 );
185 
186             auto val1 = static_cast< OutputVectorRealType >( this->GetOutputValue( oMesh, id1 ) );
187             auto val2 = static_cast< OutputVectorRealType >( this->GetOutputValue( oMesh, id2 ) );
188 
189             if( val1 > val2 )
190               {
191               OutputPointType temp_pt( q1 );
192               q1 = q2;
193               q2 = temp_pt;
194 
195               std::swap( val1, val2 );
196               std::swap( IsFar1, IsFar2 );
197               std::swap( id1, id2 );
198               }
199 
200             const OutputVectorRealType temp =
201                 this->Solve( oMesh, iNode, p, F,
202                             id1, q1, IsFar1, val1,
203                             id2, q2, IsFar2, val2 );
204 
205             outputPixel =
206                 std::min( outputPixel,
207                               static_cast< OutputPixelType >( temp ) );
208             }
209           }
210 
211         qe_it = qe_it2;
212         }
213       else
214         {
215         // throw one exception here
216         itkGenericExceptionMacro( << "qe_it2 is nullptr" );
217         }
218       }
219     while( qe_it != qe );
220 
221     if( outputPixel < this->m_LargeValue )
222       {
223       this->SetOutputValue( oMesh, iNode, outputPixel );
224 
225       this->SetLabelValueForGivenNode( iNode, Traits::Trial );
226 
227       this->m_Heap.push( NodePairType( iNode, outputPixel ) );
228       }
229     }
230   else
231     {
232     // throw one exception
233     itkGenericExceptionMacro( << "qe_it is nullptr" );
234     }
235   }
236 
237 template< typename TInput, typename TOutput >
238 const typename
239 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
240 ::OutputVectorRealType
241 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
Solve(OutputMeshType * oMesh,const NodeType & iId,const OutputPointType & iCurrentPoint,const OutputVectorRealType & iF,const NodeType & iId1,const OutputPointType & iP1,const bool & iIsFar1,const OutputVectorRealType iVal1,const NodeType & iId2,const OutputPointType & iP2,const bool & iIsFar2,const OutputVectorRealType & iVal2) const242 ::Solve( OutputMeshType* oMesh,
243        const NodeType& iId, const OutputPointType& iCurrentPoint,
244        const OutputVectorRealType& iF,
245        const NodeType& iId1, const OutputPointType& iP1,
246        const bool& iIsFar1, const OutputVectorRealType iVal1,
247        const NodeType& iId2, const OutputPointType& iP2,
248        const bool& iIsFar2, const OutputVectorRealType& iVal2 ) const
249   {
250   OutputVectorType Edge1 = iP1 - iCurrentPoint;
251   OutputVectorType Edge2 = iP2 - iCurrentPoint;
252 
253   OutputVectorRealType sq_norm1 = Edge1.GetSquaredNorm();
254   OutputVectorRealType norm1 = 0.;
255 
256   OutputVectorRealType epsilon =
257       NumericTraits< OutputVectorRealType >::epsilon();
258 
259   if( sq_norm1 > epsilon )
260     {
261     norm1 = std::sqrt( sq_norm1 );
262 
263     OutputVectorRealType inv_norm1 = 1. / norm1;
264     Edge1 *= inv_norm1;
265     }
266 
267   OutputVectorRealType sq_norm2 = Edge2.GetSquaredNorm();
268   OutputVectorRealType norm2 = 0.;
269 
270   if( sq_norm2 > epsilon )
271     {
272     norm2 = std::sqrt( sq_norm2 );
273 
274     OutputVectorRealType inv_norm2 = 1. / norm2;
275     Edge2 *= inv_norm2;
276     }
277 
278   if( !iIsFar1 && iIsFar2 )
279     {
280     // only one point is a contributor
281     return iVal2 + norm2 * iF;
282     }
283   if( iIsFar1 && !iIsFar2 )
284     {
285     // only one point is a contributor
286     return iVal1 + norm1 * iF;
287     }
288 
289   if( iIsFar1 && iIsFar2 )
290     {
291     auto dot = static_cast< OutputVectorRealType >( Edge1 * Edge2 );
292 
293     if( dot >= 0. )
294       {
295       return ComputeUpdate( iVal1, iVal2,
296                            norm2, sq_norm2,
297                            norm1, sq_norm1, dot, iF );
298       }
299     else
300       {
301       OutputVectorRealType sq_norm3, norm3, dot1, dot2;
302       OutputPointIdentifierType new_id;
303 
304       bool unfolded =
305         UnfoldTriangle( oMesh, iId, iCurrentPoint, iId1, iP1,
306                         iId2, iP2, norm3, sq_norm3, dot1, dot2 , new_id );
307 
308       if( unfolded )
309         {
310         OutputVectorRealType t_sq_norm3 = norm3 * norm3;
311 
312         auto val3 = static_cast< OutputVectorRealType >(
313               this->GetOutputValue( oMesh, new_id ) );
314         OutputVectorRealType t1 = ComputeUpdate( iVal1, val3, norm3, t_sq_norm3,
315                                                 norm1, sq_norm1, dot1, iF );
316         OutputVectorRealType t2 = ComputeUpdate( iVal2, val3, norm3, t_sq_norm3,
317                                                 norm2, sq_norm2, dot2, iF );
318 
319         return std::min( t1, t2 );
320         }
321       else
322         {
323         return ComputeUpdate( iVal1, iVal2,
324                              norm2, sq_norm2,
325                              norm1, sq_norm1, dot, iF );
326         }
327       }
328 
329 
330     }
331 
332   return this->m_LargeValue;
333   }
334 
335 template< typename TInput, typename TOutput >
336 const typename
337 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
338 ::OutputVectorRealType
339 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
ComputeUpdate(const OutputVectorRealType & iVal1,const OutputVectorRealType & iVal2,const OutputVectorRealType & iNorm1,const OutputVectorRealType & iSqNorm1,const OutputVectorRealType & iNorm2,const OutputVectorRealType & iSqNorm2,const OutputVectorRealType & iDot,const OutputVectorRealType & iF) const340 ::ComputeUpdate(
341   const OutputVectorRealType& iVal1, const OutputVectorRealType& iVal2,
342   const OutputVectorRealType& iNorm1, const OutputVectorRealType& iSqNorm1,
343   const OutputVectorRealType& iNorm2, const OutputVectorRealType& iSqNorm2,
344   const OutputVectorRealType& iDot, const OutputVectorRealType& iF )
345   const
346 {
347   auto large_value = static_cast< OutputVectorRealType >( this->m_LargeValue );
348 
349   OutputVectorRealType t = large_value;
350 
351   OutputVectorRealType CosAngle = iDot;
352   OutputVectorRealType SinAngle = std::sqrt( 1. - iDot * iDot );
353 
354   OutputVectorRealType u = iVal2 - iVal1;
355 
356   OutputVectorRealType sq_u = u * u;
357   OutputVectorRealType f2 = iSqNorm1 + iSqNorm2 - 2. * iNorm1 * iNorm2 * CosAngle;
358   OutputVectorRealType f1 = iNorm2 * u * ( iNorm1 * CosAngle - iNorm2 );
359   OutputVectorRealType f0 = iSqNorm2 * ( sq_u - iF * iF * iSqNorm1 * SinAngle * SinAngle );
360 
361   OutputVectorRealType delta = f1 * f1 - f0 * f2;
362 
363   OutputVectorRealType epsilon =
364       NumericTraits< OutputVectorRealType >::epsilon();
365 
366   if( delta >= 0. )
367     {
368     if( itk::Math::abs( f2 ) > epsilon )
369       {
370       t = ( -f1 - std::sqrt( delta ) ) / f2;
371 
372       // test if we must must choose the other solution
373       if( ( t < u ) ||
374           ( iNorm2 * ( t - u ) / t < iNorm1 * CosAngle ) ||
375           ( iNorm1 / CosAngle < iNorm2 * ( t - u ) / t ) )
376         {
377         t = ( -f1 + std::sqrt( delta ) ) / f2;
378         }
379       }
380     else
381       {
382       if( itk::Math::abs( f1 ) > epsilon )
383         {
384         t = -f0 / f1;
385         }
386       else
387         {
388         t = - large_value;
389         }
390       }
391     }
392   else
393     {
394     t = - large_value;
395     }
396 
397   // choose the update from the 2 vertex only if upwind criterion is met
398   if( ( u < t ) &&
399       ( iNorm1 * CosAngle < iNorm2 * ( t - u ) / t ) &&
400       ( iNorm2 * ( t - u ) / t < iNorm1 / CosAngle ) )
401     {
402     return t + iVal1;
403     }
404   else
405     {
406     return std::min( iNorm2 * iF + iVal1, iNorm1 * iF + iVal2 );
407     }
408 }
409 
410 template< typename TInput, typename TOutput >
411 bool
412 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
UnfoldTriangle(OutputMeshType * oMesh,const OutputPointIdentifierType & iId,const OutputPointType & iP,const OutputPointIdentifierType & iId1,const OutputPointType & iP1,const OutputPointIdentifierType & iId2,const OutputPointType & iP2,OutputVectorRealType & oNorm,OutputVectorRealType & oSqNorm,OutputVectorRealType & oDot1,OutputVectorRealType & oDot2,OutputPointIdentifierType & oId) const413 ::UnfoldTriangle(
414   OutputMeshType* oMesh,
415   const OutputPointIdentifierType& iId, const OutputPointType& iP,
416   const OutputPointIdentifierType& iId1, const OutputPointType& iP1,
417   const OutputPointIdentifierType& iId2, const OutputPointType &iP2,
418   OutputVectorRealType& oNorm, OutputVectorRealType& oSqNorm,
419   OutputVectorRealType& oDot1, OutputVectorRealType& oDot2,
420   OutputPointIdentifierType& oId ) const
421   {
422   (void) iId;
423 
424   OutputVectorType Edge1 = iP1 - iP;
425   OutputVectorRealType Norm1 = Edge1.GetNorm();
426 
427   OutputVectorRealType epsilon =
428     NumericTraits< OutputVectorRealType >::epsilon();
429 
430   if( Norm1 > epsilon )
431     {
432     OutputVectorRealType inv_Norm = 1. / Norm1;
433     Edge1 *= inv_Norm;
434     }
435 
436   OutputVectorType Edge2 = iP2 - iP;
437   OutputVectorRealType Norm2 = Edge2.GetNorm();
438   if( Norm2 > epsilon )
439     {
440     OutputVectorRealType inv_Norm = 1. / Norm2;
441     Edge2 *= inv_Norm;
442     }
443 
444   auto dot = static_cast< OutputVectorRealType >( Edge1 * Edge2 );
445 
446   // the equation of the lines defining the unfolding region
447   // [e.g. line 1 : {x ; <x,eq1>=0} ]
448   using Vector2DType = Vector< OutputVectorRealType, 2 >;
449   using Matrix2DType = Matrix< OutputVectorRealType, 2, 2 >;
450 
451   Vector2DType v1;
452   v1[0] = dot;
453   v1[1] = std::sqrt( 1. - dot * dot );
454 
455   Vector2DType v2;
456   v2[0] = 1.;
457   v2[1] = 0.;
458 
459   Vector2DType x1;
460   x1[0] = Norm1;
461   x1[1] = 0.;
462 
463   Vector2DType x2 = Norm2 * v1;
464 
465   // keep track of the starting point
466   Vector2DType x_start1( x1 );
467   Vector2DType x_start2( x2 );
468 
469   OutputPointIdentifierType id1 = iId1;
470   OutputPointIdentifierType id2 = iId2;
471 
472   OutputQEType *qe = oMesh->FindEdge( id1, id2 );
473   qe = qe->GetSym();
474 
475   OutputPointType t_pt1 = iP1;
476   OutputPointType t_pt2 = iP2;
477   OutputPointType t_pt = t_pt1;
478 
479   unsigned int nNum = 0;
480   while( nNum<50 && qe->GetLeft() != OutputMeshType::m_NoFace )
481     {
482     OutputQEType* qe_Lnext = qe->GetLnext();
483     OutputPointIdentifierType t_id = qe_Lnext->GetDestination();
484 
485     oMesh->GetPoint( t_id, &t_pt );
486 
487     Edge1 = t_pt2 - t_pt1;
488     Norm1 = Edge1.GetNorm();
489     if( Norm1 > epsilon )
490       {
491       OutputVectorRealType inv_Norm = 1. / Norm1;
492       Edge1 *= inv_Norm;
493       }
494 
495     Edge2 = t_pt - t_pt1;
496     Norm2 = Edge2.GetNorm();
497     if( Norm2 > epsilon )
498       {
499       OutputVectorRealType inv_Norm = 1. / Norm2;
500       Edge2 *= inv_Norm;
501       }
502 
503     /* compute the position of the new point x on the unfolding plane (via a rotation of -alpha on (x2-x1)/rNorm1 )
504             | cos(alpha) sin(alpha)|
505         x = |-sin(alpha) cos(alpha)| * [x2-x1]*rNorm2/rNorm1 + x1   where cos(alpha)=dot
506     */
507     Vector2DType vv;
508     if( Norm1 > epsilon )
509       {
510       vv = (x2 - x1) * Norm2 / Norm1;
511       }
512     else
513       {
514       vv.Fill( 0. );
515       }
516 
517     dot = Edge1 * Edge2;
518 
519     Matrix2DType rotation;
520     rotation[0][0] = dot;
521     rotation[0][1] = std::sqrt( 1. - dot * dot );
522     rotation[1][0] = - rotation[0][1];
523     rotation[1][1] = dot;
524 
525     Vector2DType x = rotation * vv + x1;
526 
527 
528     /* compute the intersection points.
529        We look for x=x1+lambda*(x-x1) or x=x2+lambda*(x-x2) with <x,eqi>=0, so */
530     OutputVectorRealType lambda11 = - ( x1 * v1 ) / ( ( x - x1 ) * v1 );  // left most
531     OutputVectorRealType lambda12 = - ( x1 * v2 ) / ( ( x - x1 ) * v2 );  // right most
532     OutputVectorRealType lambda21 = - ( x2 * v1 ) / ( ( x - x2 ) * v1 );  // left most
533     OutputVectorRealType lambda22 = - ( x2 * v2 ) / ( ( x - x2 ) * v2 );  // right most
534     bool bIntersect11 = (lambda11>=0.) && (lambda11<=1.);
535     bool bIntersect12 = (lambda12>=0.) && (lambda12<=1.);
536     bool bIntersect21 = (lambda21>=0.) && (lambda21<=1.);
537     bool bIntersect22 = (lambda22>=0.) && (lambda22<=1.);
538 
539     if( bIntersect11 && bIntersect12 )
540       {
541       qe = oMesh->FindEdge( id1, t_id );
542       qe = qe->GetSym();
543       id2 = t_id;
544       t_pt2 = t_pt;
545       x2 = x;
546       }
547     else
548       {
549       if( bIntersect21 && bIntersect22 )
550         {
551         qe = oMesh->FindEdge( id2, t_id );
552         qe = qe->GetSym();
553         id1 = t_id;
554         t_pt1 = t_pt;
555         x1 = x;
556         }
557       else
558         { // bIntersect11 && !bIntersect12 && !bIntersect21 && bIntersect22
559 
560         // that's it, we have found the point
561         oSqNorm = x.GetSquaredNorm();
562 
563         if( oSqNorm > epsilon )
564           {
565           oNorm = std::sqrt( oSqNorm );
566           OutputVectorRealType temp_norm = x_start1.GetNorm();
567           if( temp_norm > epsilon )
568             {
569             oDot1 = x * x_start1 / ( oNorm * temp_norm );
570             }
571           else
572             {
573             oDot1 = 0.;
574             }
575           temp_norm = x_start2.GetNorm();
576           if( temp_norm > epsilon )
577             {
578             oDot2 = x * x_start2 / ( oNorm * temp_norm );
579             }
580           else
581             {
582             oDot2 = 0.;
583             }
584           }
585         else
586           {
587           oNorm = 0.;
588           oDot1 = 0.;
589           oDot2 = 0.;
590           }
591 
592         oId = t_id;
593         return true;
594         }
595       }
596     ++nNum;
597     }
598 
599     return false;
600   }
601 
602 template< typename TInput, typename TOutput >
603 bool
604 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
CheckTopology(OutputMeshType * oMesh,const NodeType & iNode)605 ::CheckTopology( OutputMeshType* oMesh,
606                     const NodeType& iNode )
607   {
608   (void) oMesh;
609   (void) iNode;
610 
611   return true;
612   }
613 
614 template< typename TInput, typename TOutput >
615 void
616 FastMarchingQuadEdgeMeshFilterBase< TInput, TOutput >
InitializeOutput(OutputMeshType * oMesh)617 ::InitializeOutput( OutputMeshType* oMesh )
618   {
619   this->CopyInputMeshToOutputMeshGeometry();
620 
621   // Check that the input mesh is made of triangles
622     {
623     OutputCellsContainerPointer cells = oMesh->GetCells();
624     OutputCellsContainerConstIterator c_it = cells->Begin();
625     OutputCellsContainerConstIterator c_end = cells->End();
626 
627     while( c_it != c_end )
628       {
629       OutputCellType* cell = c_it.Value();
630 
631       if( cell->GetNumberOfPoints() != 3 )
632         {
633         itkGenericExceptionMacro( << "Input mesh has non triangular faces" );
634         }
635       ++c_it;
636       }
637     }
638 
639   OutputPointsContainerPointer points = oMesh->GetPoints();
640 
641   OutputPointDataContainerPointer pointdata =
642       OutputPointDataContainer::New();
643   pointdata->Reserve( points->Size() );
644 
645   OutputPointsContainerIterator p_it = points->Begin();
646   OutputPointsContainerIterator p_end = points->End();
647 
648   while( p_it != p_end )
649     {
650     pointdata->SetElement( p_it->Index(), this->m_LargeValue );
651     ++p_it;
652     }
653 
654   oMesh->SetPointData( pointdata );
655 
656   m_Label.clear();
657 
658   if ( this->m_AlivePoints )
659     {
660     NodePairContainerConstIterator pointsIter = this->m_AlivePoints->Begin();
661     NodePairContainerConstIterator pointsEnd = this->m_AlivePoints->End();
662 
663     while( pointsIter != pointsEnd )
664       {
665       // get node from alive points container
666       NodeType idx = pointsIter->Value().GetNode();
667 
668       if( points->IndexExists( idx ) )
669         {
670         OutputPixelType outputPixel = pointsIter->Value().GetValue();
671 
672         this->SetLabelValueForGivenNode( idx, Traits::Alive );
673         this->SetOutputValue( oMesh, idx, outputPixel );
674         }
675 
676       ++pointsIter;
677       }
678     }
679   if( this->m_ForbiddenPoints )
680     {
681     NodePairContainerConstIterator pointsIter = this->m_ForbiddenPoints->Begin();
682     NodePairContainerConstIterator pointsEnd = this->m_ForbiddenPoints->End();
683 
684     OutputPixelType zero = NumericTraits< OutputPixelType >::ZeroValue();
685 
686     while( pointsIter != pointsEnd )
687       {
688       NodeType idx = pointsIter->Value().GetNode();
689 
690       if( points->IndexExists( idx ) )
691         {
692         this->SetLabelValueForGivenNode( idx, Traits::Forbidden );
693         this->SetOutputValue( oMesh, idx, zero );
694         }
695 
696       ++pointsIter;
697       }
698     }
699   if ( this->m_TrialPoints )
700     {
701     NodePairContainerConstIterator pointsIter = this->m_TrialPoints->Begin();
702     NodePairContainerConstIterator pointsEnd = this->m_TrialPoints->End();
703 
704     while( pointsIter != pointsEnd )
705       {
706       NodeType idx = pointsIter->Value().GetNode();
707 
708       if( points->IndexExists( idx ) )
709         {
710         OutputPixelType outputPixel = pointsIter->Value().GetValue();
711 
712         this->SetLabelValueForGivenNode( idx, Traits::InitialTrial );
713         this->SetOutputValue( oMesh, idx, outputPixel );
714 
715         this->m_Heap.push( pointsIter->Value() );
716         }
717 
718       ++pointsIter;
719       }
720     }
721   }
722 }
723 
724 #endif // itkFastMarchingQuadEdgeMeshFilterBase_hxx
725