Finding a specific face/vertex/edge based on position value, not indices value [Looking for answers possible via python]

Hi everyone!

I'm trying to select a face/vertex/edge based on location rather than selecting it based on its specific index.  After the specific face/vertex/edge is selected, I have a code that I've found online that can then increase the size of the selected face by a radial distance, which is working the way I want it to.

I've found out that the index number changes when I run the script to generate everything in my model, so I can't (or don't know how to) select the specific face that exists in the location that i need to generate the radius of selected faces at, based on indexing.  I thought a simple solution would be to select based on location instead (ie., 0,0,1), but after searching online for a solution I haven't been able to get any closer to a resolution.

If anyone has ideas or links to help, I'd appreciate your help.  Please note though, I am a beginner in python and Blender so descriptive explanations would be appreciated.

Attached are images and code to better describe my problem:

This is an image of the working script that creates a radius of selection around a manually PRE-SELECTED FACE.  It works great, but I need the face to be selected via python (not manually) and the face that is selected can't change location because the face index changed when the script is run a second time, etc: 


Here's the script that creates the above radius around a manually pre-selected face:

# This example assumes we have a mesh object in edit-mode

import bpy
import bmesh
# from mathutils import Vector

# Get the active mesh
ob = bpy.context.object # get the active object for example
mesh = ob.data

#45438 face number to start at. &lt;---this changes when rerunning script
#length should equal radius of circle *1.1666

# Get a BMesh representation
bm = bmesh.from_edit_mesh(mesh)

# notice in Bmesh polygons are called faces
#bm.faces[45438].select = True  # select index 4  #this line doesn't work

# this is a coordinate like Vector((0,0,0))
active_median = bm.faces.active.calc_center_median()

# Modify the BMesh, can do anything here...
for f in bm.faces:
    f.select = False
    if (f.calc_center_median()-active_median).length &lt;= 0.035:
        f.select = True

# Show the updates in the viewport
# and recalculate n-gon tessellation.
bmesh.update_edit_mesh(mesh, True)
Some methods to do this, in my preferred order. All Scripts below will select the closest face to the scene cursor.

BVH Tree

The module mathutils.bvhtree 


  BVH tree structures for proximity searches and ray casts on geometry.


Make a lookup tree directly from the bmesh and use its find_nearest(location) method to return index of element closest to that location.

Test script run in edit mode 

import bpy
import bmesh
from mathutils.bvhtree import BVHTree
context = bpy.context
ob = context.object
scene = context.scene
mwi = ob.matrix_world.inverted()

loc = mwi @ scene.cursor.location

me = ob.data
bm = bmesh.from_edit_mesh(me)
bvhtree = BVHTree.FromBMesh(bm)

pos, norm, idx, d = bvhtree.find_nearest(loc)
if pos is not None: # is zero vector boolean False?
    for f in bm.faces:
        f.select = f.index == idx

    bmesh.update_edit_mesh(me)


Sort the faces

If the mesh is pretty small then sorting the faces based on distance from location to face centre, could suffice.

faces = sorted(bm.faces, 
        key=lambda f: (f.calc_center_median() - loc).length)
closest = faces[0]


Closest point on mesh.

Object.closest_point_on_mesh(...)   Uses object or local coordinates

returns valid, location of closest point, face normal, face index.

The closest point on mesh must be run in object mode.  Remember that switching modes will most likely trash any existing edit mode bmesh.

mesh version

Toggle to object mode, select then switch to edit mode, 

import bpy
import bmesh
# from mathutils import Vector
bpy.ops.object.mode_set()
context = bpy.context
ob = context.object
scene = context.scene
mwi = ob.matrix_world.inverted()

loc = mwi @ scene.cursor.location

hit, loc, norm, idx = ob.closest_point_on_mesh(loc)

if hit:
    me = ob.data
    me.polygons.foreach_set("select", 
            [p.index == idx for p in me.polygons])
    bpy.ops.object.mode_set(mode='EDIT')


bmesh version

import bpy
import bmesh
# from mathutils import Vector
bpy.ops.object.mode_set()
context = bpy.context
ob = context.object
scene = context.scene
mwi = ob.matrix_world.inverted()

loc = mwi @ scene.cursor.location

hit, loc, norm, idx = ob.closest_point_on_mesh(loc)

if hit:
    bpy.ops.object.mode_set(mode='EDIT')
    me = ob.data
    bm = bmesh.from_edit_mesh(me)
    for f in bm.faces:
        f.select = f.index == idx

    bmesh.update_edit_mesh(me, True)


Note: v2.80 Test Script(s) Substitute loc = mwi * scene.cursor_location to make them 2.7x compato