1
/***************************************************************************
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
9
***************************************************************************/
11
/***************************************************************************
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. *
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. *
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 *
28
***************************************************************************/
29
#include "VectorCurve.h"
31
#include <qwt_painter.h>
32
#include <qwt_double_rect.h>
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)
42
d_type = Graph::VectXYXY;
45
d_type = Graph::VectXYAM;
48
pen=QPen(Qt::black, 1, Qt::SolidLine);
58
void VectorCurve::copy(const VectorCurve *vc)
61
filledArrow = vc->filledArrow;
62
d_headLength = vc->d_headLength;
63
d_headAngle = vc->d_headAngle;
64
d_position = vc->d_position;
66
vectorEnd = (QwtArrayData *)vc->vectorEnd->copy();
69
void VectorCurve::draw(QPainter *painter,
70
const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
72
if ( !painter || dataSize() <= 0 )
78
QwtPlotCurve::draw(painter, xMap, yMap, from, to);
82
drawVector(painter, xMap, yMap, from, to);
86
void VectorCurve::drawVector(QPainter *painter,
87
const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
89
if (d_type == Graph::VectXYAM)
91
for (int i = from; i <= to; i++)
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);
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));
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);
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);
126
QwtPainter::drawLine(painter, xs, ys, xe, ye);
127
drawArrowHead(painter, xs, ys, xe, ye);
132
for (int i = from; i <= to; i++)
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);
144
void VectorCurve::drawArrowHead(QPainter *p, int xs, int ys, int xe, int ye) const
147
p->translate(xe, ye);
148
double t=theta(xs, ys, xe, ye);
151
double pi=4*atan(-1.0);
152
int d=qRound(d_headLength*tan(pi*(double)d_headAngle/180.0));
154
QPolygon endArray(3);
155
endArray[0] = QPoint(0, 0);
156
endArray[1] = QPoint(-d_headLength, d);
157
endArray[2] = QPoint(-d_headLength, -d);
160
p->setBrush(QBrush(pen.color(), Qt::SolidPattern));
162
QwtPainter::drawPolygon(p,endArray);
166
double VectorCurve::theta(int x0, int y0, int x1, int y1) const
168
double t,pi=4*atan(-1.0);
178
t=atan2((y1-y0)*1.0,(x1-x0)*1.0)*180/pi;
185
void VectorCurve::setVectorEnd(const QString& xColName, const QString& yColName)
187
if (d_end_x_a == xColName && d_end_y_m == yColName)
190
d_end_x_a = xColName;
191
d_end_y_m = yColName;
196
void VectorCurve::setVectorEnd(const QwtArray<double>&x, const QwtArray<double>&y)
198
vectorEnd=new QwtArrayData(x, y);
201
int VectorCurve::width()
206
void VectorCurve::setWidth(int w)
211
QColor VectorCurve::color()
216
void VectorCurve::setColor(const QColor& c)
218
if (pen.color() != c)
222
void VectorCurve::setHeadLength(int l)
224
if (d_headLength != l)
228
void VectorCurve::setHeadAngle(int a)
230
if (d_headAngle != a)
234
void VectorCurve::fillArrowHead(bool fill)
236
if (filledArrow != fill)
240
QwtDoubleRect VectorCurve::boundingRect() const
242
QwtDoubleRect rect = QwtPlotCurve::boundingRect();
243
QwtDoubleRect vrect = vectorEnd->boundingRect();
245
if (d_type == Graph::VectXYXY)
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()));
254
const double angle = vectorEnd->x(0);
255
double mag = vectorEnd->y(0);
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)));
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))));
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)));
286
void VectorCurve::updateColumnNames(const QString& oldName, const QString& newName, bool updateTableName)
290
QString s = title().text();
291
QStringList lst = s.split("_", QString::SkipEmptyParts);
292
if (lst[0] == oldName)
293
setTitle(newName + "_" + lst[1]);
295
lst = d_x_column.split("_", QString::SkipEmptyParts);
296
if (lst[0] == oldName)
297
d_x_column = newName + "_" + lst[1];
299
lst = d_end_x_a.split("_", QString::SkipEmptyParts);
300
if (lst[0] == oldName)
301
d_end_x_a = newName + "_" + lst[1];
303
lst = d_end_y_m.split("_", QString::SkipEmptyParts);
304
if (lst[0] == oldName)
305
d_end_y_m = newName + "_" + lst[1];
309
if (title().text() == oldName)
311
if (d_x_column == oldName)
312
d_x_column = newName;
313
if (d_end_x_a == oldName)
315
if (d_end_y_m == oldName)
320
QString VectorCurve::plotAssociation()
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)";
326
return base + "(X)," + d_end_y_m + "(Y)";
329
bool VectorCurve::updateData(Table *t, const QString& colName)
332
(colName != title().text() && d_x_column != colName && d_end_x_a != colName && d_end_y_m != colName))
339
void VectorCurve::loadData()
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);
346
int rows = abs(d_end_row - d_start_row) + 1;
347
QVector<double> X(rows), Y(rows), X2(rows), Y2(rows);
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);
359
Y[size] = QLocale().toDouble(yval, &valid_data);
362
X2[size] = QLocale().toDouble(xend, &valid_data);
365
Y2[size] = QLocale().toDouble(yend, &valid_data);
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);
381
VectorCurve::~VectorCurve()