Utility_Apps/Blender/simple scripts/CSV Terrain Import for Blender/Script 2.py
Ryan Schultz 9330cc2c77 The following scripts import survey-style CSV point data into Blender and generates a triangulated 3D terrain surface.
-   Reads CSV files containing `x, y, z, label`
-   Converts coordinates from feet to the current Blender scene units
-   Offsets large world coordinates near the origin for precision
-   Corrects axis orientation (Y flip + proper Z alignment)
-   Creates labeled empties for each survey point
-   Optionally filters out unwanted point types (e.g. buildings or utilities)
-   Generates a Delaunay-triangulated 3D mesh surface from the remaining points

The result is a clean, unit-accurate terrain mesh built directly from raw survey data inside Blender.
2026-02-23 16:56:03 -06:00

56 lines
No EOL
1.5 KiB
Python

import bpy
from mathutils import Vector
from scipy.spatial import Delaunay
# Name of the collection containing the empties
collection_name = "CSV_Points"
# Names to exclude (case-insensitive)
EXCLUDE_KEYWORDS = ["HSE", "FOO", "BAR"]
# Get the collection
col = bpy.data.collections.get(collection_name)
if not col:
raise ValueError(f"Collection '{collection_name}' not found")
# Filter empties
valid_objects = []
for obj in col.objects:
if obj.type != 'EMPTY':
continue
name_upper = obj.name.upper()
if any(keyword in name_upper for keyword in EXCLUDE_KEYWORDS):
continue
valid_objects.append(obj)
if len(valid_objects) < 3:
raise ValueError("Not enough valid points to triangulate.")
print(f"Using {len(valid_objects)} empties after filtering.")
print(f"Skipped {len(col.objects) - len(valid_objects)} objects.")
# Extract XY and Z
points = []
z_values = []
for obj in valid_objects:
points.append([obj.location.x, obj.location.y])
z_values.append(obj.location.z)
# Perform Delaunay triangulation
tri = Delaunay(points)
faces = tri.simplices.tolist()
# Create new mesh
mesh = bpy.data.meshes.new("TriangulatedMesh")
mesh_obj = bpy.data.objects.new("TriangulatedMesh", mesh)
bpy.context.collection.objects.link(mesh_obj)
# Create mesh
verts = [Vector((p[0], p[1], z_values[i])) for i, p in enumerate(points)]
mesh.from_pydata(verts, [], faces)
mesh.update()
print(f"Created mesh with {len(mesh.vertices)} vertices and {len(mesh.polygons)} faces.")