// SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause

#include "vtkSLACPlaneGlyphs.h"

#include "vtkCompositeDataPipeline.h"
#include "vtkCompositeDataProbeFilter.h"
#include "vtkInformation.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkSamplePlaneSource.h"
#include "vtkThresholdPoints.h"

#include "vtkNew.h"

//=============================================================================
vtkStandardNewMacro(vtkSLACPlaneGlyphs);

//-----------------------------------------------------------------------------
vtkSLACPlaneGlyphs::vtkSLACPlaneGlyphs()
{
  this->Center[0] = this->Center[1] = this->Center[2] = 0.0;
  this->Normal[0] = 0.0;
  this->Normal[1] = 0.0;
  this->Normal[2] = 1.0;
  this->Resolution = 10;
}

vtkSLACPlaneGlyphs::~vtkSLACPlaneGlyphs() = default;

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

  os << indent << "Center: (" << this->Center[0] << ", " << this->Center[1] << ", "
     << this->Center[2] << ")" << endl;
  os << indent << "Normal: (" << this->Normal[0] << ", " << this->Normal[1] << ", "
     << this->Normal[2] << ")" << endl;
  ;
  os << indent << "Resolution: " << this->Resolution << endl;
}

//-----------------------------------------------------------------------------
int vtkSLACPlaneGlyphs::FillInputPortInformation(int port, vtkInformation* info)
{
  if (port == 0)
  {
    info->Remove(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE());
    info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
    info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkCompositeDataSet");
    return 1;
  }
  return 0;
}

//-----------------------------------------------------------------------------
int vtkSLACPlaneGlyphs::RequestData(vtkInformation* vtkNotUsed(request),
  vtkInformationVector** inputVector, vtkInformationVector* outputVector)
{
  // Get the input and output objects.
  vtkDataObject* input = vtkDataObject::GetData(inputVector[0]);
  vtkPolyData* output = vtkPolyData::GetData(outputVector);

  // Make a shallow copy of the input so that we can give it to internal
  // filters.  It is NOT a good idea to feed the input directly into internal
  // filters because that can mess up the pipeline connections of this filter.
  vtkSmartPointer<vtkDataObject> inputCopy;
  inputCopy.TakeReference(input->NewInstance());
  inputCopy->ShallowCopy(input);

  // Create a plane that we will use to place the glyphs.
  vtkNew<vtkSamplePlaneSource> plane;
  plane->SetInputData(inputCopy);
  plane->SetCenter(this->Center);
  plane->SetNormal(this->Normal);
  plane->SetResolution(this->Resolution);

  // Create a probe that will extract the points of the plane.
  vtkNew<vtkCompositeDataProbeFilter> probe;
  probe->SetSourceData(inputCopy);
  probe->SetInputConnection(plane->GetOutputPort());

  // Extract the points that are actually in the geometry.
  vtkNew<vtkThresholdPoints> threshold;
  threshold->SetExecutive(vtkSmartPointer<vtkCompositeDataPipeline>::New());
  threshold->SetInputConnection(probe->GetOutputPort());
  threshold->SetThresholdFunction(vtkThresholdPoints::THRESHOLD_UPPER);
  threshold->SetUpperThreshold(0.5);
  threshold->SetInputArrayToProcess(
    0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "vtkValidPointMask");

  threshold->Update();
  output->ShallowCopy(threshold->GetOutput());
  output->GetPointData()->RemoveArray("vtkValidPointMask");

  return 1;
}
