Skip to content

Command line

satprint.cli

Command-line interface.

Usage:

satprint serve [--host 0.0.0.0] [--port 7417]
satprint build --bbox S W N E [--width 120] [--exaggeration 2] -o model.stl
satprint build --bbox S W N E --glb model.glb -o model.stl
satprint build --bbox S W N E --buildings [--building-scale 2] -o city.stl
satprint build --bbox S W N E --buildings --frame 5 --3mf city.3mf -o city.stl
satprint build --bbox S W N E --bridges [--bridge-piers 20] -o bay.stl
satprint build --bbox S W N E --buildings --roads [--road-detail major] -o city.stl
satprint build --synthetic -o demo.stl
satprint build --file dem.tif --ground-width 15000 -o model.stl

main(argv=None)

Parse argv and run the chosen subcommand.

Parameters:

Name Type Description Default
argv

arguments without the program name; None reads sys.argv.

None

Returns:

Type Description
int

the process exit code.

Source code in satprint/cli.py
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
def main(argv=None) -> int:
    """Parse ``argv`` and run the chosen subcommand.

    :param argv: arguments without the program name; None reads ``sys.argv``.
    :return: the process exit code.
    """
    p = argparse.ArgumentParser(
        prog="satprint",
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    sub = p.add_subparsers(dest="cmd", required=True)

    s = sub.add_parser("serve", help="run the web app")
    s.add_argument("--host", default="127.0.0.1")
    s.add_argument("--port", type=int, default=7417)
    s.add_argument("--reload", action="store_true")
    s.set_defaults(func=_serve)

    b = sub.add_parser("build", help="build an STL from the command line")
    src = b.add_mutually_exclusive_group()
    src.add_argument(
        "--bbox", nargs=4, type=float, metavar=("SOUTH", "WEST", "NORTH", "EAST")
    )
    src.add_argument("--file", help="PNG/TIFF/GeoTIFF heightmap")
    src.add_argument(
        "--synthetic", action="store_true", help="procedural demo terrain (offline)"
    )
    b.add_argument(
        "--ground-width", type=float, help="real-world width in meters (for --file)"
    )
    b.add_argument("--seed", type=int, default=0)
    b.add_argument("--resolution", type=int, default=256, help="grid columns (32-1024)")
    b.add_argument("--width", type=float, default=100.0, help="model width in mm")
    b.add_argument("--base", type=float, default=3.0, help="base thickness in mm")
    b.add_argument(
        "--exaggeration", type=float, default=1.5, help="vertical exaggeration"
    )
    b.add_argument(
        "--relief",
        type=float,
        help="fix the relief height in mm (overrides exaggeration)",
    )
    b.add_argument(
        "--smoothing", type=float, default=0.0, help="Gaussian sigma in pixels"
    )
    b.add_argument(
        "--keep-bathymetry",
        action="store_true",
        help="do not clamp below-sea-level data to 0",
    )
    b.add_argument("--name", default="terrain")
    b.add_argument("--preview", help="also write a hillshade PNG here")
    b.add_argument(
        "--glb", help="also write a GLB with satellite imagery here (needs --bbox)"
    )
    b.add_argument(
        "--frame",
        type=float,
        default=0.0,
        help="border frame width in mm around the model (0 = none)",
    )
    b.add_argument(
        "--frame-height",
        type=float,
        help="frame height in mm (default: base thickness + 1)",
    )
    b.add_argument(
        "--3mf",
        dest="threemf",
        help="also write a multi-color 3MF here: land, water, buildings, "
        "roads (and bridges) and border as separate parts on four filaments, "
        "the border on the land filament (needs --bbox)",
    )
    b.add_argument(
        "--plate",
        choices=list(PLATES),
        default="256",
        help="build plate the 3MF is centered on, in mm: 256 (Bambu A1, P1, "
        "X1) or 180 (A1 mini)",
    )
    b.add_argument(
        "--buildings",
        action="store_true",
        help="add OpenStreetMap buildings (needs --bbox)",
    )
    b.add_argument(
        "--roads",
        action="store_true",
        help="add OpenStreetMap roads as raised strips (needs --bbox)",
    )
    b.add_argument(
        "--road-detail",
        choices=["auto", "major", "all"],
        default="auto",
        help="which roads: auto (by model scale), major (motorway to secondary) or all",
    )
    b.add_argument(
        "--building-scale",
        type=float,
        default=1.0,
        help="building height multiplier; 1 = true proportion",
    )
    b.add_argument(
        "--bridges",
        action="store_true",
        help="add bridges over water from OpenStreetMap (needs --bbox)",
    )
    b.add_argument(
        "--bridge-piers",
        type=float,
        default=20.0,
        metavar="MM",
        help="longest distance between bridge piers in mm; 0 = no piers",
    )
    b.add_argument(
        "--building-source",
        choices=["openfreemap", "overpass", "overture"],
        default="openfreemap",
        help="OpenFreeMap vector tiles (fast, rebuilt weekly), Overpass "
        "(latest OSM edits, slower) or Overture Maps (needs the overture extra)",
    )
    b.add_argument("-o", "--output", default="terrain.stl")
    b.set_defaults(func=_build)

    args = p.parse_args(argv)
    return args.func(args)