Skip to content

Instantly share code, notes, and snippets.

@endarthur
Last active November 30, 2020 17:06
Show Gist options
  • Save endarthur/d96493022244583f3a40d45a0997d350 to your computer and use it in GitHub Desktop.
Save endarthur/d96493022244583f3a40d45a0997d350 to your computer and use it in GitHub Desktop.
Leapfrog Geo's msh file reader and converter to Wavefront .obj
# Contributors: Alexander Jüstel, Arthur Endlein Correia, Florian Wellmann
#
# This script is part of GemGIS, saved here as a standalone version.
#
# GemGIS is a Python-based, open-source geographic information processing library.
# It is capable of preprocessing spatial data such as vector data (shape files, geojson files, geopackages),
# raster data, data obtained from WMS services or XML/KML files.
#
# Preprocessed data can be stored in a dedicated Data Class to be passed to the geomodeling package GemPy
# in order to accelerate to model building process.
#
# GemGIS is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# GemGIS is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License (LICENSE.md) for more details.
import numpy as np
from pathlib import Path
dtype_conversion = {
"Integer": np.int32,
"Double": np.float64
}
def read_msh(fname):
with open(fname, "rb") as f:
header = []
chunk = f.read(512)
header_end = chunk.find(b"[binary]")
data = {}
f.seek(header_end + 0x14)
for line in chunk[chunk.find(b"[index]") + 8:header_end].decode("utf-8").strip().split("\n"):
name, dtype, *shape = line.strip().rstrip(";").split()
shape = list(map(int, reversed(shape)))
dtype = dtype_conversion[dtype]
data[name] = np.fromfile(
f,
dtype,
np.prod(shape)
).reshape(shape)
return data
def save_obj(data, fname):
with open(fname, "w") as f:
f.write("".join([f"v {x} {y} {z}\n" for x, y, z in data["Location"]]))
f.write("".join([f"f {i} {j} {k}\n" for i, j, k in data["Tri"] + 1]))
if __name__ == "__main__":
from sys import argv
if len(argv) < 2:
print("usage: python msh.py INPUT [OUTPUT]\n If output is not given, the input name will be used with extension changed to .obj")
exit()
_, msh, *obj = argv
msh = Path(msh)
if not obj:
obj = msh.with_suffix(".obj")
else:
obj = Path(obj[0])
data = read_msh(msh)
save_obj(data, obj)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment