4
$\begingroup$

With Python, how would I implement an edge slide of a vertex to a specific coordinate? For example, sliding a vertex along an edge loop to a X coordinate of, say, 10.

$\endgroup$
5
$\begingroup$

The Vertex Slide doesn't have a feature (currently Dec 2015) to limit the extent of a slide for any given axis. This means that there's no script-able way to do it from the operator by simply passing a few parameters. This doesn't mean an alternative doesn't exist, or several. Some code will have to be written though, and to make it usable as a tool also some UI code.

Projecting a vertex of an edge towards a Face on the YZ plane would have the same effect as limiting a vertex's sliding till it reached a given axis limit. (ie x = 10)

enter image description here

We can find the intersection of a line on the infinite plane using a built-in geometry function mathutils.geometry.intersect_line_plane . We then use the plane_nol=(1,0,0) to show the plane extends only in the YZ axes, and plane_co=(your_x, 0, 0) to give the plane an origin (this is the axis constraint)

# alias it first, for convenience here
intersect_l_p = mathutils.geometry.intersect_line_plane
intersect_l_p(line_a, line_b, plane_co, plane_no, no_flip=False)

and then overwrite the vertex location with the intersection location.

Let's take the example above where I have a plane on the X axis at about 4.2 units. and the Vertex i want to move along the arrow till it hits the plane.

Non-UI version.

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

import bpy
import bmesh
import mathutils

def extend_vertex(limit_axis='x', coordinate=4.2):

    obj = bpy.context.edit_object
    me = obj.data
    bm = bmesh.from_edit_mesh(me)
    verts = bm.verts
    try:
        v1, v2 = [v for v in bm.verts if v.select]
    except:
        print('need two vertices selected, or one edge')
        bm.free()
        return

    plane_idx = {'x': 0, 'y': 1, 'z': 2}.get(limit_axis)
    plane_co, plane_no = [0,0,0], [0,0,0]
    plane_no[plane_idx] = 1
    plane_co[plane_idx] = coordinate

    intersect_l_p = mathutils.geometry.intersect_line_plane
    new_co = intersect_l_p(v1.co, v2.co, plane_co, plane_no, False)
    
    # move closest of the two vertices         
    A_len = (v1.co-new_co).length
    B_len = (v2.co-new_co).length
    if A_len < B_len:
        v1.co = new_co
    else:
        v2.co = new_co

    bmesh.update_edit_mesh(me, True)


extend_vertex(limit_axis='x', coordinate=4.2)

warning:

This doesn't take into account the object's unapplied Transforms (origin may not coincide with the world's (0,0,0), you may have scaling, rotation, translation), easy enough to fix - but it complicates the example code a little.

To take matrix_world into account, do something like this: vertex_towards_plane.py

| improve this answer | |
$\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.