text: /*=========================================================================
  
    Program:   Visualization Toolkit
    Module:    vtkExtractLevel.cxx
  
    Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
    All rights reserved.
    See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  
       This software is distributed WITHOUT ANY WARRANTY; without even
       the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
       PURPOSE.  See the above copyright notice for more information.
  
  =========================================================================*/
  #include "vtkExtractLevel.h"
  
  #include "vtkCompositeDataPipeline.h"
  #include "vtkInformation.h"
  #include "vtkInformationVector.h"
  #include "vtkMultiBlockDataSet.h"
  #include "vtkObjectFactory.h"
  #include "vtkOverlappingAMR.h"
  #include "vtkUniformGrid.h"
  #include "vtkUniformGridAMR.h"
  
  #include <set>
  #include <vector>
  
  class vtkExtractLevel::vtkSet : public std::set<unsigned int>
  {
  };
  
  vtkStandardNewMacro(vtkExtractLevel);
  //------------------------------------------------------------------------------
  vtkExtractLevel::vtkExtractLevel()
  {
    this->Levels = new vtkExtractLevel::vtkSet();
  }
  
  //------------------------------------------------------------------------------
  vtkExtractLevel::~vtkExtractLevel()
  {
    delete this->Levels;
  }
  
  //------------------------------------------------------------------------------
  void vtkExtractLevel::AddLevel(unsigned int level)
  {
    this->Levels->insert(level);
    this->Modified();
  }
  
  //------------------------------------------------------------------------------
  void vtkExtractLevel::RemoveLevel(unsigned int level)
  {
    this->Levels->erase(level);
    this->Modified();
  }
  
  //------------------------------------------------------------------------------
  void vtkExtractLevel::RemoveAllLevels()
  {
    this->Levels->clear();
    this->Modified();
  }
  
  //------------------------------------------------------------------------------
  int vtkExtractLevel::FillInputPortInformation(int vtkNotUsed(port), vtkInformation* info)
  {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUniformGridAMR");
    return 1;
  }
  
  //------------------------------------------------------------------------------
  int vtkExtractLevel::FillOutputPortInformation(int vtkNotUsed(port), vtkInformation* info)
  {
    info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet");
    return 1;
  }
  
  int vtkExtractLevel::RequestUpdateExtent(
    vtkInformation*, vtkInformationVector** inputVector, vtkInformationVector*)
  {
    vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
  
    // Check if metadata are passed downstream
    if (inInfo->Has(vtkCompositeDataPipeline::COMPOSITE_DATA_META_DATA()))
    {
      vtkOverlappingAMR* metadata = vtkOverlappingAMR::SafeDownCast(
        inInfo->Get(vtkCompositeDataPipeline::COMPOSITE_DATA_META_DATA()));
  
      if (metadata)
      {
        // cout<<"Time dependent?
        // "<<inInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_DEPENDENT_INFORMATION())<<endl;
        // std::cout<<"Receive Meta Data: ";
        // for(int levelIdx=0 ; levelIdx < metadata->GetNumberOfLevels(); ++levelIdx )
        //   {
        //   std::cout << " \tL(" << levelIdx << ") = "
        //             << metadata->GetNumberOfDataSets( levelIdx ) << " ";
        //   std::cout.flush();
        //   } // END for levels
        // std::cout<<endl;
  
        // Tell reader to load all requested blocks.
        inInfo->Set(vtkCompositeDataPipeline::LOAD_REQUESTED_BLOCKS(), 1);
  
        // request the blocks
        std::vector<int> blocksToLoad;
        for (vtkExtractLevel::vtkSet::iterator iter = this->Levels->begin();
             iter != this->Levels->end(); ++iter)
        {
          unsigned int level = (*iter);
          for (unsigned int dataIdx = 0; dataIdx < metadata->GetNumberOfDataSets(level); ++dataIdx)
          {
            blocksToLoad.push_back(metadata->GetCompositeIndex(level, dataIdx));
          }
        }
  
        inInfo->Set(vtkCompositeDataPipeline::UPDATE_COMPOSITE_INDICES(), &blocksToLoad[0],
          static_cast<int>(blocksToLoad.size()));
      }
    }
  
    return 1;
  }
  
  //------------------------------------------------------------------------------
  int vtkExtractLevel::RequestData(vtkInformation* vtkNotUsed(request),
    vtkInformationVector** inputVector, vtkInformationVector* outputVector)
  {
    // STEP 0: Get input object
  
    vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
    vtkUniformGridAMR* input =
      vtkUniformGridAMR::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
    if (input == nullptr)
    {
      return (0);
    }
  
    // STEP 1: Get output object
    vtkInformation* info = outputVector->GetInformationObject(0);
    vtkMultiBlockDataSet* output =
      vtkMultiBlockDataSet::SafeDownCast(info->Get(vtkDataObject::DATA_OBJECT()));
    if (output == nullptr)
    {
      return (0);
    }
  
    // STEP 2: Compute the total number of blocks to be loaded
    unsigned int numBlocksToLoad = 0;
    vtkExtractLevel::vtkSet::iterator iter;
    for (iter = this->Levels->begin(); iter != this->Levels->end(); ++iter)
    {
      unsigned int level = (*iter);
      numBlocksToLoad += input->GetNumberOfDataSets(level);
    } // END for all requested levels
    output->SetNumberOfBlocks(numBlocksToLoad);
  
    // STEP 3: Load the blocks at the selected levels
    if (numBlocksToLoad > 0)
    {
      iter = this->Levels->begin();
      unsigned int blockIdx = 0;
      for (; iter != this->Levels->end(); ++iter)
      {
        unsigned int level = (*iter);
        unsigned int dataIdx = 0;
        for (; dataIdx < input->GetNumberOfDataSets(level); ++dataIdx)
        {
          vtkUniformGrid* data = input->GetDataSet(level, dataIdx);
          if (data != nullptr)
          {
            vtkUniformGrid* copy = data->NewInstance();
            copy->ShallowCopy(data);
            output->SetBlock(blockIdx, copy);
            copy->Delete();
            ++blockIdx;
          } // END if data is not nullptr
        }   // END for all data at level l
      }     // END for all requested levels
    }       // END if numBlocksToLoad is greater than 0
  
    return (1);
  }
  
  //------------------------------------------------------------------------------
  void vtkExtractLevel::PrintSelf(ostream& os, vtkIndent indent)
  {
    this->Superclass::PrintSelf(os, indent);
  }
  