/**
   * Extract segments' frame required by a vtkStreamingDemandDrivenPipeline object.
   */
  int VTKSegmentsFramesSource::RequestData(vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
  {
    btkNotUsed(request);
    
    vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
    VTKDataObjectAdapter* inObject = VTKDataObjectAdapter::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
    if (!inObject)
      return 0;
    
    PointCollection::Pointer input = static_pointer_cast<PointCollection>(inObject->GetBTKDataObject());
    
    vtkInformation* outInfo = outputVector->GetInformationObject(0);
    vtkPolyData* output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
    
    vtkInformation* outInfoBis = outputVector->GetInformationObject(1);
    vtkPolyData* outputBis = vtkPolyData::SafeDownCast(outInfoBis->Get(vtkDataObject::DATA_OBJECT()));
    
    int frameIndex = 0;
#if (VTK_MAJOR_VERSION >= 6)
    if (outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP()))
      frameIndex = static_cast<int>(outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP()));
#else
    if (outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEPS()))
      frameIndex = static_cast<int>(outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEPS())[0]);
#endif
      
    int markerNumber = 0;
    int linkNumber = 0;
    int faceNumber = 0;
    int inc = 0;
    for (std::list<SegmentDefinition>::const_iterator itS = this->m_Definitions.begin() ; itS != this->m_Definitions.end() ; ++itS)
    {
      if (this->mp_VisibleSegments->GetValue(inc++) == 1)
      {
        markerNumber += static_cast<int>(itS->mesh->GetVertexNumber());
        linkNumber += static_cast<int>(itS->mesh->GetEdgeNumber());
        if (itS->surfaceEnabled)
          faceNumber += static_cast<int>(itS->mesh->GetFaceNumber());
      }
    }
    
    vtkIntArray* edgeColors = vtkIntArray::New(); edgeColors->SetName("Colors"); edgeColors->SetNumberOfValues(linkNumber);
    vtkIntArray* faceColors = vtkIntArray::New(); faceColors->SetName("Colors"); faceColors->SetNumberOfValues(faceNumber);
    vtkPoints* points = vtkPoints::New(); points->SetNumberOfPoints(markerNumber);
    vtkCellArray* lines = vtkCellArray::New(); lines->Allocate(lines->EstimateSize(linkNumber,2));
    vtkCellArray* polys = vtkCellArray::New(); polys->Allocate(lines->EstimateSize(faceNumber,3));
    int segmentIndex = 0;
    int lineIndex = 0; 
    int faceIndex = 0; 
    int pointId = 0;
    output->Initialize();
    outputBis->Initialize();
    
    for (std::list<SegmentDefinition>::const_iterator itS = this->m_Definitions.begin() ; itS != this->m_Definitions.end() ; ++itS)
    {
      if (this->mp_VisibleSegments->GetValue(segmentIndex) == 0)
      {
        ++segmentIndex;
        continue;
      }
      else if (!itS->mesh->ConnectPoints(input))
      {
        btkErrorMacro("Impossible to link the segment with the markers' data.");
        ++segmentIndex;
        continue;
      }
      itS->mesh->SetCurrentFrameIndex(frameIndex);
      int markerIndex = 0;
      // Set points
      std::vector<int> idPts = std::vector<int>(itS->mesh->GetVertexNumber(), 0);
      for (TriangleMesh::VertexConstIterator itM = itS->mesh->BeginVertex() ; itM != itS->mesh->EndVertex() ; ++itM)
      {
        if (itM->IsValid())
        {
          idPts[markerIndex] = pointId;
          points->SetPoint(pointId,
                           itM->GetCoordinateX() * this->m_Scale,
                           itM->GetCoordinateY() * this->m_Scale,
                           itM->GetCoordinateZ() * this->m_Scale);
          ++pointId;
        }
        ++markerIndex;
      }
      // Set lines
      for (TriangleMesh::EdgeConstIterator itL = itS->mesh->BeginEdge() ; itL != itS->mesh->EndEdge() ; ++itL)
      {
        if (itL->IsValid())
        {
          const vtkIdType pts[2]	= {idPts[itL->GetVertex1()->GetRelativeId()], idPts[itL->GetVertex2()->GetRelativeId()]};
          lines->InsertNextCell(2, pts);
          edgeColors->SetValue(lineIndex++, this->mp_SegmentsColorIndex->GetValue(segmentIndex));
        }
      }
      // Set polys
      if (itS->surfaceEnabled)
      {
        for (TriangleMesh::FaceConstIterator itF = itS->mesh->BeginFace() ; itF != itS->mesh->EndFace() ; ++itF)
        {
          if (itF->IsValid())
          {
            const vtkIdType pts[3]	= {idPts[itF->GetVertex1()->GetRelativeId()], idPts[itF->GetVertex2()->GetRelativeId()], idPts[itF->GetVertex3()->GetRelativeId()]};
            polys->InsertNextCell(3, pts);
            faceColors->SetValue(faceIndex++, this->mp_SegmentsColorIndex->GetValue(segmentIndex));
          }
        }
      }
      ++segmentIndex;
    }
    // Edges output
    output->SetPoints(points);
    output->SetLines(lines);
    output->GetCellData()->SetScalars(edgeColors);
    // Faces output
    outputBis->SetPoints(points);
    outputBis->SetPolys(polys);
    outputBis->GetCellData()->SetScalars(faceColors);
    // Cleanup
    points->Delete();
    lines->Delete();
    polys->Delete();
    edgeColors->Delete();
    faceColors->Delete();
    
    return 1;
  };
  /**
   * Create STL files based on the given file prefix (see SetFilePrefix()) and fill them with the given acquisition (see SetInputAcquisition()) and the given mesh (see SetInputMesh()). You can also set the frames to extract using the method SetFramesOfInterest().
   */
  void MultiSTLFileWriter::GenerateData()
  {
    if (this->m_FilePrefix.empty())
      throw MultiSTLFileWriterException("File prefix must be specified.");
    
    Acquisition::Pointer acquisition = this->GetInputAcquisition();
    if (!acquisition)
    {
      btkErrorMacro("Impossible to write a null input into a file (acquisition).");
      return;
    }
    TriangleMesh::Pointer mesh = this->GetInputMesh();
    if (!mesh)
    {
      btkErrorMacro("Impossible to write a null input into a file (mesh).");
      return;
    }
      
    int ff = (this->m_FOI[0] == -1 ? acquisition->GetFirstFrame() : this->m_FOI[0]);
    int lf = (this->m_FOI[1] == -1 ? acquisition->GetLastFrame() : this->m_FOI[1]);
    
    if (ff < acquisition->GetFirstFrame())
      throw MultiSTLFileWriterException("First frame out of range.");
    else if (lf > acquisition->GetLastFrame())
      throw MultiSTLFileWriterException("Last frame out of range.");
    
    if (mesh->GetMaxVertexId() > acquisition->GetPointNumber())
      throw MultiSTLFileWriterException("Invalid vertex ID.");

    // Try to link the mesh with the acquisition data
    if (!mesh->ConnectPoints(acquisition->GetPoints()))
      throw MultiSTLFileWriterException("Marker index out of range.");
    
    int num = btkNumberOfDigits(lf);
    try
    { 
      IEEELittleEndianBinaryFileStream obfs;
      for (int i = ff ; i <= lf ; ++i)
      {
        std::stringstream filename("");
        filename << this->m_FilePrefix << std::setw(num) << std::setfill('0') << i << ".stl";
        obfs.Open(filename.str(), BinaryFileStream::Out | BinaryFileStream::Truncate);
        if (!obfs.IsOpen())
          throw(MultiSTLFileWriterException("No File access. Are you sure of the path? Have you the right privileges?"));
        std::string header = "STL binary file generated by BTK " + std::string(BTK_VERSION_STRING);
        header.resize(80);
        obfs.Write(header);
        obfs.Write((int32_t)0); // Fake number of triangles
        mesh->SetCurrentFrameIndex(i - acquisition->GetFirstFrame());
        int32_t validFaceNumber = 0;
        for (TriangleMesh::FaceConstIterator it = mesh->BeginFace() ;  it != mesh->EndFace() ; ++it)
        {
          if (!it->IsValid())
            continue;
          // Normal vector: set to 0 => Will be computed by the viewer program
          obfs.Write(0.0f);
          obfs.Write(0.0f);
          obfs.Write(0.0f);
          // Vertex 1
          obfs.Write(static_cast<float>(it->GetVertex1()->GetCoordinateX()));
          obfs.Write(static_cast<float>(it->GetVertex1()->GetCoordinateY()));
          obfs.Write(static_cast<float>(it->GetVertex1()->GetCoordinateZ()));
          // Vertex 2
          obfs.Write(static_cast<float>(it->GetVertex2()->GetCoordinateX()));
          obfs.Write(static_cast<float>(it->GetVertex2()->GetCoordinateY()));
          obfs.Write(static_cast<float>(it->GetVertex2()->GetCoordinateZ()));
          // Vertex 3
          obfs.Write(static_cast<float>(it->GetVertex3()->GetCoordinateX()));
          obfs.Write(static_cast<float>(it->GetVertex3()->GetCoordinateY()));
          obfs.Write(static_cast<float>(it->GetVertex3()->GetCoordinateZ()));
          // Attribute byte count
          obfs.Write((uint16_t)0);
          ++validFaceNumber;
        }
        // Write the true number of triangles
        obfs.SeekRead(80, BinaryFileStream::Begin);
        obfs.Write(validFaceNumber);
        obfs.Close();
      }
    }
    catch (MultiSTLFileWriterException& )
    {
      throw;
    }
    catch (std::exception& e)
    {
      throw(MultiSTLFileWriterException("Unexpected exception occurred: " + std::string(e.what())));
    }
    catch(...)
    {
      throw(MultiSTLFileWriterException("Unknown exception"));
    }
  };