On creation
Started as a comment and became an answer
Could you add some context on how the mesh came to be, are you
creating from scratch with a script.
If using bmesh operators often the new geometry is returned, for example making question model from a circle primitive using the extrude and inset operators.
Example using bmesh to add a cylinder bmesh.ops.create_cone(...)
find the top face, then inset in and up.
import bpy
import bmesh
from mathutils import Matrix
me = bpy.data.meshes.new("Wedding Cake")
segments = 16 #oops got cut
bm = bmesh.new()
bmesh.ops.create_cone(bm,
diameter1=2,
diameter2=2,
cap_ends=True,
depth=0.5,
segments=segments)
top_face = [f for f in bm.faces
if len(f.verts) == segments
and f.normal.angle((0, 0, 1)) < 1e-5]
ret = bmesh.ops.inset_region(bm,
faces=top_face,
thickness=0.5,
#depth=0.1,
use_relative_offset=True,
)
ret = bmesh.ops.inset_individual(bm,
faces=top_face,
thickness=0,
depth=1,
use_relative_offset=True,
)
bm.to_mesh(me)
To continue the "hard sell on bmesh over bpy.ops" what if we want to make something like this
is a matter of extending above to inset the faces returned from the inset operator
for f in ret["faces"]:
ret = bmesh.ops.inset_individual(bm,
faces=[f],
thickness=0.4,
depth=0.4,
use_relative_offset=True,
)
or instead with
bmesh.ops.extrude_individual(bm,
faces=ret["faces"])
Another example, adding circles and bridging edge loops (ribs) As could be done with prior, some data is used and looped.
import bpy
import bmesh
from mathutils import Matrix
me = bpy.data.meshes.new("Wedding Cake")
segments = 16
steps = ((0, 1),
(0.3, 1),
(0.3, 0.7),
(0.5, 0.7),
(0.50001, 0.4), # gltches on same
)
bm = bmesh.new()
def create_circle(h, radius):
ret = bmesh.ops.create_circle(bm,
radius=radius,
segments=segments,
matrix=Matrix.Translation((0, 0, h)))
return list(set(e for v in ret["verts"] for e in v.link_edges))
ribs = [create_circle(h, radius) for h, radius in steps]
for i in range(1, len(ribs)):
bmesh.ops.bridge_loops(bm,
use_pairs=True,
edges=ribs[i-1] + ribs[i],
)
bm.to_mesh(me)
Nothings happening
what version can this script running on? i try 2.81 but does not
produce anything
Note script only creates a mesh, the data part of an object, we only see a mesh if it is assigned to an object. To assign in UI (image above) go to properties data and change the linked mesh..
Or via python, create a new object using the mesh and link it to the context collection. Append following to scripts above
ob = bpy.data.objects.new("Wedding Cake", me)
context.collection.objects.link(ob)
or if using in a create mesh operator (self)
object_data_add(context, me, operator=self)
Selecting the verts
For finding from height and radius, and assuming the origin (0, 0, 0) lies on symmetry axis (0, 0, 1) ie the z axis , would look at the distance of verts from (0, 0, h) (v.co - Vector((0, 0, h))).length
A vector length test searches within a sphere of influence. Could narrow down further by looking at z component, I go old-school here and look for within a tolerance, abs(v.co.z - h) < TOL
where TOL = 1e-5
For really large meshes instead of sorting based on distance, could use mathutils.kdtree
to find closest.
Utilize the ngon
For this particular example the inner loop is the verts of the ngon.
Here is an example that finds the ngon whos face is closest to (0, 0, h) and selects its vertices.
Test script, Assumes mesh in edit mode, no selection. If run on default cylinder selects verts of top face.
import bpy
import bmesh
from mathutils import Vector
context = bpy.context
ob = context.object
me = ob.data
bm = bmesh.from_edit_mesh(me)
h = 1
radius = 1
eps = 1e-05
ngons = [f for f in bm.faces if len(f.verts) > 4]
# sort by distance from (0, 0, h)
ngons.sort(key=lambda f : (f.calc_center_median() - Vector((0, 0, h))).length)
if ngons:
for v in ngons.pop(0).verts:
v.select = True
bmesh.update_edit_mesh(me)
The edgeloop of the ngon would be ngon.edges
or l.edge for l in ngon.loops
can grow the selection to next loop, will be the edges in e for f in edge.link_faces for e in f.edges if not any(v.select for v in e.verts)
.