]> Creatis software - bbtk.git/commitdiff
#3501 Geodesic Deformation
authorPablo Garzon <gapablo2001@gmail.com>
Tue, 2 May 2023 14:17:11 +0000 (16:17 +0200)
committerPablo Garzon <gapablo2001@gmail.com>
Tue, 2 May 2023 14:17:11 +0000 (16:17 +0200)
packages/itkvtk/src/bbitkvtkGeodesicMeshDeformation.cxx [new file with mode: 0644]
packages/itkvtk/src/bbitkvtkGeodesicMeshDeformation.h [new file with mode: 0644]
packages/itkvtk/src/itkFastMarchingQuadEdgeMeshFilterResultsBase.h [new file with mode: 0644]
packages/itkvtk/src/itkFastMarchingQuadEdgeMeshFilterResultsBase.hxx [new file with mode: 0644]

diff --git a/packages/itkvtk/src/bbitkvtkGeodesicMeshDeformation.cxx b/packages/itkvtk/src/bbitkvtkGeodesicMeshDeformation.cxx
new file mode 100644 (file)
index 0000000..287c0e6
--- /dev/null
@@ -0,0 +1,274 @@
+//===== 
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//===== 
+#include "bbitkvtkGeodesicMeshDeformation.h"
+#include "bbitkvtkPackage.h"
+#include <vtkCellArrayIterator.h>
+namespace bbitkvtk
+{
+
+BBTK_ADD_BLACK_BOX_TO_PACKAGE(itkvtk,GeodesicMeshDeformation)
+BBTK_BLACK_BOX_IMPLEMENTATION(GeodesicMeshDeformation,bbtk::AtomicBlackBox);
+//===== 
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//===== 
+void GeodesicMeshDeformation::Process()
+{
+printf("PG GeodesicMeshDeformation::Process START \n");
+// THE MAIN PROCESSING METHOD BODY
+//   Here we simply set the input 'In' value to the output 'Out'
+//   And print out the output value
+// INPUT/OUTPUT ACCESSORS ARE OF THE FORM :
+//    void bbSet{Input|Output}NAME(const TYPE&)
+//    const TYPE& bbGet{Input|Output}NAME() const 
+//    Where :
+//    * NAME is the name of the input/output
+//      (the one provided in the attribute 'name' of the tag 'input')
+//    * TYPE is the C++ type of the input/output
+//      (the one provided in the attribute 'type' of the tag 'input')
+    std::vector<double> lstCenter = bbGetInputCenter();
+    double s   = bbGetInputS();
+    bool    ok  = false;
+    using MeshType = itk::QuadEdgeMesh<double, 3>;
+    
+    //Set up QuadEdge and filter every time polydata changes
+    if ((bbGetInputIn() != polydata) && (bbGetInputActive()==true) && (bbGetInputIn() != NULL))
+    {
+       //Reset displacement
+       if(lstCenter.size() != NULL){
+                       backLstCenter[0] = lstCenter[0];
+                       backLstCenter[1] = lstCenter[1];
+                       backLstCenter[2] = lstCenter[2];
+       }
+       /**
+               Create QuadEdge
+               */
+               using PointType = MeshType::PointType;
+               //polydataBack
+               polydata = bbGetInputIn();
+               
+               //points = points of input polydata
+               vtkPoints* points=bbGetInputIn()->GetPoints();
+               
+               quadEdgeMesh = MeshType::New();
+               double currentPoint[3] = {};
+               PointType p;
+               
+               int numberOfPoints = points->GetNumberOfPoints();;
+               for(int pointId = 0; pointId < numberOfPoints; pointId++){
+                       points->GetPoint(pointId, currentPoint);
+                       p[0] = currentPoint[0];
+                       p[1] = currentPoint[1];
+                       p[2] = currentPoint[2];
+                       quadEdgeMesh->SetPoint(pointId, p);
+                       //point data must be 1 on each point so that fast marching can calculate the distance.
+                       quadEdgeMesh->SetPointData(pointId, 1.);
+               }
+               printf("PG GeodesicMeshDeformation::Process Entered FLAG 4 \n");
+               //add cells to QuadEdge mesh
+               auto cellIterator = vtk::TakeSmartPointer(bbGetInputIn()->GetPolys()->NewIterator());
+               vtkIdList* cell;
+               for(cellIterator->GoToFirstCell(); !cellIterator->IsDoneWithTraversal(); cellIterator->GoToNextCell()){
+                       cell = cellIterator->GetCurrentCell();
+                       quadEdgeMesh->AddFaceTriangle(cell->GetId(0), cell->GetId(1), cell->GetId(2));
+               }                       
+               printf("PG GeodesicMeshDeformation::Process  FLAG 5\n");
+               
+               using FastMarchingType = itk::FastMarchingQuadEdgeMeshFilterResultsBase<MeshType, MeshType>;    
+               fmmFilter = FastMarchingType::New();
+               fmmFilter->SetInput(quadEdgeMesh);
+               
+               using NodePairType = FastMarchingType::NodePairType;
+               using NodePairContainerType = FastMarchingType::NodePairContainerType;
+               
+               auto trial = NodePairContainerType::New();
+               NodePairType nodePair(0, 0.);
+               trial->push_back(nodePair);
+               
+               fmmFilter->SetTrialPoints(trial);
+
+               using CriterionType = itk::FastMarchingThresholdStoppingCriterion<MeshType, MeshType>;
+               auto criterion = CriterionType::New();
+               sCurrent = 1;
+               criterion->SetThreshold(1);
+               fmmFilter->SetStoppingCriterion(criterion);
+               fmmFilter->SetCollectPoints(true);
+               fmmFilter->SetReleaseDataBeforeUpdateFlag(false);
+               fmmFilter->Update();
+
+               printf("PG GeodesicMeshDeformation::Process  Filter Created \n");
+    }
+    
+    if (bbGetInputTypeIn()==0) // direction
+    {
+        if (bbGetInputDirection().size()==3)
+        {
+            ok = !( (bbGetInputDirection()[0]==0) && (bbGetInputDirection()[1]==0) && (bbGetInputDirection()[2]==0) );
+        }
+    } // if TypeIn 0
+    
+    if (bbGetInputTypeIn()==1)  // center
+    {
+        ok = ( lstCenter.size()==3 );
+    } // if TypeIn 1
+
+    if ( (bbGetInputIn()!=NULL) && (ok==true) && (bbGetInputEdgeId()>=0) && (bbGetInputActive()==true) )
+    {
+        vtkPoints* points=bbGetInputIn()->GetPoints();
+        long    i,size=points->GetNumberOfPoints();
+        double  p[3];  // point
+        double  pb[3]; // point base
+        double  np[3]; // new point
+        double  sx,sy,sz;
+        sx = s*2;
+        sy = sx;
+        sz = sy;
+
+        double displcement_x = 0;
+        double displcement_y = 0;
+        double displcement_z = 0;
+        
+        if (bbGetInputTypeIn()==0) // Direction
+        {
+            displcement_x = bbGetInputDirection()[0];
+            displcement_y = bbGetInputDirection()[1];
+            displcement_z = bbGetInputDirection()[2];
+        } // if TypeIn 0 Direction
+               
+               printf(" EED GeodesicMeshDeformation::Process   %ld   %ld  -   %f %f %f \n", EdgeIdBack, bbGetInputEdgeId() , lstCenter[0],lstCenter[1],lstCenter[2] );
+               
+        if (bbGetInputTypeIn()==1) // Center
+        {
+            if (EdgeIdBack==bbGetInputEdgeId() )
+            {
+                displcement_x = (lstCenter[0]-backLstCenter[0])/1.0;
+                displcement_y = (lstCenter[1]-backLstCenter[1])/1.0;
+                displcement_z = (lstCenter[2]-backLstCenter[2])/1.0;
+            } // if EdgeIdBack!=bbGetInputEdgeId()
+            backLstCenter[0] = lstCenter[0];
+            backLstCenter[1] = lstCenter[1];
+            backLstCenter[2] = lstCenter[2];
+            
+        } // if TypeIn 1 Center
+        points->GetPoint( bbGetInputEdgeId() , pb );
+        if (EdgeIdBack!=bbGetInputEdgeId() )
+        {
+            EdgeIdBack = bbGetInputEdgeId();
+            
+                       backLstCenter[0] = lstCenter[0];
+                       backLstCenter[1] = lstCenter[1];
+                       backLstCenter[2] = lstCenter[2];
+                       
+                       using NodePairType = FastMarchingType::NodePairType;
+                       using NodePairContainerType = FastMarchingType::NodePairContainerType;
+                       
+                       auto processedPoints = NodePairContainerType::New();
+                       fmmFilter->SetProcessedPoints(processedPoints);
+
+                       auto trial = NodePairContainerType::New();
+
+                       //Seed point for fast marching with distance 0
+                       NodePairType nodePair(bbGetInputEdgeId(), 0.);
+                       trial->push_back(nodePair);
+                       
+                       fmmFilter->SetTrialPoints(trial);
+
+                       //threshold distance for fast marching method
+                       if(sCurrent != s){                      
+                               using CriterionType = itk::FastMarchingThresholdStoppingCriterion<MeshType, MeshType>;
+                               auto criterion = CriterionType::New();
+                               sCurrent = s;
+                               criterion->SetThreshold(s*2);
+                               fmmFilter->SetStoppingCriterion(criterion);
+                       }
+                       fmmFilter->Update();
+                       
+        } // if EdgeIdBack
+        
+        if ( !((displcement_x==0) &&(displcement_y==0) && (displcement_z==0)) )
+        {      
+                       if(fmmFilter != NULL){
+                               MeshType::PointDataContainer::Pointer pointData = fmmFilter->GetOutput()->GetPointData();
+                               double pPD[3];
+                               
+                               FastMarchingType::NodePairContainerType::Iterator BegProcessedIt = fmmFilter->GetProcessedPoints()->Begin();
+                               FastMarchingType::NodePairContainerType::Iterator EndProcessedIt = fmmFilter->GetProcessedPoints()->End();
+                               
+                               while (BegProcessedIt != EndProcessedIt)
+                               {       
+                                       //point modification
+                                       points->GetPoint(BegProcessedIt.Value().GetNode(), pPD);
+                                       double weight = exp(-BegProcessedIt.Value().GetValue() * 1. / s);
+                                       if(weight > 0.0001){
+                                               np[0] = pPD[0]+ weight*displcement_x;
+                                               np[1] = pPD[1]+ weight*displcement_y;
+                                               np[2] = pPD[2]+ weight*displcement_z;
+                                               points->SetPoint(BegProcessedIt.Value().GetNode(), np);
+                                       }
+                                       ++BegProcessedIt;
+                               }
+                               points->Modified();
+               bbGetInputIn()->Modified();
+                       }
+        } // if distance_x y z  != 0
+    } // In != NULL    ok    active
+    printf("PG GeodesicMeshDeformation::Process END \n");
+}
+//===== 
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//===== 
+void GeodesicMeshDeformation::bbUserSetDefaultValues()
+{
+
+//  SET HERE THE DEFAULT INPUT/OUTPUT VALUES OF YOUR BOX 
+//    Here we initialize the input 'In' to 0
+       bbSetInputActive(true);
+       bbSetInputTypeIn(0);
+       bbSetInputIn(NULL);
+       std::vector<double> direction;
+       direction.push_back(1);
+       direction.push_back(0);
+       direction.push_back(0);
+       bbSetInputDirection(direction);
+       EdgeIdBack=-1;
+       bbSetInputEdgeId(EdgeIdBack);
+       bbSetInputS(10);
+
+       backLstCenter.push_back(0);
+       backLstCenter.push_back(0);
+       backLstCenter.push_back(0);
+       polydata = NULL;
+       quadEdgeMesh = NULL;
+       sCurrent = 0;
+       fmmFilter = NULL;
+       firstTime = true;
+}
+//===== 
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//===== 
+void GeodesicMeshDeformation::bbUserInitializeProcessing()
+{
+
+//  THE INITIALIZATION METHOD BODY :
+//    Here does nothing 
+//    but this is where you should allocate the internal/output pointers 
+//    if any 
+
+  
+}
+//===== 
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//===== 
+void GeodesicMeshDeformation::bbUserFinalizeProcessing()
+{
+
+//  THE FINALIZATION METHOD BODY :
+//    Here does nothing 
+//    but this is where you should desallocate the internal/output pointers 
+//    if any
+  
+}
+}
+// EO namespace bbitkvtk
+
+
diff --git a/packages/itkvtk/src/bbitkvtkGeodesicMeshDeformation.h b/packages/itkvtk/src/bbitkvtkGeodesicMeshDeformation.h
new file mode 100644 (file)
index 0000000..1ba0448
--- /dev/null
@@ -0,0 +1,75 @@
+//===== 
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//===== 
+#ifndef __bbitkvtkGeodesicMeshDeformation_h_INCLUDED__
+#define __bbitkvtkGeodesicMeshDeformation_h_INCLUDED__
+
+#include "bbitkvtk_EXPORT.h"
+#include "bbtkAtomicBlackBox.h"
+#include "iostream"
+
+#include "vtkPolyData.h"
+#include "itkQuadEdgeMesh.h"
+#include "itkFastMarchingThresholdStoppingCriterion.h"
+//#include "itkFastMarchingQuadEdgeMeshFilterBase.h"
+#include "itkFastMarchingQuadEdgeMeshFilterResultsBase.h"
+
+namespace bbitkvtk
+{
+
+class bbitkvtk_EXPORT GeodesicMeshDeformation
+ : 
+   public bbtk::AtomicBlackBox
+{
+  BBTK_BLACK_BOX_INTERFACE(GeodesicMeshDeformation,bbtk::AtomicBlackBox);
+//===== 
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//===== 
+  BBTK_DECLARE_INPUT(Active, bool);
+  BBTK_DECLARE_INPUT(TypeIn, int);
+  BBTK_DECLARE_INPUT(In,vtkPolyData*);
+  BBTK_DECLARE_INPUT(EdgeId, long);
+  BBTK_DECLARE_INPUT(S, double);
+  BBTK_DECLARE_INPUT(Center, std::vector<double>);
+  BBTK_DECLARE_INPUT(Direction, std::vector<double>);
+  //BBTK_DECLARE_OUTPUT(Out,double);
+  BBTK_PROCESS(Process);
+  void Process();
+  
+  using MeshType = itk::QuadEdgeMesh<double, 3>;
+  using FastMarchingType = itk::FastMarchingQuadEdgeMeshFilterResultsBase<MeshType, MeshType>;
+  
+       long                                                                    EdgeIdBack;
+       std::vector<int>                                        voiIdPoints;
+       std::vector<double>                                     backLstCenter;
+       vtkPolyData                                                     *polydata;
+       MeshType::Pointer                                               quadEdgeMesh;
+       double                                                                  sCurrent;
+       FastMarchingType::Pointer                               fmmFilter;
+       bool                                                                    firstTime;
+//===== 
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//===== 
+};
+
+BBTK_BEGIN_DESCRIBE_BLACK_BOX(GeodesicMeshDeformation,bbtk::AtomicBlackBox);
+BBTK_NAME("GeodesicMeshDeformation");
+BBTK_AUTHOR("InfoDev");
+BBTK_DESCRIPTION("No Description.");
+BBTK_CATEGORY("empty");
+BBTK_INPUT(GeodesicMeshDeformation,Active,"(default true) true/false",bool,"");
+BBTK_INPUT(GeodesicMeshDeformation,TypeIn,"(default 0) 0:Direction  1:Center",int,"");
+BBTK_INPUT(GeodesicMeshDeformation,In,"vtk PolyData",vtkPolyData*,"");
+BBTK_INPUT(GeodesicMeshDeformation,EdgeId,"Edge Id",long,"");
+BBTK_INPUT(GeodesicMeshDeformation,S,"Deformation",double,"");
+BBTK_INPUT(GeodesicMeshDeformation,Center,"[X,Y,Z]",std::vector<double>,"");
+BBTK_INPUT(GeodesicMeshDeformation,Direction,"(default [1,0,0])   [X,Y,Z]",std::vector<double>,"");
+BBTK_END_DESCRIBE_BLACK_BOX(GeodesicMeshDeformation);
+//===== 
+// Before editing this file, make sure it's a file of your own (i.e.: it wasn't generated from xml description; if so : your modifications will be lost)
+//===== 
+}
+// EO namespace bbitkvtk
+
+#endif // __bbitkvtkGeodesicMeshDeformation_h_INCLUDED__
+
diff --git a/packages/itkvtk/src/itkFastMarchingQuadEdgeMeshFilterResultsBase.h b/packages/itkvtk/src/itkFastMarchingQuadEdgeMeshFilterResultsBase.h
new file mode 100644 (file)
index 0000000..a4d3b29
--- /dev/null
@@ -0,0 +1,193 @@
+/*=========================================================================\r
+ *\r
+ *  Copyright NumFOCUS\r
+ *\r
+ *  Licensed under the Apache License, Version 2.0 (the "License");\r
+ *  you may not use this file except in compliance with the License.\r
+ *  You may obtain a copy of the License at\r
+ *\r
+ *         http://www.apache.org/licenses/LICENSE-2.0.txt\r
+ *\r
+ *  Unless required by applicable law or agreed to in writing, software\r
+ *  distributed under the License is distributed on an "AS IS" BASIS,\r
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *  See the License for the specific language governing permissions and\r
+ *  limitations under the License.\r
+ *\r
+ *=========================================================================*/\r
+\r
+#ifndef itkFastMarchingQuadEdgeMeshFilterBase_h\r
+#define itkFastMarchingQuadEdgeMeshFilterBase_h\r
+\r
+#include "itkFastMarchingBase.h"\r
+#include "itkFastMarchingTraits.h"\r
+\r
+namespace itk\r
+{\r
+/**\r
+ *\class FastMarchingQuadEdgeMeshFilterBase\r
+  \brief Fast Marching Method on QuadEdgeMesh\r
+\r
+  The speed function is specified by the input mesh. Data associated to each\r
+  point is considered as the speed function. The speed function is set using\r
+  the method SetInput().\r
+\r
+  If the speed function is constant and of value one, fast marching results is\r
+  an approximate geodesic function from the initial alive points.\r
+\r
+  Implementation of this class is based on\r
+  "Fast Marching Methods on Triangulated Domains", Kimmel, R., and Sethian, J.A.,\r
+  Proc. Nat. Acad. Sci., 95, pp. 8341-8435, 1998.\r
+\r
+  \ingroup ITKFastMarching\r
+*/\r
+template <typename TInput, typename TOutput>\r
+//2023-04-27-PG class ITK_TEMPLATE_EXPORT FastMarchingQuadEdgeMeshFilterBase : public FastMarchingBase<TInput, TOutput>\r
+class ITK_TEMPLATE_EXPORT FastMarchingQuadEdgeMeshFilterResultsBase : public FastMarchingBase<TInput, TOutput>\r
+{\r
+public:\r
+  //ITK_DISALLOW_COPY_AND_MOVE(FastMarchingQuadEdgeMeshFilterBase);\r
+  ITK_DISALLOW_COPY_AND_MOVE(FastMarchingQuadEdgeMeshFilterResultsBase);\r
+\r
+  //using Self = FastMarchingQuadEdgeMeshFilterBase;\r
+  using Self =FastMarchingQuadEdgeMeshFilterResultsBase;\r
+  using Superclass = FastMarchingBase<TInput, TOutput>;\r
+  using Pointer = SmartPointer<Self>;\r
+  using ConstPointer = SmartPointer<const Self>;\r
+  using Traits = typename Superclass::Traits;\r
+\r
+  /** Method for creation through the object factory. */\r
+  itkNewMacro(Self);\r
+\r
+  /** Run-time type information (and related methods). */\r
+  //itkTypeMacro(FastMarchingQuadEdgeMeshFilterBase, FastMarchingBase);\r
+  itkTypeMacro(FastMarchingQuadEdgeMeshFilterResultsBase, FastMarchingBase);\r
+\r
+  using InputMeshType = typename Superclass::InputDomainType;\r
+  using InputMeshPointer = typename Superclass::InputDomainPointer;\r
+  using InputPixelType = typename Superclass::InputPixelType;\r
+  using InputPointType = typename InputMeshType::PointType;\r
+  using InputPointIdentifierType = typename InputMeshType::PointIdentifier;\r
+\r
+  using OutputMeshType = typename Superclass::OutputDomainType;\r
+  using OutputMeshPointer = typename Superclass::OutputDomainPointer;\r
+  using OutputPixelType = typename Superclass::OutputPixelType;\r
+  using OutputPointType = typename OutputMeshType::PointType;\r
+  using OutputVectorType = typename OutputPointType::VectorType;\r
+  using OutputVectorRealType = typename OutputVectorType::RealValueType;\r
+  using OutputQEType = typename OutputMeshType::QEType;\r
+  using OutputPointIdentifierType = typename OutputMeshType::PointIdentifier;\r
+  using OutputPointsContainer = typename OutputMeshType::PointsContainer;\r
+  using OutputPointsContainerPointer = typename OutputPointsContainer::Pointer;\r
+  using OutputPointsContainerIterator = typename OutputPointsContainer::Iterator;\r
+  using OutputPointDataContainer = typename OutputMeshType::PointDataContainer;\r
+  using OutputPointDataContainerPointer = typename OutputPointDataContainer::Pointer;\r
+\r
+  using OutputCellsContainer = typename OutputMeshType::CellsContainer;\r
+  using OutputCellsContainerPointer = typename OutputCellsContainer::Pointer;\r
+  using OutputCellsContainerConstIterator = typename OutputCellsContainer::ConstIterator;\r
+  using OutputCellType = typename OutputMeshType::CellType;\r
+\r
+\r
+  using NodeType = typename Traits::NodeType;\r
+  using NodePairType = typename Traits::NodePairType;\r
+  using NodePairContainerType = typename Traits::NodePairContainerType;\r
+  using NodePairContainerPointer = typename Traits::NodePairContainerPointer;\r
+  using NodePairContainerConstIterator = typename Traits::NodePairContainerConstIterator;\r
+\r
+  //  using NodeContainerType = typename Traits::NodeContainerType;\r
+  //  using NodeContainerPointer = typename Traits::NodeContainerPointer;\r
+  //  using NodeContainerConstIterator = typename Traits::NodeContainerConstIterator;\r
+\r
+  using LabelType = typename Superclass::LabelType;\r
+\r
+  using NodeLabelMapType = std::map<NodeType, LabelType>;\r
+  using NodeLabelMapIterator = typename NodeLabelMapType::iterator;\r
+  using NodeLabelMapConstIterator = typename NodeLabelMapType::const_iterator;\r
+\r
+protected:\r
+  //FastMarchingQuadEdgeMeshFilterBase();\r
+  FastMarchingQuadEdgeMeshFilterResultsBase();\r
+  //~FastMarchingQuadEdgeMeshFilterBase() override = default;\r
+  ~FastMarchingQuadEdgeMeshFilterResultsBase() override = default;\r
+\r
+  NodeLabelMapType m_Label;\r
+\r
+  IdentifierType\r
+  GetTotalNumberOfNodes() const override;\r
+\r
+  void\r
+  SetOutputValue(OutputMeshType * oMesh, const NodeType & iNode, const OutputPixelType & iValue) override;\r
+\r
+  const OutputPixelType\r
+  GetOutputValue(OutputMeshType * oMesh, const NodeType & iNode) const override;\r
+\r
+  unsigned char\r
+  GetLabelValueForGivenNode(const NodeType & iNode) const override;\r
+\r
+  void\r
+  SetLabelValueForGivenNode(const NodeType & iNode, const LabelType & iLabel) override;\r
+\r
+  void\r
+  UpdateNeighbors(OutputMeshType * oMesh, const NodeType & iNode) override;\r
+\r
+  void\r
+  UpdateValue(OutputMeshType * oMesh, const NodeType & iNode) override;\r
+\r
+  const OutputVectorRealType\r
+  Solve(OutputMeshType *             oMesh,\r
+        const NodeType &             iId,\r
+        const OutputPointType &      iCurrentPoint,\r
+        const OutputVectorRealType & iF,\r
+        const NodeType &             iId1,\r
+        const OutputPointType &      iP1,\r
+        const bool &                 iIsFar1,\r
+        const OutputVectorRealType   iVal1,\r
+        const NodeType &             iId2,\r
+        const OutputPointType &      iP2,\r
+        const bool &                 iIsFar2,\r
+        const OutputVectorRealType & iVal2) const;\r
+\r
+\r
+  const OutputVectorRealType\r
+  ComputeUpdate(const OutputVectorRealType & iVal1,\r
+                const OutputVectorRealType & iVal2,\r
+                const OutputVectorRealType & iNorm1,\r
+                const OutputVectorRealType & iSqNorm1,\r
+                const OutputVectorRealType & iNorm2,\r
+                const OutputVectorRealType & iSqNorm2,\r
+                const OutputVectorRealType & iDot,\r
+                const OutputVectorRealType & iF) const;\r
+\r
+  bool\r
+  UnfoldTriangle(OutputMeshType *                  oMesh,\r
+                 const OutputPointIdentifierType & iId,\r
+                 const OutputPointType &           iP,\r
+                 const OutputPointIdentifierType & iId1,\r
+                 const OutputPointType &           iP1,\r
+                 const OutputPointIdentifierType & iId2,\r
+                 const OutputPointType &           iP2,\r
+                 OutputVectorRealType &            oNorm,\r
+                 OutputVectorRealType &            oSqNorm,\r
+                 OutputVectorRealType &            oDot1,\r
+                 OutputVectorRealType &            oDot2,\r
+                 OutputPointIdentifierType &       oId) const;\r
+\r
+  bool\r
+  CheckTopology(OutputMeshType * oMesh, const NodeType & iNode) override;\r
+\r
+  void\r
+  InitializeOutput(OutputMeshType * oMesh) override;\r
+\r
+private:\r
+  const InputMeshType * m_InputMesh;\r
+  const InputMeshType * m_BackInputMesh;\r
+};\r
+} // namespace itk\r
+\r
+#ifndef ITK_MANUAL_INSTANTIATION\r
+//#  include "itkFastMarchingQuadEdgeMeshFilterBase.hxx"\r
+#  include "itkFastMarchingQuadEdgeMeshFilterResultsBase.hxx"\r
+#endif\r
+\r
+#endif // itkFastMarchingQuadEdgeMeshFilterBase_h\r
diff --git a/packages/itkvtk/src/itkFastMarchingQuadEdgeMeshFilterResultsBase.hxx b/packages/itkvtk/src/itkFastMarchingQuadEdgeMeshFilterResultsBase.hxx
new file mode 100644 (file)
index 0000000..5157413
--- /dev/null
@@ -0,0 +1,700 @@
+/*=========================================================================\r
+ *\r
+ *  Copyright NumFOCUS\r
+ *\r
+ *  Licensed under the Apache License, Version 2.0 (the "License");\r
+ *  you may not use this file except in compliance with the License.\r
+ *  You may obtain a copy of the License at\r
+ *\r
+ *         http://www.apache.org/licenses/LICENSE-2.0.txt\r
+ *\r
+ *  Unless required by applicable law or agreed to in writing, software\r
+ *  distributed under the License is distributed on an "AS IS" BASIS,\r
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *  See the License for the specific language governing permissions and\r
+ *  limitations under the License.\r
+ *\r
+ *=========================================================================*/\r
+\r
+#ifndef itkFastMarchingQuadEdgeMeshFilterResultsBase_hxx\r
+#define itkFastMarchingQuadEdgeMeshFilterResultsBase_hxx\r
+\r
+#include "itkFastMarchingQuadEdgeMeshFilterResultsBase.h"\r
+\r
+#include "itkMath.h"\r
+#include "itkVector.h"\r
+#include "itkMatrix.h"\r
+\r
+namespace itk\r
+{\r
+template <typename TInput, typename TOutput>\r
+FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::FastMarchingQuadEdgeMeshFilterResultsBase()\r
+  : Superclass()\r
+{\r
+  this->m_InputMesh = nullptr;\r
+  this->m_BackInputMesh = nullptr;\r
+}\r
+\r
+template <typename TInput, typename TOutput>\r
+IdentifierType\r
+FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::GetTotalNumberOfNodes() const\r
+{\r
+  return this->GetInput()->GetNumberOfPoints();\r
+}\r
+\r
+template <typename TInput, typename TOutput>\r
+void\r
+FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::SetOutputValue(OutputMeshType *        oMesh,\r
+                                                                    const NodeType &        iNode,\r
+                                                                    const OutputPixelType & iValue)\r
+{\r
+  oMesh->SetPointData(iNode, iValue);\r
+}\r
+\r
+template <typename TInput, typename TOutput>\r
+const typename FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::OutputPixelType\r
+FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::GetOutputValue(OutputMeshType * oMesh,\r
+                                                                    const NodeType & iNode) const\r
+{\r
+  OutputPixelType outputValue = NumericTraits<OutputPixelType>::ZeroValue();\r
+  oMesh->GetPointData(iNode, &outputValue);\r
+  return outputValue;\r
+}\r
+\r
+\r
+template <typename TInput, typename TOutput>\r
+unsigned char\r
+FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::GetLabelValueForGivenNode(const NodeType & iNode) const\r
+{\r
+  auto it = m_Label.find(iNode);\r
+\r
+  if (it != m_Label.end())\r
+  {\r
+    return it->second;\r
+  }\r
+  else\r
+  {\r
+    return Traits::Far;\r
+  }\r
+}\r
+\r
+template <typename TInput, typename TOutput>\r
+void\r
+FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::SetLabelValueForGivenNode(const NodeType &  iNode,\r
+                                                                               const LabelType & iLabel)\r
+{\r
+  m_Label[iNode] = iLabel;\r
+}\r
+\r
+template <typename TInput, typename TOutput>\r
+void\r
+FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::UpdateNeighbors(OutputMeshType * oMesh, const NodeType & iNode)\r
+{\r
+  //printf("PG FastMarchingQuadEdgeMeshFilterResultsBase::UpdateNeighbors Start \n");\r
+  OutputPointType p;\r
+  oMesh->GetPoint(iNode, &p);\r
+\r
+  OutputQEType * qe = p.GetEdge();\r
+\r
+  if (qe)\r
+  {\r
+    OutputQEType * qe_it = qe;\r
+    this->m_InputMesh = this->GetInput();\r
+    do\r
+    {\r
+      if (qe_it)\r
+      {\r
+        OutputPointIdentifierType neigh_id = qe_it->GetDestination();\r
+\r
+        const char label = this->GetLabelValueForGivenNode(neigh_id);\r
+\r
+        if ((label != Traits::Alive) && (label != Traits::InitialTrial) && (label != Traits::Forbidden))\r
+        {\r
+          this->UpdateValue(oMesh, neigh_id);\r
+        }\r
+      }\r
+      else\r
+      {\r
+        itkGenericExceptionMacro(<< "qe_it is nullptr");\r
+      }\r
+      qe_it = qe_it->GetOnext();\r
+    } while (qe_it != qe);\r
+  }\r
+  else\r
+  {\r
+    itkGenericExceptionMacro(<< "qe is nullptr");\r
+  }\r
+  //printf("PG FastMarchingQuadEdgeMeshFilterResultsBase::UpdateNeighbors End \n");\r
+}\r
+\r
+template <typename TInput, typename TOutput>\r
+void\r
+FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::UpdateValue(OutputMeshType * oMesh, const NodeType & iNode)\r
+{\r
+  OutputPointType p;\r
+  oMesh->GetPoint(iNode, &p);\r
+\r
+  InputPixelType F = NumericTraits<InputPixelType>::ZeroValue();\r
+  //this->m_InputMesh->GetPointData(iNode, &F);\r
+  F = 1.;\r
+  if (F < 0.)\r
+  {\r
+    itkGenericExceptionMacro(<< "F < 0.");\r
+  }\r
+\r
+  OutputQEType * qe = p.GetEdge();\r
+\r
+  OutputPixelType outputPixel = this->m_LargeValue;\r
+\r
+  if (qe)\r
+  {\r
+    OutputQEType * qe_it = qe;\r
+    qe_it = qe_it->GetOnext();\r
+\r
+    do\r
+    {\r
+      OutputQEType * qe_it2 = qe_it->GetOnext();\r
+\r
+      if (qe_it2)\r
+      {\r
+        if (qe_it->GetLeft() != OutputMeshType::m_NoFace)\r
+        {\r
+          OutputPointIdentifierType id1 = qe_it->GetDestination();\r
+          OutputPointIdentifierType id2 = qe_it2->GetDestination();\r
+\r
+          const auto label1 = static_cast<LabelType>(this->GetLabelValueForGivenNode(id1));\r
+          const auto label2 = static_cast<LabelType>(this->GetLabelValueForGivenNode(id2));\r
+\r
+          bool IsFar1 = (label1 != Traits::Far);\r
+          bool IsFar2 = (label2 != Traits::Far);\r
+\r
+          if (IsFar1 || IsFar2)\r
+          {\r
+            OutputPointType q1 = oMesh->GetPoint(id1);\r
+            OutputPointType q2 = oMesh->GetPoint(id2);\r
+\r
+            auto val1 = static_cast<OutputVectorRealType>(this->GetOutputValue(oMesh, id1));\r
+            auto val2 = static_cast<OutputVectorRealType>(this->GetOutputValue(oMesh, id2));\r
+\r
+            if (val1 > val2)\r
+            {\r
+              OutputPointType temp_pt(q1);\r
+              q1 = q2;\r
+              q2 = temp_pt;\r
+\r
+              std::swap(val1, val2);\r
+              std::swap(IsFar1, IsFar2);\r
+              std::swap(id1, id2);\r
+            }\r
+\r
+            const OutputVectorRealType temp =\r
+              this->Solve(oMesh, iNode, p, F, id1, q1, IsFar1, val1, id2, q2, IsFar2, val2);\r
+\r
+            outputPixel = std::min(outputPixel, static_cast<OutputPixelType>(temp));\r
+          }\r
+        }\r
+\r
+        qe_it = qe_it2;\r
+      }\r
+      else\r
+      {\r
+        // throw one exception here\r
+        itkGenericExceptionMacro(<< "qe_it2 is nullptr");\r
+      }\r
+    } while (qe_it != qe);\r
+\r
+    if (outputPixel < this->m_LargeValue)\r
+    {\r
+      this->SetOutputValue(oMesh, iNode, outputPixel);\r
+\r
+      this->SetLabelValueForGivenNode(iNode, Traits::Trial);\r
+\r
+      this->m_Heap.push(NodePairType(iNode, outputPixel));\r
+    }\r
+  }\r
+  else\r
+  {\r
+    // throw one exception\r
+    itkGenericExceptionMacro(<< "qe_it is nullptr");\r
+  }\r
+}\r
+\r
+template <typename TInput, typename TOutput>\r
+const typename FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::OutputVectorRealType\r
+FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::Solve(OutputMeshType *             oMesh,\r
+                                                           const NodeType &             iId,\r
+                                                           const OutputPointType &      iCurrentPoint,\r
+                                                           const OutputVectorRealType & iF,\r
+                                                           const NodeType &             iId1,\r
+                                                           const OutputPointType &      iP1,\r
+                                                           const bool &                 iIsFar1,\r
+                                                           const OutputVectorRealType   iVal1,\r
+                                                           const NodeType &             iId2,\r
+                                                           const OutputPointType &      iP2,\r
+                                                           const bool &                 iIsFar2,\r
+                                                           const OutputVectorRealType & iVal2) const\r
+{\r
+  OutputVectorType Edge1 = iP1 - iCurrentPoint;\r
+  OutputVectorType Edge2 = iP2 - iCurrentPoint;\r
+\r
+  OutputVectorRealType sq_norm1 = Edge1.GetSquaredNorm();\r
+  OutputVectorRealType norm1 = 0.;\r
+\r
+  OutputVectorRealType epsilon = NumericTraits<OutputVectorRealType>::epsilon();\r
+\r
+  if (sq_norm1 > epsilon)\r
+  {\r
+    norm1 = std::sqrt(sq_norm1);\r
+\r
+    OutputVectorRealType inv_norm1 = 1. / norm1;\r
+    Edge1 *= inv_norm1;\r
+  }\r
+\r
+  OutputVectorRealType sq_norm2 = Edge2.GetSquaredNorm();\r
+  OutputVectorRealType norm2 = 0.;\r
+\r
+  if (sq_norm2 > epsilon)\r
+  {\r
+    norm2 = std::sqrt(sq_norm2);\r
+\r
+    OutputVectorRealType inv_norm2 = 1. / norm2;\r
+    Edge2 *= inv_norm2;\r
+  }\r
+\r
+  if (!iIsFar1 && iIsFar2)\r
+  {\r
+    // only one point is a contributor\r
+    return iVal2 + norm2 * iF;\r
+  }\r
+  if (iIsFar1 && !iIsFar2)\r
+  {\r
+    // only one point is a contributor\r
+    return iVal1 + norm1 * iF;\r
+  }\r
+\r
+  if (iIsFar1 && iIsFar2)\r
+  {\r
+    auto dot = static_cast<OutputVectorRealType>(Edge1 * Edge2);\r
+\r
+    if (dot >= 0.)\r
+    {\r
+      return ComputeUpdate(iVal1, iVal2, norm2, sq_norm2, norm1, sq_norm1, dot, iF);\r
+    }\r
+    else\r
+    {\r
+      OutputVectorRealType      sq_norm3, norm3, dot1, dot2;\r
+      OutputPointIdentifierType new_id;\r
+\r
+      bool unfolded =\r
+        UnfoldTriangle(oMesh, iId, iCurrentPoint, iId1, iP1, iId2, iP2, norm3, sq_norm3, dot1, dot2, new_id);\r
+\r
+      if (unfolded)\r
+      {\r
+        OutputVectorRealType t_sq_norm3 = norm3 * norm3;\r
+\r
+        auto                 val3 = static_cast<OutputVectorRealType>(this->GetOutputValue(oMesh, new_id));\r
+        OutputVectorRealType t1 = ComputeUpdate(iVal1, val3, norm3, t_sq_norm3, norm1, sq_norm1, dot1, iF);\r
+        OutputVectorRealType t2 = ComputeUpdate(iVal2, val3, norm3, t_sq_norm3, norm2, sq_norm2, dot2, iF);\r
+\r
+        return std::min(t1, t2);\r
+      }\r
+      else\r
+      {\r
+        return ComputeUpdate(iVal1, iVal2, norm2, sq_norm2, norm1, sq_norm1, dot, iF);\r
+      }\r
+    }\r
+  }\r
+\r
+  return this->m_LargeValue;\r
+}\r
+\r
+template <typename TInput, typename TOutput>\r
+const typename FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::OutputVectorRealType\r
+FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::ComputeUpdate(const OutputVectorRealType & iVal1,\r
+                                                                   const OutputVectorRealType & iVal2,\r
+                                                                   const OutputVectorRealType & iNorm1,\r
+                                                                   const OutputVectorRealType & iSqNorm1,\r
+                                                                   const OutputVectorRealType & iNorm2,\r
+                                                                   const OutputVectorRealType & iSqNorm2,\r
+                                                                   const OutputVectorRealType & iDot,\r
+                                                                   const OutputVectorRealType & iF) const\r
+{\r
+  auto large_value = static_cast<OutputVectorRealType>(this->m_LargeValue);\r
+\r
+  OutputVectorRealType t = large_value;\r
+\r
+  OutputVectorRealType CosAngle = iDot;\r
+  OutputVectorRealType SinAngle = std::sqrt(1. - iDot * iDot);\r
+\r
+  OutputVectorRealType u = iVal2 - iVal1;\r
+\r
+  OutputVectorRealType sq_u = u * u;\r
+  OutputVectorRealType f2 = iSqNorm1 + iSqNorm2 - 2. * iNorm1 * iNorm2 * CosAngle;\r
+  OutputVectorRealType f1 = iNorm2 * u * (iNorm1 * CosAngle - iNorm2);\r
+  OutputVectorRealType f0 = iSqNorm2 * (sq_u - iF * iF * iSqNorm1 * SinAngle * SinAngle);\r
+\r
+  OutputVectorRealType delta = f1 * f1 - f0 * f2;\r
+\r
+  OutputVectorRealType epsilon = NumericTraits<OutputVectorRealType>::epsilon();\r
+\r
+  if (delta >= 0.)\r
+  {\r
+    if (itk::Math::abs(f2) > epsilon)\r
+    {\r
+      t = (-f1 - std::sqrt(delta)) / f2;\r
+\r
+      // test if we must must choose the other solution\r
+      if ((t < u) || (iNorm2 * (t - u) / t < iNorm1 * CosAngle) || (iNorm1 / CosAngle < iNorm2 * (t - u) / t))\r
+      {\r
+        t = (-f1 + std::sqrt(delta)) / f2;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      if (itk::Math::abs(f1) > epsilon)\r
+      {\r
+        t = -f0 / f1;\r
+      }\r
+      else\r
+      {\r
+        t = -large_value;\r
+      }\r
+    }\r
+  }\r
+  else\r
+  {\r
+    t = -large_value;\r
+  }\r
+\r
+  // choose the update from the 2 vertex only if upwind criterion is met\r
+  if ((u < t) && (iNorm1 * CosAngle < iNorm2 * (t - u) / t) && (iNorm2 * (t - u) / t < iNorm1 / CosAngle))\r
+  {\r
+    return t + iVal1;\r
+  }\r
+  else\r
+  {\r
+    return std::min(iNorm2 * iF + iVal1, iNorm1 * iF + iVal2);\r
+  }\r
+}\r
+\r
+template <typename TInput, typename TOutput>\r
+bool\r
+FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::UnfoldTriangle(OutputMeshType *                  oMesh,\r
+                                                                    const OutputPointIdentifierType & iId,\r
+                                                                    const OutputPointType &           iP,\r
+                                                                    const OutputPointIdentifierType & iId1,\r
+                                                                    const OutputPointType &           iP1,\r
+                                                                    const OutputPointIdentifierType & iId2,\r
+                                                                    const OutputPointType &           iP2,\r
+                                                                    OutputVectorRealType &            oNorm,\r
+                                                                    OutputVectorRealType &            oSqNorm,\r
+                                                                    OutputVectorRealType &            oDot1,\r
+                                                                    OutputVectorRealType &            oDot2,\r
+                                                                    OutputPointIdentifierType &       oId) const\r
+{\r
+  (void)iId;\r
+\r
+  OutputVectorType     Edge1 = iP1 - iP;\r
+  OutputVectorRealType Norm1 = Edge1.GetNorm();\r
+\r
+  OutputVectorRealType epsilon = NumericTraits<OutputVectorRealType>::epsilon();\r
+\r
+  if (Norm1 > epsilon)\r
+  {\r
+    OutputVectorRealType inv_Norm = 1. / Norm1;\r
+    Edge1 *= inv_Norm;\r
+  }\r
+\r
+  OutputVectorType     Edge2 = iP2 - iP;\r
+  OutputVectorRealType Norm2 = Edge2.GetNorm();\r
+  if (Norm2 > epsilon)\r
+  {\r
+    OutputVectorRealType inv_Norm = 1. / Norm2;\r
+    Edge2 *= inv_Norm;\r
+  }\r
+\r
+  auto dot = static_cast<OutputVectorRealType>(Edge1 * Edge2);\r
+\r
+  // the equation of the lines defining the unfolding region\r
+  // [e.g. line 1 : {x ; <x,eq1>=0} ]\r
+  using Vector2DType = Vector<OutputVectorRealType, 2>;\r
+  using Matrix2DType = Matrix<OutputVectorRealType, 2, 2>;\r
+\r
+  Vector2DType v1;\r
+  v1[0] = dot;\r
+  v1[1] = std::sqrt(1. - dot * dot);\r
+\r
+  Vector2DType v2;\r
+  v2[0] = 1.;\r
+  v2[1] = 0.;\r
+\r
+  Vector2DType x1;\r
+  x1[0] = Norm1;\r
+  x1[1] = 0.;\r
+\r
+  Vector2DType x2 = Norm2 * v1;\r
+\r
+  // keep track of the starting point\r
+  Vector2DType x_start1(x1);\r
+  Vector2DType x_start2(x2);\r
+\r
+  OutputPointIdentifierType id1 = iId1;\r
+  OutputPointIdentifierType id2 = iId2;\r
+\r
+  OutputQEType * qe = oMesh->FindEdge(id1, id2);\r
+  qe = qe->GetSym();\r
+\r
+  OutputPointType t_pt1 = iP1;\r
+  OutputPointType t_pt2 = iP2;\r
+  OutputPointType t_pt = t_pt1;\r
+\r
+  unsigned int nNum = 0;\r
+  while (nNum < 50 && qe->GetLeft() != OutputMeshType::m_NoFace)\r
+  {\r
+    OutputQEType *            qe_Lnext = qe->GetLnext();\r
+    OutputPointIdentifierType t_id = qe_Lnext->GetDestination();\r
+\r
+    oMesh->GetPoint(t_id, &t_pt);\r
+\r
+    Edge1 = t_pt2 - t_pt1;\r
+    Norm1 = Edge1.GetNorm();\r
+    if (Norm1 > epsilon)\r
+    {\r
+      OutputVectorRealType inv_Norm = 1. / Norm1;\r
+      Edge1 *= inv_Norm;\r
+    }\r
+\r
+    Edge2 = t_pt - t_pt1;\r
+    Norm2 = Edge2.GetNorm();\r
+    if (Norm2 > epsilon)\r
+    {\r
+      OutputVectorRealType inv_Norm = 1. / Norm2;\r
+      Edge2 *= inv_Norm;\r
+    }\r
+\r
+    /* compute the position of the new point x on the unfolding plane (via a rotation of -alpha on (x2-x1)/rNorm1 )\r
+            | cos(alpha) sin(alpha)|\r
+        x = |-sin(alpha) cos(alpha)| * [x2-x1]*rNorm2/rNorm1 + x1   where cos(alpha)=dot\r
+    */\r
+    Vector2DType vv;\r
+    if (Norm1 > epsilon)\r
+    {\r
+      vv = (x2 - x1) * Norm2 / Norm1;\r
+    }\r
+    else\r
+    {\r
+      vv.Fill(0.);\r
+    }\r
+\r
+    dot = Edge1 * Edge2;\r
+\r
+    Matrix2DType rotation;\r
+    rotation[0][0] = dot;\r
+    rotation[0][1] = std::sqrt(1. - dot * dot);\r
+    rotation[1][0] = -rotation[0][1];\r
+    rotation[1][1] = dot;\r
+\r
+    Vector2DType x = rotation * vv + x1;\r
+\r
+\r
+    /* compute the intersection points.\r
+       We look for x=x1+lambda*(x-x1) or x=x2+lambda*(x-x2) with <x,eqi>=0, so */\r
+    OutputVectorRealType lambda11 = -(x1 * v1) / ((x - x1) * v1); // left most\r
+    OutputVectorRealType lambda12 = -(x1 * v2) / ((x - x1) * v2); // right most\r
+    OutputVectorRealType lambda21 = -(x2 * v1) / ((x - x2) * v1); // left most\r
+    OutputVectorRealType lambda22 = -(x2 * v2) / ((x - x2) * v2); // right most\r
+    bool                 bIntersect11 = (lambda11 >= 0.) && (lambda11 <= 1.);\r
+    bool                 bIntersect12 = (lambda12 >= 0.) && (lambda12 <= 1.);\r
+    bool                 bIntersect21 = (lambda21 >= 0.) && (lambda21 <= 1.);\r
+    bool                 bIntersect22 = (lambda22 >= 0.) && (lambda22 <= 1.);\r
+\r
+    if (bIntersect11 && bIntersect12)\r
+    {\r
+      qe = oMesh->FindEdge(id1, t_id);\r
+      qe = qe->GetSym();\r
+      id2 = t_id;\r
+      t_pt2 = t_pt;\r
+      x2 = x;\r
+    }\r
+    else\r
+    {\r
+      if (bIntersect21 && bIntersect22)\r
+      {\r
+        qe = oMesh->FindEdge(id2, t_id);\r
+        qe = qe->GetSym();\r
+        id1 = t_id;\r
+        t_pt1 = t_pt;\r
+        x1 = x;\r
+      }\r
+      else\r
+      { // bIntersect11 && !bIntersect12 && !bIntersect21 && bIntersect22\r
+\r
+        // that's it, we have found the point\r
+        oSqNorm = x.GetSquaredNorm();\r
+\r
+        if (oSqNorm > epsilon)\r
+        {\r
+          oNorm = std::sqrt(oSqNorm);\r
+          OutputVectorRealType temp_norm = x_start1.GetNorm();\r
+          if (temp_norm > epsilon)\r
+          {\r
+            oDot1 = x * x_start1 / (oNorm * temp_norm);\r
+          }\r
+          else\r
+          {\r
+            oDot1 = 0.;\r
+          }\r
+          temp_norm = x_start2.GetNorm();\r
+          if (temp_norm > epsilon)\r
+          {\r
+            oDot2 = x * x_start2 / (oNorm * temp_norm);\r
+          }\r
+          else\r
+          {\r
+            oDot2 = 0.;\r
+          }\r
+        }\r
+        else\r
+        {\r
+          oNorm = 0.;\r
+          oDot1 = 0.;\r
+          oDot2 = 0.;\r
+        }\r
+\r
+        oId = t_id;\r
+        return true;\r
+      }\r
+    }\r
+    ++nNum;\r
+  }\r
+\r
+  return false;\r
+}\r
+\r
+template <typename TInput, typename TOutput>\r
+bool\r
+FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::CheckTopology(OutputMeshType * oMesh, const NodeType & iNode)\r
+{\r
+  (void)oMesh;\r
+  (void)iNode;\r
+\r
+  return true;\r
+}\r
+\r
+template <typename TInput, typename TOutput>\r
+void\r
+FastMarchingQuadEdgeMeshFilterResultsBase<TInput, TOutput>::InitializeOutput(OutputMeshType * oMesh)\r
+{\r
+  printf("PG FastMarchingQuadEdgeMeshFilterResultsBase::InitializeOutput Start \n");\r
+  if(this->GetInput() != m_InputMesh || this->GetOutput() == NULL){\r
+         this->CopyInputMeshToOutputMeshGeometry();\r
+  }\r
+  else{\r
+               printf("PG FastMarchingQuadEdgeMeshFilterResultsBase::InitializeOutput FLAG 0.5 \n");\r
+         oMesh = this->GetOutput();\r
+  }\r
+  printf("PG FastMarchingQuadEdgeMeshFilterResultsBase::InitializeOutput FLAG 1 \n");\r
+  // Check that the input mesh is made of triangles\r
+  //We already now it is made of triangles\r
+  /**\r
+  {\r
+    OutputCellsContainerPointer       cells = oMesh->GetCells();\r
+    OutputCellsContainerConstIterator c_it = cells->Begin();\r
+    OutputCellsContainerConstIterator c_end = cells->End();\r
+\r
+    while (c_it != c_end)\r
+    {\r
+      OutputCellType * cell = c_it.Value();\r
+\r
+      if (cell->GetNumberOfPoints() != 3)\r
+      {\r
+        itkGenericExceptionMacro(<< "Input mesh has non triangular faces");\r
+      }\r
+      ++c_it;\r
+    }\r
+  }*/\r
+\r
+  OutputPointsContainerPointer points = oMesh->GetPoints();\r
+\r
+  OutputPointDataContainerPointer pointdata = OutputPointDataContainer::New();\r
+  pointdata->Reserve(points->Size());\r
+\r
+  OutputPointsContainerIterator p_it = points->Begin();\r
+  OutputPointsContainerIterator p_end = points->End();\r
+\r
+  while (p_it != p_end)\r
+  {\r
+    pointdata->SetElement(p_it->Index(), this->m_LargeValue);\r
+    ++p_it;\r
+  }\r
+\r
+  oMesh->SetPointData(pointdata);\r
+\r
+  m_Label.clear();\r
+\r
+  if (this->m_AlivePoints)\r
+  {\r
+    NodePairContainerConstIterator pointsIter = this->m_AlivePoints->Begin();\r
+    NodePairContainerConstIterator pointsEnd = this->m_AlivePoints->End();\r
+    while (pointsIter != pointsEnd)\r
+    {\r
+      // get node from alive points container\r
+      NodeType idx = pointsIter->Value().GetNode();\r
+\r
+      if (points->IndexExists(idx))\r
+      {\r
+        OutputPixelType outputPixel = pointsIter->Value().GetValue();\r
+\r
+        this->SetLabelValueForGivenNode(idx, Traits::Alive);\r
+        this->SetOutputValue(oMesh, idx, outputPixel);\r
+      }\r
+\r
+      ++pointsIter;\r
+    }\r
+  }\r
+  if (this->m_ForbiddenPoints)\r
+  {\r
+    NodePairContainerConstIterator pointsIter = this->m_ForbiddenPoints->Begin();\r
+    NodePairContainerConstIterator pointsEnd = this->m_ForbiddenPoints->End();\r
+\r
+    OutputPixelType zero = NumericTraits<OutputPixelType>::ZeroValue();\r
+\r
+    while (pointsIter != pointsEnd)\r
+    {\r
+      NodeType idx = pointsIter->Value().GetNode();\r
+\r
+      if (points->IndexExists(idx))\r
+      {\r
+        this->SetLabelValueForGivenNode(idx, Traits::Forbidden);\r
+        this->SetOutputValue(oMesh, idx, zero);\r
+      }\r
+\r
+      ++pointsIter;\r
+    }\r
+  }\r
+  if (this->m_TrialPoints)\r
+  {\r
+    NodePairContainerConstIterator pointsIter = this->m_TrialPoints->Begin();\r
+    NodePairContainerConstIterator pointsEnd = this->m_TrialPoints->End();\r
+\r
+    while (pointsIter != pointsEnd)\r
+    {\r
+      NodeType idx = pointsIter->Value().GetNode();\r
+\r
+      if (points->IndexExists(idx))\r
+      {\r
+        OutputPixelType outputPixel = pointsIter->Value().GetValue();\r
+\r
+        this->SetLabelValueForGivenNode(idx, Traits::InitialTrial);\r
+        this->SetOutputValue(oMesh, idx, outputPixel);\r
+\r
+        this->m_Heap.push(pointsIter->Value());\r
+      }\r
+\r
+      ++pointsIter;\r
+    }\r
+  }printf("PG FastMarchingQuadEdgeMeshFilterResultsBase::InitializeOutput ENDED \n");\r
+}\r
+} // namespace itk\r
+\r
+#endif // itkFastMarchingQuadEdgeMeshFilterResultsBase_hxx\r