A one-degree SRTM tile holds 12,967,201 elevation samples. The terrain that comes out of it has 15,828 nodes. Almost everything is thrown away, and which parts survive is the whole point of this stage.
Where the 818 to 1 goes
SRTM gives you a regular grid: a height every arc-second, whether the ground under it is a cliff face or the middle of the Pacific. A renderer does not want a regular grid, it wants a mesh with detail where the ground has detail.
terrafit fits a surface to the grid, adding nodes until the worst
remaining error falls below a tolerance. Flat water needs almost none. A ridgeline
needs many. For N37W123 the result looks like this:

The practical consequence: a mountainous square costs more time and produces larger output than a flat one of the same size. Area is not the only thing that decides what a build costs. If you are estimating, look at the terrain, not just the bounding box.
The two commands
hgtchop 1 N37W123.hgt $WORK/SRTMGL1
terrafit -j 10 $WORK/SRTMGL1
Two seconds and one second respectively, at 29 MB and 46 MB peak memory. This is the cheap end of a TerraGear build by a wide margin; see where the time actually goes.
hgtchop: grid in, tiles out
Three positional arguments, no flags:
hgtchop <resolution> <hgt_file> <work_dir>
Resolution is 1 or 3, for 1-arc-second or
3-arc-second data, and has to match the file. Anything else exits with the usage
message.
Two things catch people. It takes a raw .hgt,
not the zip the repository README describes: unzip first. And the
directory you name has to be one genapts recognises later:
SRTM-1, SRTM-3, SRTM-30,
SRTMGL1 or SRTMGL3. Call it anything else and
tg-construct will find it while genapts will not.
One degree at latitude 37 comes out as 32 tiles: four
columns by eight rows, each 0.25° of longitude by 0.125° of latitude, all inside
the bucket w130n30/w123n37. Tiles are wider than they are tall
because longitude width grows toward the poles to keep ground area roughly
even.
terrafit: the knobs that matter
terrafit [-m minnodes] [-x maxnodes] [-e maxerror] [-j threads] [-f] <path>
Point it at a directory and it walks every .arr.gz beneath it.
Three settings decide the trade:
| Flag | Default | What raising it does |
|---|---|---|
--maxerror | 40 m | Loosens the tolerance. Fewer nodes, faster, coarser ground. |
--maxnodes | 1000 | Raises the ceiling per tile. More detail where the terrain earns it. |
--minnodes | 50 | Floor per tile. Mostly matters over water, where the fit would otherwise stop early. |
--force reprocesses tiles whose output is newer than the input.
Without it, re-running is cheap and skips finished work; useful, because the
usual reason to re-run this stage is to try a different
--maxerror.
Reading the output yourself
A .fit.gz is gzipped plain text: a node count, then one
longitude latitude elevation per line.
$ zcat 942050.fit.gz | head -3
1000
-122.50000000 +37.50000000 0.00
-122.50000000 +37.55250000 96.00
Which makes it the easiest place in the whole pipeline to check that your elevation data landed where you think it did. If a tile’s nodes are all at zero, the problem is upstream of here and you can see it without loading anything. The rest of the chain is on the files a build writes.
The other choppers
Four more preprocessing tools install alongside these, none of which this
build used: srtmchop, dtedchop and
gdalchop read other input formats, and fillvoids
patches SRTM’s data holes from a second source. SRTM version 3 is void-filled
already, so fillvoids matters mainly if you are working with older
data.