|
@@ -5,6 +5,7 @@
|
|
#include <QBrush>
|
|
#include <QBrush>
|
|
#include <random>
|
|
#include <random>
|
|
#include <algorithm>
|
|
#include <algorithm>
|
|
|
|
+#include <chrono>
|
|
|
|
|
|
#define X_AXIS_GAP_AMOUNT 5
|
|
#define X_AXIS_GAP_AMOUNT 5
|
|
#define Y_AXIS_GAP_AMOUNT 10
|
|
#define Y_AXIS_GAP_AMOUNT 10
|
|
@@ -18,7 +19,6 @@ GraphView::GraphView(QWidget* parent, QString title, Bound fixedBound):QWidget(p
|
|
{
|
|
{
|
|
|
|
|
|
linePen.setJoinStyle(Qt::PenJoinStyle::RoundJoin);
|
|
linePen.setJoinStyle(Qt::PenJoinStyle::RoundJoin);
|
|
- qDebug() << "minX:" << fixedBound.minX << " maxX:" << fixedBound.maxX << " minY:" << fixedBound.minY << " maxY:" << fixedBound.maxY;
|
|
|
|
rectPen.setWidth(0);
|
|
rectPen.setWidth(0);
|
|
//Populate data with DummyData
|
|
//Populate data with DummyData
|
|
//Draw Points
|
|
//Draw Points
|
|
@@ -26,14 +26,10 @@ GraphView::GraphView(QWidget* parent, QString title, Bound fixedBound):QWidget(p
|
|
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
|
|
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
|
|
std::uniform_real_distribution<double> doubleDistr(0.0, 1.0);
|
|
std::uniform_real_distribution<double> doubleDistr(0.0, 1.0);
|
|
hueoffset = doubleDistr(gen);
|
|
hueoffset = doubleDistr(gen);
|
|
- QRect graphDisplayRect(rect());
|
|
|
|
- graphDisplayRect.setBottom(graphDisplayRect.bottom() - 20);
|
|
|
|
- graphDisplayRect.setLeft(graphDisplayRect.left() + 50);
|
|
|
|
- graphDisplayRect.setTop(graphDisplayRect.top() + 20);
|
|
|
|
- graphDisplayRect.setRight(graphDisplayRect.right() - 10);
|
|
|
|
- graphDisplayRect.setWidth(graphDisplayRect.width() - (graphDisplayRect.width() % X_AXIS_GAP_AMOUNT) + 1);
|
|
|
|
- graphDisplayRect.setHeight(graphDisplayRect.height() - (graphDisplayRect.height() % Y_AXIS_GAP_AMOUNT) + 1);
|
|
|
|
-
|
|
|
|
|
|
+ setFocusPolicy(Qt::ClickFocus);
|
|
|
|
+ /*QTimer* timer = new QTimer(this);
|
|
|
|
+ connect(timer, &QTimer::timeout, this, QOverload<>::of(&GraphView::update));
|
|
|
|
+ timer->start(1000);*/
|
|
}
|
|
}
|
|
|
|
|
|
GraphView::~GraphView()
|
|
GraphView::~GraphView()
|
|
@@ -41,6 +37,7 @@ GraphView::~GraphView()
|
|
}
|
|
}
|
|
void GraphView::paintEvent(QPaintEvent* event)
|
|
void GraphView::paintEvent(QPaintEvent* event)
|
|
{
|
|
{
|
|
|
|
+ std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
|
|
QPainter painter(this);
|
|
QPainter painter(this);
|
|
painter.setRenderHint(QPainter::RenderHint::HighQualityAntialiasing);
|
|
painter.setRenderHint(QPainter::RenderHint::HighQualityAntialiasing);
|
|
if (graphSeriesVec.empty()) {
|
|
if (graphSeriesVec.empty()) {
|
|
@@ -64,60 +61,59 @@ void GraphView::paintEvent(QPaintEvent* event)
|
|
|
|
|
|
double stregth_factorX = graphDisplayRect.width() / rangeGraphX;
|
|
double stregth_factorX = graphDisplayRect.width() / rangeGraphX;
|
|
double stregth_factorY = graphDisplayRect.height() / rangeGraphY;
|
|
double stregth_factorY = graphDisplayRect.height() / rangeGraphY;
|
|
- for (GraphSeries graphSeries : graphSeriesVec) {
|
|
|
|
|
|
+ QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
|
|
|
|
+ for (const GraphSeries& graphSeries : graphSeriesVec) {
|
|
|
|
+ if (graphSeries.data->empty()) continue;
|
|
linePen.setColor(graphSeries.color);
|
|
linePen.setColor(graphSeries.color);
|
|
painter.setPen(linePen);
|
|
painter.setPen(linePen);
|
|
- QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
|
|
|
|
|
|
|
|
if (graphSeries.type == GraphSeries::SeriesType::Line || graphSeries.type == GraphSeries::SeriesType::LineDot) {
|
|
if (graphSeries.type == GraphSeries::SeriesType::Line || graphSeries.type == GraphSeries::SeriesType::LineDot) {
|
|
linePen.setWidth(graphSeries.lineWidth);
|
|
linePen.setWidth(graphSeries.lineWidth);
|
|
painter.setPen(linePen);
|
|
painter.setPen(linePen);
|
|
QPainterPath painterPath;
|
|
QPainterPath painterPath;
|
|
|
|
|
|
- int i;
|
|
|
|
- for (i = 0; i < graphSeries.data->size(); i++) {
|
|
|
|
- QPointF& point = graphSeries.data->at(i);
|
|
|
|
- /*if (!inBoundX(point)) continue;*/
|
|
|
|
- painterPath.moveTo(transformPoint(point, stregth_factorX, stregth_factorY));
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- for (; i < graphSeries.data->size(); i++) {
|
|
|
|
- QPointF& point = graphSeries.data->at(i);
|
|
|
|
- //if (!inBoundX(point)) break;
|
|
|
|
- //if (point.y() > actualBound.maxY) {
|
|
|
|
- // //Generate new Point
|
|
|
|
- // QPointF& oldpoint = graphSeries.data->at(i - 1);
|
|
|
|
- // double xdif = std::abs(point.x() - oldpoint.x());
|
|
|
|
- // double ydif = std::abs(point.y() - oldpoint.y());
|
|
|
|
- // double newX = (xdif / ydif) * actualBound.maxY;
|
|
|
|
- // QPointF newPoint(newX, actualBound.maxY);
|
|
|
|
- //
|
|
|
|
- //}
|
|
|
|
- //else {
|
|
|
|
-
|
|
|
|
- //}
|
|
|
|
- painterPath.lineTo(transformPoint(point, stregth_factorX, stregth_factorY));
|
|
|
|
|
|
+ QPointF oldpoint = graphSeries.data->at(0).toQPointF();
|
|
|
|
+ painterPath.moveTo(transformPoint(oldpoint, stregth_factorX, stregth_factorY));
|
|
|
|
+ for (int i = 1; i < graphSeries.data->size(); i++) {
|
|
|
|
+ QPointF newpoint = graphSeries.data->at(i).toQPointF();
|
|
|
|
+ if (!inBoundX(oldpoint) && !inBoundX(newpoint)) {
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ else if (!inBoundX(oldpoint) && inBoundX(newpoint)) {
|
|
|
|
+ painterPath.moveTo(transformPoint(oldpoint, stregth_factorX, stregth_factorY));
|
|
|
|
+ painterPath.lineTo(transformPoint(newpoint, stregth_factorX, stregth_factorY));
|
|
|
|
+ }
|
|
|
|
+ else if (inBoundX(oldpoint) && inBoundX(newpoint)) {
|
|
|
|
+ painterPath.lineTo(transformPoint(newpoint, stregth_factorX, stregth_factorY));
|
|
|
|
+ }
|
|
|
|
+ else if (inBoundX(oldpoint) && !inBoundX(newpoint)) {
|
|
|
|
+ painterPath.lineTo(transformPoint(newpoint, stregth_factorX, stregth_factorY));
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ oldpoint = newpoint;
|
|
}
|
|
}
|
|
- /*
|
|
|
|
- std::pair<std::vector<QPointF>::iterator, std::vector<QPointF>::iterator> pair = graphSeries.getFirstLastIndexInSeriesThatsInBound(actualBound.minX, actualBound.maxX);
|
|
|
|
- qDebug() << "hello";
|
|
|
|
- painterPath.moveTo(transformPoint(*pair.first++, stregth_factorX, stregth_factorY));
|
|
|
|
- for (std::vector<QPointF>::iterator it = pair.first; it != pair.second; it++) {
|
|
|
|
- painterPath.lineTo(transformPoint(*it, stregth_factorX, stregth_factorY));
|
|
|
|
- }*/
|
|
|
|
|
|
+
|
|
painterPath.translate(translation);
|
|
painterPath.translate(translation);
|
|
painter.drawPath(painterPath);
|
|
painter.drawPath(painterPath);
|
|
}
|
|
}
|
|
if (graphSeries.type == GraphSeries::SeriesType::Dot || graphSeries.type == GraphSeries::SeriesType::LineDot) {
|
|
if (graphSeries.type == GraphSeries::SeriesType::Dot || graphSeries.type == GraphSeries::SeriesType::LineDot) {
|
|
painter.setBrush(graphSeries.color);
|
|
painter.setBrush(graphSeries.color);
|
|
- for (int i = 0; i < graphSeries.data->size(); i++) {
|
|
|
|
- painter.drawEllipse(transformPoint(graphSeries.data->at(i), stregth_factorX, stregth_factorY) + translation, graphSeries.circleRadius, graphSeries.circleRadius);
|
|
|
|
|
|
+ for (auto data: *graphSeries.data) {
|
|
|
|
+ if (inBound(data.toQPointF())) {
|
|
|
|
+ painter.drawEllipse(transformPoint(data.toQPointF(), stregth_factorX, stregth_factorY) + translation, graphSeries.circleRadius, graphSeries.circleRadius);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
painter.setBrush(Qt::BrushStyle::NoBrush);
|
|
painter.setBrush(Qt::BrushStyle::NoBrush);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+ if (drawTotalBound) {
|
|
|
|
+ painter.setPen(axisPen);
|
|
|
|
+ QRectF bounds(transformPoint(QPointF(totalBound.minX, totalBound.maxY), stregth_factorX, stregth_factorY), transformPoint(QPointF(totalBound.maxX, totalBound.minY), stregth_factorX, stregth_factorY));
|
|
|
|
+ bounds.translate(translation);
|
|
|
|
+ painter.drawRect(bounds);
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -134,8 +130,8 @@ void GraphView::paintEvent(QPaintEvent* event)
|
|
painter.drawRect(topRect);
|
|
painter.drawRect(topRect);
|
|
painter.drawRect(bottomRect);
|
|
painter.drawRect(bottomRect);
|
|
painter.drawRect(rightRect);
|
|
painter.drawRect(rightRect);
|
|
-
|
|
|
|
painter.setBrush(Qt::BrushStyle::NoBrush);
|
|
painter.setBrush(Qt::BrushStyle::NoBrush);
|
|
|
|
+
|
|
//painter.drawRect(yAxisRect);
|
|
//painter.drawRect(yAxisRect);
|
|
|
|
|
|
|
|
|
|
@@ -174,13 +170,9 @@ void GraphView::paintEvent(QPaintEvent* event)
|
|
painter.drawText(textRect, Qt::AlignCenter, yAxisNumbers[i]);
|
|
painter.drawText(textRect, Qt::AlignCenter, yAxisNumbers[i]);
|
|
}
|
|
}
|
|
painter.drawPath(yAxisPath);
|
|
painter.drawPath(yAxisPath);
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- qDebug() << "minX:" << actualBound.minX << " maxX:" << actualBound.maxX << " minY:" << actualBound.minY << " maxY:" << actualBound.maxY;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+ std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
|
|
|
|
+ std::chrono::milliseconds time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
|
|
|
+ qDebug() << "PaintTime: " << time.count() << "ms";
|
|
}
|
|
}
|
|
|
|
|
|
QPointF GraphView::transformPoint(QPointF& point, double stregth_factorX, double stregth_factorY) const
|
|
QPointF GraphView::transformPoint(QPointF& point, double stregth_factorX, double stregth_factorY) const
|
|
@@ -194,40 +186,44 @@ bool GraphView::inBoundX(QPointF& point)
|
|
return point.x() >= actualBound.minX && point.x() <= actualBound.maxX;
|
|
return point.x() >= actualBound.minX && point.x() <= actualBound.maxX;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+bool GraphView::inBoundY(QPointF& point)
|
|
|
|
+{
|
|
|
|
+ return point.y() >= actualBound.minY && point.y() <= actualBound.maxY;;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool GraphView::inBound(QPointF& point)
|
|
|
|
+{
|
|
|
|
+ return inBoundX(point) && inBoundY(point);
|
|
|
|
+}
|
|
|
|
+
|
|
void GraphView::keyPressEvent(QKeyEvent* event)
|
|
void GraphView::keyPressEvent(QKeyEvent* event)
|
|
{
|
|
{
|
|
switch (event->key()) {
|
|
switch (event->key()) {
|
|
case Qt::Key_Up:
|
|
case Qt::Key_Up:
|
|
- qDebug() << "Up pressed";
|
|
|
|
fixedBound.move(this, Bound::Change::MoveUp);
|
|
fixedBound.move(this, Bound::Change::MoveUp);
|
|
break;
|
|
break;
|
|
case Qt::Key_Right:
|
|
case Qt::Key_Right:
|
|
- qDebug() << "Right pressed";
|
|
|
|
fixedBound.move(this, Bound::Change::MoveRight);
|
|
fixedBound.move(this, Bound::Change::MoveRight);
|
|
break;
|
|
break;
|
|
case Qt::Key_Left:
|
|
case Qt::Key_Left:
|
|
- qDebug() << "Key_Left pressed";
|
|
|
|
fixedBound.move(this, Bound::Change::MoveLeft);
|
|
fixedBound.move(this, Bound::Change::MoveLeft);
|
|
break;
|
|
break;
|
|
case Qt::Key_Down:
|
|
case Qt::Key_Down:
|
|
- qDebug() << "Key_Down pressed";
|
|
|
|
fixedBound.move(this, Bound::Change::MoveDown);
|
|
fixedBound.move(this, Bound::Change::MoveDown);
|
|
break;
|
|
break;
|
|
case Qt::Key_PageUp:
|
|
case Qt::Key_PageUp:
|
|
case Qt::Key_Plus:
|
|
case Qt::Key_Plus:
|
|
- qDebug() << "Key_Down pressed";
|
|
|
|
fixedBound.move(this, Bound::Change::ZoomIn);
|
|
fixedBound.move(this, Bound::Change::ZoomIn);
|
|
break;
|
|
break;
|
|
case Qt::Key_PageDown:
|
|
case Qt::Key_PageDown:
|
|
case Qt::Key_Minus:
|
|
case Qt::Key_Minus:
|
|
- qDebug() << "Key_Down pressed";
|
|
|
|
fixedBound.move(this, Bound::Change::ZoomOut);
|
|
fixedBound.move(this, Bound::Change::ZoomOut);
|
|
break;
|
|
break;
|
|
case Qt::Key_R:
|
|
case Qt::Key_R:
|
|
fixedBound = totalBound;
|
|
fixedBound = totalBound;
|
|
calculateRangeXY();
|
|
calculateRangeXY();
|
|
generateAxisNumberStrings();
|
|
generateAxisNumberStrings();
|
|
- repaint();
|
|
|
|
|
|
+ update();
|
|
default:
|
|
default:
|
|
QWidget::keyPressEvent(event);
|
|
QWidget::keyPressEvent(event);
|
|
}
|
|
}
|
|
@@ -242,7 +238,6 @@ void GraphView::wheelEvent(QWheelEvent* event)
|
|
|
|
|
|
if (!numPixels.isNull()) {
|
|
if (!numPixels.isNull()) {
|
|
//scrollWithPixels(numPixels);
|
|
//scrollWithPixels(numPixels);
|
|
- qDebug() << "NumPixels:" << numPixels;
|
|
|
|
switch (numPixels.y()) {
|
|
switch (numPixels.y()) {
|
|
case -1:
|
|
case -1:
|
|
fixedBound.move(this, Bound::Change::ZoomIn);
|
|
fixedBound.move(this, Bound::Change::ZoomIn);
|
|
@@ -255,14 +250,11 @@ void GraphView::wheelEvent(QWheelEvent* event)
|
|
}
|
|
}
|
|
else if (!numDegrees.isNull()) {
|
|
else if (!numDegrees.isNull()) {
|
|
QPoint numSteps = numDegrees / 15;
|
|
QPoint numSteps = numDegrees / 15;
|
|
- qDebug() << "numSteps:" << numSteps;
|
|
|
|
switch (numSteps.y()) {
|
|
switch (numSteps.y()) {
|
|
case 1:
|
|
case 1:
|
|
- qDebug() << "ZoomIn";
|
|
|
|
fixedBound.move(this, Bound::Change::ZoomIn);
|
|
fixedBound.move(this, Bound::Change::ZoomIn);
|
|
break;
|
|
break;
|
|
case -1:
|
|
case -1:
|
|
- qDebug() << "ZoomOut";
|
|
|
|
fixedBound.move(this, Bound::Change::ZoomOut);
|
|
fixedBound.move(this, Bound::Change::ZoomOut);
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
@@ -272,9 +264,54 @@ void GraphView::wheelEvent(QWheelEvent* event)
|
|
event->accept();
|
|
event->accept();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void GraphView::mouseMoveEvent(QMouseEvent* event)
|
|
|
|
+{
|
|
|
|
+ //QToolTip::showText(event->globalPos(), "Hello", this);
|
|
|
|
+ QPointF delta = event->pos() - oldPos;
|
|
|
|
+ oldPos = event->pos();
|
|
|
|
+ double rangeX = std::abs(actualBound.maxX - actualBound.minX);
|
|
|
|
+ int width = (rect().right() - 10) - (rect().left() + 50);
|
|
|
|
+ width -= (width % X_AXIS_GAP_AMOUNT) + 1;
|
|
|
|
+ double pixelWidthX = rangeX / (double)width ;
|
|
|
|
+ double rangeY = std::abs(actualBound.maxY - actualBound.minY);
|
|
|
|
+ int height = (rect().bottom() - 20) - (rect().top() + 20);
|
|
|
|
+ height -= (height % Y_AXIS_GAP_AMOUNT) + 1;
|
|
|
|
+ double pixelWidthY = rangeY / (double)height;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ fixedBound.move(this, delta, pixelWidthX, pixelWidthY);
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void GraphView::mousePressEvent(QMouseEvent* event)
|
|
|
|
+{
|
|
|
|
+ QString string = "Pos (" + QString::number(event->pos().x()) + "," + QString::number(event->pos().y()) + ")";
|
|
|
|
+ //QString printable = QStringLiteral("Pos(%d,%d)").arg(event->pos().x(), event->pos().y());
|
|
|
|
+ QToolTip::showText(event->globalPos() - QPoint(0, 35), string);
|
|
|
|
+ oldPos = event->pos();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void GraphView::mouseReleaseEvent(QMouseEvent* event)
|
|
|
|
+{
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void GraphView::update()
|
|
|
|
+{
|
|
|
|
+ calculateRangeXY();
|
|
|
|
+ generateAxisNumberStrings();
|
|
|
|
+ QWidget::update();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void GraphView::setDrawBound(bool value)
|
|
|
|
+{
|
|
|
|
+ drawTotalBound = value;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
void GraphView::calculateTotalGraphBound()
|
|
void GraphView::calculateTotalGraphBound()
|
|
{
|
|
{
|
|
- qDebug() << "calculateTotalGraphBound";
|
|
|
|
totalBound.minX = std::min_element(std::begin(graphSeriesVec), std::end(graphSeriesVec), [](const GraphSeries& a, const GraphSeries& b) -> bool {return a.minX < b.minX; })->minX;
|
|
totalBound.minX = std::min_element(std::begin(graphSeriesVec), std::end(graphSeriesVec), [](const GraphSeries& a, const GraphSeries& b) -> bool {return a.minX < b.minX; })->minX;
|
|
totalBound.maxX = std::max_element(std::begin(graphSeriesVec), std::end(graphSeriesVec), [](const GraphSeries& a, const GraphSeries& b) -> bool {return a.maxX < b.maxX; })->maxX;
|
|
totalBound.maxX = std::max_element(std::begin(graphSeriesVec), std::end(graphSeriesVec), [](const GraphSeries& a, const GraphSeries& b) -> bool {return a.maxX < b.maxX; })->maxX;
|
|
totalBound.minY = std::min_element(std::begin(graphSeriesVec), std::end(graphSeriesVec), [](const GraphSeries& a, const GraphSeries& b) -> bool {return a.minY < b.minY; })->minY;
|
|
totalBound.minY = std::min_element(std::begin(graphSeriesVec), std::end(graphSeriesVec), [](const GraphSeries& a, const GraphSeries& b) -> bool {return a.minY < b.minY; })->minY;
|
|
@@ -284,10 +321,7 @@ void GraphView::calculateTotalGraphBound()
|
|
|
|
|
|
void GraphView::calculateRangeXY()
|
|
void GraphView::calculateRangeXY()
|
|
{
|
|
{
|
|
- qDebug() << "calculateRangeXY";
|
|
|
|
actualBound = useFixedBound ? fixedBound : totalBound;
|
|
actualBound = useFixedBound ? fixedBound : totalBound;
|
|
- qDebug() << "calculateRangeXY " << "minX:" << actualBound.minX << " maxX:" << actualBound.maxX << " minY:" << actualBound.minY << " maxY:" << actualBound.maxY;
|
|
|
|
-
|
|
|
|
rangeGraphX = std::abs(actualBound.maxX - actualBound.minX);
|
|
rangeGraphX = std::abs(actualBound.maxX - actualBound.minX);
|
|
rangeGraphY = std::abs(actualBound.maxY - actualBound.minY);
|
|
rangeGraphY = std::abs(actualBound.maxY - actualBound.minY);
|
|
if (std::abs(rangeGraphX) < 0.01) {
|
|
if (std::abs(rangeGraphX) < 0.01) {
|
|
@@ -305,19 +339,18 @@ void GraphView::calculateRangeXY()
|
|
//TODO: graphview
|
|
//TODO: graphview
|
|
void GraphView::calculateMinMaxXY(GraphSeries& lgs)
|
|
void GraphView::calculateMinMaxXY(GraphSeries& lgs)
|
|
{
|
|
{
|
|
- qDebug() << "calculateMinMaxXY";
|
|
|
|
- auto pairX = std::minmax_element(lgs.data->begin(), lgs.data->end(), [](const QPointF& a, const QPointF& b) -> bool {return a.x() < b.x(); });
|
|
|
|
- lgs.minX = pairX.first->x();
|
|
|
|
- lgs.maxX = pairX.second->x();
|
|
|
|
- auto pairY = std::minmax_element(lgs.data->begin(), lgs.data->end(), [](const QPointF& a, const QPointF& b) -> bool {return a.y() < b.y(); });
|
|
|
|
- lgs.minY = pairY.first->y();
|
|
|
|
- lgs.maxY = pairY.second->y();
|
|
|
|
|
|
+ auto pairX = std::minmax_element(lgs.data->begin(), lgs.data->end(), [](const GraphDataPoint& a, const GraphDataPoint& b) -> bool {return a.x < b.x; });
|
|
|
|
+ lgs.minX = pairX.first->x;
|
|
|
|
+ lgs.maxX = pairX.second->x;
|
|
|
|
+ auto pairY = std::minmax_element(lgs.data->begin(), lgs.data->end(), [](const GraphDataPoint& a, const GraphDataPoint& b) -> bool {return a.y < b.y; });
|
|
|
|
+ lgs.minY = pairY.first->y;
|
|
|
|
+ lgs.maxY = pairY.second->y;
|
|
}
|
|
}
|
|
|
|
|
|
-void GraphView::addSeries(std::vector<QPointF>& line, QColor color, GraphSeries::SeriesType type)
|
|
|
|
|
|
+void GraphView::addSeries(std::vector<GraphDataPoint>& line, QColor color, GraphSeries::SeriesType type)
|
|
{
|
|
{
|
|
- qDebug() << "addSeries";
|
|
|
|
if (line.empty()) {
|
|
if (line.empty()) {
|
|
|
|
+ qDebug() << "Series is empty!";
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
GraphSeries lgs;
|
|
GraphSeries lgs;
|
|
@@ -329,8 +362,6 @@ void GraphView::addSeries(std::vector<QPointF>& line, QColor color, GraphSeries:
|
|
calculateTotalGraphBound();
|
|
calculateTotalGraphBound();
|
|
if (!useFixedBound) calculateRangeXY();
|
|
if (!useFixedBound) calculateRangeXY();
|
|
generateAxisNumberStrings();
|
|
generateAxisNumberStrings();
|
|
- qDebug() << "addSeries " << "minX:" << actualBound.minX << " maxX:" << actualBound.maxX << " minY:" << actualBound.minY << " maxY:" << actualBound.maxY;
|
|
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
QColor GraphView::generateNextColorForGraph()
|
|
QColor GraphView::generateNextColorForGraph()
|
|
@@ -348,8 +379,6 @@ void GraphView::generateAxisNumberStrings()
|
|
xAxisNumbers[i] = QString::number(actualBound.minX + i * (rangeGraphX / (double)X_AXIS_GAP_AMOUNT), 'f', 1);
|
|
xAxisNumbers[i] = QString::number(actualBound.minX + i * (rangeGraphX / (double)X_AXIS_GAP_AMOUNT), 'f', 1);
|
|
yAxisNumbers[i] = QString::number(actualBound.minY + i * (rangeGraphY / (double)Y_AXIS_GAP_AMOUNT), 'f', 1);
|
|
yAxisNumbers[i] = QString::number(actualBound.minY + i * (rangeGraphY / (double)Y_AXIS_GAP_AMOUNT), 'f', 1);
|
|
}
|
|
}
|
|
- qDebug() << "generateAxisNumberStrings " << "minX:" << actualBound.minX << " maxX:" << actualBound.maxX << " minY:" << actualBound.minY << " maxY:" << actualBound.maxY;
|
|
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void GraphView::setUseFixedBound(bool value)
|
|
void GraphView::setUseFixedBound(bool value)
|
|
@@ -373,41 +402,36 @@ void GraphView::generateAndAddRandomLine()
|
|
std::uniform_int_distribution<int> intScaleDistr(1, 3);
|
|
std::uniform_int_distribution<int> intScaleDistr(1, 3);
|
|
|
|
|
|
for (int randomSeries = 0; randomSeries < 1; randomSeries++) {
|
|
for (int randomSeries = 0; randomSeries < 1; randomSeries++) {
|
|
- std::vector<QPointF> randomPointVec(101);
|
|
|
|
|
|
+ std::vector<GraphDataPoint> randomPointVec(101);
|
|
int scale = intScaleDistr(gen);
|
|
int scale = intScaleDistr(gen);
|
|
for (int i = 0; i < randomPointVec.size(); i++) {
|
|
for (int i = 0; i < randomPointVec.size(); i++) {
|
|
- randomPointVec[i] = QPointF(i + 500, i * scale + realDistr(gen));
|
|
|
|
|
|
+ randomPointVec[i] = GraphDataPoint(i + 500, i * scale + realDistr(gen));
|
|
}
|
|
}
|
|
addLine(randomPointVec);
|
|
addLine(randomPointVec);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-void GraphView::addLine(std::vector<QPointF>& line)
|
|
|
|
|
|
+void GraphView::addLine(std::vector<GraphDataPoint>& line)
|
|
{
|
|
{
|
|
addSeries(line, generateNextColorForGraph(), GraphSeries::SeriesType::Line);
|
|
addSeries(line, generateNextColorForGraph(), GraphSeries::SeriesType::Line);
|
|
}
|
|
}
|
|
|
|
|
|
-void GraphView::addLine(std::vector<QPointF>& line, QColor color)
|
|
|
|
|
|
+void GraphView::addLine(std::vector<GraphDataPoint>& line, QColor color)
|
|
{
|
|
{
|
|
addSeries(line, color, GraphSeries::SeriesType::Line);
|
|
addSeries(line, color, GraphSeries::SeriesType::Line);
|
|
}
|
|
}
|
|
|
|
|
|
-void GraphView::addDots(std::vector<QPointF>& dots)
|
|
|
|
|
|
+void GraphView::addDots(std::vector<GraphDataPoint>& dots)
|
|
{
|
|
{
|
|
addSeries(dots, generateNextColorForGraph(), GraphSeries::SeriesType::Dot);
|
|
addSeries(dots, generateNextColorForGraph(), GraphSeries::SeriesType::Dot);
|
|
}
|
|
}
|
|
|
|
|
|
-void GraphView::addDots(std::vector<QPointF>& dots, QColor color)
|
|
|
|
|
|
+void GraphView::addDots(std::vector<GraphDataPoint>& dots, QColor color)
|
|
{
|
|
{
|
|
addSeries(dots, color, GraphSeries::SeriesType::Dot);
|
|
addSeries(dots, color, GraphSeries::SeriesType::Dot);
|
|
}
|
|
}
|
|
|
|
|
|
-std::pair<std::vector<QPointF>::iterator , std::vector<QPointF>::iterator> GraphSeries::getFirstLastIndexInSeriesThatsInBound(int minX, int maxX)
|
|
|
|
-{
|
|
|
|
- std::vector<QPointF>::iterator minIter = std::find_if(data->begin(), data->end(), [minX](const QPointF& p) -> bool {return p.x() >= minX; });
|
|
|
|
- std::vector<QPointF>::iterator maxIter = std::find_if(minIter, data->end(), [maxX](const QPointF& p) -> bool {return p.x() > maxX; });
|
|
|
|
- return std::make_pair(minIter, --maxIter);
|
|
|
|
-}
|
|
|
|
|
|
+
|
|
|
|
|
|
void Bound::move(GraphView* widget,const Change& type, const double changePercentage)
|
|
void Bound::move(GraphView* widget,const Change& type, const double changePercentage)
|
|
{
|
|
{
|
|
@@ -445,7 +469,30 @@ void Bound::move(GraphView* widget,const Change& type, const double changePercen
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- widget->calculateRangeXY();
|
|
|
|
- widget->generateAxisNumberStrings();
|
|
|
|
- widget->repaint();
|
|
|
|
|
|
+ //TODO: Move out of bound in calculate widget
|
|
|
|
+ widget->update();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void Bound::move(GraphView* widget, QPointF& delta, double realPixelWidthX, double realPixelWidthY)
|
|
|
|
+{
|
|
|
|
+ minX += -delta.x() * realPixelWidthX;
|
|
|
|
+ maxX += -delta.x() * realPixelWidthX;
|
|
|
|
+ minY += delta.y() * realPixelWidthY;
|
|
|
|
+ maxY += delta.y() * realPixelWidthY;
|
|
|
|
+ widget->update();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+GraphDataPoint::GraphDataPoint(double x, double y, SolutionPointData* orginalPoint) : x(x), y(y), orginalPoint(orginalPoint)
|
|
|
|
+{
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool GraphDataPoint::existLink()
|
|
|
|
+{
|
|
|
|
+ return orginalPoint != nullptr;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+QPointF GraphDataPoint::toQPointF()
|
|
|
|
+{
|
|
|
|
+ return QPointF(x, y);
|
|
}
|
|
}
|