#ifndef THREAD_H_055
#define THREAD_H_055
#include <QThread>
#ifdef Q_WS_WIN
#pragma once
#endif // Q_WS_WIN
#include <QPainter>
#include <QDockWidget>
#include <QPointF>
#include <QVector>
class PlotSettings;
/// Класс параллельного потока для отрисовки рельефа вертикальной проекции
class VThread: public QThread
{
Q_OBJECT
private:
QPainter painter; ///< рисовальщик
QDockWidget* relief_widget; ///< указатель на виджет, где будет отрисовываться рельеф
int count_read; ///< количество прочитанных элементов
PlotSettings* settings; ///< указатель на настройки для различных масштабов
QVector<QPointF> relief_vec; ///< вектор геграфических точек рельефа
QRect rect; ///< прямоугольная область, в которой будет производиться рисование
private:
QPointF initXY(double& sx, double& sy);
void drawReliefNature(QPainter* painter, QPointF cur, QPointF prev);
void drawBlackLineRelief(QPainter* painter, const QVector<QPointF>& vecBLine);
void drawCurves(QPainter* painter);
void drawTrackRelief(QPainter* painter);
protected:
virtual void run();
public:
VThread(): relief_widget(0), count_read(0), settings(0) {}
VThread(QDockWidget* rlf_widget): painter(rlf_widget), relief_widget(rlf_widget), count_read(0), settings(0) {}
~VThread() {}
void widget(QDockWidget* rlf_widget) { relief_widget = rlf_widget; }
QDockWidget* widget() { return relief_widget; }
void count(const int r) { count_read = r; }
const int count() { return count_read; }
void init(PlotSettings* s, QRect& rct) { settings = s; rect = rct; }
void init(PlotSettings* s) { settings = s; }
void init(QRect& rct) { rect = rct; }
void initVec(QVector<QPointF>& rv) { relief_vec = rv; }
void stop(const int size) { if(count_read == size) quit(); }
};
#endif // THREAD_H_055
#include "Thread.h"
#include <QtGui>
/// Инициализация координат - преобразование из координат графика (sx,sy) в экранные (x,y)
QPointF VThread::initXY(double& sx, double& sy)
{
const int shift_x = 30;
if(!rect.isValid()) return QPointF();
QRect rect_shift(rect); rect_shift.setLeft(rect_shift.left() + shift_x);
double dx, dy;
dx = sx - settings -> minX;
dy = sy - settings -> minY;
double x = rect_shift.left() + (dx * (rect_shift.width() - 1) / settings -> spanX());;
double y = rect.bottom() - (dy * (rect.height() - 1) / settings -> spanY());
return QPointF(x, y);
}
/// Настройка цвета рельефа (естественный цвет)
void VThread::drawReliefNature(QPainter* painter, QPointF cur, QPointF prev)
{
double distance = cur.x(), delta_height = cur.y();
QPointF scrPnt(initXY(distance, delta_height));
if(delta_height <= 0 || scrPnt.y() >= settings -> maxY)
return;
QColor color(demGetColor(demCalcColor(delta_height)));
double delta_height0;
int div = delta_height > 1000 ? 50 : 5;
int i = (int)(delta_height / div);
if(!((int)delta_height % div)) --i;
delta_height0 = div * i;
double prev_dist = prev.x(), prev_height = prev.y();
QPointF screenPoint(initXY(distance, delta_height0)), scrPrev(initXY(prev_dist, prev_height));
QBrush old_brush(painter -> brush());
QPen old_pen(painter -> pen());
painter -> setBrush(QBrush(color));
painter -> setPen(QPen(color));
painter -> drawLine(scrPrev, screenPoint);
for(int ix=scrPrev.x()+1; ix<screenPoint.x(); ++ix)
painter -> drawLine(QPointF(ix, scrPrev.y()), screenPoint);
painter -> setPen(old_pen);
painter -> setBrush(old_brush);
QPointF cur0(distance, delta_height0);
drawReliefNature(painter, cur0, cur);
}
/// Отрисовка черной линии рельефа для лучшей видимости его изгибов
void VThread::drawBlackLineRelief(QPainter* painter, const QVector<QPointF>& vecBLine)
{
QBrush old_brush(painter -> brush());
QPen old_pen(painter -> pen());
painter -> setPen(Qt::black);
painter -> setBrush(Qt::black);
for(int i=vecBLine.size()-1, j=vecBLine.size()-1; i>=0; --i)
{
painter -> drawLine(vecBLine[i], vecBLine[j]);
if(i != vecBLine.size() - 1) --j;
}
painter -> setPen(old_pen);
painter -> setBrush(old_brush);
}
/// Отрисовка рельефа
void VThread::drawTrackRelief(QPainter* painter)
{
QVector<QPointF> vecBLine;
int size = relief_vec.size();
for(QVector<QPointF>::iterator rlfPnt=relief_vec.begin(), i_prev=relief_vec.begin(); rlfPnt!=relief_vec.end();
++rlfPnt, ++count_read)
{
usedRlfSpace.acquire();
QPointF cur(*rlfPnt), prev(*i_prev);
double X = cur.x(), Y = cur.y(), prevX = prev.x(), prevY = prev.y();
QPointF screen(initXY(X, Y));
drawReliefNature(painter, cur, prev);
if(rlfPnt != relief_vec.begin()) ++i_prev;
usedRlfSpace.release();
vecBLine.append(screen);
}
drawBlackLineRelief(painter, vecBLine);
}
/// Запуск дополницельного потока
void VThread::run()
{
drawTrackRelief(&painter);
}
ReliefGraphics::ReliefGraphics(QWidget *parent): settings(0), main_window(0), fill_axis(0), count_logrecords(0),
maxValY(-1.0e23), minValY(1.0e23), is_resizing(false), fin_init(false)
{
int r_width = displayRelief -> rect().width() - 1.5 * toolBar -> rect().width();
int r_height = displayRelief -> rect().height() - 2.5 * VerticalGraphicClass::scroll -> rect().height();
QRect rect(displayRelief -> rect().x() + toolBar -> rect().width(), displayRelief -> rect().y() +
VerticalGraphicClass::scroll -> rect().height(), r_width, r_height);
settings = new PlotSettings();
vrt_thread = new VThread(this);
vrt_thread -> init(settings, rect);
}
/// Отрисовка графика
void ReliefGraphics::paintEvent(QPaintEvent* events)
{
painter.begin(this);
/// Что-то еще отрисовывается (траектория, например)
vrt_thread -> stop(count_logrecords);
painter.end();
}
/// Отображение вертикальной проекции
void TLV::verticProjection(QAction* _sender)
{
verticPrjAction = _sender;
if(!verticalProjection) return;
verticalProjection -> setVisible(verticPrjAction -> isChecked());
if(verticPrjAction -> isChecked()) verticalProjection -> start();
}