diff --git a/examples/basic/mainwindow.ui b/examples/basic/mainwindow.ui index 90eb174..220774c 100644 --- a/examples/basic/mainwindow.ui +++ b/examples/basic/mainwindow.ui @@ -96,93 +96,138 @@ Axes - - - 4 - - - 4 - - - 4 - - - 4 - - - 4 - - - - - Z - - - - - - - - 0 - 0 - - - - - - - - X - - - - - - - - 0 - 0 - - - - - - - - Y - - - - - - - - 0 - 0 - - - - - - - - Visible - - + + + + + + + X + + + + + + + + 0 + 0 + + + + + + + + Visible + + + + + + + 0 + + + -180.000000000000000 + + + 180.000000000000000 + + + 5.000000000000000 + + + + - - - - Visible - - + + + + + + Y + + + + + + + + 0 + 0 + + + + + + + + Visible + + + + + + + 0 + + + -180.000000000000000 + + + 180.000000000000000 + + + 5.000000000000000 + + + + - - - - Visible - - + + + + + + Z + + + + + + + + 0 + 0 + + + + + + + + Visible + + + + + + + 0 + + + -180.000000000000000 + + + 180.000000000000000 + + + 5.000000000000000 + + + + @@ -241,7 +286,7 @@ 0 0 956 - 22 + 23 diff --git a/examples/basic/mainwindow_funcs.cpp b/examples/basic/mainwindow_funcs.cpp index 6801cab..b75daca 100644 --- a/examples/basic/mainwindow_funcs.cpp +++ b/examples/basic/mainwindow_funcs.cpp @@ -15,18 +15,25 @@ MainWindow::MainWindow() : QMainWindow() connect(ui_.FlatViewCheck, SIGNAL(clicked(bool)), ui_.TestingWidget, SLOT(setFlatView(bool))); // Axes - ui_.XTitleEdit->setText(ui_.TestingWidget->xAxis()->titleText()); - connect(ui_.XTitleEdit, SIGNAL(textChanged(const QString &)), ui_.TestingWidget, SLOT(setXAxisTitle(const QString &))); - ui_.YTitleEdit->setText(ui_.TestingWidget->yAxis()->titleText()); - connect(ui_.YTitleEdit, SIGNAL(textChanged(const QString &)), ui_.TestingWidget, SLOT(setYAxisTitle(const QString &))); - ui_.ZTitleEdit->setText(ui_.TestingWidget->zAxis()->titleText()); - connect(ui_.ZTitleEdit, SIGNAL(textChanged(const QString &)), ui_.TestingWidget, SLOT(setZAxisTitle(const QString &))); + // -- Titles + ui_.XLabelEdit->setText(ui_.TestingWidget->xAxis()->labelText()); + connect(ui_.XLabelEdit, SIGNAL(textChanged(const QString &)), ui_.TestingWidget, SLOT(setXAxisLabel(const QString &))); + ui_.YLabelEdit->setText(ui_.TestingWidget->yAxis()->labelText()); + connect(ui_.YLabelEdit, SIGNAL(textChanged(const QString &)), ui_.TestingWidget, SLOT(setYAxisLabel(const QString &))); + ui_.ZLabelEdit->setText(ui_.TestingWidget->zAxis()->labelText()); + connect(ui_.ZLabelEdit, SIGNAL(textChanged(const QString &)), ui_.TestingWidget, SLOT(setZAxisLabel(const QString &))); + // -- Visibility ui_.XVisibleCheck->setChecked(ui_.TestingWidget->xAxis()->isEnabled()); connect(ui_.XVisibleCheck, SIGNAL(toggled(bool)), ui_.TestingWidget->xAxis(), SLOT(setEnabled(bool))); ui_.YVisibleCheck->setChecked(ui_.TestingWidget->yAxis()->isEnabled()); connect(ui_.YVisibleCheck, SIGNAL(toggled(bool)), ui_.TestingWidget->yAxis(), SLOT(setEnabled(bool))); ui_.ZVisibleCheck->setChecked(ui_.TestingWidget->zAxis()->isEnabled()); connect(ui_.ZVisibleCheck, SIGNAL(toggled(bool)), ui_.TestingWidget->zAxis(), SLOT(setEnabled(bool))); + // -- Rotation + ui_.XLabelRotationSpin->setValue(ui_.TestingWidget->xAxis()->labelRotation()); + connect(ui_.XLabelRotationSpin, SIGNAL(valueChanged(double)), ui_.TestingWidget, SLOT(setXAxisLabelRotation(double))); + connect(ui_.YLabelRotationSpin, SIGNAL(valueChanged(double)), ui_.TestingWidget, SLOT(setYAxisLabelRotation(double))); + connect(ui_.ZLabelRotationSpin, SIGNAL(valueChanged(double)), ui_.TestingWidget, SLOT(setZAxisLabelRotation(double))); // Mouse Coordinates ui_.mouseCoordStyleCombo->addItem(QString("Fixed Anchor")); @@ -71,11 +78,10 @@ void MainWindow::on_mouseCoordStyleCombo_currentIndexChanged(int index) break; default: throw(std::runtime_error("Unhandled coordinate display style.\n")); - break; } } void MainWindow::setExternalMouseCoordinatesText(QPointF p) { ui_.externalMouseCoordLabel->setText(QString("%1 %2").arg(QString::number(p.x()), QString::number(p.y()))); -} \ No newline at end of file +} diff --git a/src/classes/cuboid.cpp b/src/classes/cuboid.cpp index 5406644..beed85e 100644 --- a/src/classes/cuboid.cpp +++ b/src/classes/cuboid.cpp @@ -1,4 +1,5 @@ #include "classes/cuboid.h" +#include using namespace Mildred; @@ -195,3 +196,32 @@ float Cuboid::zExtent() const //! Return vector of extents QVector3D Cuboid::extents() const { return {xExtent(), yExtent(), zExtent()}; } + +//! Return bounding box cuboid required for rotated original cuboid (in degrees, around z-axis) +/*! + * Returns the bounding cuboid required to contain the original cuboid rotated @param rotation + * @return + */ +Cuboid Cuboid::zRotatedBoundingCuboid(QVector3D rotationOrigin, double thetaZ) const +{ + QMatrix4x4 m; + m.rotate(thetaZ, QVector3D{0.0, 0.0, 1.0}); + std::array corners; + corners[0] = QPointF(v1x_.value_or(0.0) - rotationOrigin.x(), v1y_.value_or(0.0) - rotationOrigin.y()); + corners[1] = QPointF(v2x_.value_or(0.0) - rotationOrigin.x(), v1y_.value_or(0.0) - rotationOrigin.y()); + corners[2] = QPointF(v1x_.value_or(0.0) - rotationOrigin.x(), v2y_.value_or(0.0) - rotationOrigin.y()); + corners[3] = QPointF(v2x_.value_or(0.0) - rotationOrigin.x(), v2y_.value_or(0.0) - rotationOrigin.y()); + + Cuboid rotated; + for (const auto &p : corners) + { + auto newP = m.map(p); + rotated.expand(newP.x() + rotationOrigin.x(), newP.y() + rotationOrigin.y(), {}); + } + + // Set Z extents + rotated.v1z_ = v1z_; + rotated.v2z_ = v2z_; + + return rotated; +} diff --git a/src/classes/cuboid.h b/src/classes/cuboid.h index 5bb24e8..6d4aee1 100644 --- a/src/classes/cuboid.h +++ b/src/classes/cuboid.h @@ -60,5 +60,7 @@ class Cuboid float zExtent() const; // Return vector of extents QVector3D extents() const; + // Return bounding box cuboid required for rotated original cuboid (in degrees, around z-axis) + Cuboid zRotatedBoundingCuboid(QVector3D rotationOrigin, double thetaZ) const; }; } // namespace Mildred \ No newline at end of file diff --git a/src/entities/axis.cpp b/src/entities/axis.cpp index 3d3f9eb..fe1e9ab 100644 --- a/src/entities/axis.cpp +++ b/src/entities/axis.cpp @@ -23,8 +23,8 @@ AxisEntity::AxisEntity(Qt3DCore::QNode *parent, AxisType type, const MildredMetr axisBarEntity_ = new LineEntity(this); ticksEntity_ = new LineEntity(this, Qt3DRender::QGeometryRenderer::Lines); subTicksEntity_ = new LineEntity(this, Qt3DRender::QGeometryRenderer::Lines); - axisTitleEntity_ = new TextEntity(this, "Unnamed Axis"); - axisTitleEntity_->setAnchorPoint(MildredMetrics::AnchorPoint::TopMiddle); + labelEntity_ = new TextEntity(this, "Unnamed Axis"); + labelEntity_->setAnchorPoint(MildredMetrics::AnchorPoint::TopMiddle); // Assign material components axisBarMaterial_ = barMaterial; @@ -32,7 +32,7 @@ AxisEntity::AxisEntity(Qt3DCore::QNode *parent, AxisType type, const MildredMetr ticksEntity_->addComponent(axisBarMaterial_); subTicksEntity_->addComponent(axisBarMaterial_); labelMaterial_ = labelMaterial; - axisTitleEntity_->setMaterial(labelMaterial_); + labelEntity_->setMaterial(labelMaterial_); // Update data dependent on the axis type setType(type_); @@ -303,24 +303,24 @@ void AxisEntity::shiftLimitsByPixels(int pixelDelta) //! Return whether the axis is logarithmic bool AxisEntity::isLogarithmic() const { return logarithmic_; } -//! Set title text +//! Set label text /*! - * Sets the display title of the axis to @param text, modifying the underlying @class TextEntity object. + * Sets the display label of the axis to @param text, modifying the underlying @class TextEntity object. */ -void AxisEntity::setTitleText(const QString &text) +void AxisEntity::setLabelText(const QString &text) { - assert(axisTitleEntity_); - axisTitleEntity_->setText(text); + assert(labelEntity_); + labelEntity_->setText(text); } -//! Return title text +//! Return label text /*! - * Returns the current text displayed as the axis title. + * Returns the current text displayed as the axis label. */ -QString AxisEntity::titleText() const +QString AxisEntity::labelText() const { - assert(axisTitleEntity_); - return axisTitleEntity_->text(); + assert(labelEntity_); + return labelEntity_->text(); } //! Set axis minimum @@ -466,6 +466,25 @@ void AxisEntity::setType(AxisType type) } } +//! Define title rotation +/*! + * Set the rotation of the main label to @param rotation (degrees). + */ +void AxisEntity::setLabelRotation(double rotation) { labelEntity_->setRotation(rotation); } + +//! Return main label rotation +double AxisEntity::labelRotation() const { return labelEntity_->rotation(); } + +//! Define tick label rotation +/*! + * Set the rotation of the tick labels to @param rotation. + */ +void AxisEntity::setTickLabelRotation(double rotation) +{ + for (auto &entity : tickLabelEntities_) + entity->setRotation(rotation); +} + //! Define direction /*! * Set the direction of the axis in 3D space to the supplied vector @param v. @@ -578,11 +597,7 @@ Cuboid AxisEntity::createTickAndLabelEntities(const std::vectorsetText(QString::number(v)); (*tickLabelEntity) ->setAnchorPosition(axisPos + tickDirection_ * (metrics_.tickPixelSize() + metrics_.tickLabelPixelGap())); - boundingCuboid.expand(TextEntity::boundingCuboid( - metrics_.axisTickLabelFont(), QString::number(v), - {axisPos + tickDirection_ * (metrics_.tickPixelSize() + metrics_.tickLabelPixelGap())}, - labelAnchorPoint_) - .first); + boundingCuboid.expand((*tickLabelEntity)->boundingCuboid(metrics_.axisTickLabelFont()).first); ++tickLabelEntity; } else @@ -636,17 +651,17 @@ void AxisEntity::recreate() auto tickLabelBounds = createTickAndLabelEntities(ticks); // Axis title - if (!axisTitleEntity_->text().isEmpty()) + if (!labelEntity_->text().isEmpty()) { - axisTitleEntity_->setEnabled(true); - axisTitleEntity_->setFont(metrics_.axisTitleFont()); - axisTitleEntity_->setAnchorPoint(labelAnchorPoint_); - axisTitleEntity_->setAnchorPosition( - direction_ * metrics_.displayVolumeExtent()[axisDirectionIndex_] * 0.5 + - tickDirection_ * (tickLabelBounds.extents()[tickDirectionIndex_] + metrics_.tickLabelPixelGap())); + labelEntity_->setEnabled(true); + labelEntity_->setFont(metrics_.axisTitleFont()); + labelEntity_->setAnchorPoint(labelAnchorPoint_); + labelEntity_->setAnchorPosition(direction_ * metrics_.displayVolumeExtent()[axisDirectionIndex_] * 0.5 + + tickDirection_ * + (tickLabelBounds.extents()[tickDirectionIndex_] + metrics_.tickLabelPixelGap())); } else - axisTitleEntity_->setEnabled(false); + labelEntity_->setEnabled(false); ticksEntity_->setBasicIndices(); ticksEntity_->finalise(); @@ -697,20 +712,20 @@ Cuboid AxisEntity::boundingCuboid(const MildredMetrics &metrics) const cuboid.expand( TextEntity::boundingCuboid(metrics.axisTickLabelFont(), QString::number(v), axisPos + tickDirection_ * (metrics_.tickPixelSize() + metrics.tickLabelPixelGap()), - labelAnchorPoint_) + labelAnchorPoint_, 0.0) .first); } else cuboid.expand({axisPos, axisPos + tickDirection_ * metrics_.tickPixelSize() * 0.5}); } // -- Title - if (!axisTitleEntity_->text().isEmpty()) - cuboid.expand(TextEntity::boundingCuboid(metrics.axisTitleFont(), axisTitleEntity_->text(), - direction_ * metrics.displayVolumeExtent()[axisDirectionIndex_] * 0.5 + - tickDirection_ * - (cuboid.extents()[tickDirectionIndex_] + metrics.tickLabelPixelGap()), - labelAnchorPoint_) - .first); + if (!labelEntity_->text().isEmpty()) + cuboid.expand( + labelEntity_ + ->boundingCuboid(metrics.axisTitleFont(), + direction_ * metrics.displayVolumeExtent()[axisDirectionIndex_] * 0.5 + + tickDirection_ * (cuboid.extents()[tickDirectionIndex_] + metrics.tickLabelPixelGap())) + .first); return cuboid; } diff --git a/src/entities/axis.h b/src/entities/axis.h index e54f30f..1f6efae 100644 --- a/src/entities/axis.h +++ b/src/entities/axis.h @@ -78,10 +78,6 @@ class AxisEntity : public Qt3DCore::QEntity void shiftLimitsByPixels(int pixelDelta); // Return whether the axis is logarithmic bool isLogarithmic() const; - // Set title text - void setTitleText(const QString &text); - // Return title text - QString titleText() const; public slots: // Set axis minimum @@ -114,6 +110,16 @@ class AxisEntity : public Qt3DCore::QEntity public: // Set axis type void setType(AxisType type); + // Set label text + void setLabelText(const QString &text); + // Return label text + QString labelText() const; + // Set main label rotation + void setLabelRotation(double rotation); + // Return label rotation + double labelRotation() const; + // Set tick label rotation + void setTickLabelRotation(double rotation); // Set explicit direction void setDirection(QVector3D v); // Return explicit direction @@ -139,8 +145,8 @@ class AxisEntity : public Qt3DCore::QEntity LineEntity *ticksEntity_{nullptr}, *subTicksEntity_{nullptr}; // Tick labels std::vector tickLabelEntities_; - // Axis title - TextEntity *axisTitleEntity_{nullptr}; + // Main label + TextEntity *labelEntity_{nullptr}; private: // Create / update ticks and labels at specified axis values, returning their bounding cuboid diff --git a/src/entities/line.cpp b/src/entities/line.cpp index 3c46c10..e8a8a3e 100644 --- a/src/entities/line.cpp +++ b/src/entities/line.cpp @@ -65,6 +65,16 @@ LineEntity::LineEntity(Qt3DCore::QNode *parent, Qt3DRender::QGeometryRenderer::P */ void LineEntity::addVertex(QVector3D v) { cachedVertices_.emplace_back(v); } +//! Append vertex to cached data +/*! + * Append the vertex defined by the coordinates @param x, @param y, and @param z to the cached vertices. The buffer objects (and + * hence the display primitive) are not regenerated until a call to the finalise() method is made. + */ +void LineEntity::addVertex(double x, double y, double z) +{ + cachedVertices_.emplace_back(QVector3D{float(x), float(y), float(z)}); +} + //! Append vertex and colour to cached data /*! * Append the vertex @param v to the cached vertices, with the specific @param colour. The buffer objects (and hence the display @@ -76,7 +86,7 @@ void LineEntity::addVertex(QVector3D v, QColor colour) cachedVertexColours_.emplace_back(colour); } -//! Append verteices to cached data +//! Append vertices to cached data /*! * Append the vector of @param vertices to the cached vertices. The buffer objects (and hence the display primitive) are not * regenerated until a call to the finalise() method is made. diff --git a/src/entities/line.h b/src/entities/line.h index 3e9ab13..169d70d 100644 --- a/src/entities/line.h +++ b/src/entities/line.h @@ -45,6 +45,7 @@ class LineEntity : public Qt3DCore::QEntity public: // Append vertices to cached data void addVertex(QVector3D v); + void addVertex(double x, double y, double z); void addVertex(QVector3D v, QColor colour); void addVertices(const std::vector &vertices); // Append indices to cached data diff --git a/src/entities/text.cpp b/src/entities/text.cpp index f878ec8..9d49bba 100644 --- a/src/entities/text.cpp +++ b/src/entities/text.cpp @@ -1,9 +1,10 @@ #include "entities/axis.h" +#include using namespace Mildred; -// Enables showing of bounding boxes around Text Entities. -constexpr auto showBoundingBoxes = false; +// Enables showing of bounding cuboids around Text Entities. +constexpr auto showBoundingCuboids = true; //! Construct a new text entity /*! @@ -34,12 +35,12 @@ TextEntity::TextEntity(Qt3DCore::QNode *parent, QString text) : Qt3DCore::QEntit textTransform_->setScale3D({10.0f, 10.0f, 1.0f}); textEntity_->addComponent(textTransform_); - // Add bounding box entity - if (showBoundingBoxes) + // Add bounding cuboid entity + if (showBoundingCuboids) { - boundingBoxEntity_ = new LineEntity(this); - boundingBoxTransform_ = new Qt3DCore::QTransform(boundingBoxEntity_); - boundingBoxEntity_->addComponent(boundingBoxTransform_); + boundingCuboidEntity_ = new LineEntity(this); + boundingCuboidTransform_ = new Qt3DCore::QTransform(boundingCuboidEntity_); + boundingCuboidEntity_->addComponent(boundingCuboidTransform_); anchorPointEntity_ = new LineEntity(this, Qt3DRender::QGeometryRenderer::PrimitiveType::Lines); anchorPointEntity_->addVertex({3.0, 0.0, 0.0}); anchorPointEntity_->addVertex({-3.0, 0.0, 0.0}); @@ -85,22 +86,25 @@ void TextEntity::updateTranslation() // Set the main positional transform positionalTransform_->setTranslation(anchorPosition_); + // Set the rotation about z. + positionalTransform_->setRotationZ(rotation_); + // Set the text translation vector so that the defined anchor point is located at {0,0,0} auto [textCuboid, translation] = boundingCuboid(textMesh_->font(), textMesh_->text(), {}, anchorPoint_, textMesh_->depth()); auto v = QVector3D(textCuboid.lowerLeftBack().x(), textCuboid.lowerLeftBack().y(), 0.0); textTransform_->setTranslation(v + translation); // Update the bounding box entity - if (boundingBoxEntity_) + if (boundingCuboidEntity_) { - boundingBoxEntity_->clear(); - boundingBoxEntity_->addVertex({textCuboid.lowerLeftBack().x(), textCuboid.lowerLeftBack().y(), 0}); - boundingBoxEntity_->addVertex({textCuboid.upperRightFront().x(), textCuboid.lowerLeftBack().y(), 0}); - boundingBoxEntity_->addVertex({textCuboid.upperRightFront().x(), textCuboid.upperRightFront().y(), 0}); - boundingBoxEntity_->addVertex({textCuboid.lowerLeftBack().x(), textCuboid.upperRightFront().y(), 0}); - boundingBoxEntity_->addVertex({textCuboid.lowerLeftBack().x(), textCuboid.lowerLeftBack().y(), 0}); - boundingBoxEntity_->setBasicIndices(); - boundingBoxEntity_->finalise(); + boundingCuboidEntity_->clear(); + boundingCuboidEntity_->addVertex(textCuboid.lowerLeftBack().x(), textCuboid.lowerLeftBack().y(), 0.0); + boundingCuboidEntity_->addVertex(textCuboid.upperRightFront().x(), textCuboid.lowerLeftBack().y(), 0.0); + boundingCuboidEntity_->addVertex(textCuboid.upperRightFront().x(), textCuboid.upperRightFront().y(), 0.0); + boundingCuboidEntity_->addVertex(textCuboid.lowerLeftBack().x(), textCuboid.upperRightFront().y(), 0.0); + boundingCuboidEntity_->addVertex(textCuboid.lowerLeftBack().x(), textCuboid.lowerLeftBack().y(), 0.0); + boundingCuboidEntity_->setBasicIndices(); + boundingCuboidEntity_->finalise(); } } @@ -142,6 +146,23 @@ void TextEntity::setAnchorPosition(QVector3D p) updateTranslation(); } +//! Set rotation of text +void TextEntity::setRotation(double rotation) +{ + rotation_ = rotation; + + updateTranslation(); +} + +//! Return rotation about anchor point +double TextEntity::rotation() const { return rotation_; } + +// Return bounding cuboid and anchor translation vector for current text and positioning +std::pair TextEntity::boundingCuboid(const QFont &font, std::optional newAnchorPosition) const +{ + return boundingCuboid(font, text(), newAnchorPosition.value_or(anchorPosition_), anchorPoint_, rotation_, 0.01); +} + //! Return simple bounding cuboid for text, along with baseline descent from font metrics /*! * Calculates a bounding cuboid in the XY plane for the specified @param font and @param text. The @param depth is applied in @@ -170,7 +191,7 @@ std::pair TextEntity::boundingCuboid(const QFont &font, const QStri * should be applied to the mesh to be rendered in order to get the correct positioning. */ std::pair TextEntity::boundingCuboid(const QFont &font, const QString &text, QVector3D anchorPosition, - MildredMetrics::AnchorPoint anchorPoint, float depth) + MildredMetrics::AnchorPoint anchorPoint, double rotation, float depth) { // Get basic bounding cuboid for the text auto [cuboid, descent] = boundingCuboid(font, text, depth); @@ -197,5 +218,6 @@ std::pair TextEntity::boundingCuboid(const QFont &font, const auto anchorFrac = MildredMetrics::anchorLocation(anchorPoint); cuboid.translate(-QVector3D(cuboid.xExtent() * anchorFrac.x(), cuboid.yExtent() * anchorFrac.y(), 0.0)); - return {cuboid, meshTranslation}; -} + // Return the bounding cuboid (accounting for rotation) + return {cuboid.zRotatedBoundingCuboid(anchorPosition, rotation), meshTranslation}; +} \ No newline at end of file diff --git a/src/entities/text.h b/src/entities/text.h index a067250..a4ea684 100644 --- a/src/entities/text.h +++ b/src/entities/text.h @@ -10,6 +10,7 @@ namespace Mildred { + //! TextEntity represents a 3D text entity /*! * TextEntity represents a renderable entity displaying a specified string with a given transform. @@ -23,6 +24,8 @@ class TextEntity : public Qt3DCore::QEntity private: // Collective positional transform Qt3DCore::QTransform *positionalTransform_{nullptr}; + // Rotation + double rotation_{0.0}; // Material RenderableMaterial *material_{nullptr}; // Main entity @@ -31,10 +34,10 @@ class TextEntity : public Qt3DCore::QEntity Qt3DExtras::QExtrudedTextMesh *textMesh_{nullptr}; // Transform Qt3DCore::QTransform *textTransform_{nullptr}; - // Bounding box and anchor point entities - LineEntity *boundingBoxEntity_{nullptr}, *anchorPointEntity_{nullptr}; - // Transforms for bounding box and anchor point entities - Qt3DCore::QTransform *boundingBoxTransform_{nullptr}; + // Bounding cuboid and anchor point entities + LineEntity *boundingCuboidEntity_{nullptr}, *anchorPointEntity_{nullptr}; + // Transforms for bounding cuboid and anchor point entities + Qt3DCore::QTransform *boundingCuboidTransform_{nullptr}; public: // Set text material @@ -64,10 +67,18 @@ class TextEntity : public Qt3DCore::QEntity void setAnchorPoint(MildredMetrics::AnchorPoint anchor); // Set anchor position void setAnchorPosition(QVector3D p); + // Set rotation about anchor point + void setRotation(double rotation); + // Return rotation about anchor point + double rotation() const; + // Return bounding cuboid and anchor translation vector for current text and positioning + std::pair boundingCuboid(const QFont &font, + std::optional newAnchorPosition = std::nullopt) const; // Return simple bounding cuboid for text, along with baseline descent from font metrics static std::pair boundingCuboid(const QFont &font, const QString &text, float depth = 0.1f); // Return bounding cuboid with translation and anchor point applied, and required translation vector for text mesh static std::pair boundingCuboid(const QFont &font, const QString &text, QVector3D anchorPosition, - MildredMetrics::AnchorPoint anchorPoint, float depth = 0.1f); + MildredMetrics::AnchorPoint anchorPoint, double rotation, + float depth = 0.1f); }; } // namespace Mildred \ No newline at end of file diff --git a/src/scenegraph.cpp b/src/scenegraph.cpp index a6b5613..ebe1c9f 100644 --- a/src/scenegraph.cpp +++ b/src/scenegraph.cpp @@ -77,7 +77,7 @@ void MildredWidget::createSceneGraph() RenderableMaterial::GeometryShaderType::None, RenderableMaterial::FragmentShaderType::Monochrome); xAxisLabelMaterial->setAmbient(QColor(0, 0, 0, 255)); xAxis_ = new AxisEntity(axesEntity, AxisEntity::AxisType::Horizontal, metrics_, xAxisBarMaterial, xAxisLabelMaterial); - xAxis_->setTitleText("X"); + xAxis_->setLabelText("X"); connect(xAxis_, SIGNAL(enabledChanged(bool)), this, SLOT(updateMetrics())); connect(xAxis_, SIGNAL(rangeChanged()), this, SLOT(updateMetrics())); @@ -90,7 +90,7 @@ void MildredWidget::createSceneGraph() RenderableMaterial::GeometryShaderType::None, RenderableMaterial::FragmentShaderType::Monochrome); yAxisLabelMaterial->setAmbient(QColor(0, 0, 0, 255)); yAxis_ = new AxisEntity(axesEntity, AxisEntity::AxisType::Vertical, metrics_, yAxisBarMaterial, yAxisLabelMaterial); - yAxis_->setTitleText("Y"); + yAxis_->setLabelText("Y"); connect(yAxis_, SIGNAL(enabledChanged(bool)), this, SLOT(updateMetrics())); connect(yAxis_, SIGNAL(rangeChanged()), this, SLOT(updateMetrics())); @@ -103,7 +103,7 @@ void MildredWidget::createSceneGraph() RenderableMaterial::GeometryShaderType::None, RenderableMaterial::FragmentShaderType::Monochrome); zAxisLabelMaterial->setAmbient(QColor(0, 0, 0, 255)); zAxis_ = new AxisEntity(axesEntity, AxisEntity::AxisType::Depth, metrics_, zAxisBarMaterial, zAxisLabelMaterial); - zAxis_->setTitleText("Z"); + zAxis_->setLabelText("Z"); connect(zAxis_, SIGNAL(enabledChanged(bool)), this, SLOT(updateMetrics())); connect(zAxis_, SIGNAL(rangeChanged()), this, SLOT(updateMetrics())); zAxis_->setEnabled(false); @@ -244,36 +244,69 @@ void MildredWidget::showAllData() updateMetrics(); } -//! Change the text of the x-axis title. +//! Change the text of the x-axis label. /*! - * Set the displayed text of the x-axis title to @param title. Metrics are updated after the change. + * Set the displayed text of the x-axis label to @param text. Metrics are updated after the change. */ -void MildredWidget::setXAxisTitle(const QString &title) +void MildredWidget::setXAxisLabel(const QString &text) { assert(xAxis_); - xAxis_->setTitleText(title); + xAxis_->setLabelText(text); updateMetrics(); } -//! Change the text of the y-axis title. +//! Change the text of the y-axis label. /*! - * Set the displayed text of the y-axis title to @param title. Metrics are updated after the change. + * Set the displayed text of the y-axis title to @param text. Metrics are updated after the change. */ -void MildredWidget::setYAxisTitle(const QString &title) +void MildredWidget::setYAxisLabel(const QString &text) { assert(yAxis_); - yAxis_->setTitleText(title); + yAxis_->setLabelText(text); updateMetrics(); } -//! Change the text of the z-axis title. +//! Change the text of the z-axis label. /*! - * Set the displayed text of the z-axis title to @param title. Metrics are updated after the change. + * Set the displayed text of the z-axis label to @param text. Metrics are updated after the change. */ -void MildredWidget::setZAxisTitle(const QString &title) +void MildredWidget::setZAxisLabel(const QString &text) { assert(zAxis_); - zAxis_->setTitleText(title); + zAxis_->setLabelText(text); + updateMetrics(); +} + +//! Change the rotation of the x-axis label. +/*! + * Set the rotation of the x-axis label about its anchor point to @param theta degrees. Metrics are updated after the change. + */ +void MildredWidget::setXAxisLabelRotation(double theta) +{ + assert(xAxis_); + xAxis_->setLabelRotation(theta); + updateMetrics(); +} + +//! Change the rotation of the y-axis label. +/*! + * Set the rotation of the y-axis label about its anchor point to @param theta degrees. Metrics are updated after the change. + */ +void MildredWidget::setYAxisLabelRotation(double theta) +{ + assert(yAxis_); + yAxis_->setLabelRotation(theta); + updateMetrics(); +} + +//! Change the rotation of the z-axis label. +/*! + * Set the rotation of the z-axis label about its anchor point to @param theta degrees. Metrics are updated after the change. + */ +void MildredWidget::setZAxisLabelRotation(double theta) +{ + assert(zAxis_); + zAxis_->setLabelRotation(theta); updateMetrics(); } diff --git a/src/widget.h b/src/widget.h index 07b1d22..518fc9a 100644 --- a/src/widget.h +++ b/src/widget.h @@ -151,10 +151,13 @@ class MildredWidget : public QWidget void resetView(); // Show all data in view void showAllData(); - // Axis Titles - void setXAxisTitle(const QString &title); - void setYAxisTitle(const QString &title); - void setZAxisTitle(const QString &title); + // Axis Main Labels + void setXAxisLabel(const QString &text); + void setYAxisLabel(const QString &text); + void setZAxisLabel(const QString &text); + void setXAxisLabelRotation(double theta); + void setYAxisLabelRotation(double theta); + void setZAxisLabelRotation(double theta); // Debug Objects void setSceneCuboidEnabled(bool enabled);