Subversion Repositories public iLand

Rev

Rev 1221 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/********************************************************************************************
**    iLand - an individual based forest landscape and disturbance model
**    http://iland.boku.ac.at
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
**
**    This program is free software: you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation, either version 3 of the License, or
**    (at your option) any later version.
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
********************************************************************************************/


#ifndef SCRIPTGLOBAL_H
#define SCRIPTGLOBAL_H

#include <QObject>
#include <QVariant>
#include <QJSValue>

// Scripting Interface for MapGrid
class MapGrid; // forward
class MapGridWrapper: public QObject
{
    Q_OBJECT
    Q_PROPERTY(int valid READ isValid)
    Q_PROPERTY(QString name READ name)
public:
    MapGridWrapper(QObject *parent=0);
    ~MapGridWrapper();
    static void addToScriptEngine(QJSEngine &engine);
    MapGrid *map() const { return mMap; } ///< acccess for C++ classes
    bool isValid() const; ///< returns true if map is successfully loaded
    QString name() const;
    //

public slots:
    // query
    double area(int id); ///< retrieve the area (m2) of the polygon denoted by 'id'
    // actions
    void load(QString file_name);
    void saveAsImage(QString file);
    void paint(double min_value, double max_value);
    // active modifications of the map
    void clear(); ///< clears the map (set all values to 0)
    void clearProjectArea(); ///< clear the project area (set to 0), but copy mask with pixels from "outside of project area" (i.e., -1, -2)
    /// paint a shape on the stand grid with id stand_id
    /// paint_function is a valid expression (paramters: x, y as *metric* coordinates)
    /// if wrap_around=true, then the shape is wrapped around the edges of the simulated area (torus)
    void createStand(int stand_id, QString paint_function, bool wrap_around);

    /// copy a bit of the source-map 'source' to this map. The
    /// source rectangle is given by coordinates (x1/y1) to (x2/y2).
    /// The rectangle will be blitted to the new coordinates destx/desty (moved from x1/y1).
    /// id_in: the id of the polygon to copy, id: the id of the pixels in the target
    /// return the size (ha) of the valid thing
    double copyPolygonFromRect(MapGridWrapper *source, int id_in, int id, double destx, double desty, double x1, double y1, double x2, double y2);

    void createMapIndex(); ///< call after creating stands with copyPolygonFromRect

private:
    MapGrid *mMap;
    bool mCreated;

};

/** ScriptGlobal contains a set of
  functions and properties that are accessible by JavaScript.
  */

class Model;
class ScriptGlobal : public QObject
{
    Q_OBJECT
    // read only properties
    Q_PROPERTY(int year READ year)
    Q_PROPERTY(int resourceUnitCount READ resourceUnitCount)
    Q_PROPERTY(QString currentDir WRITE setCurrentDir READ currentDir)
    Q_PROPERTY(double worldX READ worldX)
    Q_PROPERTY(double worldY READ worldY)
    Q_PROPERTY(bool qt5 READ qt5)
    Q_PROPERTY(int msec READ msec)
    Q_PROPERTY(QJSValue viewOptions READ viewOptions WRITE setViewOptions)


public:
    ScriptGlobal(QObject *parent=0);
    static void setupGlobalScripting();
    // properties accesible by scripts
    bool qt5() const {return true; } ///< is this the qt5-model? (changes in script object creation)
    int msec() const; ///< the milliseconds since the start of the day
    int year() const; ///< current year in the model
    int resourceUnitCount() const; ///< get number of resource uinit
    QString currentDir() const { return mCurrentDir; } ///< current execution directory (default is the Script execution directory)
    void setCurrentDir(QString newDir) { mCurrentDir = newDir; } ///< set current working dir
    double worldX(); ///< extent of the world (without buffer) in meters (x-direction)
    double worldY(); ///< extent of the world (without buffer) in meters (y-direction)

    // general functions
    static void loadScript(const QString &fileName);
    static QString executeScript(QString cmd);
    static QString executeJSFunction(QString function);
    static QObject *scriptOutput; ///< public "pipe" for script output (is redirected to GUI if available)
    static QString formattedErrorMessage(const QJSValue &error_value, const QString &sourcecode);

    // view options
    /* View options:
     * * type: {...}
     * * species: bool
     * * shade: bool
     *
    */

    QJSValue viewOptions(); ///< retrieve current viewing options (JS - object)
    void setViewOptions(QJSValue opts); ///< set current view options

public slots:
    // system stuff
    QVariant setting(QString key); ///< get a value from the global xml-settings (returns undefined if not present)
    void set(QString key, QString value); ///< set the value of a setting
    void print(QString message); ///< print the contents of the message to the log
    void alert(QString message); ///< shows a message box to the user (if in GUI mode)
    void include(QString filename); ///< "include" the given script file and evaluate. The path is relative to the "script" path
    // file stuff
    QString defaultDirectory(QString dir); ///< get default directory of category 'dir'
    QString path(QString filename); ///< get a path relative to the project main folder
    QString loadTextFile(QString fileName); ///< load content from a text file in a String (@sa CSVFile)
    void saveTextFile(QString fileName, QString content); ///< save string (@p content) to a text file.
    bool fileExists(QString fileName); ///< return true if the given file exists.
    void systemCmd(QString command); ///< execute system command (e.g., copy files)
    // add trees
    int addSingleTrees(const int resourceIndex, QString content); ///< add single trees
    int addTrees(const int resourceIndex, QString content); ///< add tree distribution
    int addTreesOnMap(const int standID, QString content); ///< add trees (distribution mode) for stand 'standID'
    // add saplings
    int addSaplingsOnMap(MapGridWrapper *map, const int mapID, QString species, int px_per_hectare, double height, int age);
    // enable/disable outputs
    bool startOutput(QString table_name); ///< starts output 'table_name'. return true if successful
    bool stopOutput(QString table_name); ///< stops output 'table_name'. return true if successful
    // miscellaneous stuff
    void setViewport(double x, double y, double scale_px_per_m); ///< set the viewport of the main project area view
    bool screenshot(QString file_name); ///< make a screenshot from the central viewing widget
    void repaint(); ///< force a repainting of the GUI visualization (if available)
    bool gridToFile(QString grid_type, QString file_name); ///< create a "ESRI-grid" text file 'grid_type' is one of a fixed list of names, 'file_name' the ouptut file location

    /// return Javascript grid for given type
    QJSValue grid(QString type);
    /// return a grid with the basal area of the given species (resource unit resolution)
    QJSValue speciesShareGrid(QString species);
    /// return a grid (level of resource units) with the result of an expression evaluated in the context of the resource unit.
    QJSValue resourceUnitGrid(QString expression);

    // DOES NOT FULLY WORK
    bool seedMapToFile(QString species, QString file_name); ///< save the "seedmap" (i.e. a grid showing the seed distribution) as ESRI rastser file
    void wait(int milliseconds); ///< wait for 'milliseconds' or (if ms=-1 until a key is pressed)
    // vegetation snapshots
    bool saveModelSnapshot(QString file_name);
    bool loadModelSnapshot(QString file_name);
    bool saveStandSnapshot(int stand_id, QString file_name);
    bool loadStandSnapshot(int stand_id, QString file_name);
    // agent-based-model of forest management
    void reloadABE();

    // UI interface
    void setUIshortcuts(QJSValue shortcuts); ///< set a list of JS shortcuts in the UI

    void test_tree_mortality(double thresh, int years, double p_death);
private:
    void throwError(const QString &errormessage);
    QString mCurrentDir;
    Model *mModel;
};

/** The ScriptObjectFactory can instantiate objects of other C++ (QObject-based) types.
 *  This factory approach is used because the V8 (QJSEngine) does not work with
 *  the "new" way of creating objects.
*/

class ScriptObjectFactory: public QObject
{
    Q_OBJECT
public:
    ScriptObjectFactory(QObject *parent=0);
public slots:
    QJSValue newCSVFile(QString filename); ///< create a new instance of CSVFile and return it
    QJSValue newClimateConverter(); ///< create new instance of ClimateConverter and return it
    QJSValue newMap(); ///< create new instance of Map and return it
    int stats() {return mObjCreated;} ///< return the number of created objects
private:
    int mObjCreated;

};

#endif // SCRIPTGLOBAL_H