MapQuickView - Can't set SpatialReference except in constructor

1135
10
Jump to solution
04-27-2020 09:15 AM
BradDuBois
New Contributor II

I noticed that screenToLocation was returning some bad values.  While tracking that down I learned that spatial reference is an important factor here for getting correct results.

If the spatial reference is set using the Map class constructor then I get correct results from screenToLocation, which is great!  The bad news is that map imagery no longer loads. I only get map imagery if use the Map class constructor that takes a basemap.  Setting basemap after construction is not working either to get the imagery to load.

I cannot find any way to set the spatial reference for the map other than at construction.

How can I get this to work?

0 Kudos
1 Solution

Accepted Solutions
NorbertThoden
Occasional Contributor III

Hi Brad!

I´m not rellay sure but maybe the network proxy is responable for not getting data from this (arcgisonline) url.

And:

I using a map in 2D/UtmProjection and scene in 3D/WebMercatorProjection. I can switch between them.

Of course i like to process events like the mouse moves identical.

I had to be aware the screenToLocation return values depending on the current projection. In 2D/UtmProjection my map has a wkid=32632; the same region in 3D/WebMercator has wkid=4326.

I use GeometryEngine::project to project the Esri::ArcGISRuntime::Point returned from screenToLocation to the desired SpatialReference.

Please have a look at

- the wkid of aour map, scene

- try to project the values.

(But attention, SceneGraphicsView::screenToLocation is expensive. I limit the computations to 4 times per second on my own)

Hope this helps!

Norbert

View solution in original post

10 Replies
BradDuBois
New Contributor II

I noticed that I was using ArcGISSceneLayer with a MapView so I did change it to ArcGISMapImageLayer but the same problem is still present.

Using:

    map_ = new Map(basemap, this);

Using 

    map_ = new Map(SpatialReference::wgs84(), this);
    map_->setBasemap(basemap);

0 Kudos
LucasDanzinger
Esri Frequent Contributor

Correct, the Map can only explicitly set the SpatialReference through the constructor. This is because it is very expensive to reproject all of the layers after everything is already initialized.

If you choose one of the other Map constructors, your map will automatically take on the spatial reference of the first layer in the basemap. In a large majority of cases (such as with our static basemap create functions), that will be Web Mercator (wkid 3857). The problem you will run into is that if you define your map in spatial reference 'A' but then your layers are in spatial reference 'B', only certain types of layers can be "projected on the fly" so that everything displays and lines up correctly. I believe the only layers that cannot be reprojected on the fly are ArcGISTiledLayer and ArcGISVectorTiledLayer. This means that if you want to use a specific spatial reference, you'll need to get basemaps that are in that spatial reference as well. Also worth noting that on-the-fly reprojection is expensive and could have a rendering hit.

In your case, it looks like you are trying to set the spatial reference to WGS84 (wkid 4326). We have a few pre-published basemaps that are in that spatial ref already - https://www.arcgis.com/home/search.html?q=owner%3Aesri%20basemap%20wgs84 

0 Kudos
BradDuBois
New Contributor II

Hello Lucas,

I finally got a chance to get back to this and I am unable to get either of two WGS84 based maps referenced on your link to work for me.  There are more than two on the linked page but only two I saw were of imagery type that I could use for my application.

Here is the code where I'm assigning the basemap the URL from your link:

I end up with gray rectangle without even any gridline:

Am I not using the correct URL? Or maybe I'm not creating the basemap correctly?

0 Kudos
NorbertThoden
Occasional Contributor III

Hi Brad!

I´m not rellay sure but maybe the network proxy is responable for not getting data from this (arcgisonline) url.

And:

I using a map in 2D/UtmProjection and scene in 3D/WebMercatorProjection. I can switch between them.

Of course i like to process events like the mouse moves identical.

I had to be aware the screenToLocation return values depending on the current projection. In 2D/UtmProjection my map has a wkid=32632; the same region in 3D/WebMercator has wkid=4326.

I use GeometryEngine::project to project the Esri::ArcGISRuntime::Point returned from screenToLocation to the desired SpatialReference.

Please have a look at

- the wkid of aour map, scene

- try to project the values.

(But attention, SceneGraphicsView::screenToLocation is expensive. I limit the computations to 4 times per second on my own)

Hope this helps!

Norbert

BradDuBois
New Contributor II

Hello Norbert,

I appreciate the suggestion to use the GeometryEngine::project() function. That alleviated my immediate problem that had me trying to use the new basemap.  So I can continue to use my current basemap for the time being.

I did detect my spatial reference WKIDs for the map view and the scene view.  I get the following results:

I'm not sure what that means to have a reference of -1 but it doesn't seem good.  The point returned by the MapQuickView::screenToLocation() method has a WKID of 3857 (WGS_1984_Web_Mercator_Auxiliary_Sphere ).

There is still a lot of API that I haven't discovered so thanks again for pointing me to the GeometryEngine.

Brad

0 Kudos
NorbertThoden
Occasional Contributor III

Hi Brad!

My advice: Try to avoid setting the wkid/spatialReference manually. The mapView/sceneView shoud get the wkid from the provided basemap. 

(If you get a -1 something went wrong. Try an example to verify this.)

Using GeometryEngine::project()  you should be able to transform the result if needed.

I am sure that that will work.

Norbert

0 Kudos
LucasDanzinger
Esri Frequent Contributor

Brad-

What you have should work, but seems like something is not quite wired up correctly for the Basemap constructor with a URL.

I tried the following and was able to get it to work (and the map is now in WGS84)

auto vtl = new ArcGISVectorTiledLayer(QUrl("https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_GCS_v2/VectorTileServer"), this);

auto basemap = new Basemap(vtl, this);

m_map = new Map(basemap, this);
0 Kudos
BradDuBois
New Contributor II

Lucas,

It does indeed work when I construct the tiled layer first and pass it in to basemap constructor.  It doesn't work when passing the URL directly to the basemap constructor.

That particular vector tile map is not the one I want to use, but it does indeed work.  With that new bit of information I attempted to use the first WGS84 map from the link you posted above:

    auto mil = new ArcGISMapImageLayer(QUrl("https://wi.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/MapServer"));
    Basemap* basemap = new Basemap(mil, this);
This does give me a gridded background but never loads any tiles. 
I am assuming that since the server URL does not end in VectorTileServer I wouldn't used the vector tile layer.
I tired the Map Image Layer object first, got the gridlines, then tried Vector Tile Layer to see if that was why.
With that I got the blank gray background.  Is there a way to tell what the layer type is by the URL?  I didn't see anything on the description page for the map I want to use:
https://www.arcgis.com/home/item.html?id=898f58f2ee824b3c97bae0698563a4b3  

Since ArcGISMapImageLayer didn't yield images perhaps another tile layer type is needed but I'm not sure.

I'm am functional currently with canned basemap using GeometryEngine::project() but I am thinking things might work better if I used native WGS84 map.

Thanks for the help!

Brad

0 Kudos
LucasDanzinger
Esri Frequent Contributor

On the right side of the page under Details, you should see Source.  The link you provide says Map Service, so you can use ArcGISTiledLayer for that. If it says Vector Tile Service like it does for this one, use ArcGISVectorTiledLayer.

0 Kudos