This method returns wrong values when the scene has an elevation.
After further debugging I found out that this method expect the absolute altitude (including baseSurface elevation) but the shapes we draw have their altitude relative to the ground.
As a consequence, when the map has an elevation on the baseSurface and we use the same AGSPoint to draw a shape then in AGSSceneView.locationToScreen, the result of this function is not corresponding to what is displayed on the screen.
Solved! Go to Solution.
Thank you for the code, it helped reproduce things here. After speaking with a member of our 3D team, I found a solution to your problem. The LocationToScreen method takes an input MapPoint but its not aware of SurfacePlacement modes unlike Graphics in a Layer. The MapPoint will be treated as absolute. To work around this, you will need to retrieve the elevation value for the X,Y of the point and add it to the Z value of the graphic/geometry you want to input into the LocationToScreen method.
sceneView.scene?.baseSurface?.elevation(for:, completion:) will retrieve the elevation, which you would then add to the Z value of your point.
I realize you mentioned that method earlier, and that it is asynchronous, but hopefully it won't be too difficult to incorporate it into your code.
Let me know if I can be of further assistance,
Mark
Thank you for your question! There are a couple of things you can try.
- You can try using the - (AGSPoint *)screenToBaseSurface:(CGPoint)screenPoint; method instead. That method Converts the specified screen point to a location on the base surface i.e. ignoring any 3D features/graphics on or above the surface that may be intersecting the screen point. The location returned will have a z-value corresponding to the elevation at the intersecting surface.
- Depending on if your features/graphics are in a layer or in a graphics overlay, look at the
AGSSurfacePlacement and AGSLayerSceneProperties classes. AGSLayerSceneProperties has a AGSSurfacePlacement property, which specifies how data belonging to the layer should be placed in relation to the scene's surface. Both AGSGraphicsOverlay and AGSFeatureLayer have a AGSLayerSceneProperties property which you can use to specify how the data is placed.
If that doesn't solve your issue, or if you have more questions, please reach out!
Mark
Hello @MarkDostal and thank you for your quick response.
We just need to know where the graphic is displayed on the screen, and to do that I don't know which screenPoint I should use to call - (AGSPoint *)screenToBaseSurface:(CGPoint)screenPoint; since I may have different elevations on the screen. We tried sceneView.scene?.baseSurface?.elevation(for: point, completion: completion) to get the elevation but it is unfortunatly asynchrone hence too complicated to use in our case.
Concerning AGSSurfacePlacement, we use AGSGraphicsOverlay and the items are placed relatively to the ground which is what we needs.
Sorry, I think I misunderstood your initial question, which was to get a screen location. So, obviously, screenToBaseSurface won't work. What do you want to do with the screen point once you have it? The screen location of a particular map point/graphic/feature will change as the map is panned/zoomed.
What kind of issues are you seeing with AGSSceneView.locationToScreen? A screen shot would be helpful, if possible.
Thanks,
Mark
Hi,
I have a graphic displayed in a 3D map and I just want to know if the graphic is visible on the map and with some padding, not too close to the edge.
The problem is when the baseSurface of the map has an elevation, the result returned by AGSSceneView.locationToScreen is wrong. It returns that the shape is visible on screen with y = 15 when in reality the shape is off screen with y ~= -10. I use the same AGSPoint to draw the shape and as a parameter to AGSSceneView.locationToScreen.
I've tried a few things out on my end, but to make sure I'm understanding things correctly, can you send me the coordinates and SR of the `AGSPoint` used to draw the graphic? Also, the `SceneView`s `currentViewpointCamera`? I can then replicate what you're seeing.
For example:
print("currentViewpointCamera: \(sceneView.currentViewpointCamera())")
print("geometry = \(g.geometry)")
Which gives this output:
currentViewpointCamera: AGSCamera: heading: 330.00, pitch: 97.00, roll: 0.00, location: AGSPoint: (-4.459500, 48.388900, 80.000000, nan), sr: 4326
geometry = Optional(AGSPoint: (-4.460926, 48.390397, 71.284401, nan), sr: 4326)
If you could also provide the elevation source you are using (if it's OK to share), that would be great.
That way I can recreate the issue here and delve into it some more.
Thank you for your patience!
Mark
Thank you for the code, it helped reproduce things here. After speaking with a member of our 3D team, I found a solution to your problem. The LocationToScreen method takes an input MapPoint but its not aware of SurfacePlacement modes unlike Graphics in a Layer. The MapPoint will be treated as absolute. To work around this, you will need to retrieve the elevation value for the X,Y of the point and add it to the Z value of the graphic/geometry you want to input into the LocationToScreen method.
sceneView.scene?.baseSurface?.elevation(for:, completion:) will retrieve the elevation, which you would then add to the Z value of your point.
I realize you mentioned that method earlier, and that it is asynchronous, but hopefully it won't be too difficult to incorporate it into your code.
Let me know if I can be of further assistance,
Mark