I would like to generate a 3d terrain model of an area, and I am stuck on creating the TIN (which I will convert to an STL). I know there are plenty of ways to use ArcGIS, QGIS, 3DEM, and various other programs to go through and generate a TIN for an area by hand and Stack Exchange answers explaining them. But that does not fit my use case, I need a solution in which I can script the whole process. Preferable in python, but if another solution exists I would not throw it out. I am also willing to sacrifice some accuracy for speed. The result will be printed and does not need to be perfect.

I have SRTM 1 arc-second data, which I downloaded from NASA. The first thing I attempted to do was generate a TRN out of it, which did work, however it was huge and unwieldy to use. There are way too many triangles. The plains have the same amount of triangle as the Himalayan Mountains. If the data were sparse, I would use scipy.spatial.Delaunay, but since it is a regular grid it doesn't simplify things any.

I also thought about just down sampling to make it smaller (or using coarser resolution data), but that doesn't actually address the real problem of needing the simplify the surface that was generated.

Is there a library I am missing to generate TINs in python?

Is there a better approach to what I am trying?

Possibly generate contour lines for an area, then triangulate them?

If that is possible, what library would I use to generate the contour lines?

If nothing else can someone point me to documentation, or a paper on how to generate a simplified TIN out of gridded elevation data?

If I have to write the library myself I will. The primary requirement I have is that it has to be something I can script. A cross platform solution would be ideal, I would like to run it on Linux, but I will take what I can get.

  • If QGIS can do it, the source is already published. All you'd need to do is port it. Therefore this isn't really a GIS question.
    – Vince
    Dec 10, 2015 at 14:01
  • hi there, what will you be doing with the TIN? just curious for some background. Dec 10, 2015 at 18:44

3 Answers 3


A solution is to generate random points and sample the elevation raster at each of these points,

enter image description here

then interpolate these points with the method that you want (as in Ordinary Kriging Example: GRASS-R Bindings).

enter image description hereenter image description here

enter image description here

If you use a script, there are many solutions

1) with R (many packages to do that)
2) with Python, one of the best scientific solution is Mayavi but there are many other solutions (Pypi: triangulation for example) in addition to SciPy.
3) you can also use PyGRASS from outside GRASS GIS and use all the GRASS commands.
4) in the same way, you can use PyQGIS from outside QGIS and use all the processing algorithms (from SAGA GIS or GRASS GIS)

  • What did you use to create the above?
    – nickves
    Dec 11, 2015 at 0:30
  • GRASS GIS with the command v.delaunay and the Antonio Alliegro Python script tin.to.raster.py
    – gene
    Dec 11, 2015 at 10:43
  • Ah, the random sampling might be the way to go. Do you know if that is how they typically generate tins in Arc or GRASS? I will play with a bunch of amounts, but is there any sort of 'best practice' number / percentage of points to sample?
    – eseglem
    Dec 11, 2015 at 12:41
  • no, it depends on what you want
    – gene
    Dec 11, 2015 at 13:01
  • What does the interpolation add if you already know the elevation at the points? I already have a 30m grid of elevation, could I just take a random sampling of them and call that good enough? Or is there a definite value add to interpolation?
    – eseglem
    Dec 11, 2015 at 14:15

I recently implemented a small package to do this in Python: pymartini. It's a port of the Martini JavaScript library. It's implemented in Cython, so it's very fast (on the order of milliseconds for a 512x512 pixel image).

This is more efficient than choosing random points, but the Martini algorithm does require a square input image.


Besides the triangulation links provided by gene, you can look into pyLidar, which has triangulation interpolators.

GRASS add-on v.delaunay3d can be an option also.

But if you need to simplify your DEM retaining detail on the mountainous areas and smoothing out flat areas, I'd say your idea of generating contours and then triangulating them is a good idea. GRASS has a very good contour algorithm.

  • Since 2008, the command v.delaunay is 3D (Pavlovsky, 2008, Google Summer of Code 2008)
    – gene
    Dec 11, 2015 at 10:28
  • I was thinking about going the countour route, but was also hoping to avoid the middle step if at all possible. Though I think it would be pretty fast. I think you woudln't actually need to do a 3d Delaunay because it is a single surface. A 2d one, should end up with the same results right?
    – eseglem
    Dec 11, 2015 at 13:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.