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

  Program:   Visualization Toolkit
  Module:    vtkIconGlyphFilter.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   vtkIconGlyphFilter
 * @brief   Filter that generates a polydata consisting of
 * quads with texture coordinates referring to a set of icons within a sheet
 * of icons.
 *
 * vtkIconGlyphFilter takes in a vtkPointSet where each point corresponds to
 * the center of an icon. Scalar integer data must also be set to give each
 * point an icon index. This index is a zero based row major index into an
 * image that contains a grid of icons (each icon is the same size). You must
 * also specify 1) the size of the icon in the icon sheet (in pixels), 2) the
 * size of the icon sheet (in pixels), and 3) the display size of each icon
 * (again in display coordinates, or pixels).
 *
 * Various other parameters are used to control how this data is combined. If
 * UseIconSize is true then the DisplaySize is ignored. If PassScalars is true,
 * then the scalar index information is passed to the output. Also, there is an
 * optional IconScale array which, if UseIconScaling is on, will scale each icon
 * independently.
 *
 * @sa
 * vtkPolyDataAlgorithm vtkGlyph3D vtkGlyph2D
*/

#ifndef vtkIconGlyphFilter_h
#define vtkIconGlyphFilter_h

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

#define VTK_ICON_GRAVITY_TOP_RIGHT     1
#define VTK_ICON_GRAVITY_TOP_CENTER    2
#define VTK_ICON_GRAVITY_TOP_LEFT      3
#define VTK_ICON_GRAVITY_CENTER_RIGHT  4
#define VTK_ICON_GRAVITY_CENTER_CENTER 5
#define VTK_ICON_GRAVITY_CENTER_LEFT   6
#define VTK_ICON_GRAVITY_BOTTOM_RIGHT  7
#define VTK_ICON_GRAVITY_BOTTOM_CENTER 8
#define VTK_ICON_GRAVITY_BOTTOM_LEFT   9

#define VTK_ICON_SCALING_OFF 0
#define VTK_ICON_SCALING_USE_SCALING_ARRAY 1


class VTKFILTERSGENERAL_EXPORT vtkIconGlyphFilter : public vtkPolyDataAlgorithm
{
public:
  //@{
  /**
   * Standard VTK methods.
   */
  static vtkIconGlyphFilter *New();
  vtkTypeMacro(vtkIconGlyphFilter,vtkPolyDataAlgorithm);
  void PrintSelf(ostream& os, vtkIndent indent) override;
  //@}

  //@{
  /**
   * Specify the Width and Height, in pixels, of an icon in the icon sheet.
   */
  vtkSetVector2Macro(IconSize,int);
  vtkGetVectorMacro(IconSize,int,2);
  //@}

  //@{
  /**
   * Specify the Width and Height, in pixels, of an icon in the icon sheet.
   */
  vtkSetVector2Macro(IconSheetSize,int);
  vtkGetVectorMacro(IconSheetSize,int,2);
  //@}

  //@{
  /**
   * Specify the Width and Height, in pixels, of the size of the icon when it
   * is rendered. By default, the IconSize is used to set the display size
   * (i.e., UseIconSize is true by default). Note that assumes that
   * IconScaling is disabled, or if enabled, the scale of a particular icon
   * is 1.
   */
  vtkSetVector2Macro(DisplaySize,int);
  vtkGetVectorMacro(DisplaySize,int,2);
  //@}

  //@{
  /**
   * Specify whether the Quad generated to place the icon on will be either
   * the dimensions specified by IconSize or the DisplaySize.
   */
  vtkSetMacro(UseIconSize,bool);
  vtkGetMacro(UseIconSize,bool);
  vtkBooleanMacro(UseIconSize, bool);
  //@}

  //@{
  /**
   * Specify how to specify individual icons. By default, icon scaling
   * is off, but if it is on, then the filter looks for an array named
   * "IconScale" to control individual icon size.
   */
  vtkSetMacro(IconScaling,int);
  vtkGetMacro(IconScaling,int);
  void SetIconScalingToScalingOff() {this->SetIconScaling(VTK_ICON_SCALING_OFF);}
  void SetIconScalingToScalingArray()
    {this->SetIconScaling(VTK_ICON_SCALING_USE_SCALING_ARRAY);}
  //@}

  //@{
  /**
   * Specify whether to pass the scalar icon index to the output. By
   * default this is not passed since it can affect color during the
   * rendering process. Note that all other point data is passed to
   * the output regardless of the value of this flag.
   */
  vtkSetMacro(PassScalars,bool);
  vtkGetMacro(PassScalars,bool);
  vtkBooleanMacro(PassScalars,bool);
  //@}

  //@{
  /**
   * Specify if the input points define the center of the icon quad or one of
   * top right corner, top center, top left corner, center right, center, center
   * center left, bottom right corner, bottom center or bottom left corner.
   */
  vtkSetMacro(Gravity, int);
  vtkGetMacro(Gravity, int);
  void SetGravityToTopRight() {this->SetGravity(VTK_ICON_GRAVITY_TOP_RIGHT);};
  void SetGravityToTopCenter() {this->SetGravity(VTK_ICON_GRAVITY_TOP_CENTER);};
  void SetGravityToTopLeft() {this->SetGravity(VTK_ICON_GRAVITY_TOP_LEFT);};
  void SetGravityToCenterRight() {this->SetGravity(VTK_ICON_GRAVITY_CENTER_RIGHT);};
  void SetGravityToCenterCenter() {this->SetGravity(VTK_ICON_GRAVITY_CENTER_CENTER);};
  void SetGravityToCenterLeft() {this->SetGravity(VTK_ICON_GRAVITY_CENTER_LEFT);};
  void SetGravityToBottomRight() {this->SetGravity(VTK_ICON_GRAVITY_BOTTOM_RIGHT);};
  void SetGravityToBottomCenter() {this->SetGravity(VTK_ICON_GRAVITY_BOTTOM_CENTER);};
  void SetGravityToBottomLeft() {this->SetGravity(VTK_ICON_GRAVITY_BOTTOM_LEFT);};
  //@}

  //@{
  /**
   * Specify an offset (in pixels or display coordinates) that offsets the icons
   * from their generating points.
   */
  vtkSetVector2Macro(Offset,int);
  vtkGetVectorMacro(Offset,int,2);
  //@}

protected:
  vtkIconGlyphFilter();
  ~vtkIconGlyphFilter() override;

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

  int IconSize[2]; // Size in pixels of an icon in an icon sheet
  int IconSheetSize[2]; // Size in pixels of the icon sheet
  int DisplaySize[2]; // Size in pixels of the icon when displayed

  int  Gravity;
  bool UseIconSize;
  int  IconScaling;
  bool PassScalars;
  int Offset[2];

private:
  vtkIconGlyphFilter(const vtkIconGlyphFilter&) = delete;
  void operator=(const vtkIconGlyphFilter&) = delete;

  void IconConvertIndex(int id, int & j, int & k);
};

inline void vtkIconGlyphFilter::IconConvertIndex(int id, int & j, int & k)
{
  int dimX = this->IconSheetSize[0]/this->IconSize[0];
  int dimY = this->IconSheetSize[1]/this->IconSize[1];

  j = id - dimX * static_cast<int>(id/dimX);
  k = dimY - static_cast<int>(id/dimX) - 1;
}

#endif
