0
$\begingroup$

As seen on the screenshot below, How can i select 1 edge loop based on its diameter (radius) and height? For example I only want to select 1 of the 2 edge loops that has different diameter but are on same height

I tried

`my_verts = [v for v in verts if (10 / 1000)  <= v.co.z <= (30 / 1000) and (-80 / 1000)  <= v.co.y <= (80 / 1000) and (-80 / 1000)  <= v.co.x <= (80 / 1000) ] `

But that does not really wors well

d

$\endgroup$

1 Answer 1

3
$\begingroup$

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.

enter image description here

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

enter image description here

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.

enter image description here

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) 

enter image description here

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).

$\endgroup$
8
  • $\begingroup$ I am using a script to place a cilinder and use inset to extrude the faces up or down Im not yest good in bmesh so i use bpy.ops for this Currently i try to make vertex groups and select these but the bpy.ops.mesh.bevel command seems to divide the new edge loops between multiple groups and thats not really what i am lookng for I will try your soution also to see what i can learn from it bmesh seems to be shorted coding then bpy $\endgroup$
    – DGRL
    Commented Dec 21, 2019 at 13:35
  • $\begingroup$ Really strongly recommend ditchng bpy.ops.mesh for bmesh. It takes a bit to get the hang of but once you do you wont go back. Added example of inset using bmesh to add to the sell. We can keep pushing the top face into the operator and need only adjust thickness and depth. $\endgroup$
    – batFINGER
    Commented Dec 21, 2019 at 14:15
  • $\begingroup$ Am i correct by saying that the difference between bpy.ops and bmes is that all the operators for example bpy.ops.object.vertex_group_select can be used in bmes except that bpy.ops is not present? What i see on the API page is that BPY.OPS is always not bold and the rest is bold So to me it looks like that the operator object.vertex_group_select can be used in combination wit py.ops as well as with bmesh I.E. bmesh.object.vertex_group_select or am i wrong? $\endgroup$
    – DGRL
    Commented Dec 21, 2019 at 14:23
  • 1
    $\begingroup$ Whoa there... Let's not make sweeping generalizations and just move slowly. Check out the bmesh inset example just added (against perhaps the code used to produce yours) . bpy.ops.mesh.primitive_cylinder_add() correlates with bmesh.ops.create_cone(...). then the inset region operator should look familiar. But there's no need to select vertices and other blah that is required to use edit mode bpy.ops.mesh.... simply keep driving in the top face. Would like to change this question to making a "wedding cake" mesh. Would be much the same as, as I understand it, selecting that loop has $\endgroup$
    – batFINGER
    Commented Dec 21, 2019 at 14:37
  • $\begingroup$ become your impasse, and selecting it based on radius and z location is probably not the way to go. $\endgroup$
    – batFINGER
    Commented Dec 21, 2019 at 14:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .