Get your own DEM Tiled into World Wind – Dan Deneau Background: Some users of my spin-off to WorldWind (“SERVIR Viz”) wanted to be able to get their own DEMs into the application. I thought there was a way, but it seemed to be kept a secret, as nobody really has done any solid documenting of the process. The SERVIR Viz spinoff, is based on the 1.3.3.1 WW source code, which seems ancient by now, but is still working perfectly for us. I will eventually be upgrading it to the 1.4 source code, or the new 1.5 release whenever that happens. I have no reason to believe that the steps outlined here will not work in the later versions of WorldWind, but try it out, and if it doesn’t work…then…maybe they’ve created a better way! I’m going to try and create this walkthrough at as low a level as I can, so that as many people can benefit from it as possible. Feel free to post questions to “geodan” on the WorldWind forums if need be, and I’ll try and help out. What you’ll need to get started: 1) Get “what_nick’s” php script for dishing up image tiles to WW. You can find it the zip file where you got this word document. 2) Download and install the FWTools suite for windows: http://fwtools.maptools.org/. While you don’t need most of this, the main part you’ll need, is the “gdalwarp.exe”. What I did, was I took the contents of the “bin” folder from “Program Files/FWTools/bin” (which has all the DLLs and EXEs), and I put it in my website directory. I created a folder in my website area on my local machine called “WorldWindElevation”, C:\website\WorldWindElevation, and dumped all the files there. 3) Put the php file in the directory “C:\website\WorldWindElevation” so that it’s at the same level as gdalwarp.exe (and all the other exe’s and dlls). 4) Get a source DEM that will be used for splitting into tiles, and serving to WorldWind. The source DEM format DOES matter to some degree. The safest format seems to be a 16-bit signed TIF. I’m using a GEOTIFF, which doesn’t use a “world file”, it has the geo-referencing built in. I believe the important part here is that the image is a 16-bit signed integer….I believe that gdalwarp.exe does take other formats as input (IMG, etc), so check their documentation on that. The DEM should be Geographic projection WGS84. Put the DEM in a folder called: “C:\website\WorldWindElevation\DEM\. 5) Create a folder: “C:\website\WorldWindElevation\wwcache\. 6) Create a folder: “C:\website\WorldWindElevation\wwcache\DEM\”. This is where the PHP file will create all the directories and BIL files to serve to WorldWind. 7) Download the “Command-Line Version” of 7-Zip, a compression application. The link is: http://www.7-zip.org/download.html. Extract the contents of the downloaded file into the “C:\website\WorldWindElevation” directory, at the same level as gdalwarp.exe, and your PHP file. You should see the 7za.exe, that’s the important file. This file is used to compress the tiles for transport to WorldWind. 8) If you want to be safe, I’m not sure if this matters, but I made sure to clip my DEM into a perfect square. The DEM I used was 1288x1288 pixels. Modifying the Earth.xml file In order for WorldWind to know that you want to access another DEM, you’ll need to add something to Earth.xml. You can see the attached Earth.xml file that I’m using, and the XML is explained below: <HigherResolutionSubsets Name="104"> <TerrainTileService> <ServerUrl>http://localhost/WorldWindElevation/WorldWindElevation.php</ServerUrl> <DataSetName>104</DataSetName> <LevelZeroTileSizeDegrees>0.1157</LevelZeroTileSizeDegrees> <NumberLevels>14</NumberLevels> <SamplesPerTile>322</SamplesPerTile> <DataFormat>Int16</DataFormat> <FileExtension>bil</FileExtension> <CompressonType>7z</CompressonType> </TerrainTileService> <LatLonBoundingBox> <North> <Value>42.995877</Value> </North> <South> <Value>42.880096</Value> </South> <West> <Value>-76.6186211</Value> </West> <East> <Value>-76.5028401</Value> </East> </LatLonBoundingBox> </HigherResolutionSubsets> 1) First, the HigherResolutionSubsets tag is used so that you can have your DEM as well as the SRTM DEM. This tag is inserted inside the TerrainAccessor tag for the SRTM, as you’ll see in the attached Earth.xml file. 2) The DataSetName is “104” because the PHP script is looking for a number as the dataset name (not sure why, but it doesn’t much matter). Keep it the same as this until you get things working. 3) The LevelZeroTileSizeDegrees value must match the $lzts variable value in the PHP script! This value is ideally calculated as the width of the image in decimal degrees. However, many people have warned that the LevelZeroTileSizeDegrees value should adhere to the formula: 180/2^n where “n” is an integer. “They say” that this is to ensure that the DEM is correctly positioned on the earth. I didn’t have a problem using just the width of my image in decimal degrees…so not totally sure on that one. Perhaps what you can do is take the width of your DEM in decimal degrees (for mine, it was 0.1157), and then try and figure out the closest “correct” value to use via the formula above. So for example, 180/2^11 equals 0.087890625 or 180/2^10 equals 0.17578125. Then maybe one of values can be used, if it works. The smaller the value, the further in you’ll need to zoom in to start seeing your data. 4) The NumberLevels value tells WorldWind to keep fetching tiles as you zoom in further and further. It wouldn’t make sense to put a value of 20 unless you have amazingly high resolution data,…and at the same time, you wouldn’t want a low number like 1 or 2 if your data was pretty good resolution…because it would stop requesting tiles as you zoom in. A value of 10-12 is usually fine for any data…I have it at 14 because I’m paranoid. 5) The SamplesPerTile, I believe, tells WorldWind how many pixels wide your tiles are. My source DEM was 1288 x 1288 pixels, so I divided by 4 and got 322. This value should match the values you enter in the GDALWARP operation in the PHP script (as you’ll see later). Since there’s so little documentation on this stuff, most of this is my best guess. 6) You’ll need to enter your bounding coordinates for your source DEM, so that WorldWind will know to start requesting tiles if you are flying over that area (and if you are at the appropriate zoom level of course). The PHP file explained a bit: The first line tells us what directory to create all the directories, for the different levels and tiles: $szMapCacheDir="C:/website/WorldWindElevation/wwcache/DEM"; These lines: $X = isset( $_REQUEST['X'] ) ? intval($_REQUEST['X']) : 0; $Y = isset( $_REQUEST['Y'] ) ? intval($_REQUEST['Y']) : 0; $L = isset( $_REQUEST['L'] ) ? intval($_REQUEST['L']) : 0; $T = isset( $_REQUEST['T'] ) ? intval($_REQUEST['T']) : "104"; These are the parameters that WorldWind sends to your PHP page. The $L is the current level that WorldWind wants tiles for, and the $T is the DataSet name, which comes from the Earth.XML. Next, the variable: $lzts = 0.1157; This variable, the LevelZeroTileSize, is a value expressed in decimal degrees. This value must match the “LevelZeroTileSizeDegrees” value in the Earth.xml file. Once you get to this part: if($T=="104") { //if(($lat1<41)||($lon1<-77)||($lat2>44)||($lon2>-75)) { //header("HTTP/1.0 404 Not Found"); //exit(); //} //else { $gdalwarp = "gdalwarp.exe -te $lon1 $lat1 $lon2 $lat2 -ot Int16 -tr 0.00008989203 0.00008989203 -ts 322 322 -of ENVI "." C:/website/WorldWindElevation/DEM/Auburn_dd_ClipSquare.TIF ".$szIntFile; exec($gdalwarp); $za7 = "7za.exe a ".$szCacheFile." ".$szIntFile; exec($za7); //} } The first “if” statement is checking to see if the requested dataset is called “104”, if so, then the DEM tiles are made with GDALWARP. You’ll notice the green text is commented out; it is some code meant to restrict the requests further based on a geographic extent…I just removed it. PHP puts together a command string, with different inputs, and then executes the process. I’m not going into the help for GDALWARP, but other inputs are possible. I’ll mention the important parts: Where I have the 0.00008989203 numbers, those represent the pixel resolution of my DEM, expressed in Decimal Degrees. Open the DEM in ArcMap, and check out its properties to get this value. The 322 values are the height and width (not sure which is which) of the tiles that we want. These values should match the “SamplesPerTile” value in the Earth.xml. The “C:/website/WorldWindElevation/DEM/Auburn_dd_ClipSquare.TIF” part is the path to my source TIF DEM. I believe you can use other formats than TIF, like IMG, etc., but make sure that the “-of ENVI” part is there, as that instructs GDALWARP to create .BIL files, a binary image format. After all that, the images are compressed with 7za.exe, and then sent back to WorldWind. Most of what I’m not mentioning in the PHP script has to do with creating the folder structure and copying the appropriate BIL files into the right folders. WorldWind is looking for this file/folder structure. You’ll notice that as you fly around in WorldWind, folders will be created in your wwcache\DEM directory “0,1,2,3” etc….those are folders for each level as you zoom in. Testing Tips If you are having trouble, or aren’t sure if it is working you can do a couple of things: 1) Hit CTRL-H to pull up the download monitor, you’ll be able to see the requests for your tiles…and more importantly, see if the tiles were successfully created. 2) If you aren’t sure if it is your DEM you’re seeing, and not the SRTM, then set the SRTM to have a NumberLevels value of zero, and then zoom into your area, and see if there is any elevation data. 3) NOTE: you will probably see some weird bumpyness in your DEM as you’re zooming in. I’m not sure that we can avoid this…but zoom in a bit further, past the bumpyness, and it should go away. 4) Turn on the USGS topo maps in order to see if your DEM is lined up correctly. Use the contour lines on those maps, and enhance the Vertical Exaggeration of the terrain to see if things match up. I’m not sure if the bumpyness thing has been resolved in WW 1.4, or if the HigherResolutionSubsets tag is still in use in that version. Read this completely, and mess around with it as much as possible before asking questions in the forum, but if needed, I will try and answer any questions in the forum, username “geodan”. Dan Deneau IAGT Software Engineer www.iagt.org