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/>.
********************************************************************************************/

#include "scriptgrid.h"
#include "globalsettings.h"
#include "helper.h"
#include "expression.h"
#include "modelcontroller.h"
#include "mapgrid.h"


#include <QJSEngine>
#include <QJSValueIterator>

int ScriptGrid::mDeleted = 0;
int ScriptGrid::mCreated = 0;

ScriptGrid::ScriptGrid(QObject *parent) : QObject(parent)
{
    mGrid = 0;
    mVariableName = "x"; // default name
    mCreated++;
}

ScriptGrid::~ScriptGrid()
{
    if (mGrid)
        delete mGrid;
    mDeleted++;
    qDebug() << "ScriptGrid::balance: created:" << mCreated << "deleted:" << mDeleted;
}

// create a ScriptGrid-Wrapper around "grid". Note: destructing the 'grid' is done via the JS-garbage-collector.
QJSValue ScriptGrid::createGrid(Grid<double> *grid, QString name)
{
    ScriptGrid *g = new ScriptGrid(grid);
    if (!name.isEmpty())
        g->setName(name);
    QJSValue jsgrid = GlobalSettings::instance()->scriptEngine()->newQObject(g);
    return jsgrid;
}

QJSValue ScriptGrid::copy()
{
    if (!mGrid)
        return QJSValue();

    ScriptGrid *newgrid = new ScriptGrid();
    // copy the data
    Grid<double> *copy_grid = new Grid<double>(*mGrid);
    newgrid->setGrid(copy_grid);

    QJSValue jsgrid = GlobalSettings::instance()->scriptEngine()->newQObject(newgrid);
    return jsgrid;
}

void ScriptGrid::clear()
{
    if (mGrid && !mGrid->isEmpty())
        mGrid->wipe();
}

void ScriptGrid::paint(double min_val, double max_val)
{
    //if (GlobalSettings::instance()->controller())
    //    GlobalSettings::instance()->controller()->addGrid(mGrid, mVariableName, GridViewRainbow, min_val, max_val);
}

QString ScriptGrid::info()
{
    if (!mGrid || mGrid->isEmpty())
        return QString("not valid / empty.");
    return QString("grid-dimensions: %1/%2 (cellsize: %5, N cells: %3), grid-name='%4'").arg(mGrid->sizeX()).arg(mGrid->sizeY()).arg(mGrid->count()).arg(mVariableName).arg(mGrid->cellsize());
}

void ScriptGrid::save(QString fileName)
{
    if (!mGrid || mGrid->isEmpty())
        return;
    fileName = GlobalSettings::instance()->path(fileName);
    QString result = gridToESRIRaster(*mGrid);
    Helper::saveToTextFile(fileName, result);
    qDebug() << "saved grid " << name() << " to " << fileName;
}

bool ScriptGrid::load(QString fileName)
{
    fileName = GlobalSettings::instance()->path(fileName);
    // load the grid from file
    MapGrid mg(fileName, false);
    if (!mg.isValid()) {
        qDebug() << "ScriptGrid::load(): load not successful of file:" << fileName;
        return false;
    }
    if (mGrid) {
        delete mGrid;
    }
    mGrid = mg.grid().toDouble(); // create a copy of the mapgrid-grid
    mVariableName = QFileInfo(fileName).baseName();
    return !mGrid->isEmpty();

}

void ScriptGrid::apply(QString expression)
{
    if (!mGrid || mGrid->isEmpty())
        return;

    Expression expr;
    double *varptr = expr.addVar(mVariableName);
    try {
        expr.setExpression(expression);
        expr.parse();
    } catch(const IException &e) {
        qDebug() << "JS - grid:apply(): ERROR: " << e.message();
        return;
    }

    // now apply function on grid
    for (double *p = mGrid->begin(); p!=mGrid->end(); ++p) {
        *varptr = *p;
        *p = expr.execute();
    }

}

void ScriptGrid::combine(QString expression, QJSValue grid_object)
{
    if (!grid_object.isObject()) {
        qDebug() << "ERROR: ScriptGrid::combine(): no valid grids object" << grid_object.toString();
        return;
    }
    QVector< Grid<double>* > grids;
    QStringList names;
    QJSValueIterator it(grid_object);
    while (it.hasNext()) {
        it.next();
        names.push_back(it.name());
        QObject *o = it.value().toQObject();
        if (o && qobject_cast<ScriptGrid*>(o)) {
            grids.push_back(qobject_cast<ScriptGrid*>(o)->grid());
            if (grids.last()->isEmpty() || grids.last()->cellsize() != mGrid->cellsize() || grids.last()->rectangle()!=mGrid->rectangle()) {
                qDebug() << "ERROR: ScriptGrid::combine(): the grid " << it.name() << "is empty or has different dimensions:" << qobject_cast<ScriptGrid*>(o)->info();
                return;
            }
        } else {
            qDebug() << "ERROR: ScriptGrid::combine(): no valid grid object with name:" << it.name();
            return;
        }
    }
    // now add names
    Expression expr;
    QVector<double *> vars;
    for (int i=0;i<names.count();++i)
        vars.push_back( expr.addVar(names[i]) );
    try {
        expr.setExpression(expression);
        expr.parse();
    } catch(const IException &e) {
        qDebug() << "JS - grid:combine(): expression ERROR: " << e.message();
        return;
    }

    // now apply function on grid
    for (int i=0;i<mGrid->count();++i) {
        // set variable values in the expression object
        for (int v=0;v<names.count();++v)
            *vars[v] = grids[v]->valueAtIndex(i);
        double result = expr.execute();
        mGrid->valueAtIndex(i) = result; // write back value
    }
}

double ScriptGrid::sum(QString expression)
{
    if (!mGrid || mGrid->isEmpty())
        return -1.;

    Expression expr;
    double *varptr = expr.addVar(mVariableName);
    try {
        expr.setExpression(expression);
        expr.parse();
    } catch(const IException &e) {
        qDebug() << "JS - grid:apply(): ERROR: " << e.message();
        return -1.;
    }

    // now apply function on grid
    double sum = 0.;
    for (double *p = mGrid->begin(); p!=mGrid->end(); ++p) {
        *varptr = *p;
        sum += expr.execute();
    }
    return sum;
}