diff options
author | RĂ©mi Benoit <remi.benoit@kdab.com> | 2015-03-10 10:59:12 +0100 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2015-03-24 14:00:49 +0000 |
commit | 5bc470958f7feabd125aa6ba6e7c487da821cb0b (patch) | |
tree | f21c770fb75ed1e80fde51a2284a73445518ee7d /src/core/qray3d.cpp | |
parent | 61a7b5b5ba8447cd98a00f036c951763e32cbda6 (diff) |
Add QRay3D
Change-Id: I5e45f6275c69ea38866086be61a1390bbb31cb9d
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/core/qray3d.cpp')
-rw-r--r-- | src/core/qray3d.cpp | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/src/core/qray3d.cpp b/src/core/qray3d.cpp new file mode 100644 index 000000000..0783c5aa1 --- /dev/null +++ b/src/core/qray3d.cpp @@ -0,0 +1,358 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qray3d.h" +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3D { + +/*! + \class QRay3D + \brief The QRay3D class defines a directional line in 3D space extending through an origin point. + \since 5.5 + \ingroup qt3d + \ingroup qt3d::math + + A ray is defined by the origin() point and the direction() vector. + Rays are infinite in length, extending out from origin() in + both directions. If the direction() is zero length, then the + behavior of the class is undefined. + + A ray can be thought of as a one-dimensional co-ordinate system. + If the co-ordinate is \b t then the origin() point is at + \b t = 0, the point origin() + direction() is at \b t = 1, + and the point origin() - direction() is at \b t = -1. + The point() method can be used to obtain the position of a point + within this one-dimensional co-ordinate system. The projectedDistance() + method can be used to convert a point into a value in this + one-dimensional co-ordinate system. +*/ + +/*! + \fn QRay3D::QRay3D() + + Construct a default ray with an origin() of (0, 0, 0) and a + direction() of (0, 0, 1). +*/ +QRay3D::QRay3D() + : m_direction(0.0f, 0.0f, 1.0f) +{ +} + +/*! + \fn QRay3D::QRay3D(const QVector3D &origin, const QVector3D &direction) + + Construct a ray given its defining \a origin and \a direction. The + \a direction does not need to be normalized. + + To construct a ray that passes through two points, use the following: + + \code + QRay3D thruAB(pointA, pointB - pointA); + \endcode +*/ +QRay3D::QRay3D(const QVector3D &origin, const QVector3D &direction) + : m_origin(origin) + , m_direction(direction) +{} + +QRay3D::~QRay3D() +{ +} + +/*! + \fn QVector3D QRay3D::origin() const + + Returns the origin of this ray. The default value is (0, 0, 0). + + \sa setOrigin(), direction() +*/ +QVector3D QRay3D::origin() const +{ + return m_origin; +} + +/*! + \fn void QRay3D::setOrigin(const QVector3D &value) + + Sets the origin point of this ray to \a value. + + \sa origin(), setDirection() + */ +void QRay3D::setOrigin(const QVector3D &value) +{ + m_origin = value; +} + +/*! + \fn QVector3D QRay3D::direction() const + + Returns the direction vector of this ray. The default value is (0, 0, 1). + + \sa setDirection(), origin() +*/ +QVector3D QRay3D::direction() const +{ + return m_direction; +} + +/*! + \fn void QRay3D::setDirection(const QVector3D &direction) + + Sets the direction vector of this ray to \a direction. + + \sa direction(), setOrigin() +*/ +void QRay3D::setDirection(const QVector3D &value) +{ + if (value.isNull()) + return; + + m_direction = value; +} + +QVector3D QRay3D::point(float t) const +{ + return m_origin + t * m_direction; +} + +QRay3D &QRay3D::transform(const QMatrix4x4 &matrix) +{ + m_origin = matrix * m_origin; + m_direction = matrix.mapVector(m_direction); + + return *this; +} + +QRay3D QRay3D::transformed(const QMatrix4x4 &matrix) const +{ + return QRay3D(matrix * m_origin, matrix.mapVector(m_direction)); +} + +bool QRay3D::operator==(const QRay3D &other) const +{ + return m_origin == other.origin() && m_direction == other.direction(); +} + +bool QRay3D::operator!=(const QRay3D &other) const +{ + return !(*this == other); +} + +/*! + Returns true if \a point lies on this ray; false otherwise. +*/ +bool QRay3D::contains(const QVector3D &point) const +{ + QVector3D ppVec(point - m_origin); + if (ppVec.isNull()) // point coincides with origin + return true; + const float dot = QVector3D::dotProduct(ppVec, m_direction); + if (qFuzzyIsNull(dot)) + return false; + return qFuzzyCompare(dot*dot, ppVec.lengthSquared() * m_direction.lengthSquared()); +} + +/*! + Returns true if \a ray lies on this ray; false otherwise. If true, + this implies that the two rays are actually the same, but with + different origin() points or an inverted direction(). +*/ +bool QRay3D::contains(const QRay3D &ray) const +{ + const float dot = QVector3D::dotProduct(m_direction, ray.direction()); + if (!qFuzzyCompare(dot*dot, m_direction.lengthSquared() * ray.direction().lengthSquared())) + return false; + return contains(ray.origin()); +} + +/*! + \fn QVector3D QRay3D::point(float t) const + + Returns the point on the ray defined by moving \a t units + along the ray in the direction of the direction() vector. + Note that \a t may be negative in which case the point returned + will lie behind the origin() point with respect to the + direction() vector. + + The units for \a t are defined by direction(). The return value + is precisely origin() + t * direction(). + + \sa projectedDistance(), distance() +*/ + +/*! + Returns the number of direction() units along the ray from origin() + to \a point. Essentially, this function computes the value t, where + \a point = origin() + t * direction(). If \a point is not on the ray, + then the closest point that is on the ray will be used instead. + + If the return value is positive, then \a point lies in front of + the origin() with respect to the direction() vector. If the return + value is negative, then \a point lies behind the origin() with + respect to the direction() vector. + + \sa point(), project() +*/ +float QRay3D::projectedDistance(const QVector3D &point) const +{ + Q_ASSERT(!m_direction.isNull()); + + return QVector3D::dotProduct(point - m_origin, m_direction) / + m_direction.lengthSquared(); +} + +/*! + Returns the projection of \a vector onto this ray. In the + following diagram, the dotted line is the ray, and V is the + \a vector. The return value will be the vector V': + + \image qray3d-project.png + + \sa projectedDistance() +*/ +QVector3D QRay3D::project(const QVector3D &vector) const +{ + QVector3D norm = m_direction.normalized(); + return QVector3D::dotProduct(vector, norm) * norm; +} + +/*! + Returns the minimum distance from this ray to \a point, or equivalently + the length of a line perpendicular to this ray which passes through + \a point. If \a point is on the ray, then this function will return zero. + + \sa point() +*/ +float QRay3D::distance(const QVector3D &point) const +{ + float t = projectedDistance(point); + return (point - (m_origin + t * m_direction)).length(); +} + +/*! + \fn QRay3D &QRay3D::transform(const QMatrix4x4 &matrix) + + Transforms this ray using \a matrix, replacing origin() and + direction() with the transformed versions. + + \sa transformed() +*/ + +/*! + \fn QRay3D QRay3D::transformed(const QMatrix4x4 &matrix) const + + Returns a new ray that is formed by transforming origin() + and direction() using \a matrix. + + \sa transform() +*/ + +/*! + \fn bool QRay3D::operator==(const QRay3D &other) + + Returns true if this ray is the same as \a other; false otherwise. + + \sa operator!=() +*/ + +/*! + \fn bool QRay3D::operator!=(const QRay3D &other) + + Returns true if this ray is not the same as \a other; false otherwise. + + \sa operator==() +*/ + +/*! + \fn bool qFuzzyCompare(const QRay3D &ray1, const QRay3D &ray2) + \relates QRay3D + + Returns true if \a ray1 and \a ray2 are almost equal; false otherwise. +*/ + +#ifndef QT_NO_DEBUG_STREAM + +QDebug operator<<(QDebug dbg, const QRay3D &ray) +{ + dbg.nospace() << "QRay3D(origin(" + << ray.origin().x() << ", " << ray.origin().y() << ", " + << ray.origin().z() << ") - direction(" + << ray.direction().x() << ", " << ray.direction().y() << ", " + << ray.direction().z() << "))"; + return dbg.space(); +} + +#endif + +#ifndef QT_NO_DATASTREAM + +/*! + \relates QRay3D + + Writes the given \a ray to the given \a stream and returns a + reference to the stream. +*/ +QDataStream &operator<<(QDataStream &stream, const QRay3D &ray) +{ + stream << ray.origin(); + stream << ray.direction(); + return stream; +} + +/*! + \relates QRay3D + + Reads a 3D ray from the given \a stream into the given \a ray + and returns a reference to the stream. +*/ +QDataStream &operator>>(QDataStream &stream, QRay3D &ray) +{ + QVector3D origin, direction; + stream >> origin; + stream >> direction; + ray = QRay3D(origin, direction); + return stream; +} + +#endif // QT_NO_DATASTREAM + +} // namespace Qt3D + +QT_END_NAMESPACE |