//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt 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 vtkLoopsMesher - generates a surface from a set of lines
// .SECTION Description
// vtkLoopsMesher is a filter that generates a surface from a set of
// lines. The lines are assumed to be "parallel" in the sense that they do
// not intersect and remain somewhat close to one another. A surface is
// generated by connecting the points defining each pair of lines with
// straight lines. This creates a strip for each pair of lines (i.e., a
// triangulation is created from two generating lines). The filter can handle
// an arbitrary number of lines, with lines i and i+1 assumed connected.
// Note that there are several different approaches for creating the ruled
// surface, the method for creating the surface can either use the input
// points or resample from the polylines (using a user-specified resolution).
//
// This filter offers some other important features. A DistanceFactor ivar is
// used to decide when two lines are too far apart to connect. (The factor is
// a multiple of the distance between the first two points of the two lines
// defining the strip.) If the distance between the two generating lines
// becomes too great, then the surface is not generated in that
// region. (Note: if the lines separate and then merge, then a hole can be
// generated in the surface.) In addition, the Offset and OnRation ivars can
// be used to create nifty striped surfaces. Closed surfaces (e.g., tubes) can
// be created by setting the CloseSurface ivar. (The surface can be closed
// in the other direction by repeating the first and last point in the
// polylines defining the surface.)
//
// An important use of this filter is to combine it with vtkStreamLine to
// generate stream surfaces. It can also be used to create surfaces from
// contours.

// .SECTION Caveats
// The number of lines must be greater than two if a surface is to be
// generated.  sides (i.e., a ribbon), use vtkRibbonFilter.

// .SECTION See Also
// vtkRibbonFilter vtkStreamLine

#ifndef __vtkLoopsMesher_h
#define __vtkLoopsMesher_h

#include "vtkCMBMeshingModule.h" // For export macro
#include "vtkPolyDataAlgorithm.h"
#include "cmbSystemConfig.h"

class vtkIdList;
class vtkPoints;
class vtkPolyData;

#define VTK_RULED_MODE_RESAMPLE 0
#define VTK_RULED_MODE_POINT_WALK 1

class VTKCMBMESHING_EXPORT vtkLoopsMesher : public vtkPolyDataAlgorithm
{
public:
  vtkTypeMacro(vtkLoopsMesher,vtkPolyDataAlgorithm);
  void PrintSelf(ostream& os, vtkIndent indent) override;

  // Description:
  // Construct object with OnRatio=1, Offset=0. DistanceFactor=3.0,
  // CloseSurface off, and PassLines off.
  static vtkLoopsMesher *New();

  // Description:
  // Indicate whether to use multiple loops to help reduce
  // "broomsticking".
  vtkSetMacro(UseSubLoops,int);
  vtkGetMacro(UseSubLoops,int);
  vtkBooleanMacro(UseSubLoops,int);

  // Description:
  // Indicate whether the resuling mesh should be quads if possible.
  // This only used if the loops contain the same number of points.
  vtkSetMacro(UseQuads,int);
  vtkGetMacro(UseQuads,int);
  vtkBooleanMacro(UseQuads,int);

  // Description:
  // Indicate whether the generating lines are to be passed to the output.
  // By defualt lines are not passed to the output.
  vtkSetMacro(PassLines,int);
  vtkGetMacro(PassLines,int);
  vtkBooleanMacro(PassLines,int);

  // Description:
  // Indicate whether the starting points of the loops need to be determined.
  // If set to 0, then its assumes that the 0th point of each loop should be
  // always connected
  // By defualt the loops are not oriented.
  vtkSetMacro(OrientLoops,int);
  vtkGetMacro(OrientLoops,int);
  vtkBooleanMacro(OrientLoops,int);

protected:
  vtkLoopsMesher();
  ~vtkLoopsMesher() override;

  // Usual data generation method
  int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *) override;
  int   UseQuads;
  int   UseSubLoops;
  int   PassLines;
  int   OrientLoops;

private:
  vtkIdList *Ids;
  double     Weights[4];

  void  PointWalk(vtkPolyData *output, vtkPoints *inPts,
                  int npts, vtkIdType *pts, int npts2, vtkIdType *pts2);

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

#endif
