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

  Program:   Visualization Toolkit
  Module:    vtkPickFilter.h

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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.

=========================================================================*/
// .NAME vtkPickFilter - Find nearest point and cell.
// .SECTION Description
// This filter is for picking points and cell in paraview.
// It executes in parallel on distributed data sets.  
// It assumes MPI we have an MPI controller.  The data remains distributed.
// The user sets a point, and the filter finds the nearest
// input point or cell.  

#ifndef __vtkPickFilter_h
#define __vtkPickFilter_h

#include "vtkUnstructuredGridAlgorithm.h"

class vtkMultiProcessController;
class vtkIdList;
class vtkIntArray;
class vtkPoints;
class vtkDataSet;
class vtkAppendFilter;

class VTK_EXPORT vtkPickFilter : public vtkUnstructuredGridAlgorithm
{
public:
  static vtkPickFilter *New();
  vtkTypeRevisionMacro(vtkPickFilter,vtkUnstructuredGridAlgorithm);
  void PrintSelf(ostream& os, vtkIndent indent);

  // Description:
  // Set your picking point here.
  vtkSetVector3Macro(WorldPoint,double);
  vtkGetVector3Macro(WorldPoint,double);

  // Description:
  // Select whether you are using a world point to pick, or
  // a cell / point id.
  vtkSetMacro(PickCell,int);
  vtkGetMacro(PickCell,int);
  vtkBooleanMacro(PickCell,int);

  // Description:
  // Select whether you are picking point or cells.
  // The default value of this flag is off (use world point).
  vtkSetMacro(UseIdToPick,int);
  vtkGetMacro(UseIdToPick,int);
  vtkBooleanMacro(UseIdToPick,int);
  
  // Description:
  // If using an Id to pick, set the ID with this method.
  vtkSetMacro(Id,vtkIdType);
  vtkGetMacro(Id,vtkIdType);
  
  // Descrption:
  // If the input point/cell attributes has an array with this name,
  // then it is used to find the point.  Defaults to GlobalId.
  vtkSetStringMacro(GlobalPointIdArrayName);
  vtkGetStringMacro(GlobalPointIdArrayName);
  vtkSetStringMacro(GlobalCellIdArrayName);
  vtkGetStringMacro(GlobalCellIdArrayName);
  
  // Description:
  // This is set by default (if compiled with MPI).
  // User can override this default.
  void SetController(vtkMultiProcessController* controller);
  
protected:
  vtkPickFilter();
  ~vtkPickFilter();

  virtual int FillInputPortInformation(int, vtkInformation *);

  virtual int RequestData(
    vtkInformation *vtkNotUsed(request),
    vtkInformationVector **inputVector,
    vtkInformationVector *outputVector);
  void PointExecute(vtkInformationVector **inputVector,
                    vtkInformationVector *outputVector);
  void CellExecute(vtkInformationVector **inputVector,
                   vtkInformationVector *outputVector);
  int CompareProcesses(double bestDist2);
  void CreateOutput(vtkInformationVector **inputVector,
                    vtkInformationVector *outputVector,
                    vtkIdList* regionCellIds);

  virtual void IdExecute(vtkInformationVector **inputVector,
                         vtkInformationVector *outputVector);
  int CellIdExecute(int numInputs, 
                    vtkDataSet* input, 
                    int inputIdx,  
                    vtkAppendFilter* append);
  int PointIdExecute(int numInputs, 
                     vtkDataSet* input, 
                     int inputIdx, 
                     vtkAppendFilter* append);

  // Flag that toggles between picking cells or picking points.
  int PickCell;

  // Input pick point.
  double WorldPoint[3];

  int UseIdToPick;
  vtkIdType Id;
  char* GlobalPointIdArrayName;
  char* GlobalCellIdArrayName;

  vtkMultiProcessController* Controller;

  // Index is the input id, value is the output id.
  vtkIdList* PointMap;
  // Index is the output id, value is the input id.
  vtkIdList* RegionPointIds;

  // I need this because I am converting this filter
  // to have multiple inputs, and removing the layer feature
  // at the same time.  Maps can only be from one input.
  int BestInputIndex;

  // Returns outputId.
  vtkIdType InsertIdInPointMap(vtkIdType inId);
  void InitializePointMap(vtkIdType numerOfInputPoints);
  void DeletePointMap();
  int ListContainsId(vtkIdList* ids, vtkIdType id);

  // Locator did no do what I wanted.
  vtkIdType FindPointId(double pt[3], vtkDataSet* input);

private:
  vtkPickFilter(const vtkPickFilter&);  // Not implemented.
  void operator=(const vtkPickFilter&);  // Not implemented.
};

#endif


