Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qgroundcontrol
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Valentin Platzgummer
qgroundcontrol
Commits
cd785b3d
Commit
cd785b3d
authored
Aug 18, 2010
by
pixhawk
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Almost finished flexible data view, only minor improvements needed
parent
263cb7c1
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
267 additions
and
61 deletions
+267
-61
QGCDataPlot2D.cc
src/ui/QGCDataPlot2D.cc
+109
-38
QGCDataPlot2D.ui
src/ui/QGCDataPlot2D.ui
+69
-12
IncrementalPlot.cc
src/ui/linechart/IncrementalPlot.cc
+76
-5
IncrementalPlot.h
src/ui/linechart/IncrementalPlot.h
+13
-6
No files found.
src/ui/QGCDataPlot2D.cc
View file @
cd785b3d
...
...
@@ -34,6 +34,8 @@ QGCDataPlot2D::QGCDataPlot2D(QWidget *parent) :
connect
(
ui
->
reloadButton
,
SIGNAL
(
clicked
()),
this
,
SLOT
(
reloadFile
()));
connect
(
ui
->
savePlotButton
,
SIGNAL
(
clicked
()),
this
,
SLOT
(
savePlot
()));
connect
(
ui
->
printButton
,
SIGNAL
(
clicked
()),
this
,
SLOT
(
print
()));
connect
(
ui
->
legendCheckBox
,
SIGNAL
(
clicked
(
bool
)),
plot
,
SLOT
(
showLegend
(
bool
)));
connect
(
ui
->
style
,
SIGNAL
(
currentIndexChanged
(
QString
)),
plot
,
SLOT
(
setStyleText
(
QString
)));
}
void
QGCDataPlot2D
::
reloadFile
()
...
...
@@ -214,6 +216,24 @@ void QGCDataPlot2D::loadRawLog(QString file, QString xAxisName, QString yAxisFil
loadCsvLog
(
logFile
->
fileName
(),
xAxisName
,
yAxisFilter
);
}
/**
* This function loads a CSV file into the plot. It tries to assign the dimension names
* based on the first data row and tries to guess the separator char.
*
* @param file Name of the file to open
* @param xAxisName Optional paramater. If given, the x axis dimension will be selected to match this string
* @param yAxisFilter Optional parameter. If given, only data dimension names present in the filter string will be
* plotted
*
* @code
*
* QString file = "/home/user/datalog.txt"; // With header: x<tab>y<tab>z
* QString xAxis = "x";
* QString yAxis = "z";
*
* // Plotted result will be x vs z with y ignored.
* @endcode
*/
void
QGCDataPlot2D
::
loadCsvLog
(
QString
file
,
QString
xAxisName
,
QString
yAxisFilter
)
{
if
(
logFile
!=
NULL
)
...
...
@@ -235,9 +255,44 @@ void QGCDataPlot2D::loadCsvLog(QString file, QString xAxisName, QString yAxisFil
// First line is header
QString
header
=
in
.
readLine
();
QString
separator
=
"
\t
"
;
qDebug
()
<<
"READING CSV:"
<<
header
;
bool
charRead
=
false
;
QString
separator
=
""
;
QList
<
QChar
>
sepCandidates
;
sepCandidates
<<
'\t'
;
sepCandidates
<<
','
;
sepCandidates
<<
';'
;
sepCandidates
<<
' '
;
sepCandidates
<<
'~'
;
sepCandidates
<<
'|'
;
// Iterate until separator is found
// or full header is parsed
for
(
int
i
=
0
;
i
<
header
.
length
();
i
++
)
{
if
(
sepCandidates
.
contains
(
header
.
at
(
i
)))
{
// Separator found
if
(
charRead
)
{
separator
+=
header
[
i
];
}
}
else
{
// Char found
charRead
=
true
;
// If the separator is not empty, this char
// has been read after a separator, so detection
// is now complete
if
(
separator
!=
""
)
break
;
}
}
QString
out
=
separator
;
out
.
replace
(
"
\t
"
,
"<tab>"
);
ui
->
filenameLabel
->
setText
(
file
.
split
(
"/"
).
last
().
split
(
"
\\
"
).
last
()
+
" Separator:
\"
"
+
out
+
"
\"
"
);
//qDebug() << "READING CSV:" << header;
// Clear plot
plot
->
removeData
();
...
...
@@ -245,7 +300,7 @@ void QGCDataPlot2D::loadCsvLog(QString file, QString xAxisName, QString yAxisFil
QVector
<
double
>
xValues
;
QMap
<
QString
,
QVector
<
double
>*
>
yValues
;
QStringList
curveNames
=
header
.
split
(
separator
);
QStringList
curveNames
=
header
.
split
(
separator
,
QString
::
SkipEmptyParts
);
QString
curveName
;
// Clear UI elements
...
...
@@ -254,73 +309,89 @@ void QGCDataPlot2D::loadCsvLog(QString file, QString xAxisName, QString yAxisFil
int
curveNameIndex
=
0
;
int
xValueIndex
=
curveNames
.
indexOf
(
xAxisName
);
if
(
xValueIndex
<
0
||
xValueIndex
>
(
curveNames
.
size
()
-
1
))
xValueIndex
=
0
;
//int xValueIndex = curveNames.indexOf(xAxisName);
QString
xAxisFilter
;
if
(
xAxisName
==
""
)
{
xAxisFilter
=
curveNames
.
first
();
}
else
{
xAxisFilter
=
xAxisName
;
}
foreach
(
curveName
,
curveNames
)
{
if
(
curveNameIndex
!=
xValueIndex
)
ui
->
xAxis
->
addItem
(
curveName
);
if
(
curveName
!=
xAxisFilter
)
{
// FIXME Add check for y value filter
if
((
ui
->
yAxis
->
text
()
==
""
)
&&
yValues
.
contains
(
curveName
))
if
((
yAxisFilter
==
""
)
||
yAxisFilter
.
contains
(
curveName
))
{
yValues
.
insert
(
curveName
,
new
QVector
<
double
>
());
ui
->
xAxis
->
addItem
(
curveName
);
// Add separator starting with second item
if
(
curveNameIndex
>
0
&&
curveNameIndex
<
curveNames
.
size
())
{
ui
->
yAxis
->
setText
(
ui
->
yAxis
->
text
()
+
"|"
);
}
ui
->
yAxis
->
setText
(
ui
->
yAxis
->
text
()
+
curveName
);
curveNameIndex
++
;
}
}
curveNameIndex
++
;
}
// Select current axis in UI
ui
->
xAxis
->
setCurrentIndex
(
curveNames
.
indexOf
(
xAxisFilter
));
// Read data
double
x
,
y
;
while
(
!
in
.
atEnd
())
{
while
(
!
in
.
atEnd
())
{
QString
line
=
in
.
readLine
();
QStringList
values
=
line
.
split
(
separator
);
QStringList
values
=
line
.
split
(
separator
,
QString
::
SkipEmptyParts
);
bool
okx
;
x
=
values
.
at
(
xValueIndex
).
toDouble
(
&
okx
);
if
(
okx
)
foreach
(
curveName
,
curveNames
)
{
// Append X value
xValues
.
append
(
x
);
QString
yStr
;
bool
oky
;
bool
okx
;
if
(
curveName
==
xAxisFilter
)
{
// X AXIS HANDLING
int
yCount
=
0
;
foreach
(
yStr
,
values
)
// Take this value as x if it is selected
x
=
values
.
at
(
curveNames
.
indexOf
(
curveName
)).
toDouble
(
&
okx
);
xValues
.
append
(
x
-
1270125570000LL
);
qDebug
()
<<
"x"
<<
x
-
1270125570000LL
;
}
else
{
//
We have already x, so only handle
// true y values
if
(
yCount
!=
xValueIndex
&&
yCount
<
curveNames
.
size
(
))
//
Y AXIS HANDLING
if
(
yAxisFilter
==
""
||
yAxisFilter
.
contains
(
curveName
))
{
y
=
yStr
.
toDouble
(
&
oky
);
// Append one of the Y values
yValues
.
value
(
curveNames
.
at
(
yCount
))
->
append
(
y
);
// Only append y values where a valid x value is present
if
(
yValues
.
value
(
curveName
)
->
size
()
==
xValues
.
size
()
-
1
)
{
bool
oky
;
int
curveNameIndex
=
curveNames
.
indexOf
(
curveName
);
if
(
values
.
size
()
>
curveNameIndex
)
{
y
=
values
.
at
(
curveNameIndex
).
toDouble
(
&
oky
);
yValues
.
value
(
curveName
)
->
append
(
y
);
}
}
}
yCount
++
;
}
}
}
QVector
<
double
>*
yCurve
;
int
yCurveIndex
=
0
;
foreach
(
yCurve
,
yValues
)
// Add data array of each curve to the plot at once (fast)
// Iterates through all x-y curve combinations
for
(
int
i
=
0
;
i
<
yValues
.
size
();
i
++
)
{
plot
->
appendData
(
yValues
.
keys
().
at
(
yCurveIndex
),
xValues
.
data
(),
yCurve
->
data
(),
xValues
.
size
());
yCurveIndex
++
;
plot
->
appendData
(
yValues
.
keys
().
at
(
i
),
xValues
.
data
(),
yValues
.
values
().
at
(
i
)
->
data
(),
xValues
.
size
());
}
}
...
...
@@ -339,7 +410,7 @@ void QGCDataPlot2D::loadCsvLog(QString file, QString xAxisName, QString yAxisFil
* the match of the regression.
* @return 1 on success, 0 on failure (e.g. because of infinite slope)
*/
int
QGCDataPlot2D
::
linearRegression
(
double
*
x
,
double
*
y
,
int
n
,
double
*
a
,
double
*
b
,
double
*
r
)
int
QGCDataPlot2D
::
linearRegression
(
double
*
x
,
double
*
y
,
int
n
,
double
*
a
,
double
*
b
,
double
*
r
)
{
int
i
;
double
sumx
=
0
,
sumy
=
0
,
sumx2
=
0
,
sumy2
=
0
,
sumxy
=
0
;
...
...
src/ui/QGCDataPlot2D.ui
View file @
cd785b3d
...
...
@@ -6,14 +6,14 @@
<rect>
<x>
0
</x>
<y>
0
</y>
<width>
736
</width>
<width>
807
</width>
<height>
308
</height>
</rect>
</property>
<property
name=
"windowTitle"
>
<string>
Form
</string>
</property>
<layout
class=
"QGridLayout"
name=
"gridLayout"
columnstretch=
"2,10,2,0,0,0,0,0,0,0,0,0"
>
<layout
class=
"QGridLayout"
name=
"gridLayout"
columnstretch=
"2,10,2,0,0,0,0,0,0,0,0,0
,0
"
>
<item
row=
"0"
column=
"0"
colspan=
"2"
>
<widget
class=
"QLabel"
name=
"label_2"
>
<property
name=
"text"
>
...
...
@@ -43,24 +43,74 @@
</item>
<item>
<property
name=
"text"
>
<string>
Dot
s
</string>
<string>
Only crosse
s
</string>
</property>
</item>
<item>
<property
name=
"text"
>
<string>
Lines
</string>
<string>
Only circles
</string>
</property>
</item>
<item>
<property
name=
"text"
>
<string>
Only dots
</string>
</property>
</item>
<item>
<property
name=
"text"
>
<string>
Lines and crosses
</string>
</property>
</item>
<item>
<property
name=
"text"
>
<string>
Lines and circles
</string>
</property>
</item>
<item>
<property
name=
"text"
>
<string>
Lines and dots
</string>
</property>
</item>
<item>
<property
name=
"text"
>
<string>
Dotted lines and crosses
</string>
</property>
</item>
<item>
<property
name=
"text"
>
<string>
Dotted lines and circles
</string>
</property>
</item>
<item>
<property
name=
"text"
>
<string>
Dotted lines and dots
</string>
</property>
</item>
<item>
<property
name=
"text"
>
<string>
Dashed lines and crosses
</string>
</property>
</item>
<item>
<property
name=
"text"
>
<string>
Dashed lines and circles
</string>
</property>
</item>
<item>
<property
name=
"text"
>
<string>
Dashed lines and dots
</string>
</property>
</item>
</widget>
</item>
<item
row=
"0"
column=
"
8
"
>
<item
row=
"0"
column=
"
9
"
>
<widget
class=
"QPushButton"
name=
"reloadButton"
>
<property
name=
"text"
>
<string>
Reload
</string>
</property>
</widget>
</item>
<item
row=
"0"
column=
"
9
"
>
<item
row=
"0"
column=
"
10
"
>
<spacer
name=
"horizontalSpacer_2"
>
<property
name=
"orientation"
>
<enum>
Qt::Horizontal
</enum>
...
...
@@ -73,14 +123,14 @@
</property>
</spacer>
</item>
<item
row=
"0"
column=
"1
0
"
>
<item
row=
"0"
column=
"1
1
"
>
<widget
class=
"QPushButton"
name=
"savePlotButton"
>
<property
name=
"text"
>
<string>
Save Plot
</string>
</property>
</widget>
</item>
<item
row=
"1"
column=
"0"
colspan=
"1
2
"
>
<item
row=
"1"
column=
"0"
colspan=
"1
3
"
>
<widget
class=
"QFrame"
name=
"plotFrame"
>
<property
name=
"frameShape"
>
<enum>
QFrame::StyledPanel
</enum>
...
...
@@ -123,7 +173,7 @@
</property>
</widget>
</item>
<item
row=
"2"
column=
"
9
"
>
<item
row=
"2"
column=
"
10
"
>
<spacer
name=
"horizontalSpacer"
>
<property
name=
"orientation"
>
<enum>
Qt::Horizontal
</enum>
...
...
@@ -136,21 +186,21 @@
</property>
</spacer>
</item>
<item
row=
"0"
column=
"1
1
"
>
<item
row=
"0"
column=
"1
2
"
>
<widget
class=
"QPushButton"
name=
"printButton"
>
<property
name=
"text"
>
<string>
Print
</string>
</property>
</widget>
</item>
<item
row=
"2"
column=
"1
1
"
>
<item
row=
"2"
column=
"1
2
"
>
<widget
class=
"QPushButton"
name=
"saveCsvButton"
>
<property
name=
"text"
>
<string>
Save CSV
</string>
</property>
</widget>
</item>
<item
row=
"2"
column=
"
8
"
>
<item
row=
"2"
column=
"
9
"
>
<widget
class=
"QPushButton"
name=
"selectFileButton"
>
<property
name=
"text"
>
<string>
Select file
</string>
...
...
@@ -164,6 +214,13 @@
</property>
</widget>
</item>
<item
row=
"0"
column=
"8"
>
<widget
class=
"QCheckBox"
name=
"legendCheckBox"
>
<property
name=
"text"
>
<string>
Legend
</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
...
...
src/ui/linechart/IncrementalPlot.cc
View file @
cd785b3d
...
...
@@ -62,6 +62,7 @@ IncrementalPlot::IncrementalPlot(QWidget *parent):
setFrameStyle
(
QFrame
::
NoFrame
);
setLineWidth
(
0
);
setStyleText
(
"solid crosses"
);
setCanvasLineWidth
(
2
);
plotLayout
()
->
setAlignCanvasToScales
(
true
);
...
...
@@ -84,6 +85,7 @@ IncrementalPlot::IncrementalPlot(QWidget *parent):
zoomer
->
setRubberBandPen
(
QPen
(
Qt
::
red
,
2
,
Qt
::
DotLine
));
zoomer
->
setTrackerPen
(
QPen
(
Qt
::
red
));
//zoomer->setZoomBase(QwtDoubleRect());
legend
=
NULL
;
colors
=
QList
<
QColor
>
();
nextColor
=
0
;
...
...
@@ -117,6 +119,75 @@ IncrementalPlot::~IncrementalPlot()
}
void
IncrementalPlot
::
showLegend
(
bool
show
)
{
if
(
show
)
{
if
(
legend
==
NULL
)
{
legend
=
new
QwtLegend
;
legend
->
setFrameStyle
(
QFrame
::
Box
);
}
insertLegend
(
legend
,
QwtPlot
::
RightLegend
);
}
else
{
delete
legend
;
legend
=
NULL
;
}
replot
();
}
/**
* Set datapoint and line style. This interface is intented
* to be directly connected to the UI and allows to parse
* human-readable, textual descriptions into plot specs.
*
* Data points: Either "circles", "crosses" or the default "dots"
* Lines: Either "dotted", ("solid"/"line") or no lines if not used
*
* No special formatting is needed, as long as the keywords are contained
* in the string. Lower/uppercase is ignored as well.
*
* @param style Formatting string for line/data point style
*/
void
IncrementalPlot
::
setStyleText
(
QString
style
)
{
foreach
(
QwtPlotCurve
*
curve
,
d_curve
)
{
// Style of datapoints
if
(
style
.
toLower
().
contains
(
"circles"
))
{
curve
->
setSymbol
(
QwtSymbol
(
QwtSymbol
::
Ellipse
,
QBrush
(
curve
->
pen
().
color
()),
curve
->
pen
(),
QSize
(
5
,
5
))
);
}
else
if
(
style
.
toLower
().
contains
(
"crosses"
))
{
curve
->
setSymbol
(
QwtSymbol
(
QwtSymbol
::
XCross
,
QBrush
(
curve
->
pen
().
color
()),
curve
->
pen
(),
QSize
(
5
,
5
))
);
}
else
// Always show dots (style.toLower().contains("dots"))
{
curve
->
setSymbol
(
QwtSymbol
(
QwtSymbol
::
Rect
,
QBrush
(
curve
->
pen
().
color
()),
curve
->
pen
(),
QSize
(
1
,
1
))
);
}
// Style of lines
if
(
style
.
toLower
().
contains
(
"dotted"
))
{
curve
->
setStyle
(
QwtPlotCurve
::
Dots
);
}
else
if
(
style
.
toLower
().
contains
(
"line"
)
||
style
.
toLower
().
contains
(
"solid"
))
{
curve
->
setStyle
(
QwtPlotCurve
::
Lines
);
}
else
{
curve
->
setStyle
(
QwtPlotCurve
::
NoCurve
);
}
}
}
void
IncrementalPlot
::
resetScaling
()
{
xmin
=
0
;
...
...
@@ -233,11 +304,11 @@ void IncrementalPlot::appendData(QString key, double *x, double *y, int size)
canvas
()
->
setPaintAttribute
(
QwtPlotCanvas
::
PaintCached
,
false
);
// FIXME Check if here all curves should be drawn
// QwtPlotCurve* plotCurve;
// foreach(plotCurve, d_curve)
// {
// plotCurve->draw(0, curve->dataSize()-1);
// }
// QwtPlotCurve* plotCurve;
// foreach(plotCurve, d_curve)
// {
// plotCurve->draw(0, curve->dataSize()-1);
// }
curve
->
draw
(
curve
->
dataSize
()
-
size
,
curve
->
dataSize
()
-
1
);
canvas
()
->
setPaintAttribute
(
QwtPlotCanvas
::
PaintCached
,
cacheMode
);
...
...
src/ui/linechart/IncrementalPlot.h
View file @
cd785b3d
...
...
@@ -4,6 +4,7 @@
#include <QTimer>
#include <qwt_array.h>
#include <qwt_plot.h>
#include <qwt_legend.h>
#include <QMap>
#include "ScrollZoomer.h"
...
...
@@ -38,12 +39,6 @@ public:
IncrementalPlot
(
QWidget
*
parent
=
NULL
);
virtual
~
IncrementalPlot
();
void
appendData
(
QString
key
,
double
x
,
double
y
);
void
appendData
(
QString
key
,
double
*
x
,
double
*
y
,
int
size
);
void
resetScaling
();
void
removeData
();
/** @brief Get color map of this plot */
QList
<
QColor
>
IncrementalPlot
::
getColorMap
();
/** @brief Get next color of color map */
...
...
@@ -51,10 +46,22 @@ public:
/** @brief Get color for curve id */
QColor
IncrementalPlot
::
getColorForCurve
(
QString
id
);
public
slots
:
void
appendData
(
QString
key
,
double
x
,
double
y
);
void
appendData
(
QString
key
,
double
*
x
,
double
*
y
,
int
size
);
void
resetScaling
();
void
removeData
();
/** @brief Show the plot legend */
void
showLegend
(
bool
show
);
/** @brief Set new plot style */
void
setStyleText
(
QString
style
);
protected:
QList
<
QColor
>
colors
;
int
nextColor
;
ScrollZoomer
*
zoomer
;
QwtLegend
*
legend
;
double
xmin
;
double
xmax
;
double
ymin
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment