diff --git a/libs/graphic3d/CMakeLists.txt b/libs/graphic3d/CMakeLists.txt new file mode 100644 index 0000000..2fb3097 --- /dev/null +++ b/libs/graphic3d/CMakeLists.txt @@ -0,0 +1,4 @@ +if (HAS_GL) + qad_library(graphic3d "Gui;Widgets;DataVisualization" "") +endif() + diff --git a/libs/graphic3d/scatter3d.cpp b/libs/graphic3d/scatter3d.cpp new file mode 100644 index 0000000..4f07246 --- /dev/null +++ b/libs/graphic3d/scatter3d.cpp @@ -0,0 +1,130 @@ +#include "scatter3d.h" + +#include +#include +#include +#include +#include + + +Scatter3D::Scatter3D(QWidget * parent): QWidget{parent} { + curGraphic = 0; + canvas = new QtDataVisualization::Q3DScatter(); + canvas->setFlag(Qt::FramelessWindowHint); + canvas->axisZ()->setReversed(true); + canvas->setShadowQuality(QtDataVisualization::QAbstract3DGraph::ShadowQualityNone); + container = QWidget::createWindowContainer(canvas); + setLayout(new QVBoxLayout(this)); + layout()->addWidget(container); +} + + +Scatter3D::~Scatter3D() { + clear(); + canvas->setParent(nullptr); + canvas->deleteLater(); +} + + +QColor Scatter3D::graphicColor(int index) const { + return graphics[index].series->baseColor(); +} + + +float Scatter3D::graphicPointSize(int index) const { + return graphics[index].series->itemSize(); +} + + +Scatter3D::Mesh Scatter3D::graphicMesh(int index) const { + return graphics[index].series->mesh(); +} + + +bool Scatter3D::labelAutoRotation() const { + return canvas->axisX()->labelAutoRotation() == 0; +} + + +void Scatter3D::setCurrentGraphic(int arg) { + if (arg < 0 || arg >= graphics.size()) return; + curGraphic = arg; +} + + +void Scatter3D::setGraphicsCount(int count) { + if (count < 0) return; + while (graphics.size() < count) { + addGraphic(); + } + while (graphics.size() > count) { + auto sg = graphics.takeLast(); + canvas->removeSeries(sg.series); + delete sg.series; + delete sg.data; + } + container->update(); +} + + +void Scatter3D::setGraphicColor(const QColor & color, int index) { + graphics[index].series->setBaseColor(color); + container->update(); +} + + +void Scatter3D::setGraphicPointSize(float sz, int index) { + graphics[index].series->setItemSize(sz); + container->update(); +} + + +void Scatter3D::setGraphicMesh(Mesh mesh, int index) { + graphics[index].series->setMesh(mesh); + container->update(); +} + + +void Scatter3D::addGraphic(const QColor & color, float pointSize, Mesh mesh) { + Scatter3DGraphic sg; + sg.data = new QtDataVisualization::QScatterDataProxy(); + sg.series = new QtDataVisualization::QScatter3DSeries(sg.data); + sg.series->setItemSize(pointSize); + sg.series->setBaseColor(color); + sg.series->setMesh(mesh); + sg.series->setMeshSmooth(true); + graphics.append(sg); + canvas->addSeries(sg.series); + container->update(); +} + + +void Scatter3D::setLabelAutoRotation(bool on) { + if (on) { + canvas->axisX()->setLabelAutoRotation(90); + canvas->axisY()->setLabelAutoRotation(90); + canvas->axisZ()->setLabelAutoRotation(90); + } else { + canvas->axisX()->setLabelAutoRotation(0); + canvas->axisY()->setLabelAutoRotation(0); + canvas->axisZ()->setLabelAutoRotation(0); + } + container->update(); +} + + +void Scatter3D::setGraphicData(const QVector & points, int index) { + auto arr = new QtDataVisualization::QScatterDataArray(); + arr->reserve(points.size()); + for (const auto & p: points) { + arr->append(p); + } + graphics[index].data->resetArray(arr); + container->update(); +} + + +void Scatter3D::addPoint(const QVector3D & point, int index) { + graphics[index].data->addItem(point); +} + diff --git a/libs/graphic3d/scatter3d.h b/libs/graphic3d/scatter3d.h new file mode 100644 index 0000000..97f2d6f --- /dev/null +++ b/libs/graphic3d/scatter3d.h @@ -0,0 +1,90 @@ +/* + QAD - Qt ADvanced + + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef SCATTER_H +#define SCATTER_H + +#include "qad_graphic3d_export.h" + +#include +#include + +namespace QtDataVisualization { +class Q3DScatter; +class QScatterDataProxy; +class QScatter3DSeries; +} // namespace QtDataVisualization + +class QAD_GRAPHIC3D_EXPORT Scatter3D: public QWidget { + Q_OBJECT + + using Mesh = QtDataVisualization::QAbstract3DSeries::Mesh; + + Q_PROPERTY(int currentGraphic READ currentGraphic WRITE setCurrentGraphic) + Q_PROPERTY(int graphicsCount READ graphicsCount WRITE setGraphicsCount) + Q_PROPERTY(QColor graphicColor READ graphicColor WRITE setGraphicColor) + Q_PROPERTY(float graphicPointSize READ graphicPointSize WRITE setGraphicPointSize) + Q_PROPERTY(Mesh graphicMesh READ graphicMesh WRITE setGraphicMesh) + Q_PROPERTY(bool labelAutoRotation READ labelAutoRotation WRITE setLabelAutoRotation) + +public: + explicit Scatter3D(QWidget * parent = nullptr); + ~Scatter3D(); + + int currentGraphic() const { return curGraphic; } + int graphicsCount() const { return graphics.size(); } + QColor graphicColor() const { return graphicColor(curGraphic); } + QColor graphicColor(int index) const; + float graphicPointSize() const { return graphicPointSize(curGraphic); } + float graphicPointSize(int index) const; + Mesh graphicMesh() const { return graphicMesh(curGraphic); } + Mesh graphicMesh(int index) const; + bool labelAutoRotation() const; + +public slots: + void setCurrentGraphic(int arg); + void setGraphicsCount(int count); + void setGraphicColor(const QColor & color, int index); + void setGraphicColor(const QColor & color) { setGraphicColor(color, curGraphic); } + void setGraphicPointSize(float sz, int index); + void setGraphicPointSize(float sz) { setGraphicPointSize(sz, curGraphic); } + void setGraphicMesh(Mesh mesh, int index); + void setGraphicMesh(Mesh mesh) { setGraphicMesh(mesh, curGraphic); } + void addGraphic(const QColor & color = Qt::darkBlue, float pointSize = 1.f, Mesh mesh = Mesh::MeshSphere); + void clear() { setGraphicsCount(0); } + void setLabelAutoRotation(bool on); + void setGraphicData(const QVector & points, int index); + void setGraphicData(const QVector & points) { setGraphicData(points, curGraphic); } + void addPoint(const QVector3D & point, int index); + void addPoint(const QVector3D & point) { addPoint(point, curGraphic); } + +private: + struct Scatter3DGraphic { + QtDataVisualization::QScatter3DSeries * series; + QtDataVisualization::QScatterDataProxy * data; + }; + + QWidget * container; + QtDataVisualization::Q3DScatter * canvas; + QVector graphics; + + int curGraphic; +}; + +#endif // SCATTER_H