Blender Script: Distance Between Two Points

We were having a lot of trouble using the measure tool in Blender — after discovering that you can hold the Ctrl key and “snap” your selection to a vertex, it actually worked in the way we wanted it to. But, before that discovery, my thought was to manually select two vertices and use a Python script to measure the distance between those points. That is “blender units” … and the metric or imperial units would be more meaningful. So I converted based on the scene configuration.

import bpy
import bmesh


def format_metric(meters: float) -> str:
    a = abs(meters)

    if a >= 1.0:
        return f"{meters:.6f} m"
    elif a >= 0.01:
        return f"{meters * 100.0:.3f} cm"
    else:
        return f"{meters * 1000.0:.3f} mm"


def format_imperial(meters: float) -> str:
    total_inches = meters / 0.0254
    sign = "-" if total_inches < 0 else ""
    total_inches = abs(total_inches)

    feet = int(total_inches // 12)
    inches = total_inches - (feet * 12)

    if feet > 0:
        return f"{sign}{feet} ft {inches:.3f} in"
    else:
        return f"{sign}{total_inches:.3f} in"


def measure_selected_vertices():
    ctx = bpy.context
    obj = ctx.edit_object

    if obj is None or obj.type != 'MESH':
        raise RuntimeError("Go into Edit Mode on a mesh and select exactly 2 vertices.")

    bm = bmesh.from_edit_mesh(obj.data)
    selected_verts = [v for v in bm.verts if v.select]

    if len(selected_verts) != 2:
        raise RuntimeError(f"Expected exactly 2 selected vertices, found {len(selected_verts)}.")

    v1, v2 = selected_verts

    # Convert local vertex coordinates to world-space coordinates
    p1 = obj.matrix_world @ v1.co
    p2 = obj.matrix_world @ v2.co

    # Raw world-space distance in Blender units
    raw_distance = (p2 - p1).length

    scene = ctx.scene
    units = scene.unit_settings
    scale_length = units.scale_length if units.scale_length != 0 else 1.0

    # Convert Blender units to meters according to the scene unit scale
    distance_meters = raw_distance * scale_length

    print("\n----- Vertex Distance -----")
    print(f"Object: {obj.name}")
    print(f"Raw distance (Blender units): {raw_distance:.6f}")
    print(f"Scene unit system: {units.system}")
    print(f"Scene unit scale: {scale_length}")

    if units.system == 'METRIC':
        print(f"Formatted distance: {format_metric(distance_meters)}")

    elif units.system == 'IMPERIAL':
        print(f"Formatted distance: {format_imperial(distance_meters)}")

    else:
        print("Formatted distance: Scene unit system is 'NONE'")
        print(f"Interpreted using current unit scale: {format_metric(distance_meters)}")


measure_selected_vertices()

Leave a Reply

Your email address will not be published. Required fields are marked *