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