Skip to content

Commit

Permalink
A new button to set camera pose from an existing 3D view
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed Aug 25, 2018
1 parent 0fd2962 commit 7eb5d22
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 81 deletions.
110 changes: 76 additions & 34 deletions src/app/layout/qgslayout3dmapwidget.cpp
Expand Up @@ -19,8 +19,57 @@
#include "qgs3dmapcanvas.h"
#include "qgs3dmapcanvasdockwidget.h"
#include "qgs3dmapsettings.h"
#include "qgscameracontroller.h"
#include <QMenu>


float _normalizedAngle( float x )
{
x = std::fmod( x, 360 );
if ( x < 0 ) x += 360;
return x;
}

template<typename Func1>
void _prepare3DViewsMenu( QMenu *menu, QgsLayout3DMapWidget *w, Func1 slot )
{
QObject::connect( menu, &QMenu::aboutToShow, w, [menu, w, slot]
{
const QList<Qgs3DMapCanvasDockWidget *> lst = QgisApp::instance()->findChildren<Qgs3DMapCanvasDockWidget *>();
menu->clear();
for ( auto dock : lst )
{
QAction *a = menu->addAction( dock->mapCanvas3D()->objectName(), w, slot );
// need to use a custom property for identification because Qt likes to add "&" to the action text
a->setProperty( "name", dock->mapCanvas3D()->objectName() );
}
if ( lst.isEmpty() )
{
menu->addAction( QObject::tr( "No 3D maps defined" ) )->setEnabled( false );
}
} );
}

Qgs3DMapCanvasDockWidget *_dock3DViewFromSender( QObject *sender )
{
QAction *action = qobject_cast<QAction *>( sender );
if ( !action )
return nullptr;

QString actionText = action->property( "name" ).toString();
const QList<Qgs3DMapCanvasDockWidget *> lst = QgisApp::instance()->findChildren<Qgs3DMapCanvasDockWidget *>();
for ( auto dock : lst )
{
QString objName = dock->mapCanvas3D()->objectName();
if ( objName == actionText )
{
return dock;
}
}
return nullptr;
}


QgsLayout3DMapWidget::QgsLayout3DMapWidget( QgsLayoutItem3DMap *map3D )
: QgsLayoutItemBaseWidget( nullptr, map3D )
, mMap3D( map3D )
Expand All @@ -38,52 +87,45 @@ QgsLayout3DMapWidget::QgsLayout3DMapWidget( QgsLayoutItem3DMap *map3D )

mMenu3DCanvases = new QMenu( this );
mCopySettingsButton->setMenu( mMenu3DCanvases );
connect( mMenu3DCanvases, &QMenu::aboutToShow, this, [ = ]
{
const QList<Qgs3DMapCanvasDockWidget *> lst = QgisApp::instance()->findChildren<Qgs3DMapCanvasDockWidget *>();
mMenu3DCanvases->clear();
for ( auto dock : lst )
{
QAction *a = mMenu3DCanvases->addAction( dock->mapCanvas3D()->objectName(), this, &QgsLayout3DMapWidget::copy3DMapSettings );
// need to use a custom property for identification because Qt likes to add "&" to the action text
a->setProperty( "name", dock->mapCanvas3D()->objectName() );
}
if ( lst.isEmpty() )
{
mMenu3DCanvases->addAction( tr( "No 3D maps defined" ) )->setEnabled( false );
}
} );
_prepare3DViewsMenu( mMenu3DCanvases, this, &QgsLayout3DMapWidget::copy3DMapSettings );

QgsCameraPose pose = mMap3D->cameraPose();
mCenterXSpinBox->setValue( pose.centerPoint().x() );
mCenterYSpinBox->setValue( pose.centerPoint().y() );
mCenterZSpinBox->setValue( pose.centerPoint().z() );
mDistanceToCenterSpinBox->setValue( pose.distanceFromCenterPoint() );
mPitchAngleSpinBox->setValue( pose.pitchAngle() );
mHeadingAngleSpinBox->setValue( pose.headingAngle() );
mMenu3DCanvasesPose = new QMenu( this );
mPoseFromViewButton->setMenu( mMenu3DCanvasesPose );
_prepare3DViewsMenu( mMenu3DCanvasesPose, this, &QgsLayout3DMapWidget::copeCameraPose );

QList<QgsDoubleSpinBox *> lst;
lst << mCenterXSpinBox << mCenterYSpinBox << mCenterZSpinBox << mDistanceToCenterSpinBox << mPitchAngleSpinBox << mHeadingAngleSpinBox;
for ( QgsDoubleSpinBox *spinBox : lst )
connect( spinBox, qgis::overload<double>::of( &QgsDoubleSpinBox::valueChanged ), this, &QgsLayout3DMapWidget::updateCameraPose );

updateCameraPoseWidgetsFromItem();
}

void QgsLayout3DMapWidget::updateCameraPoseWidgetsFromItem()
{
QgsCameraPose pose = mMap3D->cameraPose();
whileBlocking( mCenterXSpinBox )->setValue( pose.centerPoint().x() );
whileBlocking( mCenterYSpinBox )->setValue( pose.centerPoint().y() );
whileBlocking( mCenterZSpinBox )->setValue( pose.centerPoint().z() );
whileBlocking( mDistanceToCenterSpinBox )->setValue( pose.distanceFromCenterPoint() );
whileBlocking( mPitchAngleSpinBox )->setValue( _normalizedAngle( pose.pitchAngle() ) );
whileBlocking( mHeadingAngleSpinBox )->setValue( _normalizedAngle( pose.headingAngle() ) );
}

void QgsLayout3DMapWidget::copy3DMapSettings()
{
QAction *action = qobject_cast<QAction *>( sender() );
if ( !action )
return;
Qgs3DMapCanvasDockWidget *dock = _dock3DViewFromSender( sender() );
if ( dock )
mMap3D->setMapSettings( new Qgs3DMapSettings( *dock->mapCanvas3D()->map() ) );
}

QString actionText = action->property( "name" ).toString();
const QList<Qgs3DMapCanvasDockWidget *> lst = QgisApp::instance()->findChildren<Qgs3DMapCanvasDockWidget *>();
for ( auto dock : lst )
void QgsLayout3DMapWidget::copeCameraPose()
{
Qgs3DMapCanvasDockWidget *dock = _dock3DViewFromSender( sender() );
if ( dock )
{
QString objName = dock->mapCanvas3D()->objectName();
if ( objName == actionText )
{
mMap3D->setMapSettings( new Qgs3DMapSettings( *dock->mapCanvas3D()->map() ) );
break;
}
mMap3D->setCameraPose( dock->mapCanvas3D()->cameraController()->cameraPose() );
updateCameraPoseWidgetsFromItem();
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/app/layout/qgslayout3dmapwidget.h
Expand Up @@ -28,14 +28,19 @@ class QgsLayout3DMapWidget : public QgsLayoutItemBaseWidget, private Ui::QgsLayo
public:
explicit QgsLayout3DMapWidget( QgsLayoutItem3DMap *map3D );

private:
void updateCameraPoseWidgetsFromItem();

private slots:
void copy3DMapSettings();
void copeCameraPose();
void updateCameraPose();

private:
QPointer< QgsLayoutItem3DMap > mMap3D;
QgsLayoutItemPropertiesWidget *mItemPropertiesWidget = nullptr;
QMenu *mMenu3DCanvases = nullptr;
QMenu *mMenu3DCanvasesPose = nullptr;
};

#endif // QGSLAYOUT3DMAPWIDGET_H
101 changes: 54 additions & 47 deletions src/ui/layout/qgslayout3dmapwidgetbase.ui
Expand Up @@ -54,9 +54,9 @@
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<y>-128</y>
<width>510</width>
<height>635</height>
<height>698</height>
</rect>
</property>
<layout class="QVBoxLayout" name="mainLayout">
Expand All @@ -82,15 +82,8 @@
<string>Camera pose</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Center X</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsDoubleSpinBox" name="mCenterXSpinBox">
<item row="1" column="1">
<widget class="QgsDoubleSpinBox" name="mCenterYSpinBox">
<property name="decimals">
<number>1</number>
</property>
Expand All @@ -102,21 +95,18 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Center Y</string>
<string>Center X</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QgsDoubleSpinBox" name="mCenterYSpinBox">
<item row="3" column="1">
<widget class="QgsDoubleSpinBox" name="mDistanceToCenterSpinBox">
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-9999999.000000000000000</double>
</property>
<property name="maximum">
<double>9999999.000000000000000</double>
</property>
Expand All @@ -129,33 +119,30 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QgsDoubleSpinBox" name="mCenterZSpinBox">
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-9999999.000000000000000</double>
</property>
<property name="maximum">
<double>9999999.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Distance</string>
<string>Center Y</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QgsDoubleSpinBox" name="mDistanceToCenterSpinBox">
<item row="5" column="1">
<widget class="QgsDoubleSpinBox" name="mHeadingAngleSpinBox">
<property name="suffix">
<string> °</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>9999999.000000000000000</double>
<double>360.000000000000000</double>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Heading</string>
</property>
</widget>
</item>
Expand All @@ -179,23 +166,43 @@
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Heading</string>
<item row="0" column="1">
<widget class="QgsDoubleSpinBox" name="mCenterXSpinBox">
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-9999999.000000000000000</double>
</property>
<property name="maximum">
<double>9999999.000000000000000</double>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QgsDoubleSpinBox" name="mHeadingAngleSpinBox">
<property name="suffix">
<string> °</string>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Distance</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QgsDoubleSpinBox" name="mCenterZSpinBox">
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-9999999.000000000000000</double>
</property>
<property name="maximum">
<double>360.000000000000000</double>
<double>9999999.000000000000000</double>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QPushButton" name="mPoseFromViewButton">
<property name="text">
<string>Set from a 3D view...</string>
</property>
</widget>
</item>
Expand Down

0 comments on commit 7eb5d22

Please sign in to comment.