Zoom in and out buttons

1869
5
Jump to solution
08-25-2021 11:56 PM
FatmaAkdemir
Occasional Contributor II

If we wanted to add zoom in and out buttons to a 3D SceneGraphicsView, what would be the way to do it? Are there any samples about it?

0 Kudos
1 Solution

Accepted Solutions
Tanner_Yould
Esri Contributor

Hi Fatma, thanks for reaching out and apologies for the delay in response.

As far as samples to reference, we created a navigation toolbar for our Dynamic Situational Awareness demo app, but I also drafted up some quick code in Qt C++ that showcases an isolated possible workflow. 

At its core, the workflow is to call SceneView::setViewpointCamera(const Camera) with a new Camera that is slightly zoomed in or out. We can create a new camera at a different elevation with Camera::elevate(double deltaAltitude).

I defined two functions: zoomIn() and zoomOut() to handle each case, but they're effectively the same. One thing to note is that I get the currentElevation of the viewpoint camera, and then use that to create a variable deltaAltitude to pass to elevate(), so the change will be larger at higher elevations and smaller at lower elevations.

 

 

// SceneZoom.cpp
void SceneZoom::zoomIn()
{
  double currentElevation = m_sceneView->currentViewpointCamera().location().z();
  m_sceneView->setViewpointCamera(m_sceneView->currentViewpointCamera().elevate(-currentElevation*.25), 0.1);
}

void SceneZoom::zoomOut()
{
  double currentElevation = m_sceneView->currentViewpointCamera().location().z();
  m_sceneView->setViewpointCamera(m_sceneView->currentViewpointCamera().elevate(currentElevation*.25), 0.1);
}
/* SceneZoom.qml
...
Column {
    Button {
        id: zoomIn
        Text {
            text: "zoom in"
        }

        onPressed: model.zoomIn();
    }
    Button {
        id: zoomOut
        Text {
            text: "zoom out"
        }
        onPressed: model.zoomOut();
    }
}
...
*/
/* SceneZoom.h
class SceneZoom : public QObject
{
  Q_OBJECT
...
public:
...
  Q_INVOKABLE void zoomIn();
  Q_INVOKABLE void zoomOut();
...
}

 

 

It's also worth noting that users can navigate using the keyboard (+/- keys will do an animated zoom in/out and j/u keys will do an immediate zoom). In order to enable these, you may need to explicitly set focus to true in the SceneView component in your qml file.

 

SceneView {
    focus: true // <----
    id: view
    anchors.fill: parent
}

 

 

I hope this helps and please let me know if there's anything else I can do for you!

 

Tanner Yould
Samples Product Engineer
ArcGIS Maps SDK for Qt
Esri

View solution in original post

0 Kudos
5 Replies
Tanner_Yould
Esri Contributor

Hi Fatma, thanks for reaching out and apologies for the delay in response.

As far as samples to reference, we created a navigation toolbar for our Dynamic Situational Awareness demo app, but I also drafted up some quick code in Qt C++ that showcases an isolated possible workflow. 

At its core, the workflow is to call SceneView::setViewpointCamera(const Camera) with a new Camera that is slightly zoomed in or out. We can create a new camera at a different elevation with Camera::elevate(double deltaAltitude).

I defined two functions: zoomIn() and zoomOut() to handle each case, but they're effectively the same. One thing to note is that I get the currentElevation of the viewpoint camera, and then use that to create a variable deltaAltitude to pass to elevate(), so the change will be larger at higher elevations and smaller at lower elevations.

 

 

// SceneZoom.cpp
void SceneZoom::zoomIn()
{
  double currentElevation = m_sceneView->currentViewpointCamera().location().z();
  m_sceneView->setViewpointCamera(m_sceneView->currentViewpointCamera().elevate(-currentElevation*.25), 0.1);
}

void SceneZoom::zoomOut()
{
  double currentElevation = m_sceneView->currentViewpointCamera().location().z();
  m_sceneView->setViewpointCamera(m_sceneView->currentViewpointCamera().elevate(currentElevation*.25), 0.1);
}
/* SceneZoom.qml
...
Column {
    Button {
        id: zoomIn
        Text {
            text: "zoom in"
        }

        onPressed: model.zoomIn();
    }
    Button {
        id: zoomOut
        Text {
            text: "zoom out"
        }
        onPressed: model.zoomOut();
    }
}
...
*/
/* SceneZoom.h
class SceneZoom : public QObject
{
  Q_OBJECT
...
public:
...
  Q_INVOKABLE void zoomIn();
  Q_INVOKABLE void zoomOut();
...
}

 

 

It's also worth noting that users can navigate using the keyboard (+/- keys will do an animated zoom in/out and j/u keys will do an immediate zoom). In order to enable these, you may need to explicitly set focus to true in the SceneView component in your qml file.

 

SceneView {
    focus: true // <----
    id: view
    anchors.fill: parent
}

 

 

I hope this helps and please let me know if there's anything else I can do for you!

 

Tanner Yould
Samples Product Engineer
ArcGIS Maps SDK for Qt
Esri
0 Kudos
FatmaAkdemir
Occasional Contributor II

Thank you very much @Tanner_Yould . Seems great! I'm gonna try this solution today.

0 Kudos
FatmaAkdemir
Occasional Contributor II

Hi @Tanner_Yould , I tried this solution and it perfectly works when the camera controller is GlobeCameraController. However when user switches to OrbitLocationCameraController it does not work. How can we adapt this solution to OrbitLocationCameraController? Or should I use NavigationController class?

0 Kudos
Tanner_Yould
Esri Contributor

@FatmaAkdemir the Orbit the camera around an object sample uses the OrbitGeoElementCameraController which shares the parent class CameraController with OrbitLocationCameraController, so you may find that helpful. However, I think OrbitLocationCameraController::moveCamera may be what you're looking for and you can pass a deltaDistance to zoom the camera in and out.

Tanner Yould
Samples Product Engineer
ArcGIS Maps SDK for Qt
Esri
0 Kudos
FatmaAkdemir
Occasional Contributor II

Thanks @Tanner_Yould , I wanted to add the code here, in case someone needs a quick solution to a similar problem.

void MainMapWidget::ZoomInSlot(){
	if(dynamic_cast<GlobeCameraController*>(m_sceneView->cameraController()) != NULL){
		double currentElevation = m_sceneView->currentViewpointCamera().location().z();
		m_sceneView->setViewpointCamera(m_sceneView->currentViewpointCamera().elevate(-currentElevation*.25), 0.1);
	}
	else{
		OrbitLocationCameraController *camCtrl = (OrbitLocationCameraController*)m_sceneView->cameraController();
		camCtrl->moveCamera(-camCtrl->cameraDistance()*.25, 0, 0, 1);
	}

}

void MainMapWidget::ZoomOutSlot(){
	if(dynamic_cast<GlobeCameraController*>(m_sceneView->cameraController()) != NULL){
		double currentElevation = m_sceneView->currentViewpointCamera().location().z();
		m_sceneView->setViewpointCamera(m_sceneView->currentViewpointCamera().elevate(currentElevation*.25), 0.1);
	}
	else{
		OrbitLocationCameraController *camCtrl = (OrbitLocationCameraController*)m_sceneView->cameraController();
		camCtrl->moveCamera(camCtrl->cameraDistance()*.25, 0,0,1);
	}
}