~valavanisalex/ubuntu/maverick/scidavis/fix-604811

« back to all changes in this revision

Viewing changes to scidavis/src/VectorCurve.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ruben Molina
  • Date: 2009-09-06 11:34:04 UTC
  • Revision ID: james.westby@ubuntu.com-20090906113404-4awaey82l3686w4q
Tags: upstream-0.2.3
ImportĀ upstreamĀ versionĀ 0.2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
    File                 : VectorCurve.cpp
 
3
    Project              : SciDAVis
 
4
    --------------------------------------------------------------------
 
5
    Copyright            : (C) 2006 by Ion Vasilief, Tilman Benkert
 
6
    Email (use @ for *)  : ion_vasilief*yahoo.fr, thzs*gmx.net
 
7
    Description          : Vector curve class
 
8
 
 
9
 ***************************************************************************/
 
10
 
 
11
/***************************************************************************
 
12
 *                                                                         *
 
13
 *  This program is free software; you can redistribute it and/or modify   *
 
14
 *  it under the terms of the GNU General Public License as published by   *
 
15
 *  the Free Software Foundation; either version 2 of the License, or      *
 
16
 *  (at your option) any later version.                                    *
 
17
 *                                                                         *
 
18
 *  This program is distributed in the hope that it will be useful,        *
 
19
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 
20
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 
21
 *  GNU General Public License for more details.                           *
 
22
 *                                                                         *
 
23
 *   You should have received a copy of the GNU General Public License     *
 
24
 *   along with this program; if not, write to the Free Software           *
 
25
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
 
26
 *   Boston, MA  02110-1301  USA                                           *
 
27
 *                                                                         *
 
28
 ***************************************************************************/
 
29
#include "VectorCurve.h"
 
30
 
 
31
#include <qwt_painter.h>
 
32
#include <qwt_double_rect.h>
 
33
#include <QPainter>
 
34
#include <QLocale>
 
35
 
 
36
VectorCurve::VectorCurve(VectorStyle style, Table *t, const QString& xColName, const char *name,
 
37
                                const QString& endCol1, const QString& endCol2, int startRow, int endRow):
 
38
    DataCurve(t, xColName, name, startRow, endRow)
 
39
{
 
40
        switch (style) {
 
41
                case XYXY:
 
42
                        d_type = Graph::VectXYXY;
 
43
                        break;
 
44
                case XYAM:
 
45
                        d_type = Graph::VectXYAM;
 
46
                        break;
 
47
        }
 
48
pen=QPen(Qt::black, 1, Qt::SolidLine);
 
49
filledArrow=true;
 
50
d_headLength=4;
 
51
d_headAngle=45;
 
52
d_position = Tail;
 
53
 
 
54
d_end_x_a = endCol1;
 
55
d_end_y_m = endCol2;
 
56
}
 
57
 
 
58
void VectorCurve::copy(const VectorCurve *vc)
 
59
{
 
60
d_type = vc->type();
 
61
filledArrow = vc->filledArrow;
 
62
d_headLength = vc->d_headLength;
 
63
d_headAngle = vc->d_headAngle;
 
64
d_position = vc->d_position;
 
65
pen = vc->pen;
 
66
vectorEnd = (QwtArrayData *)vc->vectorEnd->copy();
 
67
}
 
68
 
 
69
void VectorCurve::draw(QPainter *painter,
 
70
    const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
 
71
{
 
72
    if ( !painter || dataSize() <= 0 )
 
73
        return;
 
74
 
 
75
    if (to < 0)
 
76
        to = dataSize() - 1;
 
77
 
 
78
        QwtPlotCurve::draw(painter, xMap, yMap, from, to);
 
79
 
 
80
    painter->save();
 
81
    painter->setPen(pen);
 
82
    drawVector(painter, xMap, yMap, from, to);
 
83
    painter->restore();
 
84
}
 
85
 
 
86
void VectorCurve::drawVector(QPainter *painter,
 
87
    const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
 
88
{
 
89
if (d_type == Graph::VectXYAM)
 
90
{
 
91
 for (int i = from; i <= to; i++)
 
92
        {
 
93
        const double x0 = x(i);
 
94
        const double y0 = y(i);
 
95
        const double angle = vectorEnd->x(i);
 
96
        const double mag = vectorEnd->y(i);
 
97
 
 
98
        int xs, ys, xe, ye;
 
99
        switch(d_position)
 
100
                {
 
101
                case Tail:
 
102
                        xs = xMap.transform(x0);
 
103
                        ys = yMap.transform(y0);
 
104
                        xe = xMap.transform(x0 + mag*cos(angle));
 
105
                        ye = yMap.transform(y0 + mag*sin(angle));
 
106
                break;
 
107
 
 
108
                case Middle:
 
109
                        {
 
110
                        double dxh = 0.5*mag*cos(angle);
 
111
                        double dyh = 0.5*mag*sin(angle);
 
112
                        xs = xMap.transform(x0 - dxh);
 
113
                        ys = yMap.transform(y0 - dyh);
 
114
                        xe = xMap.transform(x0 + dxh);
 
115
                        ye = yMap.transform(y0 + dyh);
 
116
                        }
 
117
                break;
 
118
 
 
119
                case Head:
 
120
                        xs = xMap.transform(x0 - mag*cos(angle));
 
121
                        ys = yMap.transform(y0 - mag*sin(angle));
 
122
                        xe = xMap.transform(x0);
 
123
                        ye = yMap.transform(y0);
 
124
                break;
 
125
                }
 
126
        QwtPainter::drawLine(painter, xs, ys, xe, ye);
 
127
        drawArrowHead(painter, xs, ys, xe, ye);
 
128
        }
 
129
}
 
130
else
 
131
        {
 
132
        for (int i = from; i <= to; i++)
 
133
                {
 
134
                const int xs = xMap.transform(x(i));
 
135
                const int ys = yMap.transform(y(i));
 
136
                const int xe = xMap.transform(vectorEnd->x(i));
 
137
                const int ye = yMap.transform(vectorEnd->y(i));
 
138
                QwtPainter::drawLine(painter, xs, ys, xe, ye);
 
139
                drawArrowHead(painter, xs, ys, xe, ye);
 
140
                }
 
141
        }
 
142
}
 
143
 
 
144
void VectorCurve::drawArrowHead(QPainter *p, int xs, int ys, int xe, int ye) const
 
145
{
 
146
p->save();
 
147
p->translate(xe, ye);
 
148
double t=theta(xs, ys, xe, ye);
 
149
p->rotate(-t);
 
150
 
 
151
double pi=4*atan(-1.0);
 
152
int d=qRound(d_headLength*tan(pi*(double)d_headAngle/180.0));
 
153
 
 
154
QPolygon endArray(3);
 
155
endArray[0] = QPoint(0, 0);
 
156
endArray[1] = QPoint(-d_headLength, d);
 
157
endArray[2] = QPoint(-d_headLength, -d);
 
158
 
 
159
if (filledArrow)
 
160
        p->setBrush(QBrush(pen.color(), Qt::SolidPattern));
 
161
 
 
162
QwtPainter::drawPolygon(p,endArray);
 
163
p->restore();
 
164
}
 
165
 
 
166
double VectorCurve::theta(int x0, int y0, int x1, int y1) const
 
167
{
 
168
double t,pi=4*atan(-1.0);
 
169
if (x1==x0)
 
170
        {
 
171
        if (y0>y1)
 
172
                t=90;
 
173
        else
 
174
                t=270;
 
175
        }
 
176
else
 
177
        {
 
178
        t=atan2((y1-y0)*1.0,(x1-x0)*1.0)*180/pi;
 
179
        if (t<0)
 
180
                t=360+t;
 
181
        }
 
182
return t;
 
183
}
 
184
 
 
185
void VectorCurve::setVectorEnd(const QString& xColName, const QString& yColName)
 
186
{
 
187
if (d_end_x_a == xColName && d_end_y_m == yColName)
 
188
        return;
 
189
 
 
190
d_end_x_a = xColName;
 
191
d_end_y_m = yColName;
 
192
 
 
193
loadData();
 
194
}
 
195
 
 
196
void VectorCurve::setVectorEnd(const QwtArray<double>&x, const QwtArray<double>&y)
 
197
{
 
198
vectorEnd=new QwtArrayData(x, y);
 
199
}
 
200
 
 
201
int VectorCurve::width()
 
202
{
 
203
return pen.width ();
 
204
}
 
205
 
 
206
void VectorCurve::setWidth(int w)
 
207
{
 
208
pen.setWidth (w);
 
209
}
 
210
 
 
211
QColor VectorCurve::color()
 
212
{
 
213
return pen.color();
 
214
}
 
215
 
 
216
void VectorCurve::setColor(const QColor& c)
 
217
{
 
218
if (pen.color() != c)
 
219
        pen.setColor(c);
 
220
}
 
221
 
 
222
void VectorCurve::setHeadLength(int l)
 
223
{
 
224
if (d_headLength != l)
 
225
        d_headLength = l;
 
226
}
 
227
 
 
228
void VectorCurve::setHeadAngle(int a)
 
229
{
 
230
if (d_headAngle != a)
 
231
        d_headAngle = a;
 
232
}
 
233
 
 
234
void VectorCurve::fillArrowHead(bool fill)
 
235
{
 
236
if (filledArrow != fill)
 
237
        filledArrow = fill;
 
238
}
 
239
 
 
240
QwtDoubleRect VectorCurve::boundingRect() const
 
241
{
 
242
QwtDoubleRect rect = QwtPlotCurve::boundingRect();
 
243
QwtDoubleRect vrect = vectorEnd->boundingRect();
 
244
 
 
245
if (d_type == Graph::VectXYXY)
 
246
        {
 
247
        rect.setTop(QMIN(rect.top(), vrect.top()));
 
248
        rect.setBottom(QMAX(rect.bottom(), vrect.bottom()));
 
249
        rect.setLeft(QMIN(rect.left(), vrect.left()));
 
250
        rect.setRight(QMAX(rect.right(), vrect.right()));
 
251
        }
 
252
else
 
253
        {
 
254
        const double angle = vectorEnd->x(0);
 
255
        double mag = vectorEnd->y(0);
 
256
        switch(d_position)
 
257
                {
 
258
                case Tail:
 
259
                        rect.setTop(QMIN(rect.top(), rect.top()+mag*sin(angle)));
 
260
                        rect.setBottom(QMAX(rect.bottom(), rect.bottom()+mag*sin(angle)));
 
261
                        rect.setLeft(QMIN(rect.left(), rect.left()+mag*cos(angle)));
 
262
                        rect.setRight(QMAX(rect.right(), rect.right()+mag*cos(angle)));
 
263
                break;
 
264
 
 
265
                case Middle:
 
266
                        {
 
267
                        mag *= 0.5;
 
268
                        rect.setTop(QMIN(rect.top(), rect.top() - fabs(mag*sin(angle))));
 
269
                        rect.setBottom(QMAX(rect.bottom(), rect.bottom() + fabs(mag*sin(angle))));
 
270
                        rect.setLeft(QMIN(rect.left(), rect.left() - fabs(mag*cos(angle))));
 
271
                        rect.setRight(QMAX(rect.right(), rect.right() + fabs(mag*cos(angle))));
 
272
                        }
 
273
                break;
 
274
 
 
275
                case Head:
 
276
                        rect.setTop(QMIN(rect.top(), rect.top() - mag*sin(angle)));
 
277
                        rect.setBottom(QMAX(rect.bottom(), rect.bottom() - mag*sin(angle)));
 
278
                        rect.setLeft(QMIN(rect.left(), rect.left() - mag*cos(angle)));
 
279
                        rect.setRight(QMAX(rect.right(), rect.right() - mag*cos(angle)));
 
280
                break;
 
281
                }
 
282
        }
 
283
return rect;
 
284
}
 
285
 
 
286
void VectorCurve::updateColumnNames(const QString& oldName, const QString& newName, bool updateTableName)
 
287
{
 
288
    if (updateTableName)
 
289
    {
 
290
        QString s = title().text();
 
291
        QStringList lst = s.split("_", QString::SkipEmptyParts);
 
292
        if (lst[0] == oldName)
 
293
            setTitle(newName + "_" + lst[1]);
 
294
 
 
295
        lst = d_x_column.split("_", QString::SkipEmptyParts);
 
296
        if (lst[0] == oldName)
 
297
            d_x_column = newName + "_" + lst[1];
 
298
 
 
299
                lst = d_end_x_a.split("_", QString::SkipEmptyParts);
 
300
        if (lst[0] == oldName)
 
301
            d_end_x_a = newName + "_" + lst[1];
 
302
 
 
303
                lst = d_end_y_m.split("_", QString::SkipEmptyParts);
 
304
        if (lst[0] == oldName)
 
305
            d_end_y_m = newName + "_" + lst[1];
 
306
    }
 
307
    else
 
308
    {
 
309
        if (title().text() == oldName)
 
310
            setTitle(newName);
 
311
        if (d_x_column == oldName)
 
312
            d_x_column = newName;
 
313
                if (d_end_x_a == oldName)
 
314
            d_end_x_a = newName;
 
315
                if (d_end_y_m == oldName)
 
316
            d_end_y_m = newName;
 
317
    }
 
318
}
 
319
 
 
320
QString VectorCurve::plotAssociation()
 
321
{
 
322
    QString base = d_x_column + "(X)," + title().text() + "(Y)," + d_end_x_a;
 
323
    if (d_type == Graph::VectXYAM)
 
324
        return base + "(A)," + d_end_y_m + "(M)";
 
325
    else
 
326
        return base + "(X)," + d_end_y_m + "(Y)";
 
327
}
 
328
 
 
329
bool VectorCurve::updateData(Table *t, const QString& colName)
 
330
{
 
331
        if (d_table != t ||
 
332
           (colName != title().text() && d_x_column != colName && d_end_x_a != colName && d_end_y_m != colName))
 
333
                return false;
 
334
 
 
335
        loadData();
 
336
        return true;
 
337
}
 
338
 
 
339
void VectorCurve::loadData()
 
340
{
 
341
        int xcol = d_table->colIndex(d_x_column);
 
342
        int ycol = d_table->colIndex(title().text());
 
343
        int endXCol = d_table->colIndex(d_end_x_a);
 
344
        int endYCol = d_table->colIndex(d_end_y_m);
 
345
 
 
346
        int rows = abs(d_end_row - d_start_row) + 1;
 
347
    QVector<double> X(rows), Y(rows), X2(rows), Y2(rows);
 
348
    int size = 0;
 
349
        for (int i = d_start_row; i <= d_end_row; i++){
 
350
                QString xval = d_table->text(i, xcol);
 
351
                QString yval = d_table->text(i, ycol);
 
352
                QString xend = d_table->text(i, endXCol);
 
353
                QString yend = d_table->text(i, endYCol);
 
354
                if (!xval.isEmpty() && !yval.isEmpty() && !xend.isEmpty() && !yend.isEmpty()){
 
355
                    bool valid_data = true;
 
356
                        X[size] = QLocale().toDouble(xval, &valid_data);
 
357
                        if (!valid_data)
 
358
                continue;
 
359
            Y[size] = QLocale().toDouble(yval, &valid_data);
 
360
            if (!valid_data)
 
361
                continue;
 
362
                        X2[size] = QLocale().toDouble(xend, &valid_data);
 
363
                        if (!valid_data)
 
364
                continue;
 
365
            Y2[size] = QLocale().toDouble(yend, &valid_data);
 
366
                        if (valid_data)
 
367
                size++;
 
368
                }
 
369
        }
 
370
 
 
371
        if (!size)
 
372
                return;
 
373
 
 
374
    X.resize(size); Y.resize(size); X2.resize(size); Y2.resize(size);
 
375
        setData(X.data(), Y.data(), size);
 
376
        foreach(DataCurve *c, d_error_bars)
 
377
        c->setData(X.data(), Y.data(), size);
 
378
        setVectorEnd(X2, Y2);
 
379
}
 
380
 
 
381
VectorCurve::~VectorCurve()
 
382
{
 
383
delete vectorEnd;
 
384
}