Home > Blog > Sakhal Elevation Map

Creating a High Resolution Elevation Map of Sakhal

A contour map of 2.3 million points gathered from the world data. See below for how it was made.

Adjust the sliders and click the button to change the visualization. Note: very low contour interval values might freeze the page. Regardless, it takes a few seconds to redraw.

13 reset
2 reset

How It Was Made

This is part of a series of projects I'm working on for fun to visualize DayZ in various ways. If you want to chat about this, join me on Discord and/or subscribe on YouTube.

Get Y values for points on the map

I wrote an Enforce script to get the Y values (i.e. height) for a large range of points on the map. See the script below. I used a resolution of 10 meters. The map is 15,360 x 15,360 meters resulting in data for 2,359,296 points, (15360 / 10)². The script outputs to a json file. I thought I would definitely need to add a delay between points to prevent the engine (polling the data and writing to json) from getting overwhelmed. Just a 10ms delay would mean it would need 6.5 hours to get all of the data. I ran it first without any delay and crossed my fingers. When I first launched my local DayZ server with the mod loaded I though my computer would die or, at the very least, DayZ would explode 💥 . On the contrary, the entire process completed in a few seconds with no issues whatsoever. I was shocked. The result was an 11+ million line, 155 mb, json file (5 lines for each point). In retrospect I could've stored each point just as a single line vector (as DayZ uses natively), but this was workable as is.



The Enforce Script

The json Output (sample)


[
    {
        "x": 0.0,
        "y": -60.779998779296878,
        "z": 0.0
    },
    {
        "x": 10.0,
        "y": -62.74333572387695,
        "z": 0.0
    },
    {
        "x": 20.0,
        "y": -62.61333465576172,
        "z": 0.0
    },
    ...
            

If you want the entire json output for some reason, get it here (26 mb .zip file).

Fun facts:

The lowest point, at least at a 10m resolution, is -92 meters at the "Sakhal Trench" (does this have an actual name?) located off the heel of the military penninsula "boot" (x: 5730, z: 2690). Redraw the plot with a contour interval of 70 and you can see this well.

The highest point is 556 meters located at the top of the volcano (x: 10020, z: 12090).

Tranformed the Output

Next, I needed to transform the X, Y, Z json format into 2d array of Y values that could be used by Obervable Contour Mark method.

I relied on ChatGPT to do the heavy lifting on writing a Python script at first because I thought that the tranformational math would be beyond me. This ended up being a mistake in the end. Feeling confident after the Enfusion script executed in only a few seconds, I was sure this would be quick but it kept either crashing, hogging memory, at one point I even got the BSOD..., or resulting in 33GB json files which we're obviously useless. I eventually realized that ChatGPT wasn't understanding the math requried to convert the initial json data in to the 2D array that was needed to plot. I was able to work it out myself and the initial version of the data transformation took about 35 seconds to execute. The result was a 2.3 million value array containing the Y values in row major order (see here and here).

This, by far, took the longest to figure out of this entire process. It wasn't until the next day that it dawned on me that I had purely coincidentally written the original Enforce y-scraper script to run in row major order. As a result, the json X,Y,Z data was already in the right order. All I really had to do for this step was to pull each Y value and put it in an array. The simple script is below. It took 5 seconds. 🙄

The Output (sample)


[
    -60.78, -62.743, -62.613, -60.38, -61.73,
    -62.563, -62.84, -60.247, -59.99, -62.17,
    -61.433, -60.947, -60.75, -59.817, -59.17,
    ...
]
            

The above Y values start at 0,0 and represent each X iteration (so every 10 meters in this case). The negative values represent below sea level. The points in the sample above are the first 15 points starting at 0,0 (the bottom left of the plot) and going right .

Created the Plot

Creating the actual plot was fairly straightforward, following the examples on Observable's website. I added more javascript to handle loading and the functionality to adjust the contour interavls, blur, and color. The contour interval number represents a multiple at which to draw the contours. For example, 5 will draw a contour at every multiple of 5.

If you liked that, check out...