~showard314/ubuntu/natty/qtiplot/Python2.7_fix

« back to all changes in this revision

Viewing changes to qtiplot/src/MatrixModel.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fathi Boudra
  • Date: 2008-04-04 15:11:55 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20080404151155-rjp12ziov4tryj0o
Tags: 0.9.4-1
* New upstream release.
* Refresh patches.
* Remove 04_homepage_url patch. Merged upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
 *                                                                         *
28
28
 ***************************************************************************/
29
29
#include <QtGui>
 
30
#include <QFile>
 
31
#include <QTextStream>
30
32
 
31
33
#include "Matrix.h"
32
34
#include "MatrixModel.h"
 
35
#include "MatrixCommand.h"
 
36
#include "muParserScript.h"
 
37
#include "ScriptingEnv.h"
 
38
#include "analysis/fft2D.h"
 
39
 
33
40
#include <gsl/gsl_math.h>
 
41
#include <gsl/gsl_linalg.h>
 
42
#include <gsl/gsl_errno.h>
 
43
 
34
44
#include <qwt_color_map.h>
 
45
#include <stdlib.h>
35
46
 
36
47
MatrixModel::MatrixModel(int rows, int cols, QObject *parent)
37
48
     : QAbstractTableModel(parent),
38
 
         d_matrix((Matrix*)parent),
39
 
     d_rows(rows),
40
 
     d_cols(cols),
41
 
         d_data(d_rows*d_cols, GSL_NAN)
 
49
         d_matrix((Matrix*)parent)
42
50
{
 
51
        init();
 
52
        
 
53
        if (d_matrix){
 
54
                d_txt_format = d_matrix->textFormat().toAscii();
 
55
                d_num_precision = d_matrix->precision();
 
56
                d_locale = d_matrix->locale();
 
57
        }
 
58
 
 
59
        if (canResize(rows, cols)){
 
60
                d_rows = rows;
 
61
                d_cols = cols;
 
62
                int cell = 0;
 
63
                int size = rows*cols;
 
64
                for (int i = 0; i < size; i++)
 
65
            d_data[cell++] = GSL_NAN;
 
66
        }
43
67
}
44
68
 
45
69
MatrixModel::MatrixModel(const QImage& image, QObject *parent)
46
70
     : QAbstractTableModel(parent),
47
71
         d_matrix((Matrix*)parent)
48
72
{
 
73
        init();
 
74
    setImage(image);
 
75
}
 
76
 
 
77
void MatrixModel::init()
 
78
{
 
79
        d_txt_format = 'g';
 
80
        d_num_precision = 6;
 
81
        d_locale = QLocale();
 
82
        d_direct_matrix = NULL;
 
83
        d_inv_matrix = NULL;
 
84
        d_inv_perm = NULL;
 
85
        
 
86
        d_rows = 1;
 
87
        d_cols = 1;
 
88
        d_data_block_size = QSize(1, 1);
 
89
        d_data = (double *)malloc(sizeof(double));
 
90
}
 
91
 
 
92
void MatrixModel::setImage(const QImage& image)
 
93
{
 
94
        if (!canResize(image.height(), image.width()))
 
95
                return;
 
96
 
49
97
    d_rows = image.height();
50
98
    d_cols = image.width();
51
 
    d_data.resize(d_rows*d_cols);
52
 
 
 
99
        int cell = 0;
53
100
    for (int i=0; i<d_rows; i++ ){
54
 
                for (int j=0; j<d_cols; j++){
55
 
                    int index = i*d_cols + j;
56
 
            d_data[index] = qGray(image.pixel (j, i));
57
 
                }
 
101
                for (int j=0; j<d_cols; j++)
 
102
            d_data[cell++] = qGray(image.pixel (j, i));
58
103
    }
59
104
}
60
105
 
76
121
    return d_cols;
77
122
}
78
123
 
 
124
void MatrixModel::setRowCount(int rows)
 
125
{
 
126
        if (d_rows == rows)
 
127
                return;
 
128
 
 
129
   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
130
 
 
131
        if (rows > d_rows )
 
132
                insertRows(d_rows, rows - d_rows);
 
133
    else if (rows < d_rows )
 
134
                removeRows(rows, d_rows - rows);
 
135
 
 
136
        QApplication::restoreOverrideCursor();
 
137
}
 
138
 
 
139
void MatrixModel::setColumnCount(int cols)
 
140
{
 
141
        if (d_cols == cols)
 
142
                return;
 
143
 
 
144
   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
145
 
 
146
        if (cols > d_cols )
 
147
                insertColumns(d_cols, cols - d_cols);
 
148
    else if (cols < d_cols )
 
149
                removeColumns(cols, d_cols - cols);
 
150
 
 
151
        QApplication::restoreOverrideCursor();
 
152
}
 
153
 
 
154
void MatrixModel::setDimensions(int rows, int cols)
 
155
{
 
156
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
157
 
 
158
        if (rows < d_rows){//first remove rows (faster)
 
159
                removeRows(rows, d_rows - rows);
 
160
                setColumnCount(cols);
 
161
        } else {
 
162
                setColumnCount(cols);
 
163
                if (rows > d_rows )
 
164
                        insertRows(d_rows, rows - d_rows);
 
165
        }
 
166
 
 
167
        QApplication::restoreOverrideCursor();
 
168
}
 
169
 
79
170
double MatrixModel::cell(int row, int col)
80
171
{
81
172
    int i = d_cols*row + col;
82
 
    if (i < 0 || i>= d_data.size() || gsl_isnan (d_data[i]))
 
173
    double val = d_data[i];
 
174
    if (i < 0 || i>= d_rows*d_cols || gsl_isnan (val))
83
175
        return 0.0;
84
176
 
85
 
        return d_data[i];
 
177
        return val;
86
178
}
87
179
 
88
180
void MatrixModel::setCell(int row, int col, double val)
89
181
{
90
182
        int i = d_cols*row + col;
91
 
    if (i < 0 || i>= d_data.size())
 
183
    if (i < 0 || i>= d_rows*d_cols)
92
184
                return;
93
185
 
94
186
    d_data[i] = val;
97
189
QString MatrixModel::text(int row, int col)
98
190
{
99
191
        int i = d_cols*row + col;
100
 
    if (i < 0 || i>= d_data.size() || gsl_isnan (d_data[i]))
 
192
        double val = d_data[i];
 
193
    if (i < 0 || i>= d_rows*d_cols || gsl_isnan(val))
101
194
        return "";
102
195
 
103
 
        QLocale locale = d_matrix->locale();
104
 
        return locale.toString(d_data[i], d_matrix->textFormat().toAscii(), d_matrix->precision());
 
196
        if (d_matrix){
 
197
                QLocale locale = d_matrix->locale();
 
198
                return locale.toString(val, d_matrix->textFormat().toAscii(), d_matrix->precision());
 
199
        }
 
200
        return d_locale.toString(val, d_txt_format, d_num_precision);
105
201
}
106
202
 
107
203
void MatrixModel::setText(int row, int col, const QString& text)
108
204
{
109
205
        int i = d_cols*row + col;
110
 
    if (i < 0 || i>= d_data.size())
 
206
    if (i < 0 || i>= d_rows*d_cols)
111
207
                return;
112
208
 
113
209
        if (text.isEmpty())
114
210
                d_data[i] = GSL_NAN;
115
 
        else
116
 
                d_data[i] = text.toDouble();
 
211
        else {
 
212
                if (d_matrix)
 
213
                        d_data[i] = d_matrix->locale().toDouble(text);
 
214
                else
 
215
                        d_data[i] = d_locale.toDouble(text);
 
216
        }
117
217
}
118
218
 
119
219
double MatrixModel::data(int row, int col) const
120
220
{
121
221
    int i = d_cols*row + col;
122
 
    if (i < 0 || i>= d_data.size())
 
222
    if (i < 0 || i>= d_rows*d_cols)
123
223
        return 0.0;
124
224
 
125
225
        return d_data[i];
126
226
}
127
227
 
 
228
double MatrixModel::x(int col) const
 
229
{
 
230
        if (col < 0 || col >= d_cols)
 
231
        return 0.0;
 
232
 
 
233
        double start = d_matrix->xStart();
 
234
        double end = d_matrix->xEnd();
 
235
        if (start < end)
 
236
                return start + col*d_matrix->dx();
 
237
        else
 
238
                return start - col*d_matrix->dx();
 
239
 
 
240
        return 0.0;
 
241
}
 
242
 
 
243
double MatrixModel::y(int row) const
 
244
{
 
245
        if (row < 0 || row >= d_rows)
 
246
        return 0.0;
 
247
 
 
248
        double start = d_matrix->yStart();
 
249
        double end = d_matrix->yEnd();
 
250
        if (start < end)
 
251
                return start + row*d_matrix->dy();
 
252
        else
 
253
                return start - row*d_matrix->dy();
 
254
 
 
255
        return 0.0;
 
256
}
 
257
 
128
258
QVariant MatrixModel::headerData ( int section, Qt::Orientation orientation, int role) const
129
259
{
130
 
    if (d_matrix->headerViewType() == Matrix::ColumnRow)
 
260
    if (!d_matrix || d_matrix->headerViewType() == Matrix::ColumnRow)
131
261
        return QAbstractItemModel::headerData(section, orientation, role);
132
262
 
133
 
    QLocale locale = d_matrix->locale();
 
263
    QLocale locale = d_locale;
 
264
        int prec = d_num_precision;
 
265
        char fmt = d_txt_format;
 
266
        if (d_matrix){
 
267
                locale = d_matrix->locale();
 
268
                fmt = d_matrix->textFormat().toAscii();
 
269
                prec = d_matrix->precision();
 
270
        }
 
271
 
134
272
    if (role == Qt::DisplayRole || role == Qt::EditRole){
135
273
        if (orientation == Qt::Horizontal){
136
274
            double start = d_matrix->xStart();
137
275
            double end = d_matrix->xEnd();
138
276
            double dx = d_matrix->dx();
139
277
            if (start < end)
140
 
                return QVariant(locale.toString(start + section*dx, d_matrix->textFormat().toAscii(), d_matrix->precision()));
 
278
                return QVariant(locale.toString(start + section*dx, fmt, prec));
141
279
            else
142
 
                return QVariant(locale.toString(start - section*dx, d_matrix->textFormat().toAscii(), d_matrix->precision()));
 
280
                return QVariant(locale.toString(start - section*dx, fmt, prec));
143
281
        } else if (orientation == Qt::Vertical){
144
282
            double start = d_matrix->yStart();
145
283
            double end = d_matrix->yEnd();
146
284
            double dy = d_matrix->dy();
147
285
            if (start < end)
148
 
                return QVariant(locale.toString(start + section*dy, d_matrix->textFormat().toAscii(), d_matrix->precision()));
 
286
                return QVariant(locale.toString(start + section*dy, fmt, prec));
149
287
            else
150
 
                return QVariant(locale.toString(start - section*dy, d_matrix->textFormat().toAscii(), d_matrix->precision()));
 
288
                return QVariant(locale.toString(start - section*dy, fmt, prec));
151
289
        }
152
 
    } else
153
 
        return QAbstractItemModel::headerData(section, orientation, role);
 
290
    }
 
291
        return QAbstractItemModel::headerData(section, orientation, role);
154
292
}
155
293
 
156
294
QVariant MatrixModel::data(const QModelIndex &index, int role) const
159
297
                return QVariant();
160
298
 
161
299
    int i = d_cols*index.row() + index.column();
162
 
    if (gsl_isnan (d_data[i]))
 
300
        double val = d_data[i];
 
301
    if (gsl_isnan (val))
163
302
        return QVariant();
164
303
 
165
304
        if (role == Qt::DisplayRole || role == Qt::EditRole){
166
 
                QLocale locale = d_matrix->locale();
167
 
                return QVariant(locale.toString(d_data[i], d_matrix->textFormat().toAscii(), d_matrix->precision()));
168
 
        }else
 
305
                if (d_matrix)
 
306
                        return QVariant(d_matrix->locale().toString(val, d_matrix->textFormat().toAscii(), d_matrix->precision()));
 
307
                else
 
308
                        return QVariant(d_locale.toString(val, d_txt_format, d_num_precision));
 
309
        } else
169
310
                return QVariant();
170
311
}
171
312
 
175
316
                return false;
176
317
 
177
318
        int i = d_cols*index.row() + index.column();
 
319
        double valBefore = d_data[i];
178
320
        if(role == Qt::EditRole){
179
321
                if (value.toString().isEmpty())
180
322
                        d_data[i] = GSL_NAN;
187
329
                d_matrix->resetView();
188
330
        }
189
331
 
 
332
    d_matrix->undoStack()->push(new MatrixEditCellCommand(this, index, valBefore, d_data[i],
 
333
                                tr("Edited cell") + " (" + QString::number(index.row() + 1) + "," +
 
334
                                QString::number(index.column() + 1) + ")"));
 
335
    d_matrix->notifyChanges();
190
336
        d_matrix->moveCell(index);
191
337
        return false;
192
338
}
193
339
 
 
340
bool MatrixModel::canResize(int rows, int cols)
 
341
{
 
342
        if (rows <= 0 || cols <= 0 || INT_MAX/rows < cols){ //avoid integer overflow
 
343
                QApplication::restoreOverrideCursor();
 
344
        QMessageBox::critical(d_matrix, tr("QtiPlot") + " - " + tr("Input Size Error"),
 
345
        tr("The dimensions you have specified are not acceptable!") + "\n" +
 
346
                tr("Please enter positive values for which the product rows*columns does not exceed the maximum integer value available on your system!"));
 
347
                return false;
 
348
        }
 
349
        
 
350
    if (d_data_block_size.width()*d_data_block_size.height() >= rows*cols)
 
351
                return true;
 
352
 
 
353
    double *new_data = (double *)realloc(d_data, rows*cols*sizeof(double));
 
354
    if (new_data){
 
355
        d_data = new_data;
 
356
                d_data_block_size = QSize(rows, cols);
 
357
        return true;
 
358
    }
 
359
 
 
360
    QApplication::restoreOverrideCursor();
 
361
    QMessageBox::critical(d_matrix, tr("QtiPlot") + " - " + tr("Memory Allocation Error"),
 
362
    tr("Not enough memory, operation aborted!"));
 
363
    return false;
 
364
}
 
365
 
194
366
bool MatrixModel::removeColumns(int column, int count, const QModelIndex & parent)
195
367
{
196
368
        beginRemoveColumns(parent, column, column + count - 1);
197
369
 
198
 
        int new_cols = d_cols - count;
199
 
        QVector <double> d_data_new(d_rows*new_cols);
200
 
        for (int i=0; i <d_rows; i++){
201
 
                int aux1 = d_cols * i;
202
 
                int aux2 = new_cols * i;
203
 
                for (int j=0; j < column; j++)
204
 
                        d_data_new[aux2 + j] = d_data[aux1 + j];
 
370
    d_cols -= count;
 
371
        d_data_block_size = QSize(d_rows, d_cols);
205
372
 
206
 
                aux1 += count;
207
 
                for (int j = column; j < new_cols; j++)
208
 
                        d_data_new[aux2 + j] = d_data[aux1 + j];
 
373
    int size = d_rows*d_cols;
 
374
    for (int i = column; i < size; i++){
 
375
            int aux = (i - column)/d_cols + 1;
 
376
        d_data[i] = d_data[i + aux*count];
209
377
        }
210
378
 
211
 
        d_data.resize(0);
212
 
        d_data = d_data_new;
213
 
        d_cols = new_cols;
 
379
    d_data = (double *)realloc (d_data, size*sizeof(double));
214
380
 
215
381
        endRemoveColumns();
216
382
        return true;
218
384
 
219
385
bool MatrixModel::insertColumns(int column, int count, const QModelIndex & parent)
220
386
{
 
387
    if (!canResize(d_rows, d_cols + count))
 
388
        return false;
 
389
 
221
390
        beginInsertColumns(parent, column, column + count - 1);
222
391
 
223
 
        int new_cols = d_cols + count;
224
 
        QVector <double> d_data_new(d_rows*new_cols);
225
 
        d_data_new.fill(GSL_NAN);
226
 
 
227
 
        for (int i=0; i <d_rows; i++){
228
 
                int aux1 = d_cols * i;
229
 
                int aux2 = new_cols * i;
230
 
                for (int j=0; j < column; j++)
231
 
                        d_data_new[aux2 + j] = d_data[aux1 + j];
232
 
 
233
 
                aux2 += count;
234
 
                for (int j = column; j < d_cols; j++)
235
 
                        d_data_new[aux2 + j] = d_data[aux1 + j];
236
 
        }
237
 
 
238
 
        d_data.resize(0);
239
 
        d_data = d_data_new;
240
 
        d_cols = new_cols;
 
392
    int offset = column + count;
 
393
    int oldCell = d_rows*d_cols - 1;
 
394
        d_cols += count;
 
395
    int cell = d_rows*d_cols - 1;
 
396
    for (int i = d_rows - 1; i >= 0; i--){
 
397
        for (int j = d_cols - 1; j >= offset; j--)
 
398
            d_data[cell--] = d_data[oldCell--];
 
399
 
 
400
        for (int j = offset - 1; j >= column; j--)
 
401
            d_data[cell--] = GSL_NAN;
 
402
 
 
403
        for (int j = column - 1; j >= 0; j--)
 
404
            d_data[cell--] = d_data[oldCell--];
 
405
    }
241
406
 
242
407
        endInsertColumns();
243
408
        return true;
245
410
 
246
411
bool MatrixModel::insertRows(int row, int count, const QModelIndex & parent)
247
412
{
 
413
    if (!canResize(d_rows + count, d_cols))
 
414
        return false;
 
415
 
248
416
        beginInsertRows(parent, row, row + count - 1);
249
417
 
250
 
        d_data.insert(row * d_cols, count*d_cols, GSL_NAN);
 
418
    int oldSize = d_rows*d_cols;
251
419
        d_rows += count;
252
420
 
 
421
    int insertedCells = count*d_cols;
 
422
    int startCell = row*d_cols;
 
423
    for (int i = oldSize - 1; i >= startCell; i--)
 
424
        d_data[i + insertedCells] = d_data[i];
 
425
    for (int i = 0; i < insertedCells; i++)
 
426
        d_data[startCell++] = GSL_NAN;
 
427
 
253
428
        endInsertRows();
254
429
        return true;
255
430
}
258
433
{
259
434
        beginRemoveRows(parent, row, row + count - 1);
260
435
 
261
 
        d_data.remove(row * d_cols, count*d_cols);
262
 
        d_rows -= count;
 
436
    d_rows -= count;
 
437
        d_data_block_size = QSize(d_rows, d_cols);
 
438
 
 
439
        int removedCells = count*d_cols;
 
440
        int size = d_rows*d_cols;
 
441
        for (int i = row*d_cols; i < size; i++)
 
442
        d_data[i] = d_data[i + removedCells];
 
443
 
 
444
    d_data = (double *)realloc(d_data, size * sizeof(double));
263
445
 
264
446
        endRemoveRows();
265
447
        return true;
298
480
 
299
481
QImage MatrixModel::renderImage()
300
482
{
301
 
        int size = QMAX(d_cols, d_rows);
302
 
        QImage image(QSize(size, size), QImage::Format_RGB32);
303
 
        image.fill(0);
 
483
    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
484
        
 
485
        QImage image(QSize(d_cols, d_rows), QImage::Format_RGB32);
304
486
        QwtLinearColorMap color_map = d_matrix->colorMap();
305
487
 
306
488
        double minValue = 0.0, maxValue = 0.0;
309
491
    for ( int i = 0; i < d_rows; i++ ){
310
492
        QRgb *line = (QRgb *)image.scanLine(i);
311
493
                for ( int j = 0; j < d_cols; j++){
312
 
                        if(fabs(d_data[i*d_cols + j]) < HUGE_VAL)
313
 
                                *line++ = color_map.rgb(intensityRange, d_data[i*d_cols + j]);
 
494
                    double val = d_data[i*d_cols + j];
 
495
                    if (gsl_isnan (val))
 
496
                *line++ = color_map.rgb(intensityRange, 0.0);
 
497
                        else if(fabs(val) < HUGE_VAL)
 
498
                                *line++ = color_map.rgb(intensityRange, val);
314
499
                }
315
500
     }
 
501
     QApplication::restoreOverrideCursor();
316
502
         return image;
317
 
}
318
 
 
319
 
void MatrixModel::setDataVector(const QVector<double>& data)
320
 
{
321
 
        d_data = data;
 
503
}
 
504
 
 
505
bool MatrixModel::importASCII(const QString &fname, const QString &sep, int ignoredLines,
 
506
    bool stripSpaces, bool simplifySpaces, const QString& commentString, int importAs,
 
507
        const QLocale& locale, int endLineChar, int maxRows)
 
508
{
 
509
        int rows = 0;
 
510
        QString name = MdiSubWindow::parseAsciiFile(fname, commentString, endLineChar, ignoredLines, maxRows, rows);
 
511
        if (name.isEmpty())
 
512
                return false;
 
513
        QFile f(name);
 
514
        if (!f.open(QIODevice::ReadOnly))
 
515
                return false;
 
516
 
 
517
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
518
 
 
519
    QTextStream t(&f);
 
520
        QLocale l = d_locale;
 
521
        if (d_matrix)
 
522
                l = d_matrix->locale();
 
523
        bool updateDecimalSeparators = (l != locale) ? true : false;
 
524
 
 
525
        QString s = t.readLine();
 
526
        if (simplifySpaces)
 
527
                s = s.simplifyWhiteSpace();
 
528
        else if (stripSpaces)
 
529
                s = s.stripWhiteSpace();
 
530
 
 
531
        QStringList line = s.split(sep);
 
532
        int cols = line.size();
 
533
 
 
534
        int startRow = 1, startCol = 0;
 
535
        switch(importAs){
 
536
                case Matrix::Overwrite:
 
537
                        if (d_cols != cols)
 
538
                                setColumnCount(cols);
 
539
                        if (d_rows != rows)
 
540
                                setRowCount(rows);
 
541
                break;
 
542
                case Matrix::NewColumns:
 
543
                        startCol = d_cols;
 
544
                        setColumnCount(d_cols + cols);
 
545
                        if (d_rows < rows)
 
546
                                setRowCount(rows);
 
547
                break;
 
548
                case Matrix::NewRows:
 
549
                        startRow = d_rows;
 
550
                        if (d_cols < cols)
 
551
                                setColumnCount(cols);
 
552
                        setRowCount(d_rows + rows);
 
553
                break;
 
554
        }
 
555
 
 
556
        for (int j = startCol; j<d_cols; j++){
 
557
                int aux = j - startCol;
 
558
                if (cols > aux){
 
559
                        if (updateDecimalSeparators)
 
560
                                setCell(0, j, locale.toDouble(line[aux]));
 
561
                        else
 
562
                                setText(0, j, line[aux]);
 
563
                }
 
564
        }
 
565
 
 
566
        qApp->processEvents(QEventLoop::ExcludeUserInput);
 
567
        for (int i = startRow; i<d_rows; i++){
 
568
                s = t.readLine();
 
569
                if (simplifySpaces)
 
570
                        s = s.simplifyWhiteSpace();
 
571
                else if (stripSpaces)
 
572
                        s = s.stripWhiteSpace();
 
573
                line = s.split(sep);
 
574
                int lc = line.size();
 
575
                if (lc > cols)
 
576
                        setColumnCount(d_cols + lc - cols);
 
577
 
 
578
                for (int j = startCol; j<d_cols; j++){
 
579
                        int aux = j - startCol;
 
580
                    if (lc > aux){
 
581
                                if (updateDecimalSeparators)
 
582
                                        setCell(i, j, locale.toDouble(line[aux]));
 
583
                                else
 
584
                                        setText(i, j, line[aux]);
 
585
                        }
 
586
                }
 
587
        }
 
588
    f.remove(); //remove temp file
 
589
        d_matrix->resetView();
 
590
        QApplication::restoreOverrideCursor();
 
591
        return true;
 
592
}
 
593
 
 
594
void MatrixModel::setNumericFormat(char f, int prec)
 
595
{
 
596
        if (d_txt_format == f && d_num_precision == prec)
 
597
                return;
 
598
 
 
599
        d_txt_format = f;
 
600
        d_num_precision = prec;
 
601
}
 
602
 
 
603
void MatrixModel::transpose()
 
604
{
 
605
        int size = d_rows*d_cols;
 
606
        double *data = d_matrix->initWorkspace(size);
 
607
        if (!data)
 
608
                return;
 
609
 
 
610
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
611
        for(int i = 0; i < size; i++)
 
612
                data[i] = d_data[i];
 
613
 
 
614
        int old_cols = d_cols;
 
615
        d_cols = d_rows;
 
616
        d_rows = old_cols;
 
617
        int aux = 0;
 
618
        for(int i = 0; i < d_rows; i++){
 
619
                for(int j = 0; j < d_cols; j++)
 
620
                        d_data[aux++] = data[j*old_cols + i];
 
621
        }
 
622
        d_matrix->freeWorkspace();
 
623
        QApplication::restoreOverrideCursor();
 
624
}
 
625
 
 
626
void MatrixModel::flipVertically()
 
627
{
 
628
        int size = d_rows*d_cols;
 
629
        double *data = d_matrix->initWorkspace(size);
 
630
        if (!data)
 
631
                return;
 
632
 
 
633
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
634
        for(int i = 0; i < size; i++)
 
635
                data[i] = d_data[i];
 
636
 
 
637
        int aux = 0;
 
638
        for(int i = 0; i < d_rows; i++){
 
639
                int row = (d_rows - i - 1)*d_cols;
 
640
                for(int j = 0; j < d_cols; j++)
 
641
                        d_data[aux++] = data[row++];
 
642
        }
 
643
        d_matrix->freeWorkspace();
 
644
        QApplication::restoreOverrideCursor();
 
645
}
 
646
 
 
647
void MatrixModel::flipHorizontally()
 
648
{
 
649
        int size = d_rows*d_cols;
 
650
        double *data = d_matrix->initWorkspace(size);
 
651
        if (!data)
 
652
                return;
 
653
 
 
654
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
655
        for(int i = 0; i < size; i++)
 
656
                data[i] = d_data[i];
 
657
 
 
658
        int aux = 0;
 
659
        for(int i = 0; i < d_rows; i++){
 
660
                int row = i*d_cols;
 
661
                for(int j = d_cols - 1; j >= 0; j--)
 
662
                        d_data[aux++] = data[row + j];
 
663
        }
 
664
        d_matrix->freeWorkspace();
 
665
        QApplication::restoreOverrideCursor();
 
666
}
 
667
 
 
668
void MatrixModel::rotate90(bool clockwise)
 
669
{
 
670
        int size = d_rows*d_cols;
 
671
        double *data = d_matrix->initWorkspace(size);
 
672
        if (!data)
 
673
                return;
 
674
 
 
675
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
676
        for(int i = 0; i < size; i++)
 
677
                data[i] = d_data[i];
 
678
 
 
679
    int old_rows = d_rows;
 
680
    int old_cols = d_cols;
 
681
        d_cols = d_rows;
 
682
        d_rows = old_cols;
 
683
        if (clockwise){
 
684
        int cell = 0;
 
685
        int aux = old_rows - 1;
 
686
        for(int i = 0; i < d_rows; i++){
 
687
            for(int j = 0; j < d_cols; j++)
 
688
                d_data[cell++] = data[(aux - j)*old_cols + i];
 
689
        }
 
690
        } else {
 
691
            int cell = 0;
 
692
            int aux = old_cols - 1;
 
693
        for(int i = 0; i < d_rows; i++){
 
694
            int k = aux - i;
 
695
            for(int j = 0; j < d_cols; j++)
 
696
                d_data[cell++] = data[j*old_cols + k];
 
697
        }
 
698
        }
 
699
        d_matrix->freeWorkspace();
 
700
        QApplication::restoreOverrideCursor();
 
701
}
 
702
 
 
703
bool MatrixModel::initWorkspace()
 
704
{
 
705
        gsl_set_error_handler_off();
 
706
 
 
707
        if (!d_direct_matrix)
 
708
                d_direct_matrix = gsl_matrix_alloc(d_rows, d_cols);
 
709
        if (!d_inv_matrix)
 
710
                d_inv_matrix = gsl_matrix_alloc(d_rows, d_cols);
 
711
        if (!d_inv_perm)
 
712
        d_inv_perm = gsl_permutation_alloc(d_cols);
 
713
        if (!d_direct_matrix || !d_inv_matrix || !d_inv_perm){
 
714
                QApplication::restoreOverrideCursor();
 
715
                QMessageBox::critical(d_matrix, tr("QtiPlot") + " - " + tr("Memory Allocation Error"),
 
716
                tr("Not enough memory, operation aborted!"));
 
717
                return false;
 
718
        }
 
719
        return true;
 
720
}
 
721
 
 
722
void MatrixModel::invert()
 
723
{
 
724
        initWorkspace();
 
725
        if(!d_direct_matrix || !d_inv_matrix || !d_inv_perm)
 
726
                return;
 
727
 
 
728
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
729
 
 
730
        int i, aux = 0;
 
731
        for(i=0; i<d_rows; i++){
 
732
                for(int j=0; j<d_cols; j++)
 
733
                        gsl_matrix_set(d_direct_matrix, i, j, d_data[aux++]);
 
734
        }
 
735
 
 
736
        gsl_linalg_LU_decomp(d_direct_matrix, d_inv_perm, &i);
 
737
        gsl_linalg_LU_invert(d_direct_matrix, d_inv_perm, d_inv_matrix);
 
738
 
 
739
        gsl_matrix_free(d_direct_matrix);
 
740
        d_direct_matrix = NULL;
 
741
        gsl_permutation_free(d_inv_perm);
 
742
        d_inv_perm = NULL;
 
743
 
 
744
    aux = 0;
 
745
        for(int i=0; i<d_rows; i++){
 
746
                for(int j=0; j<d_cols; j++)
 
747
                        d_data[aux++] = gsl_matrix_get(d_inv_matrix, i, j);
 
748
        }
 
749
        gsl_matrix_free(d_inv_matrix);
 
750
        d_inv_matrix = NULL;
 
751
        QApplication::restoreOverrideCursor();
 
752
}
 
753
 
 
754
void MatrixModel::clear(int startRow, int endRow, int startCol, int endCol)
 
755
{
 
756
        if (endRow < 0)
 
757
                endRow = d_rows - 1;
 
758
        if (endCol < 0)
 
759
                endCol = d_cols - 1;
 
760
 
 
761
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
762
    for (int i = startRow; i <= endRow; i++){
 
763
        int aux = i*d_cols + startCol;
 
764
        for (int j = startCol; j <= endCol; j++){
 
765
            d_data[aux++] = GSL_NAN;
 
766
        }
 
767
    }
 
768
        QApplication::restoreOverrideCursor();
 
769
}
 
770
 
 
771
double * MatrixModel::dataCopy(int startRow, int endRow, int startCol, int endCol)
 
772
{
 
773
        if (endRow < 0)
 
774
                endRow = d_rows - 1;
 
775
        if (endCol < 0)
 
776
                endCol = d_cols - 1;
 
777
 
 
778
    double *buffer = (double *)malloc((endRow - startRow + 1)*(endCol - startCol + 1) * sizeof (double));
 
779
        if (!buffer)
 
780
                return NULL;
 
781
 
 
782
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
783
 
 
784
        int aux = 0;
 
785
    for (int i = startRow; i <= endRow; i++){
 
786
        int row = i*d_cols + startCol;
 
787
        for (int j = startCol; j <= endCol; j++){
 
788
            buffer[aux++] = d_data[row++];
 
789
        }
 
790
    }
 
791
 
 
792
        QApplication::restoreOverrideCursor();
 
793
        return buffer;
 
794
}
 
795
 
 
796
bool MatrixModel::muParserCalculate(int startRow, int endRow, int startCol, int endCol)
 
797
{
 
798
        ScriptingEnv *scriptEnv = d_matrix->scriptingEnv();
 
799
    muParserScript *mup = new muParserScript(scriptEnv, d_matrix->formula(), d_matrix, QString("<%1>").arg(d_matrix->objectName()));
 
800
        connect(mup, SIGNAL(error(const QString&,const QString&,int)), scriptEnv, SIGNAL(error(const QString&,const QString&,int)));
 
801
        connect(mup, SIGNAL(print(const QString&)), scriptEnv, SIGNAL(print(const QString&)));
 
802
 
 
803
        if (endRow < 0)
 
804
                endRow = d_rows - 1;
 
805
        if (endCol < 0)
 
806
                endCol = d_cols - 1;
 
807
    if (endCol >= d_cols)
 
808
                setColumnCount(endCol + 1);
 
809
        if (endRow >= d_rows)
 
810
        setRowCount(endRow + 1);
 
811
 
 
812
        double dx = d_matrix->dx();
 
813
        double dy = d_matrix->dy();
 
814
    double *ri = mup->defineVariable("i");
 
815
    double *rr = mup->defineVariable("row");
 
816
    double *cj = mup->defineVariable("j");
 
817
    double *cc = mup->defineVariable("col");
 
818
    double *x = mup->defineVariable("x");
 
819
    double *y = mup->defineVariable("y");
 
820
 
 
821
        if (!mup->compile()){
 
822
                QApplication::restoreOverrideCursor();
 
823
                return false;
 
824
        }
 
825
 
 
826
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
827
 
 
828
        double x_start = d_matrix->xStart();
 
829
        double y_start = d_matrix->yStart();
 
830
    if (mup->codeLines() == 1){
 
831
        for(int row = startRow; row <= endRow; row++){
 
832
            double r = row + 1.0;
 
833
            *ri = r; *rr = r;
 
834
            *y = y_start + row*dy;
 
835
            int aux = row*d_cols + startCol;
 
836
            for(int col = startCol; col <= endCol; col++){
 
837
                double c = col + 1.0;
 
838
                *cj = c; *cc = c;
 
839
                *x = x_start + col*dx;
 
840
                d_data[aux++] = mup->evalSingleLine();
 
841
            }
 
842
        }
 
843
    } else {
 
844
        QVariant res;
 
845
        for(int row = startRow; row <= endRow; row++){
 
846
            double r = row + 1.0;
 
847
            *ri = r; *rr = r;
 
848
            *y = y_start + row*dy;
 
849
            int aux = row*d_cols + startCol;
 
850
            for(int col = startCol; col <= endCol; col++){
 
851
                double c = col + 1.0;
 
852
                *cj = c; *cc = c;
 
853
                *x = x_start + col*dx;
 
854
                res = mup->eval();
 
855
                if (res.canConvert(QVariant::Double))
 
856
                     d_data[aux++] = res.toDouble();
 
857
                else
 
858
                    d_data[aux++] = GSL_NAN;
 
859
                qApp->processEvents();
 
860
            }
 
861
                }
 
862
        }
 
863
        QApplication::restoreOverrideCursor();
 
864
        return true;
 
865
}
 
866
 
 
867
bool MatrixModel::calculate(int startRow, int endRow, int startCol, int endCol)
 
868
{
 
869
        QString formula = d_matrix->formula();
 
870
        if (formula.isEmpty())
 
871
                return false;
 
872
 
 
873
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
874
 
 
875
        ScriptingEnv *scriptEnv = d_matrix->scriptingEnv();
 
876
        Script *script = scriptEnv->newScript(formula, this, QString("<%1>").arg(objectName()));
 
877
        connect(script, SIGNAL(error(const QString&,const QString&,int)), scriptEnv, SIGNAL(error(const QString&,const QString&,int)));
 
878
        connect(script, SIGNAL(print(const QString&)), scriptEnv, SIGNAL(print(const QString&)));
 
879
        
 
880
        if (!script->compile()){
 
881
                QApplication::restoreOverrideCursor();
 
882
                return false;
 
883
        }
 
884
 
 
885
        if (endRow < 0)
 
886
                endRow = d_rows - 1;
 
887
        if (endCol < 0)
 
888
                endCol = d_cols - 1;
 
889
    if (endCol >= d_cols)
 
890
                setColumnCount(endCol + 1);
 
891
        if (endRow >= d_rows)
 
892
        setRowCount(endRow + 1);
 
893
 
 
894
        QVariant res;
 
895
        double dx = d_matrix->dx();
 
896
        double dy = d_matrix->dy();
 
897
        double x_start = d_matrix->xStart();
 
898
        double y_start = d_matrix->yStart();
 
899
        double r = 0.0, c = 0.0;
 
900
        for(int row = startRow; row <= endRow; row++){
 
901
            r = row + 1.0;
 
902
                script->setDouble(r, "i");
 
903
                script->setDouble(r, "row");
 
904
                script->setDouble(y_start + row*dy, "y");
 
905
                int aux = row*d_cols + startCol;
 
906
                for(int col = startCol; col <= endCol; col++){
 
907
                    c = col + 1.0;
 
908
                        script->setDouble(c, "j");
 
909
                        script->setDouble(c, "col");
 
910
                        script->setDouble(x_start + col*dx, "x");
 
911
                        res = script->eval();
 
912
                        if (res.canConvert(QVariant::Double))
 
913
                                d_data[aux++] = res.toDouble();
 
914
                        else {
 
915
                                QApplication::restoreOverrideCursor();
 
916
                                d_data[aux++] = GSL_NAN;
 
917
                                return false;
 
918
                        }
 
919
                }
 
920
                qApp->processEvents();
 
921
        }
 
922
 
 
923
        QApplication::restoreOverrideCursor();
 
924
        return true;
 
925
}
 
926
 
 
927
void MatrixModel::fft(bool inverse)
 
928
{
 
929
        int width = d_cols;
 
930
    int height = d_rows;
 
931
 
 
932
    double **x_int_re = Matrix::allocateMatrixData(height, width); /* real coeff matrix */
 
933
    if (!x_int_re)
 
934
        return;
 
935
    double **x_int_im = Matrix::allocateMatrixData(height, width); /* imaginary coeff  matrix*/
 
936
        if (!x_int_im){
 
937
        Matrix::freeMatrixData(x_int_re, height);
 
938
        return;
 
939
        }
 
940
 
 
941
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
942
 
 
943
        int cell = 0;
 
944
    for (int i = 0; i < height; i++){
 
945
        for (int j = 0; j < width; j++){
 
946
            x_int_re[i][j] = d_data[cell++];
 
947
            x_int_im[i][j] = 0.0;
 
948
        }
 
949
    }
 
950
 
 
951
    if (inverse){
 
952
        double **x_fin_re = Matrix::allocateMatrixData(height, width);
 
953
        double **x_fin_im = Matrix::allocateMatrixData(height, width);
 
954
                if (!x_fin_re || !x_fin_im){
 
955
                    Matrix::freeMatrixData(x_int_re, height);
 
956
            Matrix::freeMatrixData(x_int_im, height);
 
957
                        QApplication::restoreOverrideCursor();
 
958
                        return;
 
959
                }
 
960
 
 
961
        fft2d_inv(x_int_re, x_int_im, x_fin_re, x_fin_im, width, height);
 
962
                cell = 0;
 
963
        for (int i = 0; i < height; i++){
 
964
            for (int j = 0; j < width; j++){
 
965
                double re = x_fin_re[i][j];
 
966
                double im = x_fin_im[i][j];
 
967
                d_data[cell++] = sqrt(re*re + im*im);
 
968
            }
 
969
        }
 
970
        Matrix::freeMatrixData(x_fin_re, height);
 
971
        Matrix::freeMatrixData(x_fin_im, height);
 
972
    } else {
 
973
        fft2d(x_int_re, x_int_im, width, height);
 
974
                cell = 0;
 
975
        for (int i = 0; i < height; i++){
 
976
            for (int j = 0; j < width; j++){
 
977
                double re = x_int_re[i][j];
 
978
                double im = x_int_im[i][j];
 
979
                d_data[cell++] = sqrt(re*re + im*im);
 
980
            }
 
981
        }
 
982
    }
 
983
    Matrix::freeMatrixData(x_int_re, height);
 
984
    Matrix::freeMatrixData(x_int_im, height);
 
985
 
 
986
        d_matrix->resetView();
 
987
        QApplication::restoreOverrideCursor();
 
988
}
 
989
 
 
990
void MatrixModel::pasteData(double *clipboardBuffer, int topRow, int leftCol, int rows, int cols)
 
991
{
 
992
        int newCols = leftCol + cols;
 
993
        if (newCols > d_cols)
 
994
                insertColumns(d_cols, newCols - d_cols);
 
995
        
 
996
        int newRows = topRow + rows;
 
997
        if (newRows > d_rows)
 
998
                insertRows(d_rows, newRows - d_rows);
 
999
                
 
1000
        int cell = 0;
 
1001
        int bottomRow = newRows - 1;
 
1002
        int rightCol = newCols - 1;
 
1003
    for (int i = topRow; i <= bottomRow; i++){
 
1004
        int row = i*d_cols + leftCol;
 
1005
        for (int j = leftCol; j <= rightCol; j++)
 
1006
            d_data[row++] = clipboardBuffer[cell++];
 
1007
    }
322
1008
}