GithubHelp home page GithubHelp logo

chharding / touchterrain_for_cageo Goto Github PK

View Code? Open in Web Editor NEW
181.0 13.0 44.0 24.95 MB

Touch Terrain: A python app to create 3D printable terrain models (STL/OBJ) from only elevation data (via Google Earth Engine) or from a local geotiff. Has been used for CNC terrain models. Runs as a web app (http://touchterrain.org), as .py file (standalone.py) or as jupyter notebook. Docker image: https://github.com/ChHarding/TouchTerrain_jupyter_docker

Home Page: http://touchterrain.geol.iastate.edu

Python 28.00% HTML 3.26% Jupyter Notebook 12.09% JavaScript 12.33% CSS 44.31% Shell 0.01% Dockerfile 0.01%
earth-engine python terrain 3d-printing elevation-data raster

touchterrain_for_cageo's Introduction

TouchTerrain (version 3.6)

TouchTerrain converts digital elevation data into digital model files (STL or OBJ) suitable for 3D printing. It comes as a standalone version and as a server version for a web application. To see the server version in action, go to http://touchterrain.org or http://touchterrain.geol.iastate.edu

TouchTerrain is developed by Chris Harding (Iowa State University) and Franek Hasiuk (Kansas Geological Survey). For questions email Geofablab AT gmail DOT com.

For more in-depth information:

Getting Started

TouchTerrain reads Digital Elevation model (DEM) data within a geographical extent (downloaded from Earth Engine or from a local raster file) and from it creates a 3D mesh model file suitable for 3D printing. Online data from EE is automatically UTM projected and adaptively downsampled. The 3D model (STL or OBJ format), possibly consisting of several files (tiles), is saved in a zip file along with a log file with details about the process steps.

For most users, the web app version will most likely meet their requirements. Iowa State University offers the web app here: http://touchterrain.org or http://touchterrain.geol.iastate.edu

Standalone mode

Standalone mode offers a different approach to processing than the web app. Standalone mode uses Python code, either TouchTerrain_standalone.py or a Jupyter notebook to define processing parameters in code and then processes a local DEM raster file or online DEM data from Earth Engine (google account required to authenticate). After processing the resulting zip file is stored locally. A few aspect of TouchTerrain are only exposed via the stand alone version. It also offers a way around around server processing quotas, that make it impossible to create some very large (> ~150 Mb) 3D models as all he processing is done locally (some Google Earth Engine imposed limitations still apply, see Appendix).

Although a pip setup.py file (and requirements.txt) are provided, note that it can be non-trivial to get all the required Python libraries to install locally, especially those that are wrappers around C/C++, such as GDAL. It may therefore be easier to run Touchterrain inside a docker container (see touchterrain_jupyter docker container) or to use a jupyter notebook on Colab or Binder (see below).

TouchTerrain_standalone.py

This defines the processing parameters either directly inside the file (parameters are basically values in a dictionary) of via a JSON file it reads in. An example of such a JSON config is *example_config.json- in the stuff folder. See Processing Parameters below for details. TouchTerrain_standalone.py has only one argument, the path to the JSON file, e.g. python TouchTerrain_standalone.py stuff/example_config.json would run the example configuration. Running it without an argument will create a default JSON file (same as the example) that you can then modify. TouchTerrain_standalone.py can be used in conjuction with shell scripts for batch processing (e.g. see https://github.com/ansonl/DEM2STL)

The recommended way to run the standalone version is to use our touchterrain_jupyter docker container.

To use touchterrain in standalone mode (i.e. not via a web server), either run TouchTerrain_standalone.py or TouchTerrain_standalone_jupyter_notebook.ipynb. Both sit in the project root folder and require that the touchterrain module has been installed.

The jupyter notebook version of standalone also

Jupyter Notebook version for standalone

For most users, espcially those new to Python, the preferred way to run the standalone version of TouchTerrain is via a jupyter notebook file. Inside the notebook, the same processing parameters described in the JSON config file are defined in Python (as a dictionary). The parameters are explained below for the JSON file version but the python syntax is very similar to JSON. After processing the DEM and saving the model(s) in a zip file. All notebooks offers a map interface (geemap) for digitizing the area of the model, either as box, circle or polygon.

We have created four versions of notebooks:

  1. TouchTerrain_standalone_jupyter_notebook.ipynb is meant to be run locally or via a docker container and is meant for those familiar with Python. The setup part is now somewhat outdated but the notebook may still form a useful basis. It allow the preview of the model for k3d.
  2. TouchTerrain_jupyter_for_starters.ipynb is a modification of 1) meant for Python beginners. It tries to walk a beginner through the process in much more detail by providing a template (workflow) for all major parameters. As such is may be unnecessarily verbose for non-beginners. It also can preview the model via k3d and is again meant to be run locally on via a docker container.
  3. TouchTerrain_jupyter_for_starters_colab.ipynb is a modification of 2) specifically for running on colab (free but Google account required). To run it just click on this badge: Open In Colab and follow the instructions! With some caveats, this is by far the easiest and fastest way to process DEM data with TouchTerrain standalone! The free runtime environment has plenty CPU power and disk space and, as most of the required Python packages are already installed, installation (despite being a bit quirky) is usually done under a minute. Sadly, k3d cannot be run and so it has no model preview.
  4. TouchTerrain_jupyter_for_starters_binder.ipynb is similar to 3) but tailored to run on Binder Binder Binder sets up a free docker container within a slick web interface (nice!) and uses JupyterLab. But, in my experience the installation phase is slower and less reliable than Colab. As lots of Python packages have to be installed (more than 750 Mb!), installation can take 10 - 15 minutes, with long paused w/o progress indication. Refreshing the browser sometimes helps but I've had cases where the installation simply stopped and never finished. In addition, a created instance seems to time out quite quickly, meaning that if your don't use it right away after its lengthy installation, the instance will shut down, requiring a new installation.

EarthEngine_authentication_guide.md has some notes on how to authenticate with EarthEngine, which is required when processing their online DEM data (but not when only processing uploaded local DEM raster files!).

General Processing parameters

These parameters can be used in the JSON config file or in a python dictionary for hardingcoding them in the jupyter notebook or TouchTerrain_standalone.py. The JSON config file has the following format and default values:

{
    "DEM_name": "USGS/3DEP/10m",
    "bllat": 39.32205105794382,
    "bllon": -120.37497608519418,
    "trlat": 39.45763749030933,
    "trlon": -120.2002248034559,
    "importedDEM": null,
    "printres": 0.4,
    "ntilesx": 1,
    "ntilesy": 1,
    "tilewidth": 120,
    "basethick": 0.6,
    "zscale": 2.0,
    "fileformat": "STLb",
    "tile_centered": false,
    "zip_file_name": "myterrain",
    "CPU_cores_to_use": null,
    "max_cells_for_memory_only": 25000000,
    "no_bottom": false,
    "bottom_image": null,
    "ignore_leq": null,
    "lower_leq": null,
    "unprojected": false,
    "only": null,
    "importedGPX": [],
    "smooth_borders": true,
    "offset_masks_lower": null,
    "fill_holes": null,
    "poly_file": null,
    "min_elev": null,
    "tilewidth_scale": null,
    "clean_diags": false,
    "sqrt": false,
    "use_geo_coords": null
}

Note that for Python, None and True/False need to be different:

Python JSON
None null
True true
False false
  • CPU_cores_to_use: Number of CPU cores (processes) to use.

    • 0: use all available cores, which will improve multi-tile processing times but has no effect for single tile processing.
    • null: forces use of only a single core, even for multiple tiles, which is useful when running the multi-tile code in a Debugger.
    • Note that multi-tile processing is currently broken so single processor mode will be used for now!
  • DEM_name: (resolutions are approximate and strictly true only at the equator!)

    • USGS/3DEP/10m: 10 m, continental USA only. link
    • JAXA/ALOS/AW3D30/V3_2: Global: 30 m, worldwide, but has some small "holes". link
    • USGS/SRTMGL1_003: 30 m, "worldwide", but not very far north (lower quality and older than ALOS!). link
    • MERIT/DEM/v1_0_3: 90 m, worldwide, with less error in low relief areas. link
    • USGS/GMTED2010: ~230 m, truly worldwide. link
    • GTOPO30: 30 Arc-Second, 1000 m, 1996, worldwide. link
    • CryoSat-2 Antarctica: 1000 m, antarctica only. link
    • NOAA/NGDC/ETOPO1: 2000 m, worldwide, with bathymetry. link
  • basethick: (in mm) A layer of material this thick will be added below the entire model, i.e. its thickness is counted down from the lowest elevation of the entire model. This is particularly important for models with long, deep valleys, which can cause the model to shine through if the base is not thick enough. A base thickness of at least twice the filament thickness is recommended.

  • bllat: Bottom-left latitude of area to be printed

  • bllon: Bottom-left longitude

  • trlat: Top-right latitude

  • trlon: Top-right longitude

  • Polygon to define the area: The web app version of TouchTerrain can load a polygon (or poly line) from an uploaded kml file which will supersede the bllat, etc. extent settings.

    The standalone version can read a kml file using the poly_file or polyURL parameters. For both, the first polygon found will be used as a mask, i.e. the model will only cover terrain inside the polygon. If no polygon is found, the first polyline is used instead. (Holes in polygons are ignored). kmz files are not supported at this time. To convert kmz to kml, unzip it (will be doc.kml) and rename doc to the name of the kmz file.

    • poly_file : path to a local kml file
    • polyURL : URL to a publicly readable(!) kml file on Google Drive

    The standalone version also supports: polygon : a GeoJSON polygon

  • bottom_image: (default: null). If a filename to a valid greyscale (1-band) 8-bit local image is given (e.g. TouchTerrain_bottom_example.png in the stuff folder), the image is centered, uniformly resized to have a generous fringe and used to create a relief on the bottom. Low values (black pixels, 0) create a high relief (with a large gap from the buildplate), white pixels (255) make no relief. Must have a base thickness > 0.5 mm. The highest relief is scaled to be 80% of the base thickness. Note that this relief may adversely affect bed adhesion and will certainly make the first few layers considerably slower to print!

  • clean_diags: (default: null). Eliminates 2x2 diagonal filled and empty cells in a DEM that lead to non-manifold models with 4 faces sharing the same edge. (Here 0 means undefined and 1 means a valid elevation):

    01    and    10
    10           01
    

    This only works on a model for which its raster contains undefined (NoData, NaN) values. This is off by default as it takes time and most modern slicers can handle non-manifold (i.e. non watertight) models. However, if you plan to import the model into other 3D applications (e.g. Meshmixer, Fusion 360, Microsoft 3D builder), you should set this to true.

  • fileformat: file format for 3D model file.

    • obj: wavefront obj (ascii)
    • STLa: ascii STL
    • STLb: binary STL (preferred mesh format)
    • GeoTiff: while all formats also store the raster used for making the mesh files in the zip file as a GeoTiff, this option ONLY stores the GeoTiff. This is much, much faster and permits downloading much larger areas without running into the server limit. Note that this will save a projected raster (unless unprojected is true) at the equivalent of the printres resolution but will ignore all other settings, such as z-scale, etc.
  • fill_holes: (default: null), Specify number of iterations to find and neighbor threshold to fill holes. -1 iterations will continue iterations until no more holes are found. Defaults to 7 neighbors in a 3x3 footprint with elevation > 0 to fill a hole with the average of the footprint. e.g. [10, 7]

  • ignore_leq: (default: null). Using an elevation (e.g. 0.0) will ignore any cells less or equal to that elevation. Good for omitting offshore cells and print only onshore terrain. Note that 0 may not be exactly sea level, on some DEMs you may have to experiment with slightly larger values (e.g. try 0.5 for a sharper coastline)

  • lower_leq: (default: null). An alternative to ignore_leq. Given a list in the format [threshold, offset], all cells less than or equal to threshold will be lowered by the offset. This helps with giving emphasis to coastlines. The offset is in mm with respect to the final mesh size. Unaffected by zscale.

  • importedDEM: (default: null). If null a geotiff is fetched from Earth Engine as detailed above. If it is set to a filename, this file is used as DEM. In this case, DEM_name, bllat, bllon, trlat and trlon are ignored, but all other parameters are still used.

    • You can test this with pyramid.tif (in the stuff folder) which has elevations from 0 to 255, so you probably will need a z-scale of 0.5 on a width of 100 mm. Any GDAL raster file format (http://www.gdal.org/frmt_various.html) should be readable, although geoTiffs are recommended.
    • Set printres to -1 to prevent downsampling and instead use the file's intrinsic resolution. Non-georef'ed rasters (i.e., regular images) are assumed to have a "real-world" cell size of 1.
    • The file can contain cells that are officially undefined (e.g. via teh GeoTiff meta data). These undefined cells will be omitted in the STL/OBJ file, allowing you to create 3D prints with "organic" boundaries instead of rectangular ones. Unrealistically low or high elevations (e.g. -9999999) will be treated as undefined.
  • max_cells_for_memory_only: (default: 1000000). If the number of raster cells to be processed is bigger than this number, temp files are used in the later stages of processing. This is slower but less memory intensive than assembling the entire zip file in memory alone. If your machine runs out of memory, lowering this may help.

  • min_elev: (default: null) Minimum elevation to start the model height at after basethick height. If null, the minimum elevation found in the DEM is used so the basethick height will start at the minimum elevation found in the DEM and not necessarily sea level.

  • no_bottom: (default: false). Will omit any bottom triangles i.e. only stores the top surface and the "walls". The creates ~50% smaller STL/OBJ files. When sliced it should still create a solid printed bottom (tested in Cura >3.6). Note that starting with TOuchTerrain version 3.5 for simple cases, the bottom mesh have been set to just two triangles, so the no_bottom setting is really only useful for cases involving polygon outlines (e.g. from a kml file).

  • no_normals: (default: true). Will NOT calculate normals for triangles in STL files and instead set them to 0,0,0. This is significantly faster and should not matter as on import most slicers and 3D viewers will calculate a normal for each triangle (via cross product) anyway. However, if you require properly calculated normals to be stored in the STL file, set this to false. (Contributed by idenc)

  • ntilesx: Divide the x axis evenly among this many tiles. This is useful if the area being printed would be too large to fit in the printer's bed.

  • ntilesy: See ntilesx, above.

  • only: (default: null). If given a list [x,y], will only process that tile index ([1,1] is upper left tile). This will enable users to d/l otherwise unreasonably large models by processing only one of its tiles at a time (thus staying under the server limit).

    • Example: only:[1,1] (JSON) or only = [1,1] (python) will d/l only the tile with index 1,1
      • Once this tile was downloaded, using only with [1,2], but otherwise repeating the request, will d/l tile 1,2
      • Although each tile will be in a new zip, unzipping them and putting all tiles in a common folder will create a "single" model that will make all tiles fit together when printed. In a 3D viewer, the tiles will fit together without overlaps if tile_centered was set to false.
  • printres: (in mm) Should be set to the nozzle size of your printer typically around the diameter of the nozzle (~0.4 mm). This and the tile width determines the resampled resolution of the DEM raster that is the basis of the mesh. Setting this to significantly smaller than your nozzle size is not advised:

    • Example: if you want your tile to be 80 mm wide and were to set your printres to 0.4 mm, the DEM raster will be re-sampled from its original resolution to the equivalent of 200 cells. If the tile's area is 2000 m wide in reality, each cell would cover 10 m, which is about the original resolution of the DEM source (for NED). It would be silly to ask for a resolution below the original 10m DEM resolution by lowering printres to less than 0.4. This would simple oversample the requested geotiff, resulting in no increase in detail at the cost of longer processing and larger files.
    • Note: setting printres to -1 will set it to the equivalent of the DEM sources original (i.e. non-downsampled) resolution. This sounds great, but is, in practice, somewhat limited as Google Earth Engine will not permit TouchTerrain to request rasters larger than 10 Mega Pixels (typically < 34 Mb). The only sanctioned way for using such large rasters is to run a script in the Earth Engine Code Editor that requests the raster and stores it as a Google Drive file. An example script is given in the appendix. You can then download it to a regular raster file and use it in stand alone mode with the importedDEM setting (see below). Set printres to -1 to prevent downsampling.
  • sqrt: (default: false) if true, will apply the square root to the final elevation and lower it so the smallest value is 0. This is done after applying z-scale and running _leq operations. When also using a very large z-scale (100 - 500) this can help to equalize terrain models that have a wide range of elevations, such as going from sea level to 2000 m peaks. This helps to bring out details in low areas while avoiding un-printably pointy mountains. Will only work with all-positive elevation values, so apply ignore_leq(0) if e.g. cells along a shoreline have negative elevations. In the web app, large z-scales have to be set manually, e.g. "sqrt":true, "zscale":100, "ignore_leq":0

  • tile_centered: (default: false)

    • false: All tiles are offset so they all "fit together" when they all are loaded into a 3D viewer, such as Meshlab or Meshmixer.
    • true: each tile is centered around 0/0. This means they will all overlap in a 3D viewer but each tile is already centered on the buildplate, ready to be printed separately.
  • tilewidth: The width of a tile in mm, tile height will be calculated from the aspect ratio of your area.

  • tilewidth_scale: (default: None). Uses this scale factor to calculate and override the tile width. Ex: a factor of 10000 will divide the real-world width of the area by 10000 and multiply that value by 1000 to arrive at a new tilewidth (in mm). Note that the final x/y scale (reported in the log file) may be slightly different due to some projection adjustments. (New in 3.6.1)

  • unprojected: (default: false). (Works only for exporting GeoTiffs, not for meshes) Normally, the DEM from EE is projected either into the UTM zone of the center of the selected region or into a polar-stereographic projection (m based) for Arctic/Antarctic regions. If this option is true, the raster is left unprojected. This means you will have to figure out a (very large) z-scale to make the result look somewhat realistic!

  • zip_file_name: default: "terrain" Prefix of the output filename for stand-alone. (.zip is added)

  • zscale: (default: 1.0). Vertical exaggeration versus horizontal units.

  • projection: (default: null). By default, the DEM is reprojected to the UTM zone (datum: WGS84) the model center falls into. The EPSG code of that UTM projection is shown in the log file, e.g. UTM 13 N, EPSG:32613. If a number(!) is given for this projection setting, the system will request the Earth Engine DEM to be reprojected into its EPSG code. For example, maybe your data spans 2 UTM zones (13 and 14) and you want UTM 14 to be used, so you set projection to (EPSG) 32614. Or maybe you need to use UTM 13 with NAD83 instead of WGS84, so you use 26913. For continent-size models, WGS84 Web Mercator (EPSG 3857), may work better than UTM. See [https://spatialreference.org/] for descriptions of EPSG codes.

    • Be aware, however, that Earth Engine does not support all possible EPSG codes. For example, North America Lambert Conformal Conic (EPSG 102009) is not supported and gives the error message: The CRS of a map projection could not be parsed. I can't find a list of EPSG codes that are supported by EE, so you'll need to use trial and error ...
    • A note on distances: Earth Engine requires that the requested area is given in lat/lon coordinates but it's worth knowing the approximate real-world meter distance in order to select good values for the tile width, number of tiles and the printres. The server version displays the tile width in Javascript but for the standalone version you need to calculate it yourself. This haversine distance (https://en.wikipedia.org/wiki/Haversine_formula, interactive calculator here: http://www.movable-type.co.uk/scripts/latlong.html) depends on the latitude of your area.
    • Once you know the width of your tile in meters, divide it by the number of cells along x (400 cells in the example above) to get an idea of the re-sampled real-world resolution of your model and its scale. This Help file goes into the interplay of these parameters in the section: Understanding the linkage of tile size, tile number, source DEM resolution and 3D print resolution
  • use_geo_coords: (default: null)

    • with null, x/y coordinates are in mm and refer to the buildplate
    • "UTM" will use meter based UTM x/y coordinates instead. See this for some background. This is useful to import the mesh file into a 3D GIS, such as ArcGIS Pro. Note that, once imported, you will have to set the coordinate system of the mesh manually, b/c the mesh model file can't contain that information. Unless overwritten, this will be a UTM zone with WGS84. The TouchTerrain log file will contain the equivalent EPSG code.
    • "centered" will set the UTM origin to the center of the full tile, this is make it work together with BlenderGIS
  • smooth_borders: (default: true). For rasters with NoData cells, determines if the borders of "islands" should be smoothed by selectively removing certain outer triangles. This makes printing the easier and puts less "rattle" in the motion system. However, if adjacent areas are printed this option should be set to false to prevent gaps between the areas.

GPX Path config

  • importedGPX: list of GPX file paths that are to be plotted on the model (default: null)
  • gpxPathHeight: (default 40) Drape GPX path by adjusting the raster elevation by this value in meters at the specified lat/lon. Negative numbers will create a dent.
  • gpxPixelsBetweenPoints: (default 20) Controls how many pixel distance there should be between points, effectively causing fewer lines to be drawn. A higher number will create more space between lines drawn on the model and can have the effect of making the paths look a bit cleaner at the expense of less precision
  • gpxPathThickness: (default: 5) Stacks that number of parallel lines on either side of primary line to create thickness.

Note on using GPX files: this will simply extrude those pixels covered by a path away from the top surface, i.e. it will not insert proper 90 deg. "walls" for delineating them. To generate a "crisp" path, it may be advisable to use a much higher printres (e.g. 0.2 mm) which allows the extrusion to create steeper (but still non-90 deg.) walls that are more noticeable when 3D printed.

Offset Mask config

  • offset_masks_lower: (default: null) Masked regions (pixel values > 0) in the file will be lowered (same method as GPX extrusion described above) by offset(mm) pixel value in the final model. e.g. [[filename, offset], [filename2, offset2],...]

Unit tests (new in 3.5)

  • The test folder contains a (somewhat simplistic) setup for running unit tests.
  • Each test is defined by a set of input parameters (see above section) and will create a folder (same name as the test) that will contain the resulting files (log, geotiff, STL, etc.) This should make it possible to test (or re-test) specific combination of parameters in the event of a suspected bug.
  • Note that some of these tests "fail" with their parameters b/c the expected effect is not yet implemented E.g. kml files cannot (yet) be used with a local geotiff DEM. These will be flagged as WAI (working as intended)
  • Note that the current set of tests do not capture all possible combinations as there are simply too many. The number of tests will grow over time but will probably never be complete.
  • Running test works by editing test_TouchTerrain_standalone.py and selecting the desired test methods by commenting out its @unittest.skip() decorator that otherwise forces that test to be skipped and then running the .py file main part (inside the test folder!)
  • The test folder also contains a csv file capturing which test uses which parameter settings.

Server version

All server related files are in touchterrain/server

Running TouchTerrain_app.py starts a Flask server module, which will be run inside Apache. Contact us if you want to know about the dockerized Gunicorn version we run at ISU. The server creates a webpage, through which the user inputs the area selection and print parameters.

The server presents users with index.html (in templates), which can be styled to suit your needs, provided the various input dialogs and JavaScript remain. Starting with version 3, it is based on Bootstrap 4.

The config.py file inside the server folder contains server specific config settings:

  • NUM_CORES: 0 means: use all cores, 1 means: use only 1 core (useful for debugging)
  • MAX_CELLS: if the raster has more cells than this number, tempfiles are used instead of memory during the later stages of processing. This is slower but less memory intensive than assembling the entire zip file in memory alone.
  • MAX_CELLS_PERMITED: if the number of cells is bigger than this number, processing is not started. This help to prevents jobs that are so big that the server would start thrashing. It is, however, just a heuristic. Recommended practice is to start a job and see if virtual memory (swapspace) is used and to lower MAX_CELLS_PERMITED until this does not happen.
  • GOOGLE_ANALYTICS_TRACKING_ID is the Google Analytics tracking id that gets inlined into index.html. By default it's our GA id, so be sure to change this to yours or set it to UA-XXXXXXXX to disable tracking.
  • PROJ_DIR: (default: None). Workaround for a OSgeo/GDAL problem with projecting points. This will only matter if you a) run standalone and b) use the GPX path option. Will set the path to a folder that must contain the proj.db database that the point projection needs and store it in an environment variable (PROJ). In some installations, PROJ points to a folder that doesn’t contain proj.db, so use this override to current this issue.

The touchterrain/common directory contains files used by both, the standalone and server versions.

touchterrain/stuff contains, well, stuff, such as pdfs and example data files.

Appendix

Server version (web app)

The server version offers a Google Map interface to select the area and a simple GUI to specify the processing parameters. To run your own server version, an Earth Engine account is needed. It provides a setup.py file that will build and install a module called touchterrain and also install all prerequisites. We recommend using pip for the installation: run 'pip install .' in the same folder as the setup.py file.

More specific details on how to set up and run your own server are beyond the scope of this ReadMe. If you are interested in the nitty-gritty details on how Iowa State IT deploys the server, please contact us.

Getting large geotiffs from Google Earth Engine

  • The example script below shows how to download potentially very large, high resolution geotiffs from Google Earth Engine. It works around Google's 10 mega-pixel download limitation by exporting it to Google Drive instead, from which it can then be downloaded and processed with the standalone version of TouchTerrain.

  • The example area will only create a 1 Mb geotiff but has been shown to work for larger areas. Be warned that exporting large areas to a Google Drive can potentially take hours(!).

  • To run this code, you'll need a Google Earth Engine account. Then, go to https://code.earthengine.google.com/, create a new Script (left side) and copy/paste the code below into it.

  • You will need to know the designation for the DEM source (e.g. JAXA/ALOS/AW3D30/V2_2) and what the elevation band is called (e.g. AVE_DSM) which you can get from the Explore in Earth Engine code snippet you get from the DEM info link on the web app example. This will also tells you the meter resolution of the DEM, which is the smallest number you can put into the scale parameter of the Export routine.

  • To get the lat/long coordinates of the top right and bottom left corner of your print area box, use the web app and look at the coordinate info in the Area selection box.

  • Finally you'll need to know the EPSG code for the coordinate system to use. For UTM, just export a low res version of the are you want with the web app and look into the log file (search for EPSG). Other coordinate systems (EPSG codes) can/may/should work, just remember that some codes seem to not be supported by EE.

  • When you run the script you'll get a simple map visualization and a new Task will be created in the Tasks tab (right). RUN this task to have Google save the geotiff into your Google Drive. If you want, you can still change the file name and the resolution at this stage. Hit Run one more to start the job. Again, this job may take a long time when exporting large areas.

  • When the job is done, you'll see a check mark for your task. Click on the question mark and a popup will appear, hit Open in Drive. In Google Drive, download the geotiff.

  • Run TouchTerrain in standalone mode and set the importDEM parameter to your geotiff. To use the actual (source) resolution of the geotiff for generating your model, set printres to -1.

// Example of exporting a raster from EE to Google Drive (Jan. 2021)

// You will need the corner coords, which you can get from the Area Selection Box display
// on the web app and the EPSG code for whatever projection you want to use. If you want
// to use a UTM zon, look at the log file from the web app.
// You also should know the source resolution of your DEM so you can set the scale parameter
// of the export to it.


// Set DEM source  
var dataset = ee.Image('JAXA/ALOS/AW3D30/V2_2');
var elevation = dataset.select('AVE_DSM');
print(elevation); // print some metadata into console

// make a spectral color scheme for elevation data layer
var elevationVis = { 
  min: 0,
  max: 4000,
  palette: ['0000ff', '00ffff', 'ffff00', 'ff0000', 'ffffff'],
  opacity: 0.5,
};
Map.addLayer(elevation, elevationVis, 'Elevation');

// define area to export and show as box layer
var trlat = 46.78374215384358
var trlon = 8.071201291153262
var bllat = 46.63448889213306
var bllon = 7.574375128591488
var geometry = ee.Geometry.Rectangle([ trlon, trlat, bllon, bllat ]);
Map.addLayer(geometry, {'opacity': 0.5}, 'box');  

// Fly to center of Box
Map.setCenter(
  trlon - ((trlon - bllon) / 2), 
  trlat - ((trlat - bllat) / 2), 
  8 // zoomlevel
);

// Export the image, specifying scale and region.
// https://developers.google.com/earth-engine/guides/exporting
Export.image.toDrive({
  image: elevation,
  description: 'EE_to_Google_Drive_example', // name of geotiff (.tif will be added)
  fileFormat: 'GeoTIFF',
  scale: 30, // resolution in meters
  maxPixels: 1e12, // overwrites the default of 1e08
  region: geometry,
  crs: "EPSG:32632" // EPSG code for the UTM zone or whatever coordinate system you want to use
});

// When this code is run, an export task will be created in the Code Editor Tasks tab. 
// Click the Run button next to the task to start it. 
// The image will be created in your Drive account with the specified fileFormat.

touchterrain_for_cageo's People

Contributors

ansonl avatar atrevarrow avatar baberlevi avatar chharding avatar dpy102 avatar glidersharma avatar kohlhardtc avatar mdezube avatar njbooher avatar r-barnes avatar thomaspe avatar trainerred151 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

touchterrain_for_cageo's Issues

Set base hight in reference to Vertical datum

if you want to manually create adjacent tiles they can't be set to a common base height.
The best solution would be an option that allows the following: that the lowest point of the tile is not referenced to base height but base height plus the height that this point is above the Vertical datum.

My goal is to print many tiles to have more or less a wall with a mountain range relief on it (lager than 1m²) and the maximum file size limit would compromise the quality drastically.

Standalone Python Library only using one core

Hi at all

Firstly thank you for developing and maintaining such a great project. I am really enjoying it.
My issue is, that although I set the CPU_cores_to_use argument to 8 the script is still using only one core. It also logs using single-core only.

Is there a setting I am missing or what would be the steps to enable the script to use more than one core?

Thanks and have a nice one

MemoryError: Unable to allocate 330. GiB for an array with shape (641646, 137974) and data type float32

I'm trying to run TT in the docker notebook against an Aussie DEM. The DEM was sourced from Geosciences Australia and seems to load into the map without issues.

Here is a code that reproduces the problem:

from geojson import Polygon
poly = Polygon([[[145.147961, -37.874657], [145.146262, -37.874848], [145.144699, -37.875406], [145.143395, -37.876287], [145.142454, -37.87742], [145.141952, -37.878715], [145.141928, -37.880069], [145.142384, -37.881375], [145.143285, -37.882528], [145.144557, -37.883437], [145.146101, -37.884029], [145.147792, -37.884257], [145.149497, -37.884103], [145.15108, -37.88358], [145.152415, -37.882728], [145.153394, -37.881616], [145.153942, -37.880332], [145.154013, -37.878979], [145.153602, -37.877664], [145.152743, -37.876491], [145.151503, -37.875555], [145.149981, -37.87493], [145.148298, -37.874665], [145.147961, -37.874657]]])
args = {'importedDEM': '/data/nationalz55_ag.tif', 'DEM_name': 'JAXA/ALOS/AW3D30/V2_2', 'bllat': -37.88327658196921, 'bllon': 145.13953117216852, 'trlat': -37.87247077823912, 'trlon': 145.15559581602838, 'tilewidth': 200, 'printres': 0.4, 'ntilesx': 1, 'ntilesy': 1, 'basethick': 1, 'zscale': 3, 'fileformat': 'STLb', 'zip_file_name': 'myterrain', 'tile_centered': False, 'CPU_cores_to_use': 0, 'max_cells_for_memory_only': 5002, 'no_bottom': False, 'no_normal': True, 'bottom_image': None, 'ignore_leq': None, 'lower_leq': None, 'unprojected': False, 'projection': None, 'only': None, 'importedGPX': [], 'polygon': poly}
from touchterrain.common import TouchTerrainEarthEngine as TouchTerrain

totalsize, full_zip_file_name = TouchTerrain.get_zipped_tiles(**args) # args are in a dict
print("\nDONE!\n\nCreated zip file", full_zip_file_name,  "%.2f" % totalsize, "Mb")

This produces:

INFO:root:EE init() worked with .config/earthengine/credentials
INFO:root:Using GeoJSON polygon for masking with 24 points
INFO:root:Log for creating 1 x 1 3D model tile(s) from nationalz55_ag.tif 
 
INFO:root:started: 08:18:47.116651 
Log for creating 1 x 1 3D model tile(s) from nationalz55_ag.tif 
 
started: 08:18:47.116651 
---------------------------------------------------------------------------
MemoryError                               Traceback (most recent call last)
Cell In[1], line 6
      3 args = {'importedDEM': '/data/nationalz55_ag.tif', 'DEM_name': 'JAXA/ALOS/AW3D30/V2_2', 'bllat': -37.88327658196921, 'bllon': 145.13953117216852, 'trlat': -37.87247077823912, 'trlon': 145.15559581602838, 'tilewidth': 200, 'printres': 0.4, 'ntilesx': 1, 'ntilesy': 1, 'basethick': 1, 'zscale': 3, 'fileformat': 'STLb', 'zip_file_name': 'myterrain', 'tile_centered': False, 'CPU_cores_to_use': 0, 'max_cells_for_memory_only': 5002, 'no_bottom': False, 'no_normal': True, 'bottom_image': None, 'ignore_leq': None, 'lower_leq': None, 'unprojected': False, 'projection': None, 'only': None, 'importedGPX': [], 'polygon': poly}
      4 from touchterrain.common import TouchTerrainEarthEngine as TouchTerrain
----> 6 totalsize, full_zip_file_name = TouchTerrain.get_zipped_tiles(**args) # args are in a dict
      7 print("\nDONE!\n\nCreated zip file", full_zip_file_name,  "%.2f" % totalsize, "Mb")

File /TouchTerrain/standalone/touchterrain/common/TouchTerrainEarthEngine.py:973, in get_zipped_tiles(DEM_name, trlat, trlon, bllat, bllon, polygon, polyURL, poly_file, importedDEM, printres, ntilesx, ntilesy, tilewidth, basethick, zscale, fileformat, tile_centered, CPU_cores_to_use, max_cells_for_memory_only, temp_folder, zip_file_name, no_bottom, bottom_image, ignore_leq, lower_leq, unprojected, only, original_query_string, no_normals, projection, use_geo_coords, importedGPX, gpxPathHeight, gpxPixelsBetweenPoints, gpxPathThickness, map_img_filename, smooth_borders, offset_masks_lower, fill_holes, min_elev, **otherargs)
    971 dem = gdal.Open(importedDEM)
    972 band = dem.GetRasterBand(1)
--> 973 npim = band.ReadAsArray().astype(numpy.float64)
    975 # Read in offset mask file
    976 # offset_npim = [] # Define offset_npim in parent scope before importedDEM "if statement" to avoid python unbound error
    977 if offset_masks_lower is not None:

File /usr/local/lib/python3.10/site-packages/osgeo/gdal.py:4142, in Band.ReadAsArray(self, xoff, yoff, win_xsize, win_ysize, buf_xsize, buf_ysize, buf_type, buf_obj, resample_alg, callback, callback_data)
   4137 """ Reading a chunk of a GDAL band into a numpy array. The optional (buf_xsize,buf_ysize,buf_type)
   4138 parameters should generally not be specified if buf_obj is specified. The array is returned"""
   4140 from osgeo import gdal_array
-> 4142 return gdal_array.BandReadAsArray(self, xoff, yoff,
   4143                                    win_xsize, win_ysize,
   4144                                    buf_xsize, buf_ysize, buf_type, buf_obj,
   4145                                    resample_alg=resample_alg,
   4146                                    callback=callback,
   4147                                    callback_data=callback_data)

File /usr/local/lib/python3.10/site-packages/osgeo/gdal_array.py:428, in BandReadAsArray(band, xoff, yoff, win_xsize, win_ysize, buf_xsize, buf_ysize, buf_type, buf_obj, resample_alg, callback, callback_data)
    426     if buf_type == gdalconst.GDT_Byte and band.GetMetadataItem('PIXELTYPE', 'IMAGE_STRUCTURE') == 'SIGNEDBYTE':
    427         typecode = numpy.int8
--> 428     buf_obj = numpy.empty([buf_ysize, buf_xsize], dtype=typecode)
    430 else:
    431     if len(buf_obj.shape) not in (2, 3):

MemoryError: Unable to allocate 330. GiB for an array with shape (641646, 137974) and data type float32

Output min and max elevations within generated output

On the output page that lists the parameters used for generation, I would like to request that you also output the minimum and maximum elevations within the data set. That provides the information necessary to determine the actual Z-scaling used if the data is scaled to a fixed height, as well as the base offset elevation. I'm working on a small program to generate topographic elevation lines from the data set to laser etch them into a CNC'd topographic relief, and need that info to get the line labels right. Very much a work in progress, see: https://github.com/doug-harriman/topo-box

gcloud not available from within the dev container

I'm trying to run the project from within the dev container, using vs code on a windows machine. When I open a terminal in the dev container, it doesn't recognize gcloud as a command. This (seems to be) getting in the way of authenticating with earth engine. Is my container set up improperly? Is the gcloud command not necessary within the container?

STL not watertight

I noticed that the STL created by Touchterrain isn't watertight, therefore giving me errors in most tools I import the model. The tools are usually able to fix the issue (e.g. Microsoft 3D Builder, Fusion 360) but having a correct STL returned would obviously be better.

This can also be confirmed programatically using trimesh:

import trimesh
data = trimesh.load('/workspaces/map2stl/test/V2_2_11.18_48.01_tile_1_1.STL')
print(data.is_watertight)

I started looking into why that is but wanted to track it here early in case this is a known issue.

Preview .STL file in notebook while running in Docker

In the notebook TouchTerrain_jupyter_for_starters.ipynb it mentions the following in the Preview the model section:

Dec. 8, 2022: This may not work when run inside Docker ...

I found that all a user needs to do is run the following commands within the docker container before launching the notebook:

jupyter nbextension install --py --user k3d
jupyter nbextension enable --py --user k3d

Source: K3D-tools/K3D-jupyter#324 (comment)

ValueError: cannot set WRITEABLE flag to True of this array

Any thoughts on why I am getting "ValueError: cannot set WRITEABLE flag to True of this array"?

ValueError Traceback (most recent call last)
in
4 # This may take some time! You'll see In[*] and some log messages (will also be in the logfile inside the zip)
5 # You may see some red stuff with 10%, etc. - don't worry, that's normal
----> 6 totalsize, full_zip_file_name = TouchTerrain.get_zipped_tiles(**args) # all args are in a dict
7 print("\nDONE!\n\nCreated zip file", full_zip_file_name, "%.2f" % totalsize, "Mb")
8

~\Downloads\TouchTerrain_for_CAGEO-master\common\TouchTerrainEarthEngine.py in get_zipped_tiles(DEM_name, trlat, trlon, bllat, bllon, importedDEM, printres, ntilesx, ntilesy, tilewidth, basethick, zscale, fileformat, tile_centered, CPU_cores_to_use, max_cells_for_memory_only, temp_folder, zip_file_name, no_bottom, bottom_image, ignore_leq, unprojected, only, original_query_string, no_normals, projection, **otherargs)
780 cell_size_m *= scale_factor
781 pr(" ",npim.shape[::-1], adjusted_print3D_resolution, "mm ", cell_size_m, "m ", numpy.nanmin(npim), "-", numpy.nanmax(npim), "m")
--> 782 npim.flags.writeable = True # not sure why it's not writeable after the PIL interpolation but this fixes it
783
784 if adjusted_print3D_resolution != print3D_resolution:

ValueError: cannot set WRITEABLE flag to True of this array

Error Message when using AW3D30

Hello guys,

not sure if this is the right place to ask but whenever I try to create a model using the AW3D30 database, I get the following error message:

Error: ImageCollection.load: Expected asset 'JAXA/ALOS/AW3D30/V2_2' to be an ImageCollection, found 'Image'.

The error does not appear when I change back to USGS and leave all the other parameters the same.

Does someone know how to fix this? Thank you!

Type in Coordinates

I would like the ability to type in coordinates for fine-tuning rather than rely on the dragging the box on the map. I will try to implement when I have time and create a pull request. Thanks!

Website is down

Just wanted to point out that the site has been down for a week or two. I miss being able to use touchterrain. Will it be coming back online, or do I need to install it locally?

Inconsistent GPX track width

When adding a gpx track, the algorithm for stacking multiple lines to produce a single thick track produces inconsistent results depending on the direction of the line.

For example:

image

As you can see, NW-SE portions are very thin (no added thickness) whereas SW-NE parts are fine.

I have created a PR to improve this: #75

With the new version, the same track looks like this:

image

Still not perfect, but I think an improvement.

(BTW, thanks for creating this open-source project 👍)

Issue while reading custom config file: importedDEM not recognized

Issue:
ImportedDEM not working with my custom config file.

Using the same string ["importedDEM": "./stuff/pyramid.tif",] in my "custom" config file doesnt work and sets the importedDEM to None, but when using the default layout from [example_config.json] the importedDEM is used successfully.

reading atiff.json

Using these config values:
...
importedDEM = None
...

I have moved some things around in my config files since I usually only edit a few items. I believe something about this structure breaks the importedDEM feature.

file is structured as following:

{
"zip_file_name": "attempt1",
"importedDEM": "./stuff/pyramid.tif",
"DEM_name": "JAXA/ALOS/AW3D30/V2_2",
"printres": 0.5,
"tilewidth": 275,
"ntilesx": 1,
"ntilesy": 1,

"trlat": 46.13101542129134,
"trlon": 7.839429301234198,
"bllat": 45.94432505455063,
"bllon": 7.593839091273287,

"trlat": 45.98389420078675,
"trlon": 7.669536937449504,
"bllat": 45.967530444713745,
"bllon": 7.64599071857746,

"zscale": 1,
"basethick": 1.5,




"importedGPX": [],
"gpxPathHeight": -150,
"gpxPathThickness": 4,
"gpxPixelsBetweenPoints": 1,

"CPU_cores_to_use": 0,
"bottom_image": null,
"fileformat": "STLb",
"fill_holes": null,
"ignore_leq": null,
"importedDEM": null,
"lower_leq": null,
"max_cells_for_memory_only": 100000000000000000000,
"no_bottom": false,
"offset_masks_lower": null,
"only": null,
"polyURL": null,
"poly_file": null,
"smooth_borders": true,
"tile_centered": false,
"unprojected": false
}

Combine Terrain with CityGML

hey, really love your tool!
Lately I was investigating on how to best combine terrain models (geotiff) with CityGML or CityJSON files. Since I'm new to Python I wanted to hear your thoughts on how to best approach this and perhaps contribute back to this codebase.

I tried combining seperately generated STLs (using cjio for the CityJSON model) afterwards with somewhat okayish results but that was a lot of work and error-prone.

I'm wondering if integrating the model generation into the TouchTerrain workflow would be the best approach (similar to how the GPX addition works), but I'm worried it might not be a simple as that as the addition of CityGML would potentially introduce holes to the model (thinking of bridges, for example).

The other approach would be to combine the STLs programatically later, however that would probably be also difficult to properly align all parts when the Geo-Data isn't there anymore.

Is there maybe something obivious I'm missing? Seems like there's a reason why not many tools (only found 1 tbh) can do this kind of merge already.

EE Limit hit... Is there a workaround?

I am trying to generate a fairly heavy STL set. This is my following config:

{
"CPU_cores_to_use": 4,
"DEM_name": "JAXA/ALOS/AW3D30/V2_2",
"basethick": 5,
"bottom_image": null,
"fileformat": "STLb",
"ignore_leq": null,
"importedDEM": null,
"lower_leq": null,
"max_cells_for_memory_only": 25000000,
"no_bottom": false,
"ntilesx": 6,
"ntilesy": 3,
"only": null,
"printres": 0.2,
"tile_centered": false,
"tilewidth": 200,
"unprojected": false,
"zip_file_name": "terrain",
"zscale": 1.0,
"trlat": 47.81622262056006,
"trlon": 10.519218241500798,
"bllat": 45.805185338248926,
"bllon": 5.926325117874116
}

Now the web version says this is too big to process. So I tried doing it locally via python (made an EE account and everything). Using the local python version I get:

lon/lat size in degrees: [4.592893123626682, 2.011037282311136]
INFO:root:lon/lat size in degrees: [4.592893123626682, 2.011037282311136]
requesting 58.42479269311229 m resolution from EarthEngine
Earth Engine raster: JAXA/ALOS/AW3D30/V2_2
INFO:root:Earth Engine raster: JAXA/ALOS/AW3D30/V2_2
 ALOS DSM: Global 30m
INFO:root: ALOS DSM: Global 30m
Traceback (most recent call last):
  File "/usr/local/anaconda3/lib/python3.8/site-packages/ee/data.py", line 330, in _execute_cloud_call
    return call.execute(num_retries=num_retries)
  File "/usr/local/anaconda3/lib/python3.8/site-packages/googleapiclient/_helpers.py", line 134, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/local/anaconda3/lib/python3.8/site-packages/googleapiclient/http.py", line 915, in execute
    raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://earthengine.googleapis.com/v1alpha/projects/earthengine-legacy/thumbnails?fields=name&alt=json returned "Total request size (95398144 bytes) must be less than or equal to 33554432 bytes.">

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "TouchTerrain_standalone.py", line 253, in <module>
    main()
  File "TouchTerrain_standalone.py", line 208, in main
    totalsize, full_zip_file_name = TouchTerrain.get_zipped_tiles(**args) # all args are in a dict
  File "/Users/lukaszirngibl/Desktop/TouchTerrain_for_CAGEO/touchterrain/common/TouchTerrainEarthEngine.py", line 692, in get_zipped_tiles
    request = image1.getDownloadUrl(request_dict)
  File "/usr/local/anaconda3/lib/python3.8/site-packages/ee/deprecation.py", line 32, in Wrapper
    return func(*args, **kwargs)
  File "/usr/local/anaconda3/lib/python3.8/site-packages/ee/image.py", line 435, in getDownloadURL
    return data.makeDownloadUrl(data.getDownloadId(request))
  File "/usr/local/anaconda3/lib/python3.8/site-packages/ee/data.py", line 888, in getDownloadId
    result = _execute_cloud_call(
  File "/usr/local/anaconda3/lib/python3.8/site-packages/ee/data.py", line 332, in _execute_cloud_call
    raise _translate_cloud_exception(e)
ee.ee_exception.EEException: Total request size (95398144 bytes) must be less than or equal to 33554432 bytes.

So this seems to be some sort of limit EE..

Then I tried to doing the tiles individually but that is causing all sorts of headaches because the tiles don’t quite line up (even though I’m computing all the correct lat/lon coordinates for each tile).

Any ideas on how I can fix this? Thank you so much for you time. Any help at all would be greatly appreciated :)

STL top max value not scaling correctly

I'm running the standalone Jupyter notebook version inside of the docker container. I downloaded 2 (because the mountain I'm interested in, Pikes Peak, falls right on the boundary) GeoTIFF files on the USGS website from the 3DEP program, merged them using QGIS, and then extracted just the area I wanted into a new GeoTIFF file. When I run the python code, it seems to mess up the scaling and the top max value for the model ends up being like 2000m. So the resulting dimensions of the STL object end up as 300mm x 300mm x 2000000mm. Looking at the log files from other issues submitted here, it seems like the problem might be that the code is interpreting the lat/long values of the raster file as x/y values, hence messing up the scaling.

Log for creating 1 x 1 3D model tile(s) from pikes_peak_area.tif 
 
started: 20:17:59.980281 
Warning: raster cells are not square (9.259300388672895e-05x9.259341472438034e-05) , using9.259300388672895e-05
source raster upper left corner (x/y):  -106.00056 39.00056 
source raster cells size 9.259300388672895e-05 m  (10812, 21612) 
projection: WGS 84 
z-scale: 1 
basethickness: 0.5 
fileformat: STLb 
tile_centered: False 
no_bottom: True 
no_normals: True 
ignore_leq: None 
lower_leq: None 
importedGPX: ['stuff/Pikes_Peak_via_Barr_Trail.gpx'] 
undefined GDAL value: -3.4028234663852886e+38 
process gpx file: stuff/Pikes_Peak_via_Barr_Trail.gpx 
1 GPX tracks found 
Plotting track 1 
Time to add GPX paths:1.0155231952667236 
tile_width: 300 
tile_height: 150.08328706274293 
source raster width 2.001119999999986 m, cell size: 9.259300388672895e-05 m, elev. min/max is -5.369226455688477 65753.40625 m 
source raster 3D print resolution would be 0.0138811771238201 mm 
re-sampling scaled.tif :
  (21612, 10812) 0.0138811771238201 mm  9.259300388672895e-05 m  -5.369226455688477 - 65753.40625 m to 
  (1499, 750) 0.200133422281521 mm  0.0013340799999999908 m  0.0009282126 - 65534.996 m 
after resampling, requested print res was adjusted from 0.2 to 0.200133422281521 to ensure correct model dimensions 
map scale is 1 : 6.665953066666621 
Cells per tile (x/y) 1499 x 750 
using single-core only (multi-core is currently broken :( 

1 x 1 tiles, tile size 300.00 x 150.10 mm
 
tile 1 1 : height:  0.0009282126 - 9831302.0 mm , file size: 108 Mb 

total size for all tiles: 108 Mb 

processing finished: 20:18:23.266631 

[Errno 12] Cannot allocate memory

I don't know much of coding, but I do not know how to get around this error. I do not think it is my computer's problem either but will gladly try and solution or idea anyone has. It is not letting me create any models at this moment
screenshot 212
.

Thanks!

Max File Size Setting

I managed to get the standalone TouchTerrain server running on my Ubuntu 22.04 server and I'm able to use it just like the public site, including the size limits of the files. I was hoping with this standalone servers I could generate files above the limit of the public site to create very large 3d printed maps. Where can I find the setting to change the size limit? And what would be a reasonable limit to set it to so I don't crash my system or fill my SSD in one go, this is a fairly beefy system, 12 xeon gold cores and 32gb of ram with a 100gb NVMe SSD.

ImportError: No module named ee

Upon running TouchTerrain_standalone.py with Python2.7, I get this error:

Traceback (most recent call last):
  File "TouchTerrain_standalone.py", line 85, in <module>
    import config # this needs to be set up for your dev account and needs a .pem file
  File "/z/TouchTerrain_for_CAGEO/config.py", line 5, in <module>
    from ee import oauth
ImportError: No module named ee

Allow lowering of water

Add a configuration option to lower the height of oceans for emphasis? I wouldn't mind helping to implement this if someone could point me in the right direction

How do I get started?

The ReadMe.md file does not give users a very good idea about which of 7 python files to run, or what they do. Configuration is apparently necessary, but not well-described by the readme.

[feature-request] requirements.txt

Love the flask-webapp!

Would it be possible to add your requirements.txt to make the installation nice and easy in a virtualenv?

Thanks!

Issue with area selection on custom data of lake Constance

I am trying to extract a part of lake Constance, but I always get STLs of the complete lake instead of the selected area.

Maybe someone can help with choosing the correct input model and/or better defining the area. I guess that maybe the input data is not global coordinate based or something like that.

Data is available here:

https://doi.pangaea.de/10.1594/PANGAEA.855987?format=html#download

Would appreciate any help, project is awsome anyway!

INFO:root:Log for creating 1 x 1 3D model tile(s) from LC_All_20151208_ETRS89_10m_ac_int.asc 
 
INFO:root:started: 14:00:02.099580 
Log for creating 1 x 1 3D model tile(s) from LC_All_20151208_ETRS89_10m_ac_int.asc 
 
started: 14:00:02.099580 
INFO:root:source raster upper left corner (x/y):  487600.0 5297000.0 
INFO:root:source raster cells size 10.0 m  (4000, 6990) 
INFO:root:projection:  
INFO:root:z-scale: 1 
INFO:root:basethickness: 3 
INFO:root:fileformat: STLb 
INFO:root:tile_centered: False 
INFO:root:no_bottom: False 
INFO:root:no_normals: True 
INFO:root:ignore_leq: None 
INFO:root:lower_leq: None 
INFO:root:importedGPX: [] 
INFO:root:undefined GDAL value: -9999.0 
source raster upper left corner (x/y):  487600.0 5297000.0 
source raster cells size 10.0 m  (4000, 6990) 
projection:  
z-scale: 1 
basethickness: 3 
fileformat: STLb 
tile_centered: False 
no_bottom: False 
no_normals: True 
ignore_leq: None 
lower_leq: None 
importedGPX: [] 
undefined GDAL value: -9999.0 
INFO:root:tile_width: 750 
INFO:root:tile_height: 429.1845493562232 
INFO:root:source raster width 69900.0 m, cell size: 10.0 m, elev. min/max is 190.63699340820312 611.9719848632812 m 
INFO:root:source raster 3D print resolution would be 0.1072961373390558 mm 
tile_width: 750 
tile_height: 429.1845493562232 
source raster width 69900.0 m, cell size: 10.0 m, elev. min/max is 190.63699340820312 611.9719848632812 m 
source raster 3D print resolution would be 0.1072961373390558 mm 
INFO:root:re-sampling LC_All_20151208_ETRS89_10m_ac_int.asc :
  (6990, 4000) 0.1072961373390558 mm  10.0 m  190.63699340820312 - 611.9719848632812 m to 
re-sampling LC_All_20151208_ETRS89_10m_ac_int.asc :
  (6990, 4000) 0.1072961373390558 mm  10.0 m  190.63699340820312 - 611.9719848632812 m to 
INFO:root:  (1875, 1072) 0.4 mm  37.28 m  190.63815 - 583.76794 m 
INFO:root:print res is 0.4 mm 
INFO:root:map scale is 1 : 93200.0 
INFO:root:Cells per tile (x/y) 1875 x 1072 
INFO:root:using single-core only 
  (1875, 1072) 0.4 mm  37.28 m  190.63815 - 583.76794 m 
print res is 0.4 mm 
map scale is 1 : 93200.0 
elev min/max : 190.64 to 583.77
Cells per tile (x/y) 1875 x 1072 
using single-core only 
processing tile: 1 1
top min/max: 3.0 7.2181306
creating internal triangle data structure for <_MainProcess name='MainProcess' parent=None started>
10 % <_MainProcess name='MainProcess' parent=None started>
20 % <_MainProcess name='MainProcess' parent=None started>
30 % <_MainProcess name='MainProcess' parent=None started>
40 % <_MainProcess name='MainProcess' parent=None started>
50 % <_MainProcess name='MainProcess' parent=None started>
60 % <_MainProcess name='MainProcess' parent=None started>
70 % <_MainProcess name='MainProcess' parent=None started>
80 % <_MainProcess name='MainProcess' parent=None started>
90 % <_MainProcess name='MainProcess' parent=None started>
100% <_MainProcess name='MainProcess' parent=None started> 

Writing tile into temp. file /TouchTerrain/standalone/tmp/myterrain11.tmp
assembling binary stl from 1779772 triangles  tmp/myterrain11.tmp
10 %, 20 %, 30 %, 40 %, 50 %, 60 %, 70 %, 80 %, 90 %, 100 %, 

tile 1 1 STLb 84.8662223815918 Mb 
INFO:root:
1 x 1 tiles, tile size 750.00 x 428.80 mm
 
INFO:root:tile 1 1 : height:  3.0 - 7.2181306 mm , file size: 85 Mb 
INFO:root:
total size for all tiles: 85 Mb 
INFO:root:
processing finished: 14:00:53.361382 

1 x 1 tiles, tile size 750.00 x 428.80 mm
 
tile 1 1 : height:  3.0 - 7.2181306 mm , file size: 85 Mb 

total size for all tiles: 85 Mb 
zip finished: 14:00:53.361324

processing finished: 14:00:53.361382 

DONE!

Created zip file tmp/myterrain.zip 84.87 Mb
´´´

[Suggestion] Define Scale instead of bed size

It could be interesting to set a scale factor instead of defining the bed size. This would allow the layer lines to convey meaningful information. While the math for this can be done manually, it is difficult when using KMLs.

Misaligned Tiles

Hey Chris,

I seem to be getting misaligned tiles when generating.

Aligned bottom:
Screen Shot 2023-04-03 at 15 57 57

Aligned ridge (misaligned bottom):
Screen Shot 2023-04-03 at 16 02 43

My config:

          "trlat": 47.88266953319475,# bottom left corner lat
          "trlon": 10.707753906131003,# bottom left corner long
          "bllat": 45.62561851186426, #top right corner lat
          "bllon": 5.813401946902514,# top right corner long
          "importedDEM": "./data.tif", # if not None, the raster file to use as DEM instead of using GEE (null in JSON)
          "printres": 0.5,  # resolution (horizontal) of 3D printer (= size of one pixel) in mm
          "ntilesx": 9,      # number of tiles in x and y
          "ntilesy": 6,
          "tilewidth": 100, # width of each tile in mm (<- !!!!!), tile height is calculated
          "basethick": 15, # thickness (in mm) of printed base
          "zscale": 1.0,      # elevation (vertical) scaling
          "fileformat": "STLb",  # format of 3D model files: "obj" wavefront obj (ascii),"STLa" ascii STL or "STLb" binary STL
          "tile_centered": False, # True-> all tiles are centered around 0/0, False, all tiles "fit together"
          "zip_file_name": "alps",   # base name of zipfile, .zip will be added
          "CPU_cores_to_use" : 0,  # 0 means all cores, None (null in JSON!) => don't use multiprocessing
          "max_cells_for_memory_only" : 1000 * 1000, # if raster is bigger, use temp_files instead of memory
          "no_bottom": False, # omit bottom triangles?
          #"rot_degs": 0, # rotate by degrees ccw  # CH disabled for now
          "bottom_image": None,  # 1 band greyscale image used for bottom relief
          "ignore_leq": None, # set values <= this to NaN, so they are ignored
          "lower_leq": None,  # e.g. [0.0, 2.0] values <= 0.0 will be lowered by 2mm in the final model
          "unprojected": False, # don't project to UTM, only usefull when using GEE for DEM rasters
          "only": None,# list of tile index [x,y] with is the only tile to be processed. None means process all tiles (index is 1 based)
          "poly_file": None, #"idaho.kml", #TT_poly_test.kml",
          "smooth_borders": True, # smooth borders

logfile:

Log for creating 9 x 6 3D model tile(s) from data.tif 
 
started: 16:25:38.556908 
source raster upper left corner (x/y):  229110.0 5305650.0 
source raster cells size 30.0 m  (7769, 13815) 
projection: WGS 84 / UTM zone 32N 
z-scale: 1.3 
basethickness: 15 
fileformat: STLb 
tile_centered: False 
no_bottom: False 
no_normals: True 
ignore_leq: None 
lower_leq: None 
importedGPX: None 
undefined GDAL value: None 
tile_width: 100 
tile_height: 56.23597538906985 
source raster width 414450.0 m, cell size: 30.0 m, elev. min/max is 40.0 4809.0 m 
source raster 3D print resolution would be 0.06514657980456026 mm 
re-sampling data.tif :
  (13815, 7769) 0.06514657980456026 mm  30.0 m  40.0 - 4809.0 m to 
  (1800, 1012) 0.5 mm  230.25 m  59.468372 - 4736.3257 m 
print res is 0.5 mm 
Cropping for nice fit of 9 (width) x 6 (height) tiles, removing: 0 columns, 4 rows 
 cropped (1800, 1012) to (1800, 1008) 
 cropping changed physical size from 100 mm x 84.33333333333333 mm 
 to 100.0 mm x 84.0 mm 
map scale is 1 : 460500.0 
Cells per tile (x/y) 200 x 168 
using single-core only 

9 x 6 tiles, tile size 100.00 x 84.00 mm
 
tile 1 1 : height:  191.6655 - 15.802115 mm , file size: 3 Mb 
tile 1 2 : height:  183.84213 - 15.860547 mm , file size: 3 Mb 
tile 1 3 : height:  191.79538 - 17.04288 mm , file size: 3 Mb 
tile 1 4 : height:  195.88974 - 18.080755 mm , file size: 3 Mb 
tile 1 5 : height:  291.8095 - 18.951483 mm , file size: 3 Mb 
tile 1 6 : height:  225.69896 - 19.047348 mm , file size: 3 Mb 
tile 2 1 : height:  206.6946 - 16.24718 mm , file size: 3 Mb 
tile 2 2 : height:  216.4829 - 17.125134 mm , file size: 3 Mb 
tile 2 3 : height:  318.2327 - 18.50724 mm , file size: 3 Mb 
tile 2 4 : height:  368.91043 - 18.62294 mm , file size: 3 Mb 
tile 2 5 : height:  366.321 - 19.982578 mm , file size: 3 Mb 
tile 2 6 : height:  427.32034 - 21.141172 mm , file size: 3 Mb 
tile 3 1 : height:  246.68542 - 17.778305 mm , file size: 3 Mb 
tile 3 2 : height:  297.28238 - 17.79468 mm , file size: 3 Mb 
tile 3 3 : height:  422.0 - 18.236658 mm , file size: 3 Mb 
tile 3 4 : height:  369.37585 - 20.451563 mm , file size: 3 Mb 
tile 3 5 : height:  365.57553 - 22.839916 mm , file size: 3 Mb 
tile 3 6 : height:  454.22202 - 27.088457 mm , file size: 3 Mb 
tile 4 1 : height:  197.90182 - 18.331402 mm , file size: 3 Mb 
tile 4 2 : height:  257.0738 - 18.244726 mm , file size: 3 Mb 
tile 4 3 : height:  427.58197 - 17.398708 mm , file size: 3 Mb 
tile 4 4 : height:  528.4612 - 22.796164 mm , file size: 3 Mb 
tile 4 5 : height:  477.08356 - 24.418552 mm , file size: 3 Mb 
tile 4 6 : height:  845.9084 - 25.337296 mm , file size: 3 Mb 
tile 5 1 : height:  282.0828 - 18.356377 mm , file size: 3 Mb 
tile 5 2 : height:  286.19427 - 16.958464 mm , file size: 3 Mb 
tile 5 3 : height:  393.76727 - 21.491447 mm , file size: 3 Mb 
tile 5 4 : height:  470.08173 - 25.131504 mm , file size: 3 Mb 
tile 5 5 : height:  310.43695 - 25.670383 mm , file size: 3 Mb 
tile 5 6 : height:  191.5922 - 26.507986 mm , file size: 3 Mb 
tile 6 1 : height:  342.41873 - 16.677013 mm , file size: 3 Mb 
tile 6 2 : height:  355.72488 - 17.600143 mm , file size: 3 Mb 
tile 6 3 : height:  350.1448 - 22.64892 mm , file size: 3 Mb 
tile 6 4 : height:  453.6622 - 23.638344 mm , file size: 3 Mb 
tile 6 5 : height:  191.46535 - 23.769928 mm , file size: 3 Mb 
tile 6 6 : height:  173.82703 - 20.547045 mm , file size: 3 Mb 
tile 7 1 : height:  384.13315 - 16.263924 mm , file size: 3 Mb 
tile 7 2 : height:  391.51416 - 20.61398 mm , file size: 3 Mb 
tile 7 3 : height:  419.2372 - 22.603453 mm , file size: 3 Mb 
tile 7 4 : height:  564.86 - 22.121048 mm , file size: 3 Mb 
tile 7 5 : height:  181.94656 - 23.711742 mm , file size: 3 Mb 
tile 7 6 : height:  180.76138 - 21.588915 mm , file size: 3 Mb 
tile 8 1 : height:  401.62704 - 18.00505 mm , file size: 3 Mb 
tile 8 2 : height:  391.97302 - 21.087027 mm , file size: 3 Mb 
tile 8 3 : height:  490.00018 - 22.85838 mm , file size: 3 Mb 
tile 8 4 : height:  979.11 - 21.507284 mm , file size: 3 Mb 
tile 8 5 : height:  266.41058 - 25.268267 mm , file size: 3 Mb 
tile 8 6 : height:  182.18958 - 22.7939 mm , file size: 3 Mb 
tile 9 1 : height:  645.9717 - 18.776098 mm , file size: 3 Mb 
tile 9 2 : height:  656.80676 - 20.969414 mm , file size: 3 Mb 
tile 9 3 : height:  740.87946 - 23.244572 mm , file size: 3 Mb 
tile 9 4 : height:  633.40533 - 23.986706 mm , file size: 3 Mb 
tile 9 5 : height:  596.34216 - 23.880842 mm , file size: 3 Mb 
tile 9 6 : height:  59.468372 - 24.534832 mm , file size: 3 Mb 

total size for all tiles: 177 Mb 

processing finished: 16:26:05.614725 

Any idea what could be causing this? Thanks for your help!

Applying Rotation to Selection

Is it possible to apply a rotation to a selection? I am able to do this manually right now by creating a polygon (that is just a rotated rectangle), but the edges of the STL are all jagged when I do that (see attached image).

Any ideas on how I can get around this?

Screen Shot 2022-12-02 at 9 05 46 AM

UnboundLocalError when Processing test Pyramid

I'm having some problems getting access to Earth Engine on Google's end. I have a token and everything but I cannot sign in to the code editor even though they have sent me an email saying I had access.

While I work this out, I was trying to use the sample pyramid .tif file. I've uncommented out the "importedDEM" in Section A of the args and commented out "importedDEM" in section B. When I move to the next cell, I am given an error when I run it.

I'm running Anaconda 3, Python 3.8.2, Pillow 7.0.0, numpy 1.18.1, gdal 3.0.4, vectors 1.0.0, earthengine-api 0.1.219

I included the args and error I am receiving. What can I do to fix this?

args.txt
error.txt

No module named gdal

I get the following when I begin the "Process the data" section

ImportErrorTraceback (most recent call last)
in ()
----> 1 from common import TouchTerrainEarthEngine as TouchTerrain
2 # Process the data
3
4 # This may take some time! You'll see In[*] and some log messages
5 # You may see some red stuff with 10%, etc. - don't worry, that's normal

C:\Users\t\Downloads\TouchTerrain_for_CAGEO-master\common\TouchTerrainEarthEngine.py in ()
40 import numpy
41 from PIL import Image
---> 42 import gdal # for reading/writing geotiffs
43
44 import time

ImportError: No module named gdal

I tried Installing gdal in Anaconda, but after spinning for many hours, it would not install

Adding option to set custom min_elev

Chris, I'd like to add an option that lets the user set a custom min_elev in the tile_info dict that is passed to processing for tiles.

When generating 3D models for adjacent regions (dems) that will be fit together, a different min_elev for each generated region will lead to the two regions 3D model having a different height so the top surfaces that are the same DEM height are not the same 3D model height.

I've been getting around this at the moment by manually setting min_elev as 0 for now. I'm a bit busy at the moment and this workaround works so I haven't created a toggleable option for a user selectable min_elev but would like to do so in the future (this issue also helps me not forget the workaround and solution).

[Errno 28] No space left on device:

Running into this error and unable to create/download STL files.

[Errno 28] No space left on device: '/var/www/html/touchterrain/server/tmp/596314982299_dem.tif'

Running Out Of Memory

I am trying to run this on a computer with limited resources and I keep getting crashes because I run out of memory. I saw the arg called max_cells_for_memory_only which from what I understand will use a temp file instead of memory if the cells are bigger than that value. I set that value to 0 so it will always use temp files. When I run something I see it get into the expected if statements for the temp file stuff but when I watch the memory usage of the process it still goes way up, almost to 1 gig in my example.

Is there something else I have to do to disable in-memory processing?

3d STL height differences

I'm creating two versions of (ideally) the same terrain stl, except one of them has a gpx file. Even though they have the same settings, the STLs aren't the same height: the "plain" stl being 47.09391mm while the one with gpx "notch" (using negative gpxPathHeight) ends up taller at 47.45476mm.

What I end up doing with them is bringing into Blender to perform a boolean subtraction that extracts the gpx "trails" (image attached). Then I can combine that with the "notched" terrain file in 3dPrinter slicer to print in separate colors.

I can get it working, with some manual tweaking and post processing of the STLs, just thought I'd report the issue in case it's something that can be fixed or controlled (like passing in a max height in mm?).

Or, even better, an option to output two STLs: the base "notched" terrain and the part that was removed (i.e. the trail). That would be sweet.

logfile.txt
logfile.txt
Screenshot 2023-07-16 at 2 29 31 PM

Possible Invalid STL File

I am trying to import an STL into a program called PyCAM. When I import it I get many errors about invalid triangles:

Skipping invalid triangle: (160.36862182617188, 6.439293542825908e-15, 0.0) / (160.36862182617188, 6.439293542825908e-15, 39.96474075317383) / (158.62548828125, 6.439293542825908e-15, 40.60410690307617)
[many more...]

Inconsistent normal/vertices found in facet definition 21833 of '/pycam/tmptc037vdc.stl'. Please validate the STL file!

The model ends up loading but is missing the edges of the STL. The top mesh seems fine. It seems like data connecting the bottom rectangle data to the top mesh is corrupt possibly?

Screenshot 2022-12-05 at 7 31 25 AM

The STL seems to load fine in other programs so I'm not sure if most programs have built-in validation and PyCAM does not.

Any ideas?

Local install (non Docker) causing Storage to fill up

I ran the "pip install ." with the setup.py and all other files in the working directory of Python, and my Mac started asking me for permission to access Photos, Contacts etc, witch I found odd, and noticed that the write speed to my local storage was very high and filling up my SSD. I terminated the code and only had a few gigs left on the drive. After a restart the storage returned back to where it was before I attempted the install. What the heck is all that about? Im new to python, but I dont think I did anything that drastically wrong. I have been working with the docker version beforehand, but wanted to see if there was any better performance in the undockerized version.

Missing example_config.json file

The README and standalone files mention an example_config.json file in the stuff folder for reference when running TouchTerrain_standalone.py.

I can't find an example configuration file in json to build my custom config off of. Can an example config file in JSON format be added? Thanks.

Error when trying to generate the STL model file

Hi there

I'm trying TouchTerrain running in docker to create STL tiles for later 3D printing. I was using the online version of the tool but the data is too big to be processed. So I want to do it on my own within docker.

I went through the instructions from TouchTerrain_jupyter_for_starters.ipynb. One of the final steps fails when I try it to run. Generating the STL model file produces the following output. Something in TouchTerrainEarthEngine.py seems to be wrong. Any idea? Am I missing some preconfiguration? I would really like to get it done with this tool. I tried others but this has by far the most features :)

/TouchTerrain/standalone/touchterrain/common/TouchTerrainEarthEngine.py in get_zipped_tiles(DEM_name, trlat, trlon, bllat, bllon, polygon, polyURL, poly_file, importedDEM, printres, ntilesx, ntilesy, tilewidth, basethick, zscale, fileformat, tile_centered, CPU_cores_to_use, max_cells_for_memory_only, temp_folder, zip_file_name, no_bottom, bottom_image, ignore_leq, lower_leq, unprojected, only, original_query_string, no_normals, projection, use_geo_coords, importedGPX, gpxPathHeight, gpxPixelsBetweenPoints, gpxPathThickness, map_img_filename, smooth_borders, offset_masks_lower, fill_holes, **otherargs)
   1102             pr(" cropped", old_shape[::-1], "to", npim.shape[::-1]   )
   1103 
-> 1104             for index, offset_layer in enumerate(offset_npim):
   1105                 offset_npim[index] = offset_layer[0:offset_layer.shape[0]-remy, 0:offset_layer.shape[1]-remx]
   1106 

UnboundLocalError: local variable 'offset_npim' referenced before assignment

Polygon failure at Antarctic

I encounter the following issue when trying to create a stl file for an area in the Antarctic using polygons. I tried switching over to the USGS/GMTED2010 map, since it seems like the error complains about the polygon being outside the map, but even with USGS/GMTED2010 which should be global I am getting this issue.

The polygon coordinates are from https://datahub.io/core/geo-countries, but there could of course easily be a problem with them as well. I have written out the coordinates explicitly for the problematic polygon at the end of the issue in case that helps determining why this fails.


Log for creating 3D model tile(s) for  GMTED2010_-162.20_-81.43 
 
DEM_name = USGS/GMTED2010 
trlat = -81.26699187 
trlon = -160.37812728 
bllat = -81.60217713 
bllon = -164.02582272 
printres = 0.4 
ntilesx = 1 
ntilesy = 1 
tilewidth = 120 
basethick = 0 
zscale = 2.0 
fileformat = STLb 
no_bottom = False 
unprojected = False 
no_normals = True 

process started: 15:49:54.104320 

Region (lat/lon):
   -81.26699187 -160.37812728 (top right)
   -81.60217713 -164.02582272 (bottom left) 
Too far south for UTM - using Antarctic Polar Stereographic projection (EPSG 3031) 
lon/lat size in degrees: [3.647695440000007, 0.3351852600000029] 
requesting 202.25598122260257 m resolution from EarthEngine

INFO:root:Earth Engine raster: USGS/GMTED2010 
INFO:root: GMTED2010: Global Multi-resolution Terrain Elevation Data 2010 

Earth Engine raster: USGS/GMTED2010 
 GMTED2010: Global Multi-resolution Terrain Elevation Data 2010 

INFO:root:URL for geotiff is:  https://earthengine.googleapis.com/v1alpha/projects/earthengine-legacy/thumbnails/cb64ca3d581a0439a2faf8d47efdb426-ec6bf552d7e0be4a8fc702c7e5026fcd:getPixels 

URL for geotiff is:  https://earthengine.googleapis.com/v1alpha/projects/earthengine-legacy/thumbnails/cb64ca3d581a0439a2faf8d47efdb426-ec6bf552d7e0be4a8fc702c7e5026fcd:getPixels 

INFO:root: geotiff size: 0.0007810592651367188 Mb 
INFO:root: cell size 202.25598122260257 m, upper left corner (x/y):  -307631.3474395785 -862014.9919707321 

 geotiff size: 0.0007810592651367188 Mb 
 cell size 202.25598122260257 m, upper left corner (x/y):  -307631.3474395785 -862014.9919707321 

---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[30], line 40
     37             print(f"{outname}: {A:2.2e}")
     38             if A > minarea: 
     39                 #try:
---> 40                 totalsize, full_zip_file_name = TouchTerrain.get_zipped_tiles(**args)
     41                 print("Created zip file", full_zip_file_name, "%.2f" % totalsize, "Mb")
     42                 #except:
     43                 #    print(f"Failure at: {outname}: {A:2.2e}")
     44                 #    print(polygon)
     45                 #    failure = True
     46 #                    break
     47     else:

File /TouchTerrain/standalone/touchterrain/common/TouchTerrainEarthEngine.py:896, in get_zipped_tiles(DEM_name, trlat, trlon, bllat, bllon, polygon, polyURL, poly_file, importedDEM, printres, ntilesx, ntilesy, tilewidth, basethick, zscale, fileformat, tile_centered, CPU_cores_to_use, max_cells_for_memory_only, temp_folder, zip_file_name, no_bottom, bottom_image, ignore_leq, lower_leq, unprojected, only, original_query_string, no_normals, projection, use_geo_coords, importedGPX, gpxPathHeight, gpxPixelsBetweenPoints, gpxPathThickness, map_img_filename, smooth_borders, offset_masks_lower, fill_holes, min_elev, **otherargs)
    894     s += "For the web app, ensure that your red selection box is at least partially covered by the grey hillshade overlay "
    895     s += "or try using AW3D30 as DEM source."
--> 896     assert False, s # bail out
    898 # For AU/GA/AUSTRALIA_5M_DEM, replace all exact 0 value with NaN
    899 # b/c there are spots on land that have no pixels, but these are encoded as 0 and 
    900 # need to be marked as NaN otherwise they screw up the thickness of the base
    901 if DEM_name == "AU/GA/AUSTRALIA_5M_DEM":

AssertionError: All(!) elevation values are -32768.0! This may happen if the DEM source does not cover the selected area.
For the web app, ensure that your red selection box is at least partially covered by the grey hillshade overlay or try using AW3D30 as DEM source.


{"coordinates": [[[-160.48766, -81.597101], [-160.571116, -81.598891], [-161.022171, -81.582138], [-161.473227, -81.565385], [-161.924283, -81.548633], [-162.375338, -81.53188], [-162.826394, -81.515127], [-163.277449, -81.498375], [-163.728505, -81.481622], [-163.753163, -81.470473], [-163.748606, -81.468683], [-163.67101, -81.465427], [-163.658193, -81.461602], [-163.670155, -81.45436], [-163.948842, -81.418878], [-163.990061, -81.403497], [-163.969838, -81.393162], [-163.949208, -81.378351], [-163.932118, -81.361017], [-163.922678, -81.343357], [-163.851186, -81.318943], [-163.417531, -81.29461], [-162.983876, -81.270278], [-162.522247, -81.308787], [-162.060618, -81.347296], [-161.598988, -81.385805], [-161.137359, -81.424314], [-160.67573, -81.462823], [-160.632273, -81.490899], [-160.628529, -81.496759], [-160.671498, -81.507989], [-160.685129, -81.514744], [-160.647206, -81.517836], [-160.442209, -81.560235], [-160.413889, -81.573663], [-160.445383, -81.590509], [-160.48766, -81.597101]]], "type": "Polygon"}

Server Setup

Thanks for the work on this! It is a very cool project. I'm attempting to setup the server side and have been able to get through all of the authentication, however, when I run the python script to setup the server, it finishes with no server set up. I think I am missing the step on editing the ansible script, but I am not familiar with .yaml formatting or ansible in general. Could someone help me out? Thanks.

z-scale problem with USGS/GMTED2010 data set

Thanks for this great tool - I really love it !
I am using the TouchTerrain_jupyter_docker image to create STL files of the Alpine region with the USGS/GMTED2010 DEM as input data. The program works fine, but I have a problem with the z-dimension. I request a vertical exaggeration (z-scale) of 5. According to the logfile (see below), the z-dimension in the output is between 1 and ~94 mm for an elevation range of -4 to 4633 m asl. The map scale is 1:1'247'128. My expectation for the z-dimension extent would be 5*(4637m)/1'247'128 ~19 mm and not the 93 mm in the STL-output. Does this make sense or am I missing something here?

DEM_name = USGS/GMTED2010
trlat = 48.1
trlon = 16.2
bllat = 43.5
bllon = 5.1
printres = 0.4
ntilesx = 4
ntilesy = 3
tilewidth = 180
basethick = 1
zscale = 5
fileformat = STLb
no_bottom = False
unprojected = False
no_normals = True

process started: 18:07:50.558343

Region (lat/lon):
48.1 16.2 (top right)
43.5 5.1 (bottom left)
center at [10.649999999999999, 45.8] UTM 32 N , EPSG:32632
lon/lat size in degrees: [11.1, 4.600000000000001]
Earth Engine raster: USGS/GMTED2010
GMTED2010: Global Multi-resolution Terrain Elevation Data 2010
URL for geotiff is: https://earthengine.googleapis.com/v1alpha/projects/earthengine-legacy/thumbnails/c9e352d5f77975a4fe2f4ea838f5595d-f08027df12f33821bd3e5a339654a8ff:getPixels
geotiff size: 2.3989439010620117 Mb
cell size 479.40833227702973 m, upper left corner (x/y): 184572.20792665644 5352594.029873037
Time to add GPX paths:0.0063588619232177734
full (untiled) raster (height,width) (1119, 1873) float64 elev. min/max: -6.0 4633.0
cell size: 479.40833227702973 m
adjusted print res from the requested 0.4 mm to 0.38441003737319807 mm to ensure correct model dimensions
total model size in mm: 720 x 430.15483182060865
Cropping for nice fit of 4 (width) x 3 (height) tiles, removing: 1 columns, 0 rows
cropped (1873, 1119) to (1872, 1119)
cropping changed physical size from 180 mm x 143.38494394020287 mm
to 179.9038974906567 mm x 143.38494394020287 mm
map scale is 1 : 1247127.5088262174
Cells per tile (x/y) 468 x 373
Multiprocessing: using all cores (no logging info available while processing) ...
... multi-core processing done, logging resumed

4 x 3 tiles, tile size 179.90 x 143.38 mm

tile 1 1 : height: 4.2274165805133155 - 40.12992028050926 mm , file size: 33 Mb
tile 1 2 : height: 4.087094120490997 - 93.99369886336191 mm , file size: 33 Mb
tile 1 3 : height: 1.120276394304844 - 77.31537218642355 mm , file size: 33 Mb
tile 2 1 : height: 4.267508711948263 - 73.1858826486239 mm , file size: 33 Mb
tile 2 2 : height: 1.4610595115019023 - 89.44324194549532 mm , file size: 33 Mb
tile 2 3 : height: 1.060138197152422 - 43.217014401000256 mm , file size: 33 Mb
tile 3 1 : height: 7.955984803963481 - 73.90754101445296 mm , file size: 33 Mb
tile 3 2 : height: 1.020046065717474 - 67.13197080194675 mm , file size: 33 Mb
tile 3 3 : height: 1.0 - 42.27484931227898 mm , file size: 33 Mb
tile 4 1 : height: 3.325343623226985 - 53.88152136269643 mm , file size: 33 Mb
tile 4 2 : height: 1.080184262869896 - 53.420461851194524 mm , file size: 33 Mb
tile 4 3 : height: 1.0 - 34.93798925968349 mm , file size: 33 Mb

total size for all tiles: 401 Mb
added full geotiff as GMTED2010_10.65_45.80.tif

processing finished: 18:08:34.664949

No `example_config.json` file

Running TouchTerrain_standalone.py gives the message:

Wrote example_config.json with default value, use it as a template but make sure to rename it!

But the file example_config.json does not appear to exist.

How to get a consistent scale across multiple polygon maps?

I am trying to combine Touch Terrain with geo-countries, (which gives me Polygons and MultiPolygons for all countries in the world). My overall hobby project is essentially to combine these two in order to produce maps sorta similar to this.

One conceptual issue I am having though is how do I get a consistent scaling of all countries?
Unfortunately it does not seem like there is a scaling parameter from what I can see. I should be able to get a similar result by using tilewidth, but I am unsure how exactly bllat, bllon, trlat, and trlon gets calculated for a polygon and what exactly tilewidth is in such a case?

Cheers

Converting Lat/Lng to X/Y position on tile

I am trying to project a Lat/Lng pin onto the 3D printed tile. Given the topright & bottomleft coordinates.. How would you suggest mapping any given latlng to XY position on the print?

Option to create straight edges for imported DEMs

Is it possible to add an option to have higher resolution for side edges of the final model than specified for the rest of the model surface?
I am importing DEMs of individual US states (USGS GMTED2010) and would like to fit multiple printed pieces together.
I've set the print resolution and scale to match my nozzle and get an acceptable level of detail on the surface of the model. However, downscaling the resolution leads to edges of the models becoming jagged. As seen below, the Virginia, North Carolina border which is slightly curved in the base DEMs becomes a jagged approximation.

Thanks.

image

Website error

When using website with any args the following error is thrown:

Error:,Projection: Argument 'crs': Invalid type. Expected: String. Actual: Type.

Tried:
Changing source
Adding param "projection":26913
"projection":null
All tests generate same err

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.