void TestQgs3DUtils::testTransforms() { QgsVector3D map123( 1, 2, 3 ); QgsVector3D world123 = Qgs3DUtils::mapToWorldCoordinates( map123, QgsVector3D() ); QCOMPARE( world123, QgsVector3D( 1, 3, -2 ) ); QgsVector3D world123map = Qgs3DUtils::worldToMapCoordinates( world123, QgsVector3D() ); QCOMPARE( world123map, map123 ); // now with non-zero origin QgsVector3D origin( -10, -20, -30 ); QgsVector3D world123x = Qgs3DUtils::mapToWorldCoordinates( map123, origin ); QCOMPARE( world123x, QgsVector3D( 11, 33, -22 ) ); QgsVector3D world123xmap = Qgs3DUtils::worldToMapCoordinates( world123x, origin ); QCOMPARE( world123xmap, map123 ); // // transform world point from one system to another // QgsVector3D worldPoint1( 5, 7, -6 ); QgsVector3D origin1( 10, 20, 30 ); QgsVector3D origin2( 1, 2, 3 ); QgsVector3D worldPoint2 = Qgs3DUtils::transformWorldCoordinates( worldPoint1, origin1, QgsCoordinateReferenceSystem(), origin2, QgsCoordinateReferenceSystem(), QgsCoordinateTransformContext() ); QCOMPARE( worldPoint2, QgsVector3D( 14, 34, -24 ) ); // verify that both are the same map point QgsVector3D mapPoint1 = Qgs3DUtils::worldToMapCoordinates( worldPoint1, origin1 ); QgsVector3D mapPoint2 = Qgs3DUtils::worldToMapCoordinates( worldPoint2, origin2 ); QCOMPARE( mapPoint1, mapPoint2 ); }
QgsVector3D Qgs3DUtils::mapToWorldCoordinates( const QgsVector3D &mapCoords, const QgsVector3D &origin ) { return QgsVector3D( mapCoords.x() - origin.x(), mapCoords.z() - origin.z(), -( mapCoords.y() - origin.y() ) ); }
void Qgs3DMapConfigWidget::apply() { QgsRasterLayer *demLayer = qobject_cast<QgsRasterLayer *>( cboTerrainLayer->currentLayer() ); bool needsUpdateOrigin = false; if ( demLayer ) { bool tGenNeedsUpdate = true; if ( mMap->terrainGenerator()->type() == QgsTerrainGenerator::Dem ) { // if we already have a DEM terrain generator, check whether there was actually any change QgsDemTerrainGenerator *oldDemTerrainGen = static_cast<QgsDemTerrainGenerator *>( mMap->terrainGenerator() ); if ( oldDemTerrainGen->layer() == demLayer && oldDemTerrainGen->resolution() == spinTerrainResolution->value() && oldDemTerrainGen->skirtHeight() == spinTerrainSkirtHeight->value() ) tGenNeedsUpdate = false; } if ( tGenNeedsUpdate ) { QgsDemTerrainGenerator *demTerrainGen = new QgsDemTerrainGenerator; demTerrainGen->setCrs( mMap->crs(), QgsProject::instance()->transformContext() ); demTerrainGen->setLayer( demLayer ); demTerrainGen->setResolution( spinTerrainResolution->value() ); demTerrainGen->setSkirtHeight( spinTerrainSkirtHeight->value() ); mMap->setTerrainGenerator( demTerrainGen ); needsUpdateOrigin = true; } } else if ( !demLayer && mMap->terrainGenerator()->type() != QgsTerrainGenerator::Flat ) { QgsFlatTerrainGenerator *flatTerrainGen = new QgsFlatTerrainGenerator; flatTerrainGen->setCrs( mMap->crs() ); flatTerrainGen->setExtent( mMainCanvas->fullExtent() ); mMap->setTerrainGenerator( flatTerrainGen ); needsUpdateOrigin = true; } if ( needsUpdateOrigin ) { // reproject terrain's extent to map CRS QgsRectangle te = mMap->terrainGenerator()->extent(); QgsCoordinateTransform terrainToMapTransform( mMap->terrainGenerator()->crs(), mMap->crs(), QgsProject::instance() ); te = terrainToMapTransform.transformBoundingBox( te ); QgsPointXY center = te.center(); mMap->setOrigin( QgsVector3D( center.x(), center.y(), 0 ) ); } mMap->setTerrainVerticalScale( spinTerrainScale->value() ); mMap->setMapTileResolution( spinMapResolution->value() ); mMap->setMaxTerrainScreenError( spinScreenError->value() ); mMap->setMaxTerrainGroundError( spinGroundError->value() ); mMap->setShowLabels( chkShowLabels->isChecked() ); mMap->setShowTerrainTilesInfo( chkShowTileInfo->isChecked() ); mMap->setShowTerrainBoundingBoxes( chkShowBoundingBoxes->isChecked() ); mMap->setShowCameraViewCenter( chkShowCameraViewCenter->isChecked() ); }
void QgsCameraController::readXml( const QDomElement &elem ) { float x = elem.attribute( QStringLiteral( "x" ) ).toFloat(); float y = elem.attribute( QStringLiteral( "y" ) ).toFloat(); float elev = elem.attribute( QStringLiteral( "elev" ) ).toFloat(); float dist = elem.attribute( QStringLiteral( "dist" ) ).toFloat(); float pitch = elem.attribute( QStringLiteral( "pitch" ) ).toFloat(); float yaw = elem.attribute( QStringLiteral( "yaw" ) ).toFloat(); setLookingAtPoint( QgsVector3D( x, elev, y ), dist, pitch, yaw ); }
void QgsCameraController::setViewFromTop( float worldX, float worldY, float distance, float yaw ) { QgsCameraPose camPose; camPose.setCenterPoint( QgsVector3D( worldX, 0, worldY ) ); camPose.setDistanceFromCenterPoint( distance ); camPose.setHeadingAngle( yaw ); // a basic setup to make frustum depth range long enough that it does not cull everything mCamera->setNearPlane( distance / 2 ); mCamera->setFarPlane( distance * 2 ); setCameraPose( camPose ); }
void QgsCameraController::updateCameraFromPose( bool centerPointChanged ) { if ( std::isnan( mCameraPose.centerPoint().x() ) || std::isnan( mCameraPose.centerPoint().y() ) || std::isnan( mCameraPose.centerPoint().z() ) ) { // something went horribly wrong but we need to at least try to fix it somehow qDebug() << "camera position got NaN!"; mCameraPose.setCenterPoint( QgsVector3D( 0, 0, 0 ) ); } if ( mCameraPose.pitchAngle() > 180 ) mCameraPose.setPitchAngle( 180 ); // prevent going over the head if ( mCameraPose.pitchAngle() < 0 ) mCameraPose.setPitchAngle( 0 ); // prevent going over the head if ( mCameraPose.distanceFromCenterPoint() < 10 ) mCameraPose.setDistanceFromCenterPoint( 10 ); if ( mCamera ) mCameraPose.updateCamera( mCamera ); if ( mCamera && mTerrainEntity && centerPointChanged ) { // figure out our distance from terrain and update the camera's view center // so that camera tilting and rotation is around a point on terrain, not an point at fixed elevation QVector3D intersectionPoint; QgsRayCastingUtils::Ray3D ray = QgsRayCastingUtils::rayForCameraCenter( mCamera ); if ( mTerrainEntity->rayIntersection( ray, intersectionPoint ) ) { float dist = ( intersectionPoint - mCamera->position() ).length(); mCameraPose.setDistanceFromCenterPoint( dist ); mCameraPose.setCenterPoint( QgsVector3D( intersectionPoint ) ); mCameraPose.updateCamera( mCamera ); } } emit cameraChanged(); }
QgsVector3D Qgs3DUtils::worldToMapCoordinates( const QgsVector3D &worldCoords, const QgsVector3D &origin ) { return QgsVector3D( worldCoords.x() + origin.x(), -worldCoords.z() + origin.y(), worldCoords.y() + origin.z() ); }