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

  Program:   Visualization Toolkit
  Module:    vtkCookieCutter.h

  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.

=========================================================================*/
/**
 * @class   vtkCookieCutter
 * @brief   cut vtkPolyData defined on the 2D plane with one or more polygons
 *
 * This filter crops an input vtkPolyData consisting of cells (i.e., points,
 * lines, polygons, and triangle strips) with trim loops specified by a second
 * input containing polygons and/or polylines. The input vtkPolyData and the
 * loops must lie on the same plane. Note that this filter can handle concave
 * polygons and/or loops. It may produce multiple output polygons for each
 * polygon/loop interaction. Similarly, it may produce multiple line segments
 * and so on. (The input to cookie cut (input0) is referred to as the input
 * mesh, while the loops used to cut the input mesh (input1) are referred to
 * as the trim loops.)
 *
 * The filter has the option to pass through and generate point and cell
 * data.  If PassCellData is enabled, then the cell data associated with the
 * cropped cells, or cells passed through from the input mesh, are passed
 * through to the output. If PassPointData is enabled, then in similar
 * fashion the point data is passed through; however new points generated by
 * intersection may have point data interpolated in one of two ways. First,
 * the input mesh edges are interpolated at the new intersection points to
 * generate point data, or the trim loop edges are interpolated at the new
 * intersection points to generate point data. Note: for PassPointData and
 * point interpolation to function, the filter requires that the point data
 * attributes (from the mesh and trim loop) are exactly the same. If they are
 * not, then a set intersection operation is performed which uses the point
 * data arrays common to both the mesh and trim loops.
 *
 * @warning
 * The mesh and trim loops must lie on the same plane and the plane may be
 * arbitrarily oriented. If not on the same plane, tolerancing issues can
 * produce erratic results.
 *
 * @sa
 * vtkImprintFilter
 */

#ifndef vtkCookieCutter_h
#define vtkCookieCutter_h

#include "vtkFiltersModelingModule.h" // For export macro
#include "vtkPolyDataAlgorithm.h"

class VTKFILTERSMODELING_EXPORT vtkCookieCutter : public vtkPolyDataAlgorithm
{
public:
  ///@{
  /**
   * Standard methods to instantiate, print and provide type information.
   */
  static vtkCookieCutter* New();
  vtkTypeMacro(vtkCookieCutter, vtkPolyDataAlgorithm);
  void PrintSelf(ostream& os, vtkIndent indent) override;
  ///@}

  /**
   * Specify the a second vtkPolyData input which defines trim loops used to
   * cut the input polygonal data. These loops must be manifold, i.e., do not
   * self intersect. The loops are defined from the polygons and polylines
   * defined in this second input. Note that if polylines are used, they are
   * assumed to be closed.
   */
  void SetLoopsConnection(vtkAlgorithmOutput* algOutput);
  vtkAlgorithmOutput* GetLoopsConnection();

  ///@{
  /**
   * Specify the a second vtkPolyData input which defines trim loops used to
   * cut the input polygonal data. These loops must be manifold, i.e., do not
   * self intersect. The loops are defined from the polygons and polylines
   * defined in this second input.
   */
  void SetLoopsData(vtkDataObject* loops);
  vtkDataObject* GetLoops();
  ///@}

  ///@{
  /**
   * Indicate whether cell data from the input mesh is to be passed through
   * to the output mesh. By default, PassCellData is enabled.
   */
  vtkSetMacro(PassCellData, bool);
  vtkGetMacro(PassCellData, bool);
  vtkBooleanMacro(PassCellData, bool);
  ///@}

  ///@{
  /**
   * Indicate whether point data from the input mesh are to be passed through
   * and/or interpolated to the output mesh. By default, PassPointData is
   * enabled. Note: both the input mesh points and the trim
   * loops, must have identical point data. Otherwise, a set operation will
   * be performed to process just the point data arrays common to both the
   * mesh point data and loops point data.
   */
  vtkSetMacro(PassPointData, bool);
  vtkGetMacro(PassPointData, bool);
  vtkBooleanMacro(PassPointData, bool);
  ///@}

  enum PointInterpolationType
  {
    USE_MESH_EDGES = 0,
    USE_LOOP_EDGES = 1
  };

  ///@{
  /**
   * If PassPointData is on, indicate how new point data is to generated at
   * the intersection points between the input mesh edges and the trim edges
   * (trim edges form the loops). By default, PointInterpolation is set to
   * USE_MESH_EDGES.
   */
  vtkSetClampMacro(PointInterpolation, int, USE_MESH_EDGES, USE_LOOP_EDGES);
  vtkGetMacro(PointInterpolation, int);
  void SetPointInterpolationToMeshEdges() { this->SetPointInterpolation(USE_MESH_EDGES); }
  void SetPointInterpolationToLoopEdges() { this->SetPointInterpolation(USE_LOOP_EDGES); }
  ///@}

  ///@{
  /**
   * Specify a spatial locator for merging points. By default, an
   * instance of vtkMergePoints is used.
   */
  void SetLocator(vtkIncrementalPointLocator* locator);
  vtkGetObjectMacro(Locator, vtkIncrementalPointLocator);
  ///@}

  /**
   * Create default locator. Used to create one when none is specified. The
   * locator is used to merge coincident points.
   */
  void CreateDefaultLocator();

protected:
  vtkCookieCutter();
  ~vtkCookieCutter() override;

  int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
  int RequestUpdateExtent(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
  int FillInputPortInformation(int, vtkInformation*) override;

  bool PassCellData;
  bool PassPointData;
  int PointInterpolation;

  vtkIncrementalPointLocator* Locator;

private:
  vtkCookieCutter(const vtkCookieCutter&) = delete;
  void operator=(const vtkCookieCutter&) = delete;
};

#endif
