How to build a 3d terrain model from Google Earth data (and why you may not want to)

Calvin Froedge
Aug 8, 2019 · 3 min read

I am developing some land in Panama (a technology campus for remote workers). The architect I am working with asked if I could get him a 3d model of the land for CAD renderings. I decided to see if I could use Google earth to accomplish this.

I started out by downloading Google Earth and making a bounding box around the land:

I simply dropped some markers and created a rectangular grid (222m by 275m) around the development. I started with the bottom left point and top right point and then added two more equidistant points. I saved these coordinates in a JavaScript file.

I then decided to divide the area into a grid, spot checking elevation at every 1 meter. I used the Google Elevation API to grab this data. I used the following JavaScript function to generate ~50,000 points within my grid:

function getLocations(){
var current_lat = LAT_MIN;
var current_long = LONG_MIN;
let locations = []; while(current_lat < (LAT_MAX + increment)){
while(current_long < (LONG_MAX + increment)){
locations.push([current_lat, current_long]);
current_long = current_long + increment;
}
current_lat = current_lat + increment;
current_long = LONG_MIN;
}
console.log('width of grid', distance(LAT_MIN, LONG_MIN, LAT_MAX, LONG_MIN));
console.log('height of grid', distance(LAT_MIN, LONG_MIN, LAT_MIN, LONG_MAX));
console.log('points', locations.length);
let firstPoints = locations.slice(0, 2);
console.log('firstPoints', firstPoints);
console.log('distance between points', distance(firstPoints[0][0], firstPoints[0][1], firstPoints[1][0], firstPoints[1][1]));
return locations.map((item)=>{
return {
lat: String(item[0].toFixed(5)),
lng: String(item[1].toFixed(5))
}
});
}

Next, I chunked these points into groups of 500 (more economical API call to Google) to request elevations:

async function getResult(locations){
let response = await googleMapsClient.elevation({
locations
})
.asPromise()
return response.json.results;
}
async function getElevations(locations=null){
var chunkSize = 500;
var chunked = _.chunk(locations, chunkSize);
var lines = [];
for(var i=0;i<chunked.length;i++){
var chunk = chunked[i];
try {
var result = await getResult(chunk);
} catch(e){
console.log('e', e);
return;
}

for(var k=0;k<result.length;k++){
var item = result[k];
var line = `${item.location.lat} ${item.location.lng} ${item.elevation}\r\n`;
console.log('line', line);
lines.push(line);
}
}
await fs.writeFile('data.txt', lines.join(''));
}

Finally, I converted the lat / lng coordinates into a grid with origin 0,0 in meters:

async function convertDataToGrid(){
let data = await fs.readFile('data.txt');
data = data.toString().split('\r\n').filter((item)=>{ return item.length > 0 }).map((item)=>{ return item.split(' ') });
data = data.map((item)=>{
lat = item[0];
lng = item[1];
alt = item[2];
return [
((lat - LAT_MIN) / increment).toFixed(0),
((lng - LONG_MIN) / increment).toFixed(0),
alt
].join(' ')
});
await fs.writeFile('grid.txt', data.join('\r\n'));
}

This gave me an XYZ file (separated by spaces):

x y alt

I then used MeshLab to import the file (File -> Import Mesh) and generate a model:

Note that you can add grid lines and modify colors and point size using the project explorer sidebar.

Great! We have a 3d model of our terrain. The only problem — It only loosely fits the actual contour of the land. A quick search tells me that Google Earth elevation data simply isn’t very accurate.

Onto using a drone + lidar!

Sign up for Top 10 Stories

By The Startup

Get smarter at building your thing. Subscribe to receive The Startup's top 10 most read stories — delivered straight into your inbox, once a week. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Calvin Froedge

Written by

Software developer, investor, energy markets analyst.

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +792K followers.

Calvin Froedge

Written by

Software developer, investor, energy markets analyst.

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +792K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store