text: /*=========================================================================
  
    Program:   Visualization Toolkit
    Module:    vtkThresholdPoints.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 "vtkThresholdPoints.h"
  
  #include "vtkCellArray.h"
  #include "vtkDataArray.h"
  #include "vtkDataSet.h"
  #include "vtkInformation.h"
  #include "vtkInformationVector.h"
  #include "vtkObjectFactory.h"
  #include "vtkPointData.h"
  #include "vtkPoints.h"
  #include "vtkPolyData.h"
  
  vtkStandardNewMacro(vtkThresholdPoints);
  
  //------------------------------------------------------------------------------
  // Construct with lower threshold=0, upper threshold=1, and threshold
  // function=upper.
  vtkThresholdPoints::vtkThresholdPoints()
  {
    this->LowerThreshold = 0.0;
    this->UpperThreshold = 1.0;
    this->OutputPointsPrecision = DEFAULT_PRECISION;
  
    this->ThresholdFunction = &vtkThresholdPoints::Upper;
  
    // by default process active point scalars
    this->SetInputArrayToProcess(
      0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS);
  }
  
  //------------------------------------------------------------------------------
  // Criterion is cells whose scalars are less than lower threshold.
  void vtkThresholdPoints::ThresholdByLower(double lower)
  {
    int isModified = 0;
  
    if (this->ThresholdFunction != &vtkThresholdPoints::Lower)
    {
      this->ThresholdFunction = &vtkThresholdPoints::Lower;
      isModified = 1;
    }
  
    if (this->LowerThreshold != lower)
    {
      this->LowerThreshold = lower;
      isModified = 1;
    }
  
    if (isModified)
    {
      this->Modified();
    }
  }
  
  //------------------------------------------------------------------------------
  // Criterion is cells whose scalars are less than upper threshold.
  void vtkThresholdPoints::ThresholdByUpper(double upper)
  {
    int isModified = 0;
  
    if (this->ThresholdFunction != &vtkThresholdPoints::Upper)
    {
      this->ThresholdFunction = &vtkThresholdPoints::Upper;
      isModified = 1;
    }
  
    if (this->UpperThreshold != upper)
    {
      this->UpperThreshold = upper;
      isModified = 1;
    }
  
    if (isModified)
    {
      this->Modified();
    }
  }
  
  //------------------------------------------------------------------------------
  // Criterion is cells whose scalars are between lower and upper thresholds.
  void vtkThresholdPoints::ThresholdBetween(double lower, double upper)
  {
    int isModified = 0;
  
    if (this->ThresholdFunction != &vtkThresholdPoints::Between)
    {
      this->ThresholdFunction = &vtkThresholdPoints::Between;
      isModified = 1;
    }
  
    if (this->LowerThreshold != lower)
    {
      this->LowerThreshold = lower;
      isModified = 1;
    }
  
    if (this->UpperThreshold != upper)
    {
      this->UpperThreshold = upper;
      isModified = 1;
    }
  
    if (isModified)
    {
      this->Modified();
    }
  }
  
  //------------------------------------------------------------------------------
  int vtkThresholdPoints::RequestData(vtkInformation* vtkNotUsed(request),
    vtkInformationVector** inputVector, vtkInformationVector* outputVector)
  {
    // get the info objects
    vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
    vtkInformation* outInfo = outputVector->GetInformationObject(0);
  
    // get the input and output
    vtkDataSet* input = vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
    vtkPolyData* output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
  
    vtkDataArray* inScalars;
    vtkPoints* newPoints;
    vtkPointData *pd, *outPD;
    vtkCellArray* verts;
    vtkIdType ptId, numPts, pts[1];
    double x[3];
  
    vtkDebugMacro(<< "Executing threshold points filter");
  
    if (!(inScalars = this->GetInputArrayToProcess(0, inputVector)))
    {
      vtkErrorMacro(<< "No scalar data to threshold");
      return 1;
    }
  
    numPts = input->GetNumberOfPoints();
  
    if (numPts < 1)
    {
      vtkErrorMacro(<< "No points to threshold");
      return 1;
    }
  
    newPoints = vtkPoints::New();
  
    // Set the desired precision for the points in the output.
    if (this->OutputPointsPrecision == vtkAlgorithm::DEFAULT_PRECISION)
    {
      vtkPointSet* inputPointSet = vtkPointSet::SafeDownCast(input);
      if (inputPointSet)
      {
        newPoints->SetDataType(inputPointSet->GetPoints()->GetDataType());
      }
      else
      {
        newPoints->SetDataType(VTK_FLOAT);
      }
    }
    else if (this->OutputPointsPrecision == vtkAlgorithm::SINGLE_PRECISION)
    {
      newPoints->SetDataType(VTK_FLOAT);
    }
    else if (this->OutputPointsPrecision == vtkAlgorithm::DOUBLE_PRECISION)
    {
      newPoints->SetDataType(VTK_DOUBLE);
    }
  
    newPoints->Allocate(numPts);
    pd = input->GetPointData();
    outPD = output->GetPointData();
    outPD->CopyAllocate(pd);
    verts = vtkCellArray::New();
    verts->AllocateEstimate(numPts, 1);
  
    // Check that the scalars of each point satisfy the threshold criterion
    int abort = 0;
    vtkIdType progressInterval = numPts / 20 + 1;
  
    for (ptId = 0; ptId < numPts && !abort; ptId++)
    {
      if (!(ptId % progressInterval))
      {
        this->UpdateProgress((double)ptId / numPts);
        abort = this->GetAbortExecute();
      }
  
      if ((this->*(this->ThresholdFunction))(inScalars->GetComponent(ptId, 0)))
      {
        input->GetPoint(ptId, x);
        pts[0] = newPoints->InsertNextPoint(x);
        outPD->CopyData(pd, ptId, pts[0]);
        verts->InsertNextCell(1, pts);
      } // satisfied thresholding
    }   // for all points
  
    vtkDebugMacro(<< "Extracted " << output->GetNumberOfPoints() << " points.");
  
    // Update ourselves and release memory
    //
    output->SetPoints(newPoints);
    newPoints->Delete();
  
    output->SetVerts(verts);
    verts->Delete();
  
    output->Squeeze();
  
    return 1;
  }
  
  //------------------------------------------------------------------------------
  int vtkThresholdPoints::FillInputPortInformation(int, vtkInformation* info)
  {
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
    return 1;
  }
  
  //------------------------------------------------------------------------------
  void vtkThresholdPoints::PrintSelf(ostream& os, vtkIndent indent)
  {
    this->Superclass::PrintSelf(os, indent);
  
    os << indent << "Lower Threshold: " << this->LowerThreshold << "\n";
    os << indent << "Upper Threshold: " << this->UpperThreshold << "\n";
    os << indent << "Output Points Precision: " << this->OutputPointsPrecision << "\n";
  }
  