A tutorial on terrain modeling in Grasshopper.
Docofossor, is a Grasshopper plugin for efficiently and iteratively modeling terrain using signed distance functions. Grasshopper is the visual programming interface for the 3D modeling program Rhino. To learn more about Grasshopper watch Grasshopper Basics with David Rutten, read the Grasshopper Primer, or study my course Generative Landscapes.
In Docofossor terrain is represented as a grid of elevation values (Z). Docofossor’s data structure (df) – which is based on rasters – has a header that defines the properties of the grid and then a list of Z values. This grid of values can be transformed using signed distance functions, enabling an efficient, iterative process for terrain modeling in Grasshopper. To visualize the terrain data in Grasshopper the grid can be converted into either 3D points or a quadrilateral mesh.
To install on Windows first download Docofossor, right click on the zip archive to open properties and unblock it, then extract the zip archive, move the contents to your Grasshopper components library, and restart Rhino and Grasshopper. To learn more about Docofossor read the documentation and the paper Computational Terrain Modeling with Distance Functions for Large Scale Landscape Design.
This tutorial uses Docofossor to model Governor’s Island, NYC from a gridded XYZ point cloud exported from GIS. For reference download the Grasshopper definition for this tutorial. To learn how to grade topography and calculate cut and fill with Docofossor watch my tutorials on Terrain Modeling, Terrain Analysis, and Grading Terrain.
Download the gridded point cloud
for the landforms on Governor’s Island.
In Grasshopper add the file path for this dataset
to your canvas as a parameter.
Params tab under
Primitive select and add a
File Path parameter.
Right click on the parameter, choose
select an existing file,
and set the path to the downloaded
Docofossor tab under
IO add the
f to the
File Path parameter
to import the point cloud as a Docofossor grid (
Optionally add a skip parameter
n to reduce the size of the point cloud.
Docofossor tab under
Grid add the
component and set the grid as its input
to shift the grid to from its geographic coordinates
to the XY origin of the local Cartesian coordinate system.
Docofossor tab under
Geometry add the
component to generate a quadrilateral mesh from the shifted grid.
Connect a custom preview with a color swatch
to output mesh to better visualize the landscape.
Since Docofossor expects points to be listed from left to right and from bottom to top, XYZ point clouds that are sorted differently - such as governors-island-landform.xyz - will be mirrored vertically on import. To fix this use the mirror component with the grid mesh as the input geometry and an XZ plane with its origin set to the center of the mesh as the input plane. To find the center of the mesh generate a bounding box for the mesh and then use evaluate box to find the centroid of the box.
Docofossor requires XYZ point clouds with regular grid spacing. Rasters, which have regular grid spacing, can be exported as XYZ point clouds. To find raster elevation data, see my list of geospatial data sources. This section of the tutorial covers how to process raster data in GRASS GIS and export it for use in Rhino and Grasshopper.
Download and extract the
Governor’s Island Dataset for GRASS GIS.
and create a new mapset named
Add the raster
to the map display.
First remove any raster mask with
Either zoom to the desired extent and
set the computational region from the display
under various zoom options
g.region n=189850 s=189100 e=978550 w=976850 res=1 save=landforms
in the command line.
Docofossor does not handle grid cells with no data,
so any null cells should be filled.
Since the digital elevation model for Governor’s Island
has null cells in the harbor around the island,
these should be filled with elevation of sea level at low tide.
First use univariate raster statistics with
to find the minimum elevation value in the digital elevation model
as a proxy for sea level at low tide.
This may be between -3 to -4 feet depending on your region.
Use map algebra with the raster calculator
to crop the digital elevation model to the computational region
and fill the nulls cells.
Write a map expression with a conditional if, then, else statement reading
if cells in the map
elevation_2017 are null,
else write values from
Export the resulting raster as an ASCII XYZ point cloud using the module
r.mask -r g.region n=189850 s=189100 e=978550 w=976850 res=1 save=landforms r.univar map=elevation_2017 r.mapcalc expression="elevation = if(isnull(elevation_2017), -3.39, elevation_2017)" r.out.xyz input=elevation separator=comma
Orthoimagery - such as aerial photographs -
can be mapped onto the surfaces or meshes in Rhino.
To export raster imagery for Governor’s Island
first set the computational region,
then crop the raster to the region with
and then export the map
.png in portable network graphics format with
g.region region=landforms r.mapcalc expression="imagery = imagery_2018" r.out.png --overwrite input=imagery output=D:\generative-design\grasshopper\data\govenors-island-imagery.png
To drape the aerial photograph over the terrain mesh in Rhino,
first bake the mesh,
then assign the picture as a material,
and map the texture as plane to the bounding box of the mesh.
In Grasshopper bake the mesh (from the mirror component)
Disable the preview for all components and disable the custom preview.
In Rhino set all viewports to rendered mode.
Set a new material for the layer with the baked mesh
by clicking on the layer’s material orb in the layer manager.
Name the material
change the type to picture,
and set the texture to
Select the mesh
and open the texture mapping tab
in the object properties panel,
and choose apply planar mapping.
In the command line set the parameters for
Set the plane to
the coordinate system to
and the mapping to
Rasters can be imported into GRASS GIS with the module r.in.gdal. For imagery each channel will import as a separate raster map and will need to be combined together with r.composite. If rasters have been divided into tiles they can be patched together with r.patch.
the 2017 digital surface model tile
and 2018 orthoimagery tiles
for Governor’s Island.
Note that FTP support is being disabled or removed
from web browsers like Chome and Firefox
due to security concerns.
Either use a program such as FileZilla,
the command line with curl,
or enable FTP in your browser.
For Chrome in
enable support for FTP URLs.
Start GRASS GIS
and create a new location from georeferenced data.
When creating the new location
read the projection and datum terms
from the digital surface model
First import the digital surface model
Set the computational region around the fort on the north of the island
Crop the digital surface model to the region with
and then export the resulting raster as an ASCII XYZ point cloud using
r.in.gdal input=hh_NYC_020.tif output=surface_2017 g.region n=191531 s=190812 w=979477 e=980181 res=1 save=fort r.mapcalc expression="surface = surface_2017" r.out.xyz input=surface output=governors-island-fort.xyz separator=comma
Import the imagery tiles
-r flag to limit the import to the computational region.
Since the imagery has red, green, blue, and near-infrared channels,
each tile of imagery will import as a series of four rasters.
Composite each set together with
and then patch the resulting rasters together with
Finally export the map
.png in portable network graphics format with
r.in.gdal -r input=980190.jp2 output=imagery_2018_b r.in.gdal -r input=977190.jp2 output=imagery_2018_a r.composite red=imagery_2018_a.1 green=imagery_2018_a.2 blue=imagery_2018_a.3 output=imagery_2018_a r.composite red=imagery_2018_b.1 green=imagery_2018_b.2 blue=imagery_2018_b.3 output=imagery_2018_b r.patch input=imagery_2018_a,imagery_2018_b output=imagery_2018 r.out.png input=imagery_2018 output=governors-island-fort.png
Import the XYZ point cloud into Grasshopper as grid using Docofossor, generate a mesh from the grid, and bake the mesh to Rhino. Then map the imagery as a texture on the mesh.
Lidar, laser scanning, and photogrammetry
generate unstructured point clouds.
can generate a raster surface from a point cloud
either though binning or interpolation.
To bin ASCII XYZ point clouds use the module
.las LASer point clouds use the module
To interpolate a point cloud first import it as vector points with
if it is in ASCII XYZ format
or with v.in.lidar
if it is in LASer format.
Use regularized spline with tension interpolation with
to approximate a raster surface from the vector points.
Point clouds can also be gridded in
CloudCompare with its