1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-06 23:03:22 +02:00
GPXSee/src/graphitem.cpp

194 lines
3.9 KiB
C++
Raw Normal View History

2016-09-19 00:56:10 +02:00
#include <QPainter>
2016-08-19 19:48:44 +02:00
#include "graphitem.h"
2016-09-19 00:56:10 +02:00
GraphItem::GraphItem(const Graph &graph, QGraphicsItem *parent)
: QGraphicsObject(parent)
{
_id = 0;
2016-12-06 01:48:26 +01:00
_width = 1;
2016-09-19 00:56:10 +02:00
2016-12-06 01:48:26 +01:00
_pen = QPen(Qt::black, _width);
_type = Distance;
_graph = graph;
_sx = 1.0; _sy = 1.0;
2016-09-19 00:56:10 +02:00
2016-12-06 01:48:26 +01:00
setZValue(1.0);
updatePath();
updateBounds();
2016-09-19 00:56:10 +02:00
}
void GraphItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
painter->setPen(_pen);
painter->drawPath(_path);
/*
QPen p = QPen(QBrush(Qt::red), 0);
painter->setPen(p);
painter->drawRect(boundingRect());
*/
2016-09-19 00:56:10 +02:00
}
2016-09-25 18:08:39 +02:00
void GraphItem::setGraphType(GraphType type)
{
prepareGeometryChange();
2016-09-25 18:08:39 +02:00
_type = type;
updatePath();
updateBounds();
2016-09-25 18:08:39 +02:00
}
2016-08-19 19:48:44 +02:00
void GraphItem::setColor(const QColor &color)
{
_pen.setColor(color);
update();
2016-09-19 00:56:10 +02:00
}
2016-12-06 01:48:26 +01:00
void GraphItem::setWidth(int width)
{
prepareGeometryChange();
_width = width;
_pen.setWidth(width);
}
2016-09-19 00:56:10 +02:00
qreal GraphItem::yAtX(qreal x)
{
int low = 0;
int high = _graph.count() - 1;
int mid = 0;
Q_ASSERT(high > low);
Q_ASSERT(x >= _graph.at(low).x(_type) && x <= _graph.at(high).x(_type));
while (low <= high) {
mid = low + ((high - low) / 2);
const GraphPoint &p = _graph.at(mid);
if (p.x(_type) > x)
high = mid - 1;
else if (p.x(_type) < x)
low = mid + 1;
else
return -p.y();
}
QLineF l;
if (_graph.at(mid).x(_type) < x)
l = QLineF(_graph.at(mid).x(_type), _graph.at(mid).y(),
_graph.at(mid+1).x(_type), _graph.at(mid+1).y());
else
l = QLineF(_graph.at(mid-1).x(_type), _graph.at(mid-1).y(),
_graph.at(mid).x(_type), _graph.at(mid).y());
return -l.pointAt((x - l.p1().x()) / (l.p2().x() - l.p1().x())).y();
2016-09-19 00:56:10 +02:00
}
qreal GraphItem::distanceAtTime(qreal time)
{
int low = 0;
int high = _graph.count() - 1;
2016-09-19 00:56:10 +02:00
int mid = 0;
Q_ASSERT(high > low);
Q_ASSERT(time >= _graph.at(low).t() && time <= _graph.at(high).t());
2016-09-19 00:56:10 +02:00
while (low <= high) {
mid = low + ((high - low) / 2);
const GraphPoint &p = _graph.at(mid);
if (p.t() > time)
2016-09-19 00:56:10 +02:00
high = mid - 1;
else if (p.t() < time)
2016-09-19 00:56:10 +02:00
low = mid + 1;
else
return _graph.at(mid).s();
2016-09-19 00:56:10 +02:00
}
2016-09-27 01:48:45 +02:00
QLineF l;
if (_graph.at(mid).t() < time)
l = QLineF(_graph.at(mid).t(), _graph.at(mid).s(), _graph.at(mid+1).t(),
_graph.at(mid+1).s());
2016-09-19 00:56:10 +02:00
else
l = QLineF(_graph.at(mid-1).t(), _graph.at(mid-1).s(),
_graph.at(mid).t(), _graph.at(mid).s());
2016-09-27 01:48:45 +02:00
return l.pointAt((time - l.p1().x()) / (l.p2().x() - l.p1().x())).y();
2016-09-19 00:56:10 +02:00
}
void GraphItem::emitSliderPositionChanged(qreal pos)
{
2016-09-19 23:35:04 +02:00
if (_type == Time) {
2016-11-05 17:37:04 +01:00
if (_graph.hasTime()) {
2016-11-18 09:23:43 +01:00
if (pos >= _graph.first().t() && pos <= _graph.last().t())
2016-09-19 00:56:10 +02:00
emit sliderPositionChanged(distanceAtTime(pos));
else
2016-11-18 18:02:40 +01:00
emit sliderPositionChanged(NAN);
2016-09-19 00:56:10 +02:00
} else
2016-11-18 18:02:40 +01:00
emit sliderPositionChanged(NAN);
2016-09-19 00:56:10 +02:00
} else
emit sliderPositionChanged(pos);
2016-08-19 19:48:44 +02:00
}
void GraphItem::selected(bool selected)
{
if (selected) {
2016-12-06 01:48:26 +01:00
_pen.setWidth(_width + 1);
setZValue(zValue() + 1.0);
} else {
2016-12-06 01:48:26 +01:00
_pen.setWidth(_width);
setZValue(zValue() - 1.0);
}
update();
}
void GraphItem::setScale(qreal sx, qreal sy)
{
if (_sx == sx && _sy == sy)
return;
prepareGeometryChange();
_sx = sx; _sy = sy;
updatePath();
}
void GraphItem::updatePath()
{
_path = QPainterPath();
2016-11-05 17:37:04 +01:00
if (_type == Time && !_graph.hasTime())
return;
_path.moveTo(_graph.first().x(_type) * _sx, -_graph.first().y() * _sy);
for (int i = 1; i < _graph.size(); i++)
_path.lineTo(_graph.at(i).x(_type) * _sx, -_graph.at(i).y() * _sy);
}
void GraphItem::updateBounds()
{
2016-11-05 17:37:04 +01:00
if (_type == Time && !_graph.hasTime()) {
_bounds = QRectF();
return;
}
qreal bottom, top, left, right;
QPointF p = QPointF(_graph.first().x(_type), -_graph.first().y());
bottom = p.y(); top = p.y(); left = p.x(); right = p.x();
for (int i = 1; i < _graph.size(); i++) {
p = QPointF(_graph.at(i).x(_type), -_graph.at(i).y());
bottom = qMax(bottom, p.y()); top = qMin(top, p.y());
right = qMax(right, p.x()); left = qMin(left, p.x());
}
_bounds = QRectF(QPointF(left, top), QPointF(right, bottom));
}