/*! \since 5.5 Creates a rotation matrix that corresponds to this quaternion. \note If this quaternion is not normalized, the resulting rotation matrix will contain scaling information. \sa fromRotationMatrix(), getAxes() */ QMatrix3x3 QQuaternion::toRotationMatrix() const { // Algorithm from: // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54 QMatrix3x3 rot3x3(Qt::Uninitialized); const float f2x = xp + xp; const float f2y = yp + yp; const float f2z = zp + zp; const float f2xw = f2x * wp; const float f2yw = f2y * wp; const float f2zw = f2z * wp; const float f2xx = f2x * xp; const float f2xy = f2x * yp; const float f2xz = f2x * zp; const float f2yy = f2y * yp; const float f2yz = f2y * zp; const float f2zz = f2z * zp; rot3x3(0, 0) = 1.0f - (f2yy + f2zz); rot3x3(0, 1) = f2xy - f2zw; rot3x3(0, 2) = f2xz + f2yw; rot3x3(1, 0) = f2xy + f2zw; rot3x3(1, 1) = 1.0f - (f2xx + f2zz); rot3x3(1, 2) = f2yz - f2xw; rot3x3(2, 0) = f2xz - f2yw; rot3x3(2, 1) = f2yz + f2xw; rot3x3(2, 2) = 1.0f - (f2xx + f2yy); return rot3x3; }
/*! \since 5.5 Returns the 3 orthonormal axes (\a xAxis, \a yAxis, \a zAxis) defining the quaternion. \sa fromAxes(), toRotationMatrix() */ void QQuaternion::getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const { Q_ASSERT(xAxis && yAxis && zAxis); const QMatrix3x3 rot3x3(toRotationMatrix()); *xAxis = QVector3D(rot3x3(0, 0), rot3x3(1, 0), rot3x3(2, 0)); *yAxis = QVector3D(rot3x3(0, 1), rot3x3(1, 1), rot3x3(2, 1)); *zAxis = QVector3D(rot3x3(0, 2), rot3x3(1, 2), rot3x3(2, 2)); }
/*! \since 5.5 Constructs the quaternion using 3 axes (\a xAxis, \a yAxis, \a zAxis). \note The axes are assumed to be orthonormal. \sa getAxes(), fromRotationMatrix() */ QQuaternion QQuaternion::fromAxes(const QVector3D &xAxis, const QVector3D &yAxis, const QVector3D &zAxis) { QMatrix3x3 rot3x3(Qt::Uninitialized); rot3x3(0, 0) = xAxis.x(); rot3x3(1, 0) = xAxis.y(); rot3x3(2, 0) = xAxis.z(); rot3x3(0, 1) = yAxis.x(); rot3x3(1, 1) = yAxis.y(); rot3x3(2, 1) = yAxis.z(); rot3x3(0, 2) = zAxis.x(); rot3x3(1, 2) = zAxis.y(); rot3x3(2, 2) = zAxis.z(); return QQuaternion::fromRotationMatrix(rot3x3); }
void QgsPoint3DSymbolWidget::setSymbol( const QgsPoint3DSymbol &symbol ) { cboAltClamping->setCurrentIndex( static_cast<int>( symbol.altitudeClamping() ) ); QVariantMap vm = symbol.shapeProperties(); int index = cboShape->findData( symbol.shape() ); cboShape->setCurrentIndex( index != -1 ? index : 1 ); // use cylinder by default if shape is not set widgetMaterial->setEnabled( true ); switch ( cboShape->currentIndex() ) { case 0: // sphere spinRadius->setValue( vm[QStringLiteral( "radius" )].toDouble() ); break; case 1: // cylinder spinRadius->setValue( vm[QStringLiteral( "radius" )].toDouble() ); spinLength->setValue( vm[QStringLiteral( "length" )].toDouble() ); break; case 2: // cube spinSize->setValue( vm[QStringLiteral( "size" )].toDouble() ); break; case 3: // cone spinTopRadius->setValue( vm[QStringLiteral( "topRadius" )].toDouble() ); spinBottomRadius->setValue( vm[QStringLiteral( "bottomRadius" )].toDouble() ); spinLength->setValue( vm[QStringLiteral( "length" )].toDouble() ); break; case 4: // plane spinSize->setValue( vm[QStringLiteral( "size" )].toDouble() ); break; case 5: // torus spinRadius->setValue( vm[QStringLiteral( "radius" )].toDouble() ); spinMinorRadius->setValue( vm[QStringLiteral( "minorRadius" )].toDouble() ); break; case 6: // 3d model lineEditModel->setText( vm[QStringLiteral( "model" )].toString() ); bool overwriteMaterial = vm[QStringLiteral( "overwriteMaterial" )].toBool(); widgetMaterial->setEnabled( overwriteMaterial ); cbOverwriteMaterial->setChecked( overwriteMaterial ); break; } widgetMaterial->setMaterial( symbol.material() ); // decompose the transform matrix // assuming the last row has values [0 0 0 1] // see https://math.stackexchange.com/questions/237369/given-this-transformation-matrix-how-do-i-decompose-it-into-translation-rotati QMatrix4x4 m = symbol.transform(); float *md = m.data(); // returns data in column-major order float sx = QVector3D( md[0], md[1], md[2] ).length(); float sy = QVector3D( md[4], md[5], md[6] ).length(); float sz = QVector3D( md[8], md[9], md[10] ).length(); float rd[9] = { md[0] / sx, md[4] / sy, md[8] / sz, md[1] / sx, md[5] / sy, md[9] / sz, md[2] / sx, md[6] / sy, md[10] / sz, }; QMatrix3x3 rot3x3( rd ); // takes data in row-major order QVector3D rot = QQuaternion::fromRotationMatrix( rot3x3 ).toEulerAngles(); spinTX->setValue( md[12] ); spinTY->setValue( md[13] ); spinTZ->setValue( md[14] ); spinSX->setValue( sx ); spinSY->setValue( sy ); spinSZ->setValue( sz ); spinRX->setValue( rot.x() ); spinRY->setValue( rot.y() ); spinRZ->setValue( rot.z() ); }