Implements selection tool that identifies mesh objects where ALL edges are oriented at specific angles (40-60° or 120-140°) relative to the X axis. Designed for filtering diagonal line segments at approximately ±45 degrees, particularly useful for processing imported SVG paths or similar geometric data.
78 lines
No EOL
2.3 KiB
Python
78 lines
No EOL
2.3 KiB
Python
import bpy
|
|
import bmesh
|
|
import math
|
|
from mathutils import Vector
|
|
|
|
def all_edges_in_angle_range(obj, ranges=[(40, 60), (120, 140)]):
|
|
"""
|
|
Check if ALL edges in a mesh object have angles to the X axis
|
|
within any of the specified ranges.
|
|
Returns True only if ALL edges satisfy the condition.
|
|
"""
|
|
bm = bmesh.new()
|
|
bm.from_mesh(obj.data)
|
|
bm.edges.ensure_lookup_table()
|
|
|
|
if len(bm.edges) == 0:
|
|
bm.free()
|
|
return False
|
|
|
|
x_axis = Vector((1, 0, 0))
|
|
|
|
for edge in bm.edges:
|
|
v1, v2 = edge.verts
|
|
|
|
# Get world space coordinates
|
|
v1_world = obj.matrix_world @ v1.co
|
|
v2_world = obj.matrix_world @ v2.co
|
|
|
|
# Calculate direction vector
|
|
direction = v2_world - v1_world
|
|
|
|
if direction.length > 0:
|
|
direction.normalize()
|
|
|
|
# Calculate angle from X axis
|
|
angle_rad = direction.angle(x_axis)
|
|
angle_deg = math.degrees(angle_rad)
|
|
|
|
# Check if this edge is in any of the valid ranges
|
|
edge_in_range = False
|
|
for min_angle, max_angle in ranges:
|
|
if min_angle <= angle_deg <= max_angle:
|
|
edge_in_range = True
|
|
break
|
|
|
|
# If this edge is NOT in any range, return False immediately
|
|
if not edge_in_range:
|
|
bm.free()
|
|
return False
|
|
|
|
# If we got here, all edges are in valid ranges
|
|
bm.free()
|
|
return True
|
|
|
|
def select_edges_by_angle():
|
|
"""
|
|
Select all mesh objects where ALL edges are angled 40-60° or 120-140° from X axis.
|
|
"""
|
|
# Deselect all objects first
|
|
bpy.ops.object.select_all(action='DESELECT')
|
|
|
|
selected_count = 0
|
|
|
|
# Check for both +45° (40-60°) and -45° (120-140°) ranges
|
|
angle_ranges = [(40, 60), (120, 140)]
|
|
|
|
# Iterate through all objects in the scene
|
|
for obj in bpy.context.scene.objects:
|
|
if obj.type == 'MESH':
|
|
if all_edges_in_angle_range(obj, ranges=angle_ranges):
|
|
obj.select_set(True)
|
|
selected_count += 1
|
|
print(f"Selected: {obj.name}")
|
|
|
|
print(f"\nTotal objects selected: {selected_count}")
|
|
|
|
# Run the script
|
|
select_edges_by_angle() |