Skip to content
Permalink
Browse files

Merge pull request #5768 from wonder-sk/fix-17514-crs-change

Fix 3D view if terrain DEM is in different CRS
  • Loading branch information
wonder-sk committed Nov 30, 2017
2 parents ded892e + 997286f commit 8aa05735de1fcca27a48f2c3db171af0894e64d8
@@ -11,6 +11,7 @@ SET(QGIS_3D_SRCS
qgstessellatedpolygongeometry.cpp
qgstessellator.cpp
qgstilingscheme.cpp
qgsvector3d.cpp
qgsvectorlayer3drenderer.cpp

chunks/qgschunkboundsentity_p.cpp
@@ -84,6 +85,7 @@ SET(QGIS_3D_HDRS
qgstessellatedpolygongeometry.h
qgstessellator.h
qgstilingscheme.h
qgsvector3d.h
qgsvectorlayer3drenderer.h

chunks/qgschunkboundsentity_p.h
@@ -28,9 +28,7 @@

Qgs3DMapSettings::Qgs3DMapSettings( const Qgs3DMapSettings &other )
: QObject()
, mOriginX( other.mOriginX )
, mOriginY( other.mOriginY )
, mOriginZ( other.mOriginZ )
, mOrigin( other.mOrigin )
, mCrs( other.mCrs )
, mBackgroundColor( other.mBackgroundColor )
, mTerrainVerticalScale( other.mTerrainVerticalScale )
@@ -59,9 +57,10 @@ Qgs3DMapSettings::~Qgs3DMapSettings()
void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
{
QDomElement elemOrigin = elem.firstChildElement( "origin" );
mOriginX = elemOrigin.attribute( "x" ).toDouble();
mOriginY = elemOrigin.attribute( "y" ).toDouble();
mOriginZ = elemOrigin.attribute( "z" ).toDouble();
mOrigin = QgsVector3D(
elemOrigin.attribute( "x" ).toDouble(),
elemOrigin.attribute( "y" ).toDouble(),
elemOrigin.attribute( "z" ).toDouble() );

QDomElement elemCrs = elem.firstChildElement( "crs" );
mCrs.readXml( elemCrs );
@@ -85,7 +84,9 @@ void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteConte
QString terrainGenType = elemTerrainGenerator.attribute( "type" );
if ( terrainGenType == "dem" )
{
mTerrainGenerator.reset( new QgsDemTerrainGenerator );
QgsDemTerrainGenerator *demTerrainGenerator = new QgsDemTerrainGenerator;
demTerrainGenerator->setCrs( mCrs );
mTerrainGenerator.reset( demTerrainGenerator );
}
else if ( terrainGenType == "quantized-mesh" )
{
@@ -139,9 +140,9 @@ QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteCon
QDomElement elem = doc.createElement( "qgis3d" );

QDomElement elemOrigin = doc.createElement( "origin" );
elemOrigin.setAttribute( "x", QString::number( mOriginX ) );
elemOrigin.setAttribute( "y", QString::number( mOriginY ) );
elemOrigin.setAttribute( "z", QString::number( mOriginZ ) );
elemOrigin.setAttribute( "x", QString::number( mOrigin.x() ) );
elemOrigin.setAttribute( "y", QString::number( mOrigin.y() ) );
elemOrigin.setAttribute( "z", QString::number( mOrigin.z() ) );
elem.appendChild( elemOrigin );

QDomElement elemCrs = doc.createElement( "crs" );
@@ -210,11 +211,14 @@ void Qgs3DMapSettings::resolveReferences( const QgsProject &project )
}
}

void Qgs3DMapSettings::setOrigin( double originX, double originY, double originZ )
QgsVector3D Qgs3DMapSettings::mapToWorldCoordinates( const QgsVector3D &mapCoords ) const
{
mOriginX = originX;
mOriginY = originY;
mOriginZ = originZ;
return Qgs3DUtils::mapToWorldCoordinates( mapCoords, mOrigin );
}

QgsVector3D Qgs3DMapSettings::worldToMapCoordinates( const QgsVector3D &worldCoords ) const
{
return Qgs3DUtils::worldToMapCoordinates( worldCoords, mOrigin );
}

void Qgs3DMapSettings::setCrs( const QgsCoordinateReferenceSystem &crs )
@@ -25,6 +25,7 @@
#include "qgscoordinatereferencesystem.h"
#include "qgsmaplayerref.h"
#include "qgsterraingenerator.h"
#include "qgsvector3d.h"

class QgsMapLayer;
class QgsRasterLayer;
@@ -37,6 +38,7 @@ class QgsProject;

class QDomElement;


/**
* \ingroup 3d
* Definition of the world
@@ -72,13 +74,14 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
* Need to look into more advanced techniques like "relative to center" or "relative to eye"
* to improve the precision.
*/
void setOrigin( double originX, double originY, double originZ );
//! Returns X coordinate in map CRS at which 3D scene has origin (zero)
double originX() const { return mOriginX; }
//! Returns Y coordinate in map CRS at which 3D scene has origin (zero)
double originY() const { return mOriginY; }
//! Returns Z coordinate in map CRS at which 3D scene has origin (zero)
double originZ() const { return mOriginZ; }
void setOrigin( const QgsVector3D &origin ) { mOrigin = origin; }
//! Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
QgsVector3D origin() const { return mOrigin; }

//! Converts map coordinates to 3D world coordinates (applies offset and turns (x,y,z) into (x,-z,y))
QgsVector3D mapToWorldCoordinates( const QgsVector3D &mapCoords ) const;
//! Converts 3D world coordinates to map coordinates (applies offset and turns (x,y,z) into (x,-z,y))
QgsVector3D worldToMapCoordinates( const QgsVector3D &worldCoords ) const;

//! Sets coordinate reference system used in the 3D scene
void setCrs( const QgsCoordinateReferenceSystem &crs );
@@ -218,12 +221,8 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
void showLabelsChanged();

private:
//! X coordinate in map CRS at which our 3D world has origin (0,0,0)
double mOriginX = 0;
//! Y coordinate in map CRS at which our 3D world has origin (0,0,0)
double mOriginY = 0;
//! Z coordinate in map CRS at which our 3D world has origin (0,0,0)
double mOriginZ = 0;
//! Offset in map CRS coordinates at which our 3D world has origin (0,0,0)
QgsVector3D mOrigin;
QgsCoordinateReferenceSystem mCrs; //!< Destination coordinate system of the world
QColor mBackgroundColor = Qt::black; //!< Background color of the scene
QColor mSelectionColor; //!< Color to be used for selected map features
@@ -194,7 +194,7 @@ QList<QVector3D> Qgs3DUtils::positions( const Qgs3DMapSettings &map, QgsVectorLa
h = terrainZ + geomZ;
break;
}
positions.append( QVector3D( pt.x() - map.originX(), h, -( pt.y() - map.originY() ) ) );
positions.append( QVector3D( pt.x() - map.origin().x(), h, -( pt.y() - map.origin().y() ) ) );
//qDebug() << positions.last();
}
}
@@ -255,3 +255,39 @@ bool Qgs3DUtils::isCullable( const QgsAABB &bbox, const QMatrix4x4 &viewProjecti
return out;
}

QgsVector3D Qgs3DUtils::mapToWorldCoordinates( const QgsVector3D &mapCoords, const QgsVector3D &origin )
{
return QgsVector3D( mapCoords.x() - origin.x(),
mapCoords.z() - origin.z(),
-( mapCoords.y() - origin.y() ) );

}

QgsVector3D Qgs3DUtils::worldToMapCoordinates( const QgsVector3D &worldCoords, const QgsVector3D &origin )
{
return QgsVector3D( worldCoords.x() + origin.x(),
-worldCoords.z() + origin.y(),
worldCoords.y() + origin.z() );
}

QgsVector3D Qgs3DUtils::transformWorldCoordinates( const QgsVector3D &worldPoint1, const QgsVector3D &origin1, const QgsCoordinateReferenceSystem &crs1, const QgsVector3D &origin2, const QgsCoordinateReferenceSystem &crs2 )
{
QgsVector3D mapPoint1 = worldToMapCoordinates( worldPoint1, origin1 );
QgsVector3D mapPoint2 = mapPoint1;
if ( crs1 != crs2 )
{
// reproject if necessary
QgsCoordinateTransform ct( crs1, crs2 );
try
{
QgsPointXY pt = ct.transform( QgsPointXY( mapPoint1.x(), mapPoint1.y() ) );
mapPoint2.set( pt.x(), pt.y(), mapPoint1.z() );
}
catch ( const QgsCsException & )
{
// bad luck, can't reproject for some reason
}
}
return mapToWorldCoordinates( mapPoint2, origin2 );
}

@@ -84,6 +84,14 @@ class _3D_EXPORT Qgs3DUtils
This is used to perform object culling checks.
*/
static bool isCullable( const QgsAABB &bbox, const QMatrix4x4 &viewProjectionMatrix );

//! Converts map coordinates to 3D world coordinates (applies offset and turns (x,y,z) into (x,-z,y))
static QgsVector3D mapToWorldCoordinates( const QgsVector3D &mapCoords, const QgsVector3D &origin );
//! Converts 3D world coordinates to map coordinates (applies offset and turns (x,y,z) into (x,-z,y))
static QgsVector3D worldToMapCoordinates( const QgsVector3D &worldCoords, const QgsVector3D &origin );

//! Transforms a world point from (origin1, crs1) to (origin2, crs2)
static QgsVector3D transformWorldCoordinates( const QgsVector3D &worldPoint1, const QgsVector3D &origin1, const QgsCoordinateReferenceSystem &crs1, const QgsVector3D &origin2, const QgsCoordinateReferenceSystem &crs2 );
};

#endif // QGS3DUTILS_H
@@ -14,6 +14,7 @@
***************************************************************************/

#include "qgscameracontroller.h"
#include "qgsvector3d.h"

#include "qgis.h"

@@ -295,9 +296,14 @@ void QgsCameraController::setViewFromTop( float worldX, float worldY, float dist
emit cameraChanged();
}

void QgsCameraController::translateWorld( const QVector3D &vWorld )
QgsVector3D QgsCameraController::lookingAtPoint() const
{
setCameraData( mCameraData.x - vWorld.x(), mCameraData.y + vWorld.y(), mCameraData.dist, mCameraData.pitch, mCameraData.yaw );
return QgsVector3D( mCameraData.x, 0, mCameraData.y );
}

void QgsCameraController::setLookingAtPoint( const QgsVector3D &point )
{
setCameraData( point.x(), point.z(), mCameraData.dist, mCameraData.pitch, mCameraData.yaw );
emit cameraChanged();
}

@@ -22,6 +22,7 @@
#include <Qt3DInput>
#include <Qt3DRender>

class QgsVector3D;

/**
* \ingroup 3d
@@ -60,8 +61,10 @@ class _3D_EXPORT QgsCameraController : public Qt3DCore::QEntity
//! Sets camera to look down towards given point in world coordinate, in given distance from plane with zero elevation
void setViewFromTop( float worldX, float worldY, float distance, float yaw = 0 );

//! Moves the point toward which the camera is looking - this is used when world origin changes (e.g. after terrain generator changes)
void translateWorld( const QVector3D &vWorld );
//! Returns the point in the world coordinates towards which the camera is looking
QgsVector3D lookingAtPoint() const;
//! Sets the point toward which the camera is looking - this is used when world origin changes (e.g. after terrain generator changes)
void setLookingAtPoint( const QgsVector3D &point );

private:
void setCameraData( float x, float y, float dist, float pitch = 0, float yaw = 0 );
@@ -0,0 +1,16 @@
/***************************************************************************
qgsvector3d.h
--------------------------------------
Date : November 2017
Copyright : (C) 2017 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsvector3d.h"
@@ -0,0 +1,81 @@
/***************************************************************************
qgsvector3d.h
--------------------------------------
Date : November 2017
Copyright : (C) 2017 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSVECTOR3D_H
#define QGSVECTOR3D_H

#include "qgis_3d.h"

/**
* \ingroup 3d
* Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double precision
* instead of single precision floating point numbers.
*
* \since QGIS 3.0
*/
class _3D_EXPORT QgsVector3D
{
public:
//! Constructs a null vector
QgsVector3D() = default;

//! Constructs a vector from given coordinates
QgsVector3D( double x, double y, double z )
: mX( x ), mY( y ), mZ( z ) {}

//! Returns true if all three coordinates are zero
bool isNull() const { return mX == 0 && mY == 0 && mZ == 0; }

//! Returns X coordinate
double x() const { return mX; }
//! Returns Y coordinate
double y() const { return mY; }
//! Returns Z coordinate
double z() const { return mZ; }

//! Sets vector coordinates
void set( double x, double y, double z )
{
mX = x;
mY = y;
mZ = z;
}

bool operator==( const QgsVector3D &other ) const
{
return mX == other.mX && mY == other.mY && mZ == other.mZ;
}
bool operator!=( const QgsVector3D &other ) const
{
return !operator==( other );
}

//! Returns sum of two vectors
QgsVector3D operator+( const QgsVector3D &other )
{
return QgsVector3D( mX + other.mX, mY + other.mY, mZ + other.mZ );
}

//! Returns difference of two vectors
QgsVector3D operator-( const QgsVector3D &other )
{
return QgsVector3D( mX - other.mX, mY - other.mY, mZ - other.mZ );
}

private:
double mX = 0, mY = 0, mZ = 0;
};

#endif // QGSVECTOR3D_H
@@ -93,7 +93,7 @@ QgsLine3DSymbolEntityNode::QgsLine3DSymbolEntityNode( const Qgs3DMapSettings &ma

Qt3DRender::QGeometryRenderer *QgsLine3DSymbolEntityNode::renderer( const Qgs3DMapSettings &map, const QgsLine3DSymbol &symbol, const QgsVectorLayer *layer, const QgsFeatureRequest &request )
{
QgsPointXY origin( map.originX(), map.originY() );
QgsPointXY origin( map.origin().x(), map.origin().y() );

// TODO: configurable
int nSegments = 4;
@@ -121,7 +121,7 @@ QgsPolygon3DSymbolEntityNode::QgsPolygon3DSymbolEntityNode( const Qgs3DMapSettin

Qt3DRender::QGeometryRenderer *QgsPolygon3DSymbolEntityNode::renderer( const Qgs3DMapSettings &map, const QgsPolygon3DSymbol &symbol, const QgsVectorLayer *layer, const QgsFeatureRequest &request )
{
QgsPointXY origin( map.originX(), map.originY() );
QgsPointXY origin( map.origin().x(), map.origin().y() );
QList<QgsPolygon *> polygons;
QList<float> extrusionHeightPerPolygon; // will stay empty if not needed per polygon

0 comments on commit 8aa0573

Please sign in to comment.
You can’t perform that action at this time.