2
$\begingroup$

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

$\endgroup$
2
$\begingroup$

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.

$\endgroup$
2
  • $\begingroup$ 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)? $\endgroup$ – Can Hicabi Tartanoglu Jul 21 '19 at 14:53
  • $\begingroup$ 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. $\endgroup$ – lemon Jul 21 '19 at 15:01
0
$\begingroup$

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.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.