Are there any tools that can take a DTM, in asc or geotiff format and generate a mesh from this that can used in meshlab or similar software.
I have asc DTM file that I need to convert to a ply mesh file. Is this possible?
In response to the comment. Then these DTM asc files are not the ones that meshlab understands.
The files starts with:
ncols 6250
nrows 6250
xllcorner 630000.000000000000
yllcorner 6070000.000000000000
cellsize 1.600000000000
NODATA_value -9999
Answer
A DTM raster can be represented by triangle meshes by finding a set of non-overlapping triangles that covers the entire mesh and approximates the elevation field. There are two different types of triangle meshes that can be used for this purpose:
- a triangulated regular network (TRN), in which every pixel of the raster is represented by a vertex, and all triangles have the same size and shape. All the original information of the DTM raster is present in the TRN, but the memory required for storing the mesh is typically quite high.
- a triangulated irregular network (TIN), in which there are fewer vertices than raster pixels and the triangles have different shapes and sizes. The vertices and the triangulation are chosen in such a way that the resulting surface approximates the original DTM raster up to a specified error. This typically results in much smaller files, since plane or nearly plane areas can be represented using only a couple of vertices.
In most applications, if you need to deal with elevation meshes, you'd go with a TIN since throwing out redundant or nearly redundant information allows for more efficient computations. However, creating TINs from rasters isn't straightforward, since there are many different triangulations that approximate a grid with the same error, but using different vertex sets.
Software for creating TINs
- Michael Garland's Terra software.
- ArcGIS:
Raster to TIN
function from the 3D Analyst toolbox. - SAGA GIS:
Grid to TIN (Surface Specific Points)
function, followed byExport TIN to Stereo Lithography File (STL)
function to export the TIN to a mesh format readable by Meshlab.
Software for creating TRNs
- VTBuilder, which is part of the Virtual Terrain Project: load the DTM raster using "Layer | Import Layer" and then convert it to a TRN using "Elevation | Convert grid to TIN". Then you select the newly generated layer in the Layer overview and select "Elevation | Export To...". VTBuilder can read all raster formats that GDAL supports, and exports the TRN to OBJ, PLY, GMS, DXF, DAE or WRL formats.
- SAGA GIS:
Grid to TIN
function. Roll your own solution: Implementing it isn't particularly hard. Here's a Python script that uses the GDAL library to read a raster DTM, and then writes out a binary PLY mesh.
Save the script as
gdal_rastertotrn.py
, then call it usingpython gdal_rastertotrn.py
.Here's an example. Converting a raster DTM of Crater Lake called
crater_lake.tif
...... by calling
python gdal_rastertotrn.py crater_lake.tif crater_lake.ply
, and opening the resultingcrater_lake.ply
in Meshlab:Here's the (unpolished) script. Since it uses the GDAL library, it can convert all raster types supported by GDAL. It only writes PLY files.
#!/usr/bin/python
import sys
import numpy as np
from osgeo import gdal
def write_ply(filename, coordinates, triangles, binary=True):
template = "ply\n"
if binary:
template += "format binary_" + sys.byteorder + "_endian 1.0\n"
else:
template += "format ascii 1.0\n"
template += """element vertex {nvertices:n}
property float x
property float y
property float z
element face {nfaces:n}
property list int int vertex_index
end_header
"""
context = {
"nvertices": len(coordinates),
"nfaces": len(triangles)
}
if binary:
with open(filename,'wb') as outfile:
outfile.write(template.format(**context))
coordinates = np.array(coordinates, dtype="float32")
coordinates.tofile(outfile)
triangles = np.hstack((np.ones([len(triangles),1], dtype="int") * 3,
triangles))
triangles = np.array(triangles, dtype="int32")
triangles.tofile(outfile)
else:
with open(filename,'w') as outfile:
outfile.write(template.format(**context))
np.savetxt(outfile, coordinates, fmt="%.3f")
np.savetxt(outfile, triangles, fmt="3 %i %i %i")
def readraster(filename):
raster = gdal.Open(filename)
return raster
def createvertexarray(raster):
transform = raster.GetGeoTransform()
width = raster.RasterXSize
height = raster.RasterYSize
x = np.arange(0, width) * transform[1] + transform[0]
y = np.arange(0, height) * transform[5] + transform[3]
xx, yy = np.meshgrid(x, y)
zz = raster.ReadAsArray()
vertices = np.vstack((xx,yy,zz)).reshape([3, -1]).transpose()
return vertices
def createindexarray(raster):
width = raster.RasterXSize
height = raster.RasterYSize
ai = np.arange(0, width - 1)
aj = np.arange(0, height - 1)
aii, ajj = np.meshgrid(ai, aj)
a = aii + ajj * width
a = a.flatten()
tria = np.vstack((a, a + width, a + width + 1, a, a + width + 1, a + 1))
tria = np.transpose(tria).reshape([-1, 3])
return tria
def main(argv):
inputfile = argv[0]
outputfile = argv[1]
raster = readraster(inputfile)
vertices = createvertexarray(raster)
triangles = createindexarray(raster)
write_ply(outputfile, vertices, triangles, binary=True)
if __name__ == "__main__":
main(sys.argv[1:])
No comments:
Post a Comment