GeoGmsh.jl

GeoGmshModule
GeoGmsh

Convert geospatial data to Gmsh geometry (.geo) and mesh (.msh) files. Accepts any GeoInterface-compatible source: Shapefiles, GeoJSON, GeoPackage, GeoParquet, NaturalEarth data, or raw GeoInterface geometries.

Typical workflow

using GeoGmsh

# From Natural Earth (no files needed)
using NaturalEarth
geoms_to_geo(naturalearth("admin_0_countries", 110), "countries";
  # target_crs defaults to :auto_utm — UTM zone detected from geometry centroid
  simplify_alg = MinEdgeLength(tol = 5_000.0),
  mesh_size    = 2.0,
)

# From any file (Shapefile, GeoJSON, GeoPackage, …)
df = read_geodata("regions.shp")
geoms_to_geo(df, "output"; mesh_size = 2.0)   # auto UTM by default

# 3D terrain mesh
geoms_to_msh_3d("region.shp", "srtm.tif", "terrain";
  target_crs = "EPSG:32632",
  mesh_size  = 500.0,
)

Pipeline (2D)

geoms_to_geo / geoms_to_msh run these steps:

  1. GeometryOps.reproject — reproject coordinates (Proj.jl)
  2. GeometryOps.simplify(MinEdgeLength…) — remove short edges
  3. GeometryOps.segmentize — split long edges
  4. ingest — convert to Gmsh-ready Geometry2D
  5. filter_components — drop degenerate rings
  6. rescale — normalise into an L × L bounding box
  7. write_geo or generate_mesh — write output

Pipeline (3D surface)

geoms_to_geo_3d / geoms_to_msh_3d add after step 6:

  1. read_dem — read DEM raster (GeoTIFF, SRTM, NetCDF, …)
  2. lift_to_3d — sample boundary point elevations
  3. write_geo or generate_mesh with Geometry3D

Pipeline (3D volume)

geoms_to_msh_3d_volume produces a tetrahedral solid mesh by extruding the terrain surface downward by depth (in CRS units):

  1. read_dem — read DEM raster
  2. lift_to_3d — sample boundary point elevations
  3. generate_mesh_volume — flat 2D mesh → prism extrusion → 3 tets per prism
source

A Julia package that converts geospatial data into Gmsh geometry (.geo) and mesh (.msh) files. Built on the JuliaGeo ecosystem — GeoInterface, GeometryOps, Proj, ArchGDAL — and accepts any GeoInterface-compatible source: Shapefiles, GeoJSON, GeoPackage, GeoParquet, NaturalEarth data, or raw geometries.


Flat 2D meshes from any geospatial boundary:

IberiaCataloniaAustralia geometryAustralia mesh
Iberian PeninsulaCataloniaAustralia — geometryAustralia — mesh

3D terrain manifolds by sampling a Digital Elevation Model at every mesh node:

Mont Blanc terrainEverest terrain
Mont BlancEverest

Features

  • Universal reader — load any geospatial format (Shapefile, GeoJSON, GeoPackage, GeoParquet, …) through a single read_geodata call backed by GDAL. Read directly from ZIP archives via the /vsizip/ virtual filesystem.
  • Reproject — convert between coordinate systems via GeometryOps.jl / Proj.jl (e.g. geographic degrees → UTM metres).
  • Simplify — remove short edges (MinEdgeLength), suppress zig-zag spikes (AngleFilter), or chain algorithms with (ComposedAlg).
  • Segmentize — subdivide long edges via GeometryOps.segmentize to control maximum element size.
  • Rescale — normalise geometry into a dimensionless bounding box so mesh_size stays consistent across datasets.
  • 3D terrain — lift a 2D mesh to terrain elevation by sampling a DEM raster (GeoTIFF, SRTM, NetCDF, …) at every node.
  • Output — write a human-readable .geo script or call the Gmsh API to produce a .msh file directly; linear/quadratic elements and quad recombination supported.

Installation

using Pkg
Pkg.add(url = "https://github.com/JordiManyer/GeoGmsh.jl")

Quick start

From NaturalEarth (no files needed)

using GeoGmsh, NaturalEarth

countries = naturalearth("admin_0_countries", 110)

geoms_to_msh(countries, "france";
  select       = row -> get(row, :NAME, "") == "France" && row.ring == 1,
  target_crs   = "EPSG:3857",
  simplify_alg = MinEdgeLength(tol = 5_000.0),
  bbox_size    = 100.0,
  mesh_size    = 2.0,
)
# → france.msh

From a file (Shapefile, GeoJSON, …)

using GeoGmsh

# Inspect available features and rings
list_components("NUTS_RG_01M_2024_4326_LEVL_0.geojson")

# Mesh mainland Germany
geoms_to_msh("NUTS_RG_01M_2024_4326_LEVL_0.geojson", "germany";
  select       = row -> row.NUTS_ID == "DE" && row.ring == 1,
  target_crs   = "EPSG:3857",
  simplify_alg = MinEdgeLength(tol = 10_000.0),
  bbox_size    = 100.0,
  mesh_size    = 2.0,
)
# → germany.msh

3D terrain mesh

using GeoGmsh

geoms_to_msh_3d("region.geojson", "dem_utm.tif", "terrain";
  select       = row -> row.NAME == "MyRegion" && row.ring == 1,
  target_crs   = "EPSG:32632",   # must match the DEM CRS
  simplify_alg = MinEdgeLength(tol = 500.0),
  mesh_size    = 500.0,
)
# → terrain.msh  (z-coordinates sampled from DEM)

Pipeline overview

StepFunctionPurpose
Readread_geodataParse any geospatial format; filter by attribute
ReprojectGeometryOps.reprojectConvert coordinates via PROJ
SimplifyMinEdgeLength, AngleFilter, ComposedAlgRemove redundant vertices
SegmentizeGeometryOps.segmentizeSubdivide long edges
IngestingestNormalise ring orientation for Gmsh
Filterfilter_componentsDrop degenerate rings
RescalerescaleNormalise into an L × L bounding box
DEMread_dem, lift_to_3dSample elevations (3D only)
Outputwrite_geo / generate_meshWrite .geo or .msh
Volumegenerate_mesh_volumeExtrude surface → tetrahedral solid (3D only)

See the Pipeline guide and API reference for details, or browse the Examples section in the sidebar for full worked examples.

Data sources