#ifndef qwt3d_SurfacePlot_h
#define qwt3d_SurfacePlot_h

#include "qwt3d_plot.h"

namespace Qwt3D {
//! A class representing  Surfaces
/**
        A SurfacePlot ...

*/
class QWT3D_EXPORT SurfacePlot : public Plot3D
{
    Q_OBJECT

public:
    SurfacePlot(QWidget *parent = 0);
    ~SurfacePlot();
    void updateNormals(); //!< Recalculates surface normals;
    int resolution() const { return resolution_p; } //!< Returns data resolution (1 means all data)
    std::pair<int, int> facets() const; //!< Returns the number of mesh cells for the ORIGINAL data
    bool loadFromData(Qwt3D::Triple **data, unsigned int columns, unsigned int rows,
                      bool uperiodic = false, bool vperiodic = false);
    bool loadFromData(double **data, unsigned int columns, unsigned int rows, double minx,
                      double maxx, double miny, double maxy);
    bool loadFromData(Qwt3D::TripleField const &data, Qwt3D::CellField const &poly);

    //! Equivalent to loadFromData();
    /**
    \deprecated  Use loadFromData instead
    */
    bool createDataRepresentation(Qwt3D::Triple **data, unsigned int columns, unsigned int rows,
                                  bool uperiodic = false, bool vperiodic = false)
    {
        return loadFromData(data, columns, rows, uperiodic, vperiodic);
    }
    //! Equivalent to loadFromData();
    /**
    \deprecated  Use loadFromData instead
    */
    bool createDataRepresentation(double **data, unsigned int columns, unsigned int rows,
                                  double minx, double maxx, double miny, double maxy)
    {
        return loadFromData(data, columns, rows, minx, maxx, miny, maxy);
    }
    //! Equivalent to loadFromData();
    /**
    \deprecated  Use loadFromData instead
    */
    bool createDataRepresentation(Qwt3D::TripleField const &data, Qwt3D::CellField const &poly)
    {
        return loadFromData(data, poly);
    }

    Qwt3D::FLOORSTYLE floorStyle() const { return floorstyle_; } //!< Return floor style
    void setFloorStyle(Qwt3D::FLOORSTYLE val) { floorstyle_ = val; } //!< Sets floor style
    void showNormals(bool); //!< Draw normals to every vertex
    bool normals() const { return datanormals_p; } //!< Returns \c true, if normal drawing is on

    void setNormalLength(double val); //!< Sets length of normals in percent per hull diagonale
    double normalLength() const { return normalLength_p; } //!< Returns relative length of normals
    void setNormalQuality(int val); //!< Increases plotting quality of normal arrows
    int normalQuality() const
    {
        return normalQuality_p;
    } //!< Returns plotting quality of normal arrows

Q_SIGNALS:
    void resolutionChanged(int);

public Q_SLOTS:
    void setResolution(int);

protected:
    bool datanormals_p;
    double normalLength_p;
    int normalQuality_p;

    virtual void calculateHull();
    virtual void createData();
    virtual void createEnrichment(Qwt3D::Enrichment &p);
    virtual void createFloorData();
    void createNormals();
    void createPoints();

    int resolution_p;

    void readIn(Qwt3D::GridData &gdata, Triple **data, unsigned int columns, unsigned int rows);
    void readIn(Qwt3D::GridData &gdata, double **data, unsigned int columns, unsigned int rows,
                double minx, double maxx, double miny, double maxy);
    void calcNormals(GridData &gdata);
    void sewPeriodic(GridData &gdata);

    // void calcLowResolution();
private:
    void Data2Floor();
    void Isolines2Floor();

    Qwt3D::FLOORSTYLE floorstyle_;

    // grid plot

    Qwt3D::GridData *actualDataG_;
    virtual void createDataG();
    virtual void createFloorDataG();
    void createNormalsG();
    void Data2FloorG();
    void Isolines2FloorG();
    void setColorFromVertexG(int ix, int iy, bool skip = false);

    // mesh plot

    Qwt3D::CellData *actualDataC_;
    virtual void createDataC();
    virtual void createFloorDataC();
    void createNormalsC();
    void Data2FloorC();
    void Isolines2FloorC();
    void setColorFromVertexC(int node, bool skip = false);
};

} // ns

#endif
