Skip to content

Commit 7eb5d22

Browse files
committed
A new button to set camera pose from an existing 3D view
1 parent 0fd2962 commit 7eb5d22

File tree

3 files changed

+135
-81
lines changed

3 files changed

+135
-81
lines changed

src/app/layout/qgslayout3dmapwidget.cpp

+76-34
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,57 @@
1919
#include "qgs3dmapcanvas.h"
2020
#include "qgs3dmapcanvasdockwidget.h"
2121
#include "qgs3dmapsettings.h"
22+
#include "qgscameracontroller.h"
2223
#include <QMenu>
2324

25+
26+
float _normalizedAngle( float x )
27+
{
28+
x = std::fmod( x, 360 );
29+
if ( x < 0 ) x += 360;
30+
return x;
31+
}
32+
33+
template<typename Func1>
34+
void _prepare3DViewsMenu( QMenu *menu, QgsLayout3DMapWidget *w, Func1 slot )
35+
{
36+
QObject::connect( menu, &QMenu::aboutToShow, w, [menu, w, slot]
37+
{
38+
const QList<Qgs3DMapCanvasDockWidget *> lst = QgisApp::instance()->findChildren<Qgs3DMapCanvasDockWidget *>();
39+
menu->clear();
40+
for ( auto dock : lst )
41+
{
42+
QAction *a = menu->addAction( dock->mapCanvas3D()->objectName(), w, slot );
43+
// need to use a custom property for identification because Qt likes to add "&" to the action text
44+
a->setProperty( "name", dock->mapCanvas3D()->objectName() );
45+
}
46+
if ( lst.isEmpty() )
47+
{
48+
menu->addAction( QObject::tr( "No 3D maps defined" ) )->setEnabled( false );
49+
}
50+
} );
51+
}
52+
53+
Qgs3DMapCanvasDockWidget *_dock3DViewFromSender( QObject *sender )
54+
{
55+
QAction *action = qobject_cast<QAction *>( sender );
56+
if ( !action )
57+
return nullptr;
58+
59+
QString actionText = action->property( "name" ).toString();
60+
const QList<Qgs3DMapCanvasDockWidget *> lst = QgisApp::instance()->findChildren<Qgs3DMapCanvasDockWidget *>();
61+
for ( auto dock : lst )
62+
{
63+
QString objName = dock->mapCanvas3D()->objectName();
64+
if ( objName == actionText )
65+
{
66+
return dock;
67+
}
68+
}
69+
return nullptr;
70+
}
71+
72+
2473
QgsLayout3DMapWidget::QgsLayout3DMapWidget( QgsLayoutItem3DMap *map3D )
2574
: QgsLayoutItemBaseWidget( nullptr, map3D )
2675
, mMap3D( map3D )
@@ -38,52 +87,45 @@ QgsLayout3DMapWidget::QgsLayout3DMapWidget( QgsLayoutItem3DMap *map3D )
3887

3988
mMenu3DCanvases = new QMenu( this );
4089
mCopySettingsButton->setMenu( mMenu3DCanvases );
41-
connect( mMenu3DCanvases, &QMenu::aboutToShow, this, [ = ]
42-
{
43-
const QList<Qgs3DMapCanvasDockWidget *> lst = QgisApp::instance()->findChildren<Qgs3DMapCanvasDockWidget *>();
44-
mMenu3DCanvases->clear();
45-
for ( auto dock : lst )
46-
{
47-
QAction *a = mMenu3DCanvases->addAction( dock->mapCanvas3D()->objectName(), this, &QgsLayout3DMapWidget::copy3DMapSettings );
48-
// need to use a custom property for identification because Qt likes to add "&" to the action text
49-
a->setProperty( "name", dock->mapCanvas3D()->objectName() );
50-
}
51-
if ( lst.isEmpty() )
52-
{
53-
mMenu3DCanvases->addAction( tr( "No 3D maps defined" ) )->setEnabled( false );
54-
}
55-
} );
90+
_prepare3DViewsMenu( mMenu3DCanvases, this, &QgsLayout3DMapWidget::copy3DMapSettings );
5691

57-
QgsCameraPose pose = mMap3D->cameraPose();
58-
mCenterXSpinBox->setValue( pose.centerPoint().x() );
59-
mCenterYSpinBox->setValue( pose.centerPoint().y() );
60-
mCenterZSpinBox->setValue( pose.centerPoint().z() );
61-
mDistanceToCenterSpinBox->setValue( pose.distanceFromCenterPoint() );
62-
mPitchAngleSpinBox->setValue( pose.pitchAngle() );
63-
mHeadingAngleSpinBox->setValue( pose.headingAngle() );
92+
mMenu3DCanvasesPose = new QMenu( this );
93+
mPoseFromViewButton->setMenu( mMenu3DCanvasesPose );
94+
_prepare3DViewsMenu( mMenu3DCanvasesPose, this, &QgsLayout3DMapWidget::copeCameraPose );
6495

6596
QList<QgsDoubleSpinBox *> lst;
6697
lst << mCenterXSpinBox << mCenterYSpinBox << mCenterZSpinBox << mDistanceToCenterSpinBox << mPitchAngleSpinBox << mHeadingAngleSpinBox;
6798
for ( QgsDoubleSpinBox *spinBox : lst )
6899
connect( spinBox, qgis::overload<double>::of( &QgsDoubleSpinBox::valueChanged ), this, &QgsLayout3DMapWidget::updateCameraPose );
100+
101+
updateCameraPoseWidgetsFromItem();
102+
}
103+
104+
void QgsLayout3DMapWidget::updateCameraPoseWidgetsFromItem()
105+
{
106+
QgsCameraPose pose = mMap3D->cameraPose();
107+
whileBlocking( mCenterXSpinBox )->setValue( pose.centerPoint().x() );
108+
whileBlocking( mCenterYSpinBox )->setValue( pose.centerPoint().y() );
109+
whileBlocking( mCenterZSpinBox )->setValue( pose.centerPoint().z() );
110+
whileBlocking( mDistanceToCenterSpinBox )->setValue( pose.distanceFromCenterPoint() );
111+
whileBlocking( mPitchAngleSpinBox )->setValue( _normalizedAngle( pose.pitchAngle() ) );
112+
whileBlocking( mHeadingAngleSpinBox )->setValue( _normalizedAngle( pose.headingAngle() ) );
69113
}
70114

71115
void QgsLayout3DMapWidget::copy3DMapSettings()
72116
{
73-
QAction *action = qobject_cast<QAction *>( sender() );
74-
if ( !action )
75-
return;
117+
Qgs3DMapCanvasDockWidget *dock = _dock3DViewFromSender( sender() );
118+
if ( dock )
119+
mMap3D->setMapSettings( new Qgs3DMapSettings( *dock->mapCanvas3D()->map() ) );
120+
}
76121

77-
QString actionText = action->property( "name" ).toString();
78-
const QList<Qgs3DMapCanvasDockWidget *> lst = QgisApp::instance()->findChildren<Qgs3DMapCanvasDockWidget *>();
79-
for ( auto dock : lst )
122+
void QgsLayout3DMapWidget::copeCameraPose()
123+
{
124+
Qgs3DMapCanvasDockWidget *dock = _dock3DViewFromSender( sender() );
125+
if ( dock )
80126
{
81-
QString objName = dock->mapCanvas3D()->objectName();
82-
if ( objName == actionText )
83-
{
84-
mMap3D->setMapSettings( new Qgs3DMapSettings( *dock->mapCanvas3D()->map() ) );
85-
break;
86-
}
127+
mMap3D->setCameraPose( dock->mapCanvas3D()->cameraController()->cameraPose() );
128+
updateCameraPoseWidgetsFromItem();
87129
}
88130
}
89131

src/app/layout/qgslayout3dmapwidget.h

+5
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,19 @@ class QgsLayout3DMapWidget : public QgsLayoutItemBaseWidget, private Ui::QgsLayo
2828
public:
2929
explicit QgsLayout3DMapWidget( QgsLayoutItem3DMap *map3D );
3030

31+
private:
32+
void updateCameraPoseWidgetsFromItem();
33+
3134
private slots:
3235
void copy3DMapSettings();
36+
void copeCameraPose();
3337
void updateCameraPose();
3438

3539
private:
3640
QPointer< QgsLayoutItem3DMap > mMap3D;
3741
QgsLayoutItemPropertiesWidget *mItemPropertiesWidget = nullptr;
3842
QMenu *mMenu3DCanvases = nullptr;
43+
QMenu *mMenu3DCanvasesPose = nullptr;
3944
};
4045

4146
#endif // QGSLAYOUT3DMAPWIDGET_H

src/ui/layout/qgslayout3dmapwidgetbase.ui

+54-47
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@
5454
<property name="geometry">
5555
<rect>
5656
<x>0</x>
57-
<y>0</y>
57+
<y>-128</y>
5858
<width>510</width>
59-
<height>635</height>
59+
<height>698</height>
6060
</rect>
6161
</property>
6262
<layout class="QVBoxLayout" name="mainLayout">
@@ -82,15 +82,8 @@
8282
<string>Camera pose</string>
8383
</property>
8484
<layout class="QGridLayout" name="gridLayout_3">
85-
<item row="0" column="0">
86-
<widget class="QLabel" name="label">
87-
<property name="text">
88-
<string>Center X</string>
89-
</property>
90-
</widget>
91-
</item>
92-
<item row="0" column="1">
93-
<widget class="QgsDoubleSpinBox" name="mCenterXSpinBox">
85+
<item row="1" column="1">
86+
<widget class="QgsDoubleSpinBox" name="mCenterYSpinBox">
9487
<property name="decimals">
9588
<number>1</number>
9689
</property>
@@ -102,21 +95,18 @@
10295
</property>
10396
</widget>
10497
</item>
105-
<item row="1" column="0">
106-
<widget class="QLabel" name="label_3">
98+
<item row="0" column="0">
99+
<widget class="QLabel" name="label">
107100
<property name="text">
108-
<string>Center Y</string>
101+
<string>Center X</string>
109102
</property>
110103
</widget>
111104
</item>
112-
<item row="1" column="1">
113-
<widget class="QgsDoubleSpinBox" name="mCenterYSpinBox">
105+
<item row="3" column="1">
106+
<widget class="QgsDoubleSpinBox" name="mDistanceToCenterSpinBox">
114107
<property name="decimals">
115108
<number>1</number>
116109
</property>
117-
<property name="minimum">
118-
<double>-9999999.000000000000000</double>
119-
</property>
120110
<property name="maximum">
121111
<double>9999999.000000000000000</double>
122112
</property>
@@ -129,33 +119,30 @@
129119
</property>
130120
</widget>
131121
</item>
132-
<item row="2" column="1">
133-
<widget class="QgsDoubleSpinBox" name="mCenterZSpinBox">
134-
<property name="decimals">
135-
<number>1</number>
136-
</property>
137-
<property name="minimum">
138-
<double>-9999999.000000000000000</double>
139-
</property>
140-
<property name="maximum">
141-
<double>9999999.000000000000000</double>
142-
</property>
143-
</widget>
144-
</item>
145-
<item row="3" column="0">
146-
<widget class="QLabel" name="label_5">
122+
<item row="1" column="0">
123+
<widget class="QLabel" name="label_3">
147124
<property name="text">
148-
<string>Distance</string>
125+
<string>Center Y</string>
149126
</property>
150127
</widget>
151128
</item>
152-
<item row="3" column="1">
153-
<widget class="QgsDoubleSpinBox" name="mDistanceToCenterSpinBox">
129+
<item row="5" column="1">
130+
<widget class="QgsDoubleSpinBox" name="mHeadingAngleSpinBox">
131+
<property name="suffix">
132+
<string> °</string>
133+
</property>
154134
<property name="decimals">
155135
<number>1</number>
156136
</property>
157137
<property name="maximum">
158-
<double>9999999.000000000000000</double>
138+
<double>360.000000000000000</double>
139+
</property>
140+
</widget>
141+
</item>
142+
<item row="5" column="0">
143+
<widget class="QLabel" name="label_7">
144+
<property name="text">
145+
<string>Heading</string>
159146
</property>
160147
</widget>
161148
</item>
@@ -179,23 +166,43 @@
179166
</property>
180167
</widget>
181168
</item>
182-
<item row="5" column="0">
183-
<widget class="QLabel" name="label_7">
184-
<property name="text">
185-
<string>Heading</string>
169+
<item row="0" column="1">
170+
<widget class="QgsDoubleSpinBox" name="mCenterXSpinBox">
171+
<property name="decimals">
172+
<number>1</number>
173+
</property>
174+
<property name="minimum">
175+
<double>-9999999.000000000000000</double>
176+
</property>
177+
<property name="maximum">
178+
<double>9999999.000000000000000</double>
186179
</property>
187180
</widget>
188181
</item>
189-
<item row="5" column="1">
190-
<widget class="QgsDoubleSpinBox" name="mHeadingAngleSpinBox">
191-
<property name="suffix">
192-
<string> °</string>
182+
<item row="3" column="0">
183+
<widget class="QLabel" name="label_5">
184+
<property name="text">
185+
<string>Distance</string>
193186
</property>
187+
</widget>
188+
</item>
189+
<item row="2" column="1">
190+
<widget class="QgsDoubleSpinBox" name="mCenterZSpinBox">
194191
<property name="decimals">
195192
<number>1</number>
196193
</property>
194+
<property name="minimum">
195+
<double>-9999999.000000000000000</double>
196+
</property>
197197
<property name="maximum">
198-
<double>360.000000000000000</double>
198+
<double>9999999.000000000000000</double>
199+
</property>
200+
</widget>
201+
</item>
202+
<item row="6" column="0" colspan="2">
203+
<widget class="QPushButton" name="mPoseFromViewButton">
204+
<property name="text">
205+
<string>Set from a 3D view...</string>
199206
</property>
200207
</widget>
201208
</item>

0 commit comments

Comments
 (0)