Get administrative places hierarchy: Country->State->County->City->District

Get administrative places in their hierarchy (country->state->county->city->district) utilizing HERE Map Attributes API

I. Prior knowledge

  • List of all map layers


Administrative orderArea name in most countriesLayerLevel
0 = Country type 1111CountryADMIN_PLACE_07
1 = Order1 type 1112StateADMIN_PLACE_18
2 = Order2 type 1113CountyADMIN_PLACE_29
8 = Order8 type 1119CityADMIN_PLACE_810
9 = Built-up type 3110DistrictADMIN_PLACE_911



II. Get a list of all countries & their properties

1. Request: https://smap.hereapi.com/v8/maps/attributes?in=tile:0&layers=COUNTRY&apikey=yourapikey
2. From response you can search your interested country by ISO_COUNTRY_CODE
3. Remember the COUNTRY_ID. This is ADMIN_PLACE_ID in layer property.
4. We remember for example country Slovakia: 20428682

III. Get all tile ids that covered Slovakia country

1. Request: https://smap.hereapi.com/v8/maps/index?apikey=yourapikey&layer=ADMIN_PLACE_0&attributes=ADMIN_PLACE_ID&values=20428682
2. In response we get "tileIDs": [25232,25228,25485,24973,25230,25487,25484,25227,25229,25486,24972,25231]

IV. For example calculate all tile ids for all cities administrative places for Slovakia country

1. From above table we know that for city administrative place is the level is 10 and layer is ADMIN_PLACE_8

2. See below program code that you need to calculate it:

<br />proc getCoord*(level, tileX, tileY: int): (float, float) = let tileSize = 180 / (2 ^ level) (tileY.float * tileSize - 90, tileX.float * tileSize - 180) #return coorinates as tuple (float, float)proc getTileXY*(level: int, lat, lng: float): (int, int) = let tileSize = 180 / (2 ^ level) (trunc( (lng + 180) / tileSize ).int, trunc( (lat + 90) / tileSize ).int)#convert TileId(TileXY) to another levelproc toTileXYOtherLevel*(fromLevel, fromTileX, fromTileY, toLevel: int): seq[(int, int)] = let c = getCoord(fromLevel, fromTileX, fromTileY) let tileXY = getTileXY(toLevel, c[0], c[1]) if fromLevel < toLevel: let cntLevels = (toLevel - fromLevel) * 2 - 1 for x in 0..cntLevels: for y in 0..cntLevels: result.add (tileXY[0] + x, tileXY[1] + y) else: result.add tileXYproc toTileId(tileXy: (int, int), level: int): int = tileXy[1] * 2 * (2 ^ level) + tileXy[0]proc toTileIds(tileXys: seq[(int, int)], level: int): seq[int] = for tileXy in tileXys: result.add toTileId(tileXy, level)#[getTileXYLevel calculates tileX and tileY out of a given tileId and a level @param tileId - the tile id @param level - the PDE layer level]#proc getTileXYLevel(tileId: int, level: int): (int, int, int) = let numTilesVertical = 1 shl level #left shift, equivalent to JAVA: 1L << level let tileX = tileId mod (2 * numTilesVertical) if (tileX < 0 or tileX >= numTilesVertical * 2): echo ("Invalid tileX=" & $tileX & " for level " & $level & ", must be [0 ... " & $(numTilesVertical * 2 - 1) & "]") let tileY = ((tileId - tileX) / (2 * numTilesVertical)).int if (tileY < 0 or tileY >= numTilesVertical): echo("Invalid tileY=" & $tileY & " for level " & $level & ", must be [0 ... " & $(numTilesVertical - 1) & "]"); (tileX, tileY, level)proc tileIdsToOtherLevel(fromTileIds: seq[int], fromLevel: int, toLevel: int): seq[int] = var tileXysFromLevel = newSeq[(int, int, int)]() #all TileXys for fromTileIds (tuple[tileX, tileY, level]) for tileId in fromTileIds: let tileXy = getTileXYLevel(tileId, fromLevel) #decode tileId to tileX & tileY tileXysFromLevel.add tileXy var allTileXysToLevel = newSeq[seq[(int, int)]]() #all TileXys for all toLevel in fromLevel for tileXy in tileXysFromLevel: let tileXysToLevel = toTileXYOtherLevel(fromLevel, tileXy[0], tileXy[1], toLevel) #convert the tileX & tileY to another level: in result is sequence of tileX & tileY allTileXysToLevel.add tileXysToLevel for tileXys in allTileXysToLevel: result.add toTileIds(tileXys, toLevel) #convert the sequence of tileX & tileY to sequense of tileIds<br />

3. Above code is only functionality, below code is main code which uses above code:

<br />let tileIdsCountry = @[ 25232, 25228, 25485, 24973, 25230, 25487, 25484, 25227, 25229, 25486, 24972, 25231 ] #This we got from chapter III. ISO_COUNTRY_CODE: SVK - Slovakia#10 is level for City level (or Admin Order8)let tileIdsCities = tileIdsToOtherLevel(tileIdsCountry, 7, 10)echo "tileIdsCities count:", tileIdsCities.lenecho tileIdsCities<br />

4. The result is:

tileIdsCities count:432

@[1606784, 1608832, 1610880, 1612928, 1614976, 1617024, 1606785, 1608833, 1610881, 1612929, 1614977, 1617025, 1606786, 1608834, 1610882, 1612930, 1614978, 1617026, 1606787, 1608835, 1610883, 1612931, 1614979, 1617027, 1606788, 1608836, 1610884, 1612932, 1614980, 1617028, 1606789, 1608837, 1610885, 1612933, 1614981, 1617029, 1606752, 1608800, 1610848, 1612896, 1614944, 1616992, etc...

V. Get all cities from above list of tile Ids

1. Request should be like: https://smap.hereapi.com/v8/maps/attributes?layers=ADMIN_PLACE_8,ADMIN_PLACE_8,ADMIN_PLACE_8,ADMIN_PLACE_8,ADMIN_PLACE_8∈=tile:1524840,1526888,1528936,1530984,1533032&apikey=yourapikey

2. Above request only for five tile ids but you can put in request only 64 maximum therefore you need to send a few (7 requests by 64 tile ids) like above request to cover all 432 tile ids.

3. In results filter out all rows with "COUNTRY_ID" != "20428682"

VI. How to get all cities from administrative place state e.g. '**Presovsky kraj' only?**

1. Get all states tile ids:

<br />let tileIdsCountry = @[ 25232, 25228, 25485, 24973, 25230, 25487, 25484, 25227, 25229, 25486, 24972, 25231 ] #ISO_COUNTRY_CODE: SVK - Slovakia#8 is level for State level (or Admin Order1)let tileIdsStates = tileIdsToOtherLevel(tileIdsCountry, 7, 8)echo "tileIdsStates count:", tileIdsStates.lenecho tileIdsStates<br />

2. In results:

tileIdsStates count:48

@[100640, 101152, 100641, 101153, 100632, 101144, 100633, 101145, 101658, 102170, 101659, 102171, 99610, 100122, 99611, 100123, 100636, 101148, 100637, 101149, 101662, 102174, 101663, 102175, 101656, 102168, 101657, 102169, 100630, 101142, 100631, 101143, 100634, 101146, 100635, 101147, 101660, 102172, 101661, 102173, 99608, 100120, 99609, 100121, 100638, 101150, 100639, 101151]

3. Get all states (sure for 48 tileIds) like: