2

In this case, the object is a 2d plane in 3d space. I want to select the vertexes on the corners of the object using the Blender Python API. In this case the corners would be the boundaries of the plane:

Picture of plane

You are welcome to just name the commands that you would use if you don't know how to use the API.

Thank you

2 Answers2

2

Considering the mesh is close to a plane,

that can be done by taking boundary vertices, then try to see which 4 of them are closest to a 90° degrees angle.

This script does that:

import bpy
import bmesh
from mathutils import Vector
import heapq

bpy.ops.object.mode_set(mode = 'OBJECT')

# Get active object
obj = bpy.context.active_object
# Deselect all vertices
bpy.ops.object.mode_set(mode = 'EDIT') 
bpy.ops.mesh.select_mode(type="VERT")
bpy.ops.mesh.select_all(action = 'DESELECT')

# Back to object mode so that we can select vertices
bpy.ops.object.mode_set(mode = 'OBJECT')

# Gets bmesh from obj data
bm = bmesh.new()
bm.from_mesh( obj.data )

# Allow indexed access for vertices and edges
bm.verts.ensure_lookup_table()
bm.edges.ensure_lookup_table()

# Vector from an edge
def vect_from_edge( e ):
    return (e.verts[0].co - e.verts[1].co).normalized()

# Absolute of the dot product: the smaller the closer to 90°
# => "corner intensity"
def abs_dot( e1, e2 ):
    return abs( vect_from_edge( e1 ).dot( vect_from_edge( e2 ) ) )

boundary_vertices = []
# Collect boundary vertices
for vert in (v for v in bm.verts if v.is_boundary):
    # Corresponding boundary edges
    edges = [e for e in vert.link_edges if e.is_boundary]
    # But consider only 2 (we dont want vertices at the jonction of 2 parts)
    if len( edges ) == 2:
        # Associates the vertex to its "corner intensity"
        boundary_vertices.append( (vert, abs_dot( edges[0], edges[1] ) ) )

# Get the 4 smallest "corner intensity" which should correspond to the wanted result
for v in [vi[0] for vi in heapq.nsmallest( 4, boundary_vertices, key = lambda vi:vi[1] )]:
    obj.data.vertices[v.index].select = True

# Release the bmesh
bm.free()

Note: not sure this approach solves all the situations, though.

lemon
  • 60,295
  • 3
  • 66
  • 136
  • This works as intended in my case, thank you! How would you select all the vertices on the boundary of the plane (not just the corners)? – Can H. Tartanoglu Jul 21 '19 at 14:53
  • Edges have a 'is_boundary' property (as you can see in the code above). If your mesh has no hole, it is ok to consider this is an edge that surrounds your shape. – lemon Jul 21 '19 at 15:01
0

I had the same question today. I just found this:

How do I select specific vertices in blender using python script?

just change the 0 to whichever vert you need. Also probably set select = False for the ones you are no longer using.

Cole
  • 51
  • 4