2

I just started learning about ArcGIS.

I am building a webapp (django) and we need map images (jpg) of a given location (lat,long), using various basemaps (topology, satellite, etc). Later I need to layer shapefiles on top.

The Google static image API does exactly what I need. Unfortunately, they only provide 3 different types of maps and we need other basemaps.

ArcGIS has all the basemaps we need. But, how do I use it?

I can see they have an ArcGIS API for Python and an ArcGIS REST API. But, browsing those docs I cannot find a way to generate map images.

Basically, I need a URL that implements the following function: "Generate a .jpg of map range lat,long to lat1,long1 using Basemap XYZ (and layer shapefile A.shp on top)", where I can tell it what lat,long, XYZ and A.shp I want. Does such a thing exist? in arcgis, or anywhere? Paid services are OK.

  • I am still hoping this exists. Anyone? – Jose M Vidal Mar 27 at 10:51
  • Most services that call themselves REST aren't (they fail HATEOAS) so the simple answer to a such a question Does such a thing exist is probably no – nmtoken Mar 27 at 12:19
  • Thanks! But, I don't really care if the answers have hypermedia links or not. I just need the .jpg. – Jose M Vidal Mar 28 at 13:52
  • 1
    But to get the jpg in a REST architecture you need hypermedia, that's a REST requirement. So your basically statement that you .need a REST function that implements the following is basically wrong. You need an HTTP request that gives a jpg (nothing to do with REST). It sounds like an operation that you might be able to achieve using a WCS. – nmtoken Mar 28 at 14:12
  • Ok, I fixed my question. – Jose M Vidal Mar 29 at 15:15
2
+100

You could use the Export Map function in the ArcGIS REST API. It works very similarly to the geoprocessing function for ArcGIS Server.

You could take your XY coordinates and zoom level, use it to calculate a bounding box extents as a list, and feed them into the API as parameters for your map JSON, point it at your existing map service (with our without layers) that has the basemap you want, and fire away.

There's a short tutorial here too, with a code sample. As long as you have access to ArcGIS Online even free accounts, you're good. I also pasted the JSON sample below.

{
  "mapOptions": {
    "extent": {
      "xmin": -118.85360990096176,
      "ymin": 33.99062491328014,
      "xmax": -118.75318799544432,
      "ymax": 34.04042561067984,
      "spatialReference": {
        "wkid": 4326
      }
    }
  },
  "operationalLayers": [],
  "baseMap" : {
    "title" : "Topographic Basemap",
    "baseMapLayers" :  [
      {
        "url" : "https://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer"
      }
    ]
  },
  "exportOptions": {
    "outputSize" :  [600,400]
  }
  • 1
    I believe this is the right answer if we are to address the "layer shapefile A.shp on top" – Simon Mar 30 at 2:08
  • @Simon you can also export without any layers in the map as well, if the OP just wants the JPEG (or PNG, which I think is the default export option). – JonR Mar 30 at 18:04
  • @Jose M Vidal The only extra code that you would need to write is the math to calculate the extent of the bounding box. That would mostly depend on the distance from your map center that you want included. – JonR Mar 30 at 18:07
  • To follow up on why you cannot access the ESRI basemaps directly from a URL: you need a valid API access token (which requires an ArcGIS Online account. If you were trying to brute-force this, you would still need to log in every hour or so to get a new valid access token, update your script that was pulling down tiles, and re-start it. Clunky, and if you did this often enough, ESRI would notice that you are spamming their servers and block your IP temporarily. Much easier to just set up a free AGOL account, write some quick code, and run it. – JonR Mar 30 at 18:36
  • Thanks! If I have a shapefile that I want to draw on top of one of the basemaps, I would first have to publish/upload it to the arcgis server, so I can get its "url". Correct? (I can make this a new question if needed). – Jose M Vidal Mar 31 at 10:39
0

One possible answer, following @GeospatialInformationTech hints (I think), is to directly access the tiles from the server.

For arcgisonline.com the various map services are listed here. Each one of them (I think) provides the map tiles at URLs that have the following pattern:

https://services.arcgisonline.com/arcgis/rest/services/service_name/MapServer/tile/zoom/ytile/xtile

The mapping from lat-long to xtile,ytile,zoom is explained here and here. Basically use the function

import math
def deg2num(lat_deg, lon_deg, zoom):
  lat_rad = math.radians(lat_deg)
  n = 2.0 ** zoom
  xtile = int((lon_deg + 180.0) / 360.0 * n)
  ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
  return (xtile, ytile)

As an example deg2num(34,-81,13) returns (2252, 3272) which becomes the URL

https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/13/3272/2252 which seems roughly correct.

This is what I've got. I don't know if this is the best way to get an image from a lat-long. Maybe someone knows an easier method?

One problem is that these images are always 256x256. I might need different aspect ratios.

  • Tile Servers are always in multiples of 256, 512, 1024, etc. Tiles Larger than 256 are often called hidpi or retina display tiles. It seems like you are creating more work for yourself trying to use that static image API. Bad idea! – GeospatialInformationTech Jan 28 at 14:31
  • So, how do I generate a jpg from a pair of coordinates? Sorry if the answer is obvious. I have never used arcgis before. – Jose M Vidal Jan 29 at 15:47
  • There is a take_screenshot() method, but it only works in Jupyter notebooks (I assume, they are using the browser's capabilities) esri.github.io/arcgis-python-api/apidoc/html/… – Jose M Vidal Jan 29 at 15:59
0

ESRI basemaps are XYZ tile server just like 90% of all online basemaps (WMTS is also XYZ naming). Check out URL to basemaps at Leaflet provider's plugin. Zoom Column Row are the keys all JavaScript mapping libraries enabling quickly adding tile URL. http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}.png

take a look at the TileLayer Plugin for QGIS and then add XYZ TileLayer Reference Grid you will clearly see Zoom, Column and Row information. Otherwise look at https://www.maptiler.com/google-maps-coordinates-tile-bounds-projection/

If you are using a mapping framework that does not support tile servers then switch. I recommend going with OpenLayers or ArcGIS JavaScript.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.