Drawing Graphics on Different esri Basemaps

1957
6
Jump to solution
01-31-2013 06:53 AM
ChristopherBarger
New Contributor
I am trying to draw a graphic on an esri basemap. I started with the ESRI_StreetMap_World_2D basemap. It is created in the viewDidLoad method of my view controller like this:


Code:
    AGSTiledMapServiceLayer *tiledLayer =
    [AGSTiledMapServiceLayer
     tiledMapServiceLayerWithURL:[NSURL URLWithString:@"http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"]];
    [self.mapView addMapLayer:tiledLayer withName:@"World Imagery"];



I then draw a graphic, a blue simple marker symbol, on user input. However, if i switch to http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer as my basemap, the graphic no longer draws. Is there something with the imagery layer where you cannot draw graphics on it? The only change I make to my code that results in the graphic not being drawn is changing the URL of the basemap.
0 Kudos
1 Solution

Accepted Solutions
DanaMaher
Occasional Contributor
Just to clarify, after implementing your atIndex solution the behavior is exactly the same, as always, the graphic draws when using the streets basemap, and does not draw when using the world imagery basemap


Ok. I have seen AGSGraphicsLayers fail to draw if the spatial reference of the geometries for the graphics does not match the spatial reference of the AGSMapView. Are the spatial references of your base maps different? For instance, take a look at ESRI's World Street Map and World Ocean Map services. The Street map service has a spatial reference of WKID 4326 (see the 'Spatial Reference' field), which is straight wgs84 latitude/longitude. The Ocean map service has a spatial reference of WKID 102100, which is the web mercator projection pushed by Google. If you add the Ocean map as your first layer, the AGSMapView will have the 102100 spatial reference, and if you add the Street map as your first layer, the AGSMapView will have the 4326 spatial reference. In either case, the spatial reference of the AGSGeometry objects you use to create your AGSGraphics must be the same as the spatial reference of the AGSMapView, or the graphics won't draw.

If your base maps *do* have separate spatial references, I worked up a quick demo when I saw your reply this morning, saw the behavior you are describing, and realized that I was using base map layers with different spatial references. I changed it to work around this using AGSGeometryEngine to project the geometry for the graphics if needed. I did notice that the AGSMapView does not function very well if you swap from a base layer with one spatial reference to a base layer with another, so I am calling reload on the map. See attached zip.

View solution in original post

0 Kudos
6 Replies
DanaMaher
Occasional Contributor


I then draw a graphic, a blue simple marker symbol, on user input. However, if i switch to http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer as my basemap, the graphic no longer draws. Is there something with the imagery layer where you cannot draw graphics on it? The only change I make to my code that results in the graphic not being drawn is changing the URL of the basemap.



So are you removing the first AGSTiledMapServiceLayer and adding a new AGSTiledMapServiceLayer ? And you are drawing your graphic in an AGSGraphicsLayer? If you are using the -(void)addMapLayer: method of AGSMapView, you are probably adding the new tiled layer on top of the graphics layer, which is why your graphic is disappearing.

If so, use the -(void)insertMapLayer:atIndex: or -(void)insertMapLayer:withName:atIndex: methods to insert the new base map underneath the graphics layer. The appropriate index would probably be 0.

The ArcGIS Runtime SDK is different from other map SDKs in that it doesn't presume a base map that always underlies other data and layers. For instance, the MKMapView class in iOS's MKMapKit has a mapType typedef that is used to swap between several always-on, always-under base map options (street, satellite, hybrid). In the ArcGIS Runtime SDK, you are responsible for establishing and maintaining the visual hierarchy for every layer. With great power comes great responsibility 😉
0 Kudos
ChristopherBarger
New Contributor
Thanks for your reply.

I am adding the layers in order, but implemented your solution As Below

Code:

tiledMapServiceLayerWithURL:[NSURL URLWithString:@"http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"]];
    [self.mapView insertMapLayer:tiledLayer withName:@"World Imagery" atIndex:0];

    graphicsLayer = [AGSGraphicsLayer graphicsLayer];
    [self.mapView addMapLayer:graphicsLayer withName:@"GraphicsLayer"];

End Code


Later in the application, on user input, graphics are added to the graphics layer via the addGraphics method. if the above URL for the tiled layer is changed to: http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer, the street basemap, then the graphic is added to the graphics layer and appears as it should.

To further complicate things, After I added the graphic in the World_Imagery situation, I tried removing the World Imagery layer to see if the graphic was behind it, but, when I remove that layer, i am left with nothing but the black screen with the checker-box pattern on it.
0 Kudos
DanaMaher
Occasional Contributor

Later in the application, on user input, graphics are added to the graphics layer via the addGraphics method. if the above URL for the tiled layer is changed to: http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer, the street basemap, then the graphic is added to the graphics layer and appears as it should.


So it sounds like my basic solution worked? You could mark that as the answer for future readers.

To further complicate things, After I added the graphic in the World_Imagery situation, I tried removing the World Imagery layer to see if the graphic was behind it, but, when I remove that layer, i am left with nothing but the black screen with the checker-box pattern on it.


The first layer added defines the spatial reference and extent of the map. If you remove that layer, the map looks for the next layer up in the stack and uses that layer to set the spatial reference and extent. I'm not sure what happens if an AGSGraphicsLayer becomes the base/bottom layer. The documentation for AGSGraphicsLayer notes that if a graphics layer is to be a base/bottom layer, it should be created using -(id)initWithFullEnvelope: . In your case, the graphics layers might not have any envelope settings and as such will not function properly as a base layer.
0 Kudos
ChristopherBarger
New Contributor
Just to clarify, after implementing your atIndex solution the behavior is exactly the same, as always, the graphic draws when using the streets basemap, and does not draw when using the world imagery basemap
0 Kudos
DanaMaher
Occasional Contributor
Just to clarify, after implementing your atIndex solution the behavior is exactly the same, as always, the graphic draws when using the streets basemap, and does not draw when using the world imagery basemap


Ok. I have seen AGSGraphicsLayers fail to draw if the spatial reference of the geometries for the graphics does not match the spatial reference of the AGSMapView. Are the spatial references of your base maps different? For instance, take a look at ESRI's World Street Map and World Ocean Map services. The Street map service has a spatial reference of WKID 4326 (see the 'Spatial Reference' field), which is straight wgs84 latitude/longitude. The Ocean map service has a spatial reference of WKID 102100, which is the web mercator projection pushed by Google. If you add the Ocean map as your first layer, the AGSMapView will have the 102100 spatial reference, and if you add the Street map as your first layer, the AGSMapView will have the 4326 spatial reference. In either case, the spatial reference of the AGSGeometry objects you use to create your AGSGraphics must be the same as the spatial reference of the AGSMapView, or the graphics won't draw.

If your base maps *do* have separate spatial references, I worked up a quick demo when I saw your reply this morning, saw the behavior you are describing, and realized that I was using base map layers with different spatial references. I changed it to work around this using AGSGeometryEngine to project the geometry for the graphics if needed. I did notice that the AGSMapView does not function very well if you swap from a base layer with one spatial reference to a base layer with another, so I am calling reload on the map. See attached zip.
0 Kudos
ChristopherBarger
New Contributor
Fantastic, this was a projection issue. Using the geometry engine to project the graphic being added to the graphics layer solved my problem as the imagery layer was 102100. Thanks.
0 Kudos