Calculate camera position with a specific heading and pitch

1645
7
09-01-2021 09:39 AM
MichaelHamsa
Occasional Contributor

Hello,

I'm wondering if anyone has a clever way to calculate the camera position with a specified heading and pitch so that it encompasses a feature's bounds on the ground.

Thanks,

Mike...

0 Kudos
7 Replies
Nicholas-Furness
Esri Regular Contributor

Could you not create a Viewpoint with a Camera and geometry, and then read the camera's properties? You might need to actually set the viewpoint on a MapView for the camera properties to update. Would that work for what you're trying to do?

0 Kudos
MichaelHamsa
Occasional Contributor

Thank you for the reply - one question, what should pass in as the Camera? I've got the geometry (envelope) at the time of the event, but the only Camera I can get is the current one from the SceneView. Obviously when I pass that camera in it keeps me at the exact same camera position and view of the scene.

Here's what I tried:

var cam = SiteMapView.Camera;
var vp = new Viewpoint(areaOfInterest, cam);
await SiteMapView.SetViewpointAsync(vp);

 

If I do this (below), it zooms to the center of the envelope at a very tight zoom scale so I cannot see the entire bounds of the envelope - it's like it's zoomed way in on the center of the envelope. I have to manually zoom way out to see the bounds of the envelope I passed in.

var vp = new Viewpoint(areaOfInterest);
await SiteMapView.SetViewpointAsync(vp);

 

 

0 Kudos
Nicholas-Furness
Esri Regular Contributor

Well, a camera is a location plus some information about where it's looking. Maybe I misunderstood your question, but my thinking is this…

If you can work out where you want to place the camera relative to the geometry, you might get fairly close to what you're after. You can probably do some cartesian calculations to place the camera location relative to the geometry envelope's centroid (relative x/y units for heading, and relative elevation for pitch). Use that to create the camera with a location and set the heading/pitch/roll all set to 0. Pass that camera in as I suggested to create the viewpoint with a camera and geometry, and then read the camera property back once the scene view has updated.

Bear in mind there are SetViewpoint methods that animate and that don't. Make sure you read the camera once the animation is finished, or use a SetViewpoint method that doesn't animate.

Does that help?

If you need the geometry to fill the view, that might be a bit trickier.

0 Kudos
MichaelHamsa
Occasional Contributor

Yeah, I guess that's what I'm trying to figure out - where to position the camera so it has a view of the bounds of the envelope. I'd like to keep the camera at a specific heading and pitch and just move it, but that's really a nice to have and not required. If I could just implement some basic "zoom to bounds" capability using a SceneView that would be great, even if the heading and pitch changed. I haven't been able to get that working very well.

Even setting the pitch to 0 so you're looking straight down on the scene is difficult, because you've got to work out the correct elevation of the camera so it sees the bounds of the envelop, and only the bounds of the envelope. You don't want the camera too high or you see too much  (past the bounds of the envelope) and you don't want the camera too low or you don't see enough of the bounds of the envelope.

0 Kudos
Nicholas-Furness
Esri Regular Contributor

Ah. Right. I see. So really it's a question of figuring out a vector from the geometry to the camera based off heading and pitch (essentially reversing them) and then working out the length of that vector to position the camera at. Hmm. I'll have a think.

0 Kudos
MichaelHamsa
Occasional Contributor

I guess what I'm trying to figure out is the location of a new camera - so that I can view the bounds of the envelope I've created. I know the heading and the pitch (I'm just going to copy that from the current camera) but I need to figure out where to set the camera's location so it has a complete view of the envelop given that specific heading and pitch. I don't what to change the heading or the pitch, just the location.

 

Kind of like the way SetViewpointGeometryAsync works on the MapView. In that case, we can assume the heading is always 360 and the pitch is always 0 and when I call SetViewpointGeometryAsync it moves the camera into a position where the Map's view can see the entire bounds of the envelope.

0 Kudos
sandiegomonedero
New Contributor II

what about:

1) Get the centerPoint of your geometry
2) Get the maximum distance D1 from the centerPoint to your geometry
3) Calculate the distance D2 required to fit D1 while looking at the centerPoint.
D2=D1/tan(sv.FieldOfView*DegToRad) (maybe FOV has to be divided by 2)
4) Create a new camera ca= new Camera(centerPoint, D2, heading , pitch, 0)
If the terrain affects the calculation because you are too close or the pitch is too extreme, maybe you can simply put the camera on top.
just an idea, I havent tried it, hope it helps.

0 Kudos