Import GeoTIFF as DEM. Works but needs polish and features
This commit is contained in:
parent
d49c9b9c25
commit
6830d3a81b
|
|
@ -0,0 +1,6 @@
|
||||||
|
/.venv
|
||||||
|
/wheels/*.whl
|
||||||
|
|
||||||
|
__pycache__
|
||||||
|
|
||||||
|
*~
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
from . import create_mesh_from_geotiff
|
||||||
|
|
||||||
|
def register():
|
||||||
|
create_mesh_from_geotiff.register()
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
create_mesh_from_geotiff.unregister()
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
schema_version = "1.0.0"
|
||||||
|
id = "blender_mapping_tools"
|
||||||
|
version = "0.1.0"
|
||||||
|
name = "Blender Mapping Tools"
|
||||||
|
tagline = "Tools for working with GIS data in Blender"
|
||||||
|
maintainer = "Matt Gordon <matthew@gordon.earth"
|
||||||
|
type = "add-on"
|
||||||
|
tags = ["3D View", "Import-Export"]
|
||||||
|
blender_version_min = "4.4.0"
|
||||||
|
license = [
|
||||||
|
"SPDX:GPL-3.0-or-later",
|
||||||
|
]
|
||||||
|
copyright = [
|
||||||
|
"2025 Matthew Gordon"
|
||||||
|
]
|
||||||
|
wheels = [
|
||||||
|
"./wheels/affine-2.4.0-py3-none-any.whl",
|
||||||
|
"./wheels/attrs-25.3.0-py3-none-any.whl",
|
||||||
|
"./wheels/certifi-2025.4.26-py3-none-any.whl",
|
||||||
|
"./wheels/click-8.2.1-py3-none-any.whl",
|
||||||
|
"./wheels/click_plugins-1.1.1-py2.py3-none-any.whl",
|
||||||
|
"./wheels/cligj-0.7.2-py3-none-any.whl",
|
||||||
|
"./wheels/numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
||||||
|
"./wheels/pyparsing-3.2.3-py3-none-any.whl",
|
||||||
|
"./wheels/rasterio-1.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
import bpy
|
||||||
|
from bpy.props import StringProperty
|
||||||
|
from bpy_extras.io_utils import ImportHelper
|
||||||
|
import rasterio
|
||||||
|
|
||||||
|
class GridVertexGenerator():
|
||||||
|
def __init__(self, grid_size_x, grid_size_y, cell_size_x, cell_size_y, dem_array):
|
||||||
|
self.cell_size_x = cell_size_x
|
||||||
|
if cell_size_y is not None:
|
||||||
|
self.cell_size_y = cell_size_y
|
||||||
|
else:
|
||||||
|
self.cell_size_y = cell_size_x
|
||||||
|
self.grid_size_x = grid_size_x
|
||||||
|
self.grid_size_y = grid_size_y
|
||||||
|
self.dem_array = dem_array
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return self.grid_size_x * self.grid_size_y
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self._generator()
|
||||||
|
|
||||||
|
def _generator(self):
|
||||||
|
for j in range(self.grid_size_y):
|
||||||
|
for i in range(self.grid_size_x):
|
||||||
|
yield (i * self.cell_size_x,
|
||||||
|
j * self.cell_size_y,
|
||||||
|
self.dem_array[j][i])
|
||||||
|
|
||||||
|
class GridTriangleGenerator():
|
||||||
|
def __init__(self, grid_size_x, grid_size_y, cell_size_x, cell_size_y=None):
|
||||||
|
self.cell_size_x = cell_size_x
|
||||||
|
if cell_size_y is not None:
|
||||||
|
self.cell_size_y = cell_size_y
|
||||||
|
else:
|
||||||
|
self.cell_size_y = cell_size_x
|
||||||
|
self.grid_size_x = grid_size_x
|
||||||
|
self.grid_size_y = grid_size_y
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
#return (self.grid_size_x - 1) * (self.grid_size_y - 1) * 2
|
||||||
|
return (self.grid_size_x - 1) * (self.grid_size_y - 1)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self._generator()
|
||||||
|
|
||||||
|
def _generator(self):
|
||||||
|
for i in range(self.grid_size_x - 1):
|
||||||
|
for j in range(self.grid_size_y - 1):
|
||||||
|
v00 = j * self.grid_size_x + i
|
||||||
|
v01 = (j + 1) * self.grid_size_x + i
|
||||||
|
v10 = j * self.grid_size_x + i + 1
|
||||||
|
v11 = (j + 1) * self.grid_size_x + i + 1
|
||||||
|
yield (v00, v10, v11, v01)
|
||||||
|
#yield (v00, v10, v01)
|
||||||
|
#yield (v01, v10, v11)
|
||||||
|
|
||||||
|
|
||||||
|
class CreateMeshFromGeotiffOperator(bpy.types.Operator, ImportHelper):
|
||||||
|
"""Create a new object from a GeoTIFF"""
|
||||||
|
bl_idname = "object.create_mesh_from_geotiff"
|
||||||
|
bl_label = "Mesh from GeoTIFF"
|
||||||
|
|
||||||
|
filter_glob = StringProperty(default="*.tif;*.tiff", options={"HIDDEN"})
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
with rasterio.open(self.properties.filepath) as geotiff:
|
||||||
|
grid_size_x = geotiff.width
|
||||||
|
grid_size_y = geotiff.height
|
||||||
|
print(f"GeoTIFF is {grid_size_x}x{grid_size_y}")
|
||||||
|
bounds = geotiff.bounds
|
||||||
|
print(f"GeoTIFF bounds: {bounds}")
|
||||||
|
cell_size_x = (bounds.right - bounds.left) / geotiff.width
|
||||||
|
cell_size_y = (bounds.bottom - bounds.top) / geotiff.height
|
||||||
|
print(f"Calculated cell size: {cell_size_x} x {cell_size_y}")
|
||||||
|
print("Reading GeoTIFF...")
|
||||||
|
dem_array = geotiff.read(1)
|
||||||
|
print("Processing values...")
|
||||||
|
print("Done.")
|
||||||
|
mesh = bpy.data.meshes.new("mesh")
|
||||||
|
dem_obj = bpy.data.objects.new("DEM", mesh)
|
||||||
|
collection = bpy.data.collections["Collection"]
|
||||||
|
collection.objects.link(dem_obj)
|
||||||
|
context.view_layer.objects.active = dem_obj
|
||||||
|
print("Creating mesh data...")
|
||||||
|
(vertices, edges, faces) = self.construct_mesh(grid_size_x, grid_size_y, cell_size_x, cell_size_y, dem_array)
|
||||||
|
print("Constructing mesh...")
|
||||||
|
mesh.from_pydata(vertices, edges, faces, shade_flat=False)
|
||||||
|
print("Done.")
|
||||||
|
mesh.validate(verbose=True)
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
def construct_mesh(self, grid_size_x, grid_size_y, cell_size_x, cell_size_y, dem_array):
|
||||||
|
#grid_size_x = 10
|
||||||
|
#grid_size_y = 15
|
||||||
|
#cell_size_x = 0.75
|
||||||
|
#cell_size_y = 0.5
|
||||||
|
return (GridVertexGenerator(grid_size_x, grid_size_y, cell_size_x, cell_size_y, dem_array),
|
||||||
|
[],
|
||||||
|
GridTriangleGenerator(grid_size_x, grid_size_y, cell_size_x, cell_size_y))
|
||||||
|
|
||||||
|
def menu_func(self, context):
|
||||||
|
self.layout.operator(CreateMeshFromGeotiffOperator.bl_idname,
|
||||||
|
text=CreateMeshFromGeotiffOperator.bl_label)
|
||||||
|
|
||||||
|
def register():
|
||||||
|
bpy.utils.register_class(CreateMeshFromGeotiffOperator)
|
||||||
|
bpy.types.VIEW3D_MT_add.append(menu_func)
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
bpy.utils.unregister_class(CreateMeshFromGeotiffOperator)
|
||||||
|
bpy.types.VIEW3D_MT_add.remove(menu_func)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
register()
|
||||||
Loading…
Reference in New Issue