#ifndef POINTGRID3D_H
#define POINTGRID3D_H

#include <vector>
using namespace std;

#include <point.h>
#include <print.h>

/**
\brief A rectangular array of 3D points.

A vector of points uniformily covers the square from the
 bottom up.  x is the axis with the columns. The second axis
 has the rows. 

At construction time the second axis for the surface is choosen.
 A range can be given which does away with the unit square.  The 
 range bounds do include the end points. 

When constructed the surface x-y values or 
 surface x-z are calculated.

The height or surface value is not calculated.  Here is an example
 where a functional object was used.
\verbatim
#include <mathlib.h>
#include <func2dovervec3d.h>
...
  pointgrid3D g(5,4,-1.0,3.0,-1.0,3.0,true);
  tempsin2 f2;

  // Apply the function with the surface as input.
  func2Dovervec3D< point3<double> >(g.pt,g.M*g.N).evalY(f2);
\endverbatim
*/
class pointgrid3D
{
public:

  /** The number of rows. */
  uintc M;
  /** The number of columns. */
  uintc N;

  /** Sequence interpreted as a matrix from the bottom up. */
  point3<double> * pt;

  /** Access the i'th column and j'th row. */
  point3<double> const & pij(uintc i, uintc j) const
    { return pt[i+j*N]; }

  /** Construct evenly sampled points in x and y axes including 
      0.0 and 1.0. */
  pointgrid3D(uintc M_, uintc N_);

  /** Construct evenly sampled points in x and y axes 
      along [x0,x1] and [y0,y1]. */
  pointgrid3D
  (
    uintc M_, 
    uintc N_, 
    doublec x0,
    doublec x1,
    doublec y0,
    doublec y1
  );

  /** Construct evenly sampled points in x and z axes along 
      [x0,x1] and [z0,z1]. */
  pointgrid3D
  (
    uintc M_, 
    uintc N_, 
    doublec x0,
    doublec x1,
    doublec z0,
    doublec z1,
    bool const xzsurface
  );

  /** Write out the grid as indexed triangles. 
      Copies the points from pts to points. */
  void createIndexedTriangles
  (
    vector< point3<double> > & points,
    vector< point3<uint> > & vi
  ) const;

  template< typename T >
  void createIndexedTrianglesT( T & x ) const 
    { createIndexedTriangles(x.points,x.vi); } 

  /** Memory cleanup. */
  ~pointgrid3D();
};


#endif


