/*=========================================================================

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/VolViewCopyright.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 "vtkScalarsPassThroughFilter.h"

#include "vtkCellData.h"
#include "vtkDataSet.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkDataArray.h"

vtkCxxRevisionMacro(vtkScalarsPassThroughFilter, "$Revision: 1.5 $");
vtkStandardNewMacro(vtkScalarsPassThroughFilter);

//----------------------------------------------------------------------------
vtkScalarsPassThroughFilter::vtkScalarsPassThroughFilter()
{
  int i;
  for (i = 0; i < VTK_MAX_VRCOMP; i++)
    {
    this->OutputPointScalarComponent[i] = 1;
    }
}

//----------------------------------------------------------------------------
void vtkScalarsPassThroughFilter::SetOutputPointScalarComponent(
  int comp, int value)
{
  if (comp < 0 || comp >= VTK_MAX_VRCOMP || 
      this->OutputPointScalarComponent[comp] == value)
    {
    return;
    }

  this->OutputPointScalarComponent[comp] = value;

  this->Modified();
}

//----------------------------------------------------------------------------
int vtkScalarsPassThroughFilter::GetOutputPointScalarComponent(
  int comp)
{
  if (comp < 0 || comp >= VTK_MAX_VRCOMP)
    {
    return 0;
    }

  return this->OutputPointScalarComponent[comp];
}

//----------------------------------------------------------------------------
template <class T>
void vtkScalarsPassThroughFilterExecute(vtkScalarsPassThroughFilter *self,
                                        vtkDataArray *in_pscalars, 
                                        vtkDataArray *out_pscalars,
                                        T *)
{
  if (!self || !in_pscalars || !out_pscalars)
    {
    return;
    }

  T *in_ptr = static_cast<T*>(in_pscalars->GetVoidPointer(0));
  T *out_ptr = static_cast<T*>(out_pscalars->GetVoidPointer(0));

  int in_nb_components = in_pscalars->GetNumberOfComponents();
  T *in_ptr_end = in_ptr + 
    (vtkIdType)in_nb_components * in_pscalars->GetNumberOfTuples();


  while (in_ptr < in_ptr_end)
    {
    for (int comp = 0; comp < in_nb_components; comp++)
      {
      if (self->GetOutputPointScalarComponent(comp))
        {
        *out_ptr++ = *in_ptr;
        }
      in_ptr++;
      }
    }
}

//----------------------------------------------------------------------------
void vtkScalarsPassThroughFilter::Execute()
{
  int i;

  vtkDataSet *input = this->GetInput();
  vtkDataSet *output = this->GetOutput();

  // First, copy the input to the output as a starting point

  output->CopyStructure(input);

  // Then modify the point scalars, if needed

  vtkDataArray *in_pscalars = input->GetPointData()->GetScalars();
  vtkDataArray *out_pscalars = NULL;

  if (in_pscalars)
    {
    int nb_new_components = 0;
    for (i = 0; i < in_pscalars->GetNumberOfComponents(); i++)
      {
      if (this->OutputPointScalarComponent[i])
        {
        nb_new_components++;
        }
      }
  
    if (nb_new_components != in_pscalars->GetNumberOfComponents())
      {
      out_pscalars = in_pscalars->NewInstance();
      out_pscalars->SetNumberOfComponents(nb_new_components);
      out_pscalars->SetNumberOfTuples(in_pscalars->GetNumberOfTuples());
      
      switch (in_pscalars->GetDataType())
        {
        vtkTemplateMacro(vtkScalarsPassThroughFilterExecute(
                          this, 
                          in_pscalars, 
                          out_pscalars,
                          (VTK_TT *)0));
                                                
        default:
          vtkErrorMacro(<< "Execute: Unknown DataType");
          out_pscalars->Delete();
          out_pscalars = NULL;
        }
      }
    }

  // Update ourselves

  if (out_pscalars)
    {
    output->GetPointData()->CopyScalarsOff();
    }
  output->GetPointData()->PassData(input->GetPointData());

  output->GetCellData()->PassData(input->GetCellData());

  output->GetFieldData()->PassData(input->GetFieldData());

  // Set the new scalars

  if (out_pscalars)
    {
    output->GetPointData()->SetScalars(out_pscalars);
    out_pscalars->Delete();
    }
}

//----------------------------------------------------------------------------
void vtkScalarsPassThroughFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  for (int i = 0; i < VTK_MAX_VRCOMP; i++)
    {
    os << indent << "Pass Point Scalar Component " << i 
       << ": " << (this->OutputPointScalarComponent[i] ? "On" : "Off") << endl;
    }
}
