Shaded relief with BlenderGIS, part 2

With the DEM read in, we’re now ready to adjust the many parameters in Blender which determine what we’ll get. Here again is the overall procedure (mentioned in the previous post) . We’re now at step 5.

  1. Select the Cycles Renderer
  2. Read in the DEM as DEM
  3. Create new material
  4. Adjust Z scaling
  5. Create and adjust the georef camera
  6. Correct final pixel dimensions to match the input DEM
  7. Adjust lamp location and properties
  8. Test render
  9. Adjust final parameters
  10. Render

Create and adjust the georef camera

With the plane selected, go to the the (new) GIS tab on the left, and, under BlenderGIS, click Georender.

geoRender.jpg

This creates a camera at an appropriate distance above the plane. It will appear in the tree of objects (upper right) as “Georef cam”. It has been placed high enough (Z value of 16791) that it is above the highest point on the plane surface. Note that it is important to have set your Z scaling before creating the Georef cam.

georef cam set up

If you look at the camera’s Object Data>Lens, you’ll see that BlenderGIS has automatically set it to Orthographic. It’s a good idea to note the camera’s clipping Start and End, because you may have to adjust these later.

geoRefCamDetails

As well, if you check out the Scene’s Scene panel, you will see that the current camera has been set to this new Georef cam.

Correct final pixel dimensions to match the input DEM

If you go to the Render tab, under Dimensions>Resolution you can see the pixel dimensions of the final image as suggested by BlenderGIS. In this case, as I noted before, one cell has been dropped in each dimension, so it is 5029 x 3276.

resolutionInitial

I correct these to the actual values (5030 x 3277, in this case) so that the dimensions of my final image match the DEM. That way I can pair the TFW world file with the image created by Blender, and read it into QGIS georeferenced.

dimensionsRepaired

While I’m at it, I’ll set the Resolution percentage to 25%. This way I can get a test image without doing a full render. While I’m here on the Render tab, I’ll go to the Light Paths panel and set it to Limited Global IlluminationlimitedGlobalNow we’ll check that all elevations in the DEM are visible to the camera. Pop into Camera Ortho view (Numpad 0 while the mouse is over the 3D View). You are looking for  black faces where the higher parts of the DEM have been cut off. It can look something like this:orthoView1BlenderGIS was updated in December 2014 to place the Georef Cam high enough so that this typically does not happen (Thanks!), but I’ll still discuss what to do in case you do encounter it. This could happen if you, say,

  • create the Georef cam before you increase Z scaling on the DEM.
  • create the Georef cam at a time when the View number in the Subsurf modifier is low (e.g., 6). In this case the displacement is quite generalized; the Georef cam will be placed high enough to clear it, but not the actual high points that pop out when you render at 11.

What’s happening here is that the camera only “sees” objects that fall between the Start and End clip distances we noted a few steps back. The Start and End are measured from the camera outward (or down, in this case).

Specifically, in the image above, I had a camera at 11,706m, with a Clip Start of 0.5 m, and a Clip End of 8011.5 m. If you do the math, you’ll see that this means that the maximum elevation at which it can see objects is 11,705.5 (that’s 11,706 – 0.5). The minimum elevation at which it can see objects is 3694.5 (that’s 11,706 – 8011.5).  Our DEM originally contained elevations from 739 to 2379, but now we’ve scaled it up 5 times, so its minimum is 3695 (= 739 x 5) and its maximum is 11,895 (= 2379 x 5).  The black patches are the elevations that are higher than 11,705.5 m.

If I do a test render with these settings I’ll get the image below; I’ve circled the black patches where the highest peaks were cut off.SRTM_2_3_cutoff_render

In this case we need to raise the camera to just above the max value in the DEM, and then adjust the Clip Start and End distances to encompass the whole DEM. Since the DEM ranges from 3695 to 11,895, let’s put the camera at 11, 896, leave Start at 0.5, and set End to 8201.5.

 Adjust lamp location and properties

This does not differ in any way from what you would do with the Subdivide method. Set the Lamp to Sun, and click Use Nodes. I like a sun size of 1, Cast Shadows checked, and a Strength of 4.

lampSettings

Then change to the Lamp’s Object tab, Transform section, and set its X, Y and Z Rotation. In this case I want an elevation of 40°and an azimuth of 337.5°, so I choose X=0, Y=40, and Z=112.5. Remember that Blender measures the sun azimuth counterclockwise from East. lampSettings2

 Test Render

Hit F12 to see a test render at 25%. It should look grainy but basically correct.

Final adjustments

At this point you can play with:

  • lamp rotation, strength, size
  • Z scaling on the model
  • the Render number under the Subsurf modifier on your plane

When you’re ready to go,

  • On the  Render tab>Dimensions, raise the Resolution from 25% to 100%
  • On the  Render tab>Sampling set the Samples Render number to 200. This high sampling number makes the rendering process take a long time, but it’s worth it. Check out this comparison of the same scene rendered with sampling 200 (left) vs sampling 90 (right):

    Note the grain

    Note the noise in the shadows when sampling only 90 times (right image) as opposed to 200 times (left image).

  • On the Render tab>Output, set the image type to TIFF (if you want to pair it with a pre-existing TFW after you render)
  • Save your session to a .blend file using File>Save As…

Render

Two options here. One is that you can hit F12 and go out for coffee.  When it’s done, hit F3 to save.  Or, you can close Blender and render that .blend file you just saved from the command line. This saves the GUI rendering, and so it takes less time — you might get 10-40% off the regular render time.

Let’s say your  .blend file is called tile_4_4.blend. The command line to render it would be

/path/to/blender -b tile_4_4.blend -o hillshade_4_4.tif -F TIFF -f 1

The switches are:

-b     run in background (no-GUI) mode
-o     the output filename
-f 1    render just one frame.

Pulling the result back into QGIS

Let’s say you have saved the rendered image as hillshade.tif. Rename a copy of the world file you created way back at the beginning to hillshade.tfw.

QGIS should be happy to read in hillshade.tif now as raster data, although it will probably ask for the CRS. (You know the CRS because you specified it when you re-projected the DEM, and when you read it into Blender.)

It works quite well in QGIS to set the Blend Mode of the hillshade to Multiply, and then overlay it with layers representing vegetation or elevation.

The shadows can be thunderingly deep in these hillshades…

QGIS1

…so it can be good to display them with increased brightness and decreased contrast.

QGIS2

 

Advertisements

Shaded relief with BlenderGIS, part 1

[The BlenderGIS add-on has now been improved to the point where generating shaded relief is downright easy. So, I have updated this post (April 2017) to reflect how one uses its latest version. Also the latest version of Blender (2.78c).]

You may have read Daniel Huffman’s great post about created shaded relief using the free, open-source animation software, Blender. As well, Daniel posted a video tutorial for his method, which is well worth watching.

In Daniel’s method, you subdivide a plane to create a grid of finely spaced points. You then apply a Displace modifier to the plane with a DEM, and get some very realistic results.

There are a few things about this method, which I’ll call the Subdivide method, that were difficult for me. For one thing my meager 4GB of RAM precluded subdividing the plane more than about 1500 times. So I went searching around, and found to my surprise that there’s a plug-in available for Blender called BlenderGIS that does much the same thing. But unlike the Subdivide method, BlenderGIS uses a Subsurf modifier. This saves a lot of memory.

Note that distinction: subdivide vs. subsurf. That’s important

As well, BlenderGIS offers a few interesting tools for the GIS user. One is the ability to create a GeoRef camera, correctly configured and positioned to shoot an image of your lit DEM. Another, which I haven’t really explored, is the ability to read in shapefiles to add features to the DEM surface.

In this series of posts I give a tutorial for how to use Blender GIS’s subsurf method to achieve results similar to those obtained with the subdivide method.

I’ll assume that you have watched Daniel’s tutorial, so finding your way around Blender for purposes of generating a shaded relief isn’t too hard for you; and this of course implies, as well, that you are the kind of GIS user who knows what a DEM is. My workflow mostly happens under Ubuntu 14.04 using QGIS and GDAL tools.

We’ll do this in two parts. Part 1 is about installing Blender GIS,  preparing your DEM, reading it in and adjusting the vertical exaggeration. Part 2 is about creating the georef camera, placing the lamp and adjusting some final parameters.

Installation of BlenderGIS

The master instructions are in the BlenderGIS wiki at https://github.com/domlysz/BlenderGIS/wiki/Install-and-usage  However, I will paraphrase them here.

Go to the BlenderGIS site on github and hit the Clone or Download button. You will receive a .zip file, which you can store pretty much anywhere.

Within Blender,  at File>User Preferences, the Addons tab, click Install From File, and point it at the .zip file you just downloaded. (You don’t have to unzip it.)

Once its installed, you still have to do two things:

  1. Check the box next to 3D view: BlenderGIS to enable it
  2. Click Save User Settings

That’s it. BlenderGIS is installed.

Preparing your DEM

I used to use divide my DEM up into square tiles, and feed these one by one through Blender. However BlenderGIS in no way requires this.

Projection and resolution

BlenderGIS claims that it can now read a DEM projected in “WGS84 latlon”, but I have not had very good results with this. I still prefer a DEM that is in a projection that uses metres. Typically for me this would be a UTM projection.

You may also want to re-sample your DEM, so the cell size is appropriate to the scale of the map you are making.  I use this guideline: the DEM resolution should be map’s [metric] scale divided by 10,000. For example, if the map scale will be 1:100,000, I want a DEM with 10 metre cells. For a 1:30,000 scale map, I want a 3 metre DEM. It’s just a general guideline.

Before you re-sample and re-project, however, be sure to float your DEM and create a world file.

Float DEM

Most DEMs come as integer values. Floating it means converting it to a DEM that can has floating point elevation values.  You can do that with a line like this with gdal_translate.

gdal_translate -ot Float32 myDEM.tif myFloatDEM.tif

where the -ot switch specifies output type.

World file

You’ll need the world file when you are done, to georeference your hillshade.

Almost all DEMs come as GeoTiff files, and the corresponding world file extension is .tfw. An easy way to create a TFW World file is with the GDAL command gdalwarp:

gdalwarp -co "TFW=YES" myGeoTiff.tif deleteme.tif

This just makes a second copy of myGeoTiff.tif called deleteme.tif, but in doing so it creates a world file called deleteme.tfw. (The switch -co “TFW=YES” means to use the creation option “TFW=YES.”) The world file is what you really want, so delete the deleteme.tif. The world file and the main image file need to share the same name, so rename the TFW to myGeoTiff.tfw.

Re-sample and re-project

I like to do these two operations simultaneously with gdalwarp. In the following example, I am re-projecting out of 4326 (the EPSG code for lat/long/WGS84) into 32609 (the EPSG code for UTM Zone 9 north/WGS84).

Where

-s_srs
the Spatial Reference System (projection & datum) of the original
-t_srs
the SRS of the result
-r
resampling method
-tr
resolution, in metres
-of
output format
gdalwarp  -s_srs EPSG:4326 -t_srs EPSG:32609 -r bilinear -tr 5 5 -of GTiff myFloatDEM.tif myFloatDEM_32609_5x5.tif

Note that the terms “projection/datum”, SRS (Spatial Reference System) and CRS (Coordinate Reference System) are interchangeable for our purposes.

Now we’re reading to open up Blender and get started.

Overall process

The process will essentially go like this (and you can use this as a checklist once you get familiar with it):

  1. Select the Cycles Renderer
  2. Read in the DEM as DEM
  3. Create new material
  4. Adjust Z scaling
  5. Create and adjust the georef camera
  6. Correct final pixel dimensions to match the input DEM
  7. Adjust lamp location and properties
  8. Test render
  9. Adjust final parameters
  10. Render

The green steps are probably already familiar to you from Daniel’s tutorial.

Select the Cycles Renderer

Open up Blender and delete the default cube that appears. Switch the selected renderer to the Cycles Renderer.

Cycles

Reading the DEM in

File>Import> Georeferenced rasteropenDEMAsPlane

Select your floated, re-projected, re-sampled DEM, and in the left margin, where it says Import georaster, set Mode to As DEM, Subdivision as Subsurf, and select the correct CRS for your DEM.

importGeoraster

If the CRS you want to use is not on the dropdown menu,you can add it by clicking the “+” button, checking the Search box, typing in the EPSG code for your CRS into the Query box, and hitting Enter. It should appear in the Results box, and then you just click OK.

addingANewCRS

With all these things set, you click Import Georaster, and the result is a somewhat flabby-looking, grey plane.

flabby-looking grey plane

Tap n (with the cursor over the 3D view) to bring up the 3D view numeric panel, and we’re ready to go for a tour of things that BlenderGIS has done automatically. You don’t ordinarily have to check these things, but they are worth knowing about.

  • On the 3D view numeric panel we can see that the dimensions of the plane are the real-world dimensions of the DEM. In this case I’m using a 5030 x 3277 DEM with 5 m cells. For some reason BlenderGIS drops one cell in each dimension, so the DEM is 5029 x 5 on the X dimension (25145), and 3276 x 5 on the Y dimension (16380). metres on a side. We also see the thickness (Z dimension) of the DEM, which is 1911.56 metres.

transfromPanel

  • Also on the 3D View Numeric Panel, under Display, we can see adjustments to the grid floor. It gives values for Lines and Scale. Ordinarily (e.g., with the default cube) these will be values like 16 lines and a scale of 1. This means lines extend out 16 from the origin and no more, and each square is 1. After BlenderGIS has read in a DEM,  these can be more like 25 lines with a scale of 1000. In this case we have 25 lines on each side of the origin and each represents 1000 units (corresponding to metres).

gridFloor

  • Again on the 3D View Numeric Panel, under View, the clip distances represent the nearest and farthest you can see the object in perspective view. Ordinarily (e.g., with the default cube) these will be values like 0.1 to 1000. With a DEM read in these can be more like 0.1 to 250,000.

clipDistances

  • No longer on the 3D View Numeric Panel, but under Scene>Custom Properties, BlenderGIS has added a crs X and crs Y which correspond to the UTM coordinates of the centre of the plane. This is how the plane can be centred at (0,0), but any additional georeferenced data placed over it will be in the correct place. There’s also an SRID, and even a latitude and longitude.

customProperties

To understand how the DEM was used to displace a plane, go to the Modifiers tab for the plane. You will see two modifiers have been created. The upper one, called DEM, is a Subdivision Surface, or Subsurf. This kind of modifier subdivides the plane on the fly, and you can specify separate subdivision factors for View mode (what we’re doing right now) and Render mode (when you render the image). The beauty of the Subsurf modifier is that you can leave the View mode number low (e.g., 6) but set the Render number high (e.g., 11).

The factor is used as an exponent of 2, so our View mode is 2^6 or 64 subdivisions along the side of the plane. This is a small number considering that the DEM itself is thousands of points on a side. Which is why the view looks lumpy. The second modifier, called DEM.001, is a Displace modifier, and it applies the DEM to the subdivided plane much as in the Subdivide method.

Try changing the View number on the Subsurf modifier, and watch the fineness of the plane increase. You’ll notice that it takes longer to adjust the 3D view each time you increase the View number by 1, because you are doubling the number of subdivisions. A view number of 6 corresponds to 64,  7 to 128, 8 to 256, 9 to 512, 10 to 1024 and 11 to 2048 subdivisions. increasingViewNumberBy the time you get to 10 or 11, you’ll notice the status bar at the top of Blender is reporting a lot more memory use, 1.2 GB in this case.

statusBarat11

Go ahead and set the View number back to 6, but increase the Render number to 10 or 11. Because this higher number of subdivisions will be performed on the fly during render, it takes no memory now.

Create new material

If I now go to the Material panel for the plane, I’ll see that at this point I have no material.

noMaterial

I click New to create a new one. I get the default Diffuse BSDF  material, with a roughness of 0. This is fine, and if I want I can change the material or some of its parameters later.

defaultMaterial

Adjust Z scaling

Last, we’ll adjust the Z scale factor in the 3D View Numeric Panel to reflect the vertical exaggeration we want. I’ll use 5 in this case. Note that the Z dimension of the plane jumps up to 5 times its previous value, to 9794.137 in this case.

ZScaled

Go on to Part 2.

Cutting large DEMs into square, partially overlapping tiles

I’ve been doing a lot of shaded relief using Blender, and one practice I’ve developed is feeding Blender square DEM tiles.

The DEMs I use in maps tend to be too big for my installation of Blender to handle. One I had recently was 6348 x 10899 pixels; another was 4155 x 3572.  So that’s one reason for tiling them: I can produce shaded relief of the tiles separately in Blender and then mosaic the results.

And as long as I’m tiling, I’d like to use square tiles. That’s because when you subdivide a plane in Blender you have to use the same factor on both X and Y axes. Call me superstitious, but I get uncomfortable knowing that I’ve mapped 1803 pixels of DEM onto 1500 cells along one axis, and 2403 pixels to the same 1500 cells on the other. It seems to me this should cause loss of precision.

By feeding Blender square tiles, I eliminate that. I can subdivide the plane 2048 times on both axes, and feed it a 2050 x 2050 DEM.

This is not the kind of tiling that you would use a tool like gdal2tiles.py to do. That tool produces tiles that do not overlap, but I want some overlap. This is for a couple of reasons.

One is that Blender sometimes produces a bit of an edge artifact on a tile’s down-light edge (that is, the edge of the tile away from the light source). I can trim this off, and if there’s a bit of overlap between adjacent tiles, I get a nice smooth mosaic.

Left: mosaic of two non-overlapping tiles -- note the "seam" down the centre. Right: the left tile trimmed, and the right tile (with an overlap of 200 pixels) laid under it. Light is from 337.5°

Left: mosaic of two non-overlapping tiles — note the “seam” down the centre. Right: the left tile trimmed, and the right tile (with an overlap of 200 pixels) laid under it. Light is from 337.5°

Another reason for overlap is that if a shadow-casting feature (a mountain, a cliff) is just off the up-light edge of a tile, Blender can’t know to cast the shadow from that feature onto the tile. Overlap cleans this up by putting a healthy margin of features on the up-light side.

How much you overlap seems to depend on the topography and the scale. With small scale mapping, you don’t need much overlap because the mountains can’t cast their shadows very far. At large scales they can cast them many, many pixels.

Comparison of shaded relief produced for 1:1,000,000 (left), 1:150,000 (centre), and 1:30,000 (right).

Comparison of shaded relief produced for 1:1,000,000 (left), 1:150,000 (centre), and 1:30,000 (right).

To make tiling-with-overlap easier, I’ve written a bash script, called maketiles.sh, to tile large images, which you can download. This script uses the gdal_translate tool, so you also need to have GDAL installed.

Usage looks like this (assuming linux here):

./maketiles.sh <image file> <desired tile size in pixels> <number of columns in image> <number of rows in image> <tile_filename_prefix> <overlap>

It’s the rare DEM that can be cut perfectly into tiles without the last row and column being a bit off-sized. This script resolves that by increasing overlap on the final row and column so that all tiles are the requested size.

Let’s run through an example.

I have a DEM called 093L03-4-5-6_dem_26909.tif which is 4155 x 3572 pixels.

(If I don’t initially know its dimensions, I can get them through gdalinfo:

gdalinfo 093L03-4-5-6_dem_26909.tif
Driver: GTiff/GeoTIFF
Files: 093L03-4-5-6_dem_26909.tif
093L03-4-5-6_dem_26909.tfw
Size is 4155, 3572)

Let’s say I want tiles that are 2000×2000 pixels with a 100 pixel overlap, and I want the resulting tiles (and their world files) to be named tile_1_1.tif, tile_1_2.tif, etc.

The command would be

./maketiles.sh 093L03-4-5-6_dem_26909.tif 2000  4155 3572 tile 100

The script first echos back your parameters, and then tells you how many tiles will be produced. In this case we’ll be getting 6 tiles in 2 rows and 3 columns. It also tells you how much extra overlap you’ll have on the last row and column.

image file is 093L03-4-5-6_dem_26909.tif
desired tile size is  2000 x 2000
image is  4155 columns by  3572  rows
prefix is tile
overlap is 100 pixels.

Estimating 3 columns of tiles (X), by 2 rows of tiles (Y).

Taking a closer look at columns.
When laying out 3 columns of tiles, it looks like the final column will fall at 5800 pixels.
That's bigger than the image, so we'll back off the final column of tiles to begin at 2155 and end exactly at 4155.
This final column of tiles will overlap the second-to-last column by 1745 pixels.

Taking a closer look at rows.
When laying out 2 row of tiles, it looks like the final row will fall at 3900 pixels.
That's bigger than the image, so we'll back off the final row of tiles to begin at 1572 and end exactly at 3572.
This final row of tiles will overlap the second-to-last row by 428 pixels.

Layout has 6 tiles in 2 rows and 3 columns.

Finally, it computes the maximum overlap you could have without increasing the number of tiles, and asks if you want to try that.

Would you like to go with an overlap of 428, which would spread the overlap out but keep the same number of tiles? [Y/n]

If you accept this increased overlap, it confirms the change, and then you get a final chance to approve the process or exit.

Overlap set to 428.
overlap is 428.

Hit Enter to proceed with cutting tiles, or Ctrl-C to exit.

Assuming you hit Enter/Return, it then calls gdal_translate many times as is necessary, giving you extent info for each tile.

Producing tile tile_1_1.tif (row 1, column 1).  Extents: (0, 0) to (2000, 2000).
gdal_translate  -co "TFW=YES" -srcwin 0 0 2000 2000 093L03-4-5-6_dem_26909.tif tile_1_1.tif

Input file size is 4155, 3572
0...10...20...30...40...50...60...70...80...90...100 - done.

Producing tile tile_1_2.tif (row 1, column 2).  Extents: (1572, 0) to (3572, 2000).
gdal_translate  -co "TFW=YES" -srcwin 1572 0 2000 2000 093L03-4-5-6_dem_26909.tif tile_1_2.tif

Input file size is 4155, 3572
0...10...20...30...40...50...60...70...80...90...100 - done.

The final tile in the row will be a bit too big.
To keep all tiles the same size, I'm backing off the upper left corner of this tile from (3144,0) to (2155,0).

Producing tile tile_1_3.tif (row 1, column 3).  Extents: (2155, 0) to (4155, 2000).
gdal_translate  -co "TFW=YES" -srcwin 2155 0 2000 2000 093L03-4-5-6_dem_26909.tif tile_1_3.tif

Input file size is 4155, 3572
0...10...20...30...40...50...60...70...80...90...100 - done.
ROW IS FINISHED.

Producing tile tile_2_1.tif (row 2, column 1).  Extents: (0, 1572) to (2000, 3572).
gdal_translate  -co "TFW=YES" -srcwin 0 1572 2000 2000 093L03-4-5-6_dem_26909.tif tile_2_1.tif

Input file size is 4155, 3572
0...10...20...30...40...50...60...70...80...90...100 - done.

Producing tile tile_2_2.tif (row 2, column 2).  Extents: (1572, 1572) to (3572, 3572).
gdal_translate  -co "TFW=YES" -srcwin 1572 1572 2000 2000 093L03-4-5-6_dem_26909.tif tile_2_2.tif

Input file size is 4155, 3572
0...10...20...30...40...50...60...70...80...90...100 - done.

The final tile in the row will be a bit too big.
To keep all tiles the same size, I'm backing off the upper left corner of this tile from (3144,1572) to (2155,1572).

Producing tile tile_2_3.tif (row 2, column 3).  Extents: (2155, 1572) to (4155, 3572).
gdal_translate  -co "TFW=YES" -srcwin 2155 1572 2000 2000 093L03-4-5-6_dem_26909.tif tile_2_3.tif

Input file size is 4155, 3572
0...10...20...30...40...50...60...70...80...90...100 - done.
ROW IS FINISHED.
IMAGE IS FINISHED.

Tiles are named with the prefix you gave, followed by _X_Y.tif, where X is the row position, and Y the column position, of the tile. So in this case we got tile_1_1.tif, tile_1_2.tif, etc., along with tile_1_1.tfw, tile_1_2.tfw, etc

Moving Mountains

I’ve been reading Gottfried Merzbacher’s Central Tian Shan which was published in 1905. (Archive.org has a free copy here.) This German geologist spent 1902-3 in the Tian Shan exploring valleys, noting strike and dip, and, among other things, trying to figure out the actual location of the peak Khan Tengri. This 7000m peak was not marked correctly on the 40-verst Russian map he was using. (40-verst maps were a series at 40 versts to the inch, or 1:1,680,000.)

While reading Merzbacher’s account, I looked at my map of Charles Howard-Bury’s journey in the Tian Shan (posted previously) and discovered I too had Khan Tengri in the wrong place!

So I did a little homework to make sure I had it moved it to the right place, because not being sure where Khan Tengri is located should be the kind of problem they only had 100 years ago, right? Well, maybe not.  Let’s compare Google maps, on the left, and Bing maps on the right.

Google-Bing Khan Tengri comparisonWow, that’s some pretty serious difference. Not only is Khan Tengri in a different place (relative to the glaciers, for example), but the Chinese-Kyrgyz border is also in a different place. In Bing’s world the border runs atop the highest peaks, while in Google’s the upper portion of the South Inyl’chek glacier is actually in China.

Bing, by the way, is using Russian peak names, like Pobedy Peak, while Google has its Kyrgyz name, Jengish Chokisu.

Turns out that OpenStreetMap has the same border Google does; but Yahoo and Here have the border that Bing does!

A quick web search reveals that China and Kyrgyzstan settled their border disputes in 2009. It’s likely that one of the sets of lines we see above dates from prior to that settlement, and one from after. But which is which?

Administrative boundaries downloaded from GADM and DIVA indicate that Bing/Yahoo/Here are actually more up to date.

But as far as the location of Khan Tengri is concerned, I’m afraid Google/OSM are correct.