Skip to content

Commit 8aa0573

Browse files
authoredNov 30, 2017
Merge pull request #5768 from wonder-sk/fix-17514-crs-change
Fix 3D view if terrain DEM is in different CRS
2 parents ded892e + 997286f commit 8aa0573

21 files changed

+338
-51
lines changed
 

‎src/3d/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ SET(QGIS_3D_SRCS
1111
qgstessellatedpolygongeometry.cpp
1212
qgstessellator.cpp
1313
qgstilingscheme.cpp
14+
qgsvector3d.cpp
1415
qgsvectorlayer3drenderer.cpp
1516

1617
chunks/qgschunkboundsentity_p.cpp
@@ -84,6 +85,7 @@ SET(QGIS_3D_HDRS
8485
qgstessellatedpolygongeometry.h
8586
qgstessellator.h
8687
qgstilingscheme.h
88+
qgsvector3d.h
8789
qgsvectorlayer3drenderer.h
8890

8991
chunks/qgschunkboundsentity_p.h

‎src/3d/qgs3dmapsettings.cpp

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@
2828

2929
Qgs3DMapSettings::Qgs3DMapSettings( const Qgs3DMapSettings &other )
3030
: QObject()
31-
, mOriginX( other.mOriginX )
32-
, mOriginY( other.mOriginY )
33-
, mOriginZ( other.mOriginZ )
31+
, mOrigin( other.mOrigin )
3432
, mCrs( other.mCrs )
3533
, mBackgroundColor( other.mBackgroundColor )
3634
, mTerrainVerticalScale( other.mTerrainVerticalScale )
@@ -59,9 +57,10 @@ Qgs3DMapSettings::~Qgs3DMapSettings()
5957
void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
6058
{
6159
QDomElement elemOrigin = elem.firstChildElement( "origin" );
62-
mOriginX = elemOrigin.attribute( "x" ).toDouble();
63-
mOriginY = elemOrigin.attribute( "y" ).toDouble();
64-
mOriginZ = elemOrigin.attribute( "z" ).toDouble();
60+
mOrigin = QgsVector3D(
61+
elemOrigin.attribute( "x" ).toDouble(),
62+
elemOrigin.attribute( "y" ).toDouble(),
63+
elemOrigin.attribute( "z" ).toDouble() );
6564

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

141142
QDomElement elemOrigin = doc.createElement( "origin" );
142-
elemOrigin.setAttribute( "x", QString::number( mOriginX ) );
143-
elemOrigin.setAttribute( "y", QString::number( mOriginY ) );
144-
elemOrigin.setAttribute( "z", QString::number( mOriginZ ) );
143+
elemOrigin.setAttribute( "x", QString::number( mOrigin.x() ) );
144+
elemOrigin.setAttribute( "y", QString::number( mOrigin.y() ) );
145+
elemOrigin.setAttribute( "z", QString::number( mOrigin.z() ) );
145146
elem.appendChild( elemOrigin );
146147

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

213-
void Qgs3DMapSettings::setOrigin( double originX, double originY, double originZ )
214+
QgsVector3D Qgs3DMapSettings::mapToWorldCoordinates( const QgsVector3D &mapCoords ) const
214215
{
215-
mOriginX = originX;
216-
mOriginY = originY;
217-
mOriginZ = originZ;
216+
return Qgs3DUtils::mapToWorldCoordinates( mapCoords, mOrigin );
217+
}
218+
219+
QgsVector3D Qgs3DMapSettings::worldToMapCoordinates( const QgsVector3D &worldCoords ) const
220+
{
221+
return Qgs3DUtils::worldToMapCoordinates( worldCoords, mOrigin );
218222
}
219223

220224
void Qgs3DMapSettings::setCrs( const QgsCoordinateReferenceSystem &crs )

‎src/3d/qgs3dmapsettings.h

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "qgscoordinatereferencesystem.h"
2626
#include "qgsmaplayerref.h"
2727
#include "qgsterraingenerator.h"
28+
#include "qgsvector3d.h"
2829

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

3839
class QDomElement;
3940

41+
4042
/**
4143
* \ingroup 3d
4244
* Definition of the world
@@ -72,13 +74,14 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
7274
* Need to look into more advanced techniques like "relative to center" or "relative to eye"
7375
* to improve the precision.
7476
*/
75-
void setOrigin( double originX, double originY, double originZ );
76-
//! Returns X coordinate in map CRS at which 3D scene has origin (zero)
77-
double originX() const { return mOriginX; }
78-
//! Returns Y coordinate in map CRS at which 3D scene has origin (zero)
79-
double originY() const { return mOriginY; }
80-
//! Returns Z coordinate in map CRS at which 3D scene has origin (zero)
81-
double originZ() const { return mOriginZ; }
77+
void setOrigin( const QgsVector3D &origin ) { mOrigin = origin; }
78+
//! Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
79+
QgsVector3D origin() const { return mOrigin; }
80+
81+
//! Converts map coordinates to 3D world coordinates (applies offset and turns (x,y,z) into (x,-z,y))
82+
QgsVector3D mapToWorldCoordinates( const QgsVector3D &mapCoords ) const;
83+
//! Converts 3D world coordinates to map coordinates (applies offset and turns (x,y,z) into (x,-z,y))
84+
QgsVector3D worldToMapCoordinates( const QgsVector3D &worldCoords ) const;
8285

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

220223
private:
221-
//! X coordinate in map CRS at which our 3D world has origin (0,0,0)
222-
double mOriginX = 0;
223-
//! Y coordinate in map CRS at which our 3D world has origin (0,0,0)
224-
double mOriginY = 0;
225-
//! Z coordinate in map CRS at which our 3D world has origin (0,0,0)
226-
double mOriginZ = 0;
224+
//! Offset in map CRS coordinates at which our 3D world has origin (0,0,0)
225+
QgsVector3D mOrigin;
227226
QgsCoordinateReferenceSystem mCrs; //!< Destination coordinate system of the world
228227
QColor mBackgroundColor = Qt::black; //!< Background color of the scene
229228
QColor mSelectionColor; //!< Color to be used for selected map features

‎src/3d/qgs3dutils.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ QList<QVector3D> Qgs3DUtils::positions( const Qgs3DMapSettings &map, QgsVectorLa
194194
h = terrainZ + geomZ;
195195
break;
196196
}
197-
positions.append( QVector3D( pt.x() - map.originX(), h, -( pt.y() - map.originY() ) ) );
197+
positions.append( QVector3D( pt.x() - map.origin().x(), h, -( pt.y() - map.origin().y() ) ) );
198198
//qDebug() << positions.last();
199199
}
200200
}
@@ -255,3 +255,39 @@ bool Qgs3DUtils::isCullable( const QgsAABB &bbox, const QMatrix4x4 &viewProjecti
255255
return out;
256256
}
257257

258+
QgsVector3D Qgs3DUtils::mapToWorldCoordinates( const QgsVector3D &mapCoords, const QgsVector3D &origin )
259+
{
260+
return QgsVector3D( mapCoords.x() - origin.x(),
261+
mapCoords.z() - origin.z(),
262+
-( mapCoords.y() - origin.y() ) );
263+
264+
}
265+
266+
QgsVector3D Qgs3DUtils::worldToMapCoordinates( const QgsVector3D &worldCoords, const QgsVector3D &origin )
267+
{
268+
return QgsVector3D( worldCoords.x() + origin.x(),
269+
-worldCoords.z() + origin.y(),
270+
worldCoords.y() + origin.z() );
271+
}
272+
273+
QgsVector3D Qgs3DUtils::transformWorldCoordinates( const QgsVector3D &worldPoint1, const QgsVector3D &origin1, const QgsCoordinateReferenceSystem &crs1, const QgsVector3D &origin2, const QgsCoordinateReferenceSystem &crs2 )
274+
{
275+
QgsVector3D mapPoint1 = worldToMapCoordinates( worldPoint1, origin1 );
276+
QgsVector3D mapPoint2 = mapPoint1;
277+
if ( crs1 != crs2 )
278+
{
279+
// reproject if necessary
280+
QgsCoordinateTransform ct( crs1, crs2 );
281+
try
282+
{
283+
QgsPointXY pt = ct.transform( QgsPointXY( mapPoint1.x(), mapPoint1.y() ) );
284+
mapPoint2.set( pt.x(), pt.y(), mapPoint1.z() );
285+
}
286+
catch ( const QgsCsException & )
287+
{
288+
// bad luck, can't reproject for some reason
289+
}
290+
}
291+
return mapToWorldCoordinates( mapPoint2, origin2 );
292+
}
293+

‎src/3d/qgs3dutils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,14 @@ class _3D_EXPORT Qgs3DUtils
8484
This is used to perform object culling checks.
8585
*/
8686
static bool isCullable( const QgsAABB &bbox, const QMatrix4x4 &viewProjectionMatrix );
87+
88+
//! Converts map coordinates to 3D world coordinates (applies offset and turns (x,y,z) into (x,-z,y))
89+
static QgsVector3D mapToWorldCoordinates( const QgsVector3D &mapCoords, const QgsVector3D &origin );
90+
//! Converts 3D world coordinates to map coordinates (applies offset and turns (x,y,z) into (x,-z,y))
91+
static QgsVector3D worldToMapCoordinates( const QgsVector3D &worldCoords, const QgsVector3D &origin );
92+
93+
//! Transforms a world point from (origin1, crs1) to (origin2, crs2)
94+
static QgsVector3D transformWorldCoordinates( const QgsVector3D &worldPoint1, const QgsVector3D &origin1, const QgsCoordinateReferenceSystem &crs1, const QgsVector3D &origin2, const QgsCoordinateReferenceSystem &crs2 );
8795
};
8896

8997
#endif // QGS3DUTILS_H

‎src/3d/qgscameracontroller.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
***************************************************************************/
1515

1616
#include "qgscameracontroller.h"
17+
#include "qgsvector3d.h"
1718

1819
#include "qgis.h"
1920

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

298-
void QgsCameraController::translateWorld( const QVector3D &vWorld )
299+
QgsVector3D QgsCameraController::lookingAtPoint() const
299300
{
300-
setCameraData( mCameraData.x - vWorld.x(), mCameraData.y + vWorld.y(), mCameraData.dist, mCameraData.pitch, mCameraData.yaw );
301+
return QgsVector3D( mCameraData.x, 0, mCameraData.y );
302+
}
303+
304+
void QgsCameraController::setLookingAtPoint( const QgsVector3D &point )
305+
{
306+
setCameraData( point.x(), point.z(), mCameraData.dist, mCameraData.pitch, mCameraData.yaw );
301307
emit cameraChanged();
302308
}
303309

‎src/3d/qgscameracontroller.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <Qt3DInput>
2323
#include <Qt3DRender>
2424

25+
class QgsVector3D;
2526

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

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

6669
private:
6770
void setCameraData( float x, float y, float dist, float pitch = 0, float yaw = 0 );

‎src/3d/qgsvector3d.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/***************************************************************************
2+
qgsvector3d.h
3+
--------------------------------------
4+
Date : November 2017
5+
Copyright : (C) 2017 by Martin Dobias
6+
Email : wonder dot sk at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgsvector3d.h"

‎src/3d/qgsvector3d.h

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/***************************************************************************
2+
qgsvector3d.h
3+
--------------------------------------
4+
Date : November 2017
5+
Copyright : (C) 2017 by Martin Dobias
6+
Email : wonder dot sk at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSVECTOR3D_H
17+
#define QGSVECTOR3D_H
18+
19+
#include "qgis_3d.h"
20+
21+
/**
22+
* \ingroup 3d
23+
* Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double precision
24+
* instead of single precision floating point numbers.
25+
*
26+
* \since QGIS 3.0
27+
*/
28+
class _3D_EXPORT QgsVector3D
29+
{
30+
public:
31+
//! Constructs a null vector
32+
QgsVector3D() = default;
33+
34+
//! Constructs a vector from given coordinates
35+
QgsVector3D( double x, double y, double z )
36+
: mX( x ), mY( y ), mZ( z ) {}
37+
38+
//! Returns true if all three coordinates are zero
39+
bool isNull() const { return mX == 0 && mY == 0 && mZ == 0; }
40+
41+
//! Returns X coordinate
42+
double x() const { return mX; }
43+
//! Returns Y coordinate
44+
double y() const { return mY; }
45+
//! Returns Z coordinate
46+
double z() const { return mZ; }
47+
48+
//! Sets vector coordinates
49+
void set( double x, double y, double z )
50+
{
51+
mX = x;
52+
mY = y;
53+
mZ = z;
54+
}
55+
56+
bool operator==( const QgsVector3D &other ) const
57+
{
58+
return mX == other.mX && mY == other.mY && mZ == other.mZ;
59+
}
60+
bool operator!=( const QgsVector3D &other ) const
61+
{
62+
return !operator==( other );
63+
}
64+
65+
//! Returns sum of two vectors
66+
QgsVector3D operator+( const QgsVector3D &other )
67+
{
68+
return QgsVector3D( mX + other.mX, mY + other.mY, mZ + other.mZ );
69+
}
70+
71+
//! Returns difference of two vectors
72+
QgsVector3D operator-( const QgsVector3D &other )
73+
{
74+
return QgsVector3D( mX - other.mX, mY - other.mY, mZ - other.mZ );
75+
}
76+
77+
private:
78+
double mX = 0, mY = 0, mZ = 0;
79+
};
80+
81+
#endif // QGSVECTOR3D_H

‎src/3d/symbols/qgsline3dsymbol_p.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ QgsLine3DSymbolEntityNode::QgsLine3DSymbolEntityNode( const Qgs3DMapSettings &ma
9393

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

9898
// TODO: configurable
9999
int nSegments = 4;

‎src/3d/symbols/qgspolygon3dsymbol_p.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ QgsPolygon3DSymbolEntityNode::QgsPolygon3DSymbolEntityNode( const Qgs3DMapSettin
121121

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

0 commit comments

Comments
 (0)
Please sign in to comment.