Skip to content

Commit e214c6f

Browse files
committedNov 27, 2017
Introduce QgsVector3D for 3D vectors with double precision
QVector3D with single precision is not always enough (it has only ~7 significant digits)
1 parent 721551f commit e214c6f

16 files changed

+139
-43
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: 19 additions & 13 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 );
@@ -139,9 +138,9 @@ QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteCon
139138
QDomElement elem = doc.createElement( "qgis3d" );
140139

141140
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 ) );
141+
elemOrigin.setAttribute( "x", QString::number( mOrigin.x() ) );
142+
elemOrigin.setAttribute( "y", QString::number( mOrigin.y() ) );
143+
elemOrigin.setAttribute( "z", QString::number( mOrigin.z() ) );
145144
elem.appendChild( elemOrigin );
146145

147146
QDomElement elemCrs = doc.createElement( "crs" );
@@ -210,11 +209,18 @@ void Qgs3DMapSettings::resolveReferences( const QgsProject &project )
210209
}
211210
}
212211

213-
void Qgs3DMapSettings::setOrigin( double originX, double originY, double originZ )
212+
QgsVector3D Qgs3DMapSettings::mapToWorldCoordinates( const QgsVector3D &mapCoords ) const
214213
{
215-
mOriginX = originX;
216-
mOriginY = originY;
217-
mOriginZ = originZ;
214+
return QgsVector3D( mapCoords.x() - mOrigin.x(),
215+
-( mapCoords.z() - mOrigin.z() ),
216+
mapCoords.y() - mOrigin.y() );
217+
}
218+
219+
QgsVector3D Qgs3DMapSettings::worldToMapCoordinates( const QgsVector3D &worldCoords ) const
220+
{
221+
return QgsVector3D( worldCoords.x() + mOrigin.x(),
222+
-( worldCoords.z() + mOrigin.z() ),
223+
worldCoords.y() + mOrigin.y() );
218224
}
219225

220226
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: 1 addition & 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
}

‎src/3d/qgscameracontroller.cpp

Lines changed: 2 additions & 1 deletion
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,7 +296,7 @@ void QgsCameraController::setViewFromTop( float worldX, float worldY, float dist
295296
emit cameraChanged();
296297
}
297298

298-
void QgsCameraController::translateWorld( const QVector3D &vWorld )
299+
void QgsCameraController::translateWorld( const QgsVector3D &vWorld )
299300
{
300301
setCameraData( mCameraData.x - vWorld.x(), mCameraData.y + vWorld.y(), mCameraData.dist, mCameraData.pitch, mCameraData.yaw );
301302
emit cameraChanged();

‎src/3d/qgscameracontroller.h

Lines changed: 2 additions & 1 deletion
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
@@ -61,7 +62,7 @@ class _3D_EXPORT QgsCameraController : public Qt3DCore::QEntity
6162
void setViewFromTop( float worldX, float worldY, float distance, float yaw = 0 );
6263

6364
//! 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 );
65+
void translateWorld( const QgsVector3D &vWorld );
6566

6667
private:
6768
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: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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+
* Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double precision
23+
* instead of single precision floating point numbers.
24+
*
25+
* \note Added in QGIS 3.0
26+
*/
27+
class _3D_EXPORT QgsVector3D
28+
{
29+
public:
30+
//! Constructs a null vector
31+
QgsVector3D() = default;
32+
33+
//! Constructs a vector from given coordinates
34+
QgsVector3D( double x, double y, double z )
35+
: mX( x ), mY( y ), mZ( z ) {}
36+
37+
//! Returns true if all three coordinates are zero
38+
bool isNull() const { return mX == 0 && mY == 0 && mZ == 0; }
39+
40+
//! Returns X coordinate
41+
double x() const { return mX; }
42+
//! Returns Y coordinate
43+
double y() const { return mY; }
44+
//! Returns Z coordinate
45+
double z() const { return mZ; }
46+
47+
//! Sets vector coordinates
48+
void set( double x, double y, double z )
49+
{
50+
mX = x;
51+
mY = y;
52+
mZ = z;
53+
}
54+
55+
//! Returns sum of two vectors
56+
QgsVector3D operator+( const QgsVector3D &other )
57+
{
58+
return QgsVector3D( mX + other.mX, mY + other.mY, mZ + other.mZ );
59+
}
60+
61+
//! Returns difference of two vectors
62+
QgsVector3D operator-( const QgsVector3D &other )
63+
{
64+
return QgsVector3D( mX - other.mX, mY - other.mY, mZ - other.mZ );
65+
}
66+
67+
private:
68+
double mX = 0, mY = 0, mZ = 0;
69+
};
70+
71+
#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

‎src/3d/terrain/qgsdemterraintileloader_p.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ Qt3DCore::QEntity *QgsDemTerrainTileLoader::createEntity( Qt3DCore::QEntity *par
8282

8383
const Qgs3DMapSettings &map = terrain()->map3D();
8484
QgsRectangle extent = map.terrainGenerator()->tilingScheme().tileToExtent( mNode->tileX(), mNode->tileY(), mNode->tileZ() ); //node->extent;
85-
double x0 = extent.xMinimum() - map.originX();
86-
double y0 = extent.yMinimum() - map.originY();
85+
double x0 = extent.xMinimum() - map.origin().x();
86+
double y0 = extent.yMinimum() - map.origin().y();
8787
double side = extent.width();
8888
double half = side / 2;
8989

‎src/3d/terrain/qgsterraingenerator.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ QgsAABB QgsTerrainGenerator::rootChunkBbox( const Qgs3DMapSettings &map ) const
2727

2828
float hMin, hMax;
2929
rootChunkHeightRange( hMin, hMax );
30-
return QgsAABB( te.xMinimum() - map.originX(), hMin * map.terrainVerticalScale(), -te.yMaximum() + map.originY(),
31-
te.xMaximum() - map.originX(), hMax * map.terrainVerticalScale(), -te.yMinimum() + map.originY() );
30+
return QgsAABB( te.xMinimum() - map.origin().x(), hMin * map.terrainVerticalScale(), -te.yMaximum() + map.origin().y(),
31+
te.xMaximum() - map.origin().x(), hMax * map.terrainVerticalScale(), -te.yMinimum() + map.origin().y() );
3232
}
3333

3434
float QgsTerrainGenerator::rootChunkError( const Qgs3DMapSettings &map ) const

‎src/app/3d/qgs3dmapcanvas.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void Qgs3DMapCanvas::resetView()
8585

8686
void Qgs3DMapCanvas::setViewFromTop( const QgsPointXY &center, float distance, float rotation )
8787
{
88-
float worldX = center.x() - mMap->originX();
89-
float worldY = center.y() - mMap->originY();
88+
float worldX = center.x() - mMap->origin().x();
89+
float worldY = center.y() - mMap->origin().y();
9090
mScene->cameraController()->setViewFromTop( worldX, -worldY, distance, rotation );
9191
}

‎src/app/3d/qgs3dmapcanvasdockwidget.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,16 @@ void Qgs3DMapCanvasDockWidget::configure()
8585
if ( !dlg.exec() )
8686
return;
8787

88-
double oldOriginX = map->originX(), oldOriginY = map->originY(), oldOriginZ = map->originZ();
88+
QgsVector3D oldOrigin = map->origin();
8989

9090
// update map
9191
w->apply();
9292

93-
double dx = map->originX() - oldOriginX, dy = map->originY() - oldOriginY, dz = map->originZ() - oldOriginZ;
94-
if ( dx || dy || dz )
93+
QgsVector3D d = map->origin() - oldOrigin;
94+
if ( !d.isNull() )
9595
{
9696
// apply() call has moved origin of the world so let's move camera so we look still at the same place
97-
mCanvas->cameraController()->translateWorld( QVector3D( dx, dy, dz ) );
97+
mCanvas->cameraController()->translateWorld( d );
9898
}
9999
}
100100

‎src/app/3d/qgs3dmapconfigwidget.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ void Qgs3DMapConfigWidget::apply()
109109
if ( needsUpdateOrigin )
110110
{
111111
QgsPointXY center = mMap->terrainGenerator()->extent().center();
112-
mMap->setOrigin( center.x(), center.y(), 0 );
112+
mMap->setOrigin( QgsVector3D( center.x(), center.y(), 0 ) );
113113
}
114114

115115
mMap->setTerrainVerticalScale( spinTerrainScale->value() );

‎src/app/qgisapp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10243,7 +10243,7 @@ void QgisApp::new3DMapCanvas()
1024310243

1024410244
Qgs3DMapSettings *map = new Qgs3DMapSettings;
1024510245
map->setCrs( prj->crs() );
10246-
map->setOrigin( fullExtent.center().x(), fullExtent.center().y(), 0 );
10246+
map->setOrigin( QgsVector3D( fullExtent.center().x(), fullExtent.center().y(), 0 ) );
1024710247
map->setSelectionColor( mMapCanvas->selectionColor() );
1024810248
map->setBackgroundColor( mMapCanvas->canvasColor() );
1024910249
map->setLayers( mMapCanvas->layers() );

0 commit comments

Comments
 (0)
Please sign in to comment.