User Tools

Site Tools


Sidebar

Dan's Wiki

DokuWiki Instructions (local) DokuWiki Manual
Site Checker (Orphans Wanted)

Edit Sidebar

blender:python:addons:vertexdistribute

UVDistribute - Vertex Distribute

As of 2/7/2022, (see other page with better working code) this works as a script run in a Blender Text window, but isn't completed into a full add on. This allows you to select 3 or more Vertexes, select one point as the Active vertex, and they will be placed into alignment and distributed, using the farthest vertex as one anchor, and the Active vertex to be the other.

The mode set to OBJECT then to EDIT should not be necessary, but without it, the change is not visible within the 3D View window. Later I may be able to fix this.

To do this quickly, I found a copy of articles: one to determine the Active vertex, and one to determine the selected Vertexes. There probably is an easier way. But this does work.

This code is contained within my file “reflexPortExtension.blend”.

import bpy
import bmesh
import math
 
mode = bpy.context.active_object.mode
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.mode_set(mode='EDIT')
ob = bpy.context.object
me = ob.data
bm = bmesh.new()
bm.from_mesh(me)
 
def bmesh_vert_active(bm):
    if bm.select_history:
        elem = bm.select_history[-1]
        if isinstance(elem, bmesh.types.BMVert):
            return elem
    return None
 
 
def distance_between_vertexes(vert1, vert2):
    myDistance = 0
    for i in range(3):
        myDistance += (vert1.co[i] - vert2.co[i]) ** 2
    return math.sqrt(myDistance)
 
def vertsAreEqual(vert1, vert2):
    if (vert1 == None or vert2 == None):
        return False
    for i in range(3):
        if abs(vert1.co[i] - vert2.co[i]) > .00001:
            # print("out of range: ", i, vert1.co[i], vert2.co[i])
            return False
    return True
 
# For now, we'll do this the simple way. We can find the "Active" vertex with the method
# "bmesh_vert_active(bm)". Then we'll iterate and find the farthest vertex away. Then
# We'll distribute between these two points.
 
def main():
 
    activeVertex = bmesh_vert_active(bm)
    if (activeVertex == None):
        print("Active Vertex must be selected, usually the extreme left one.")
        return
 
 
    # bpy.ops.object.mode_set(mode='OBJECT')
 
 
    # bpy.ops.object.mode_set(mode='EDIT')
 
    # bpy.ops.object.mode_set(mode='EDIT')
    # we need to switch from Edit mode to Object mode so the selection gets updated
    # selectedVerts = [v for v in bpy.context.active_object.data.vertices if v.select]
    selectedVerts = [v for v in bm.verts if v.select]
    for v in selectedVerts:
        print("Selected vert: ", v.co)
    if (len(selectedVerts) < 3):
        print ("Requires 3 or more vertices to operate. Found: ", len(selectedVerts))
    else:    
        print ("\nStart")	
        print("Active vertex coordinates: ", activeVertex.co)
        # Find farthest vertex from the Active vertex
        oppositeVertex = None
        oppositeVertexDistance = 0
 
        for v in selectedVerts:
            d2verts = distance_between_vertexes(activeVertex, v)
            if d2verts > oppositeVertexDistance:
                oppositeVertex = v
                oppositeVertexDistance = d2verts
        # I have the oppositeVertex now
        print("oppositeVertex is: ", oppositeVertex.co)
 
        # Calculate amounts to change
        changeAmount = [0,0,0]
 
        for i in range(3):
            changeAmount[i] =  oppositeVertex.co[i] - activeVertex.co[i]
 
        print("changeAmount: ", changeAmount)
 
        # Now we can change the vertex(s) in between the outer 2 vertexes
        # Remove activeVertex and oppositeVertex. Have to use this
        # syntax because activeVertex is a BMVert
        print("length of selectedVerts before removing 2 maxes", len(selectedVerts))
        middleVerts = []
        for v in selectedVerts:
            if vertsAreEqual(activeVertex, v) or vertsAreEqual(oppositeVertex, v):
                pass
            else:
                # Append a tuple
                middleVerts.append((distance_between_vertexes(activeVertex,v), v))
 
        print("length of middleVerts after removing 2 maxes", len(middleVerts))
 
 
        # A function that returns the 'year' value:
 
        for mvTuple in middleVerts:
            print("middleVert Pre: ", mvTuple[1].co) 
 
        # Index is used to calculate distributed new distance
        index = 0
        for mvTuple in sorted(middleVerts):
            for xyz in range(3):
                # Distance between activeVertex and this middleVert
                mvTuple[1].co[xyz] = activeVertex.co[xyz] + changeAmount[xyz]*(1+index)/(len(middleVerts)+1)
 
            index = index + 1
 
        print("Done.")        
        for mvTuple in middleVerts:
            print("middleVert Post: ", mvTuple[1].co)  
 
 
        bpy.ops.object.mode_set(mode='OBJECT')
        bm.to_mesh(me)
        bm.free()
 
        bpy.ops.object.mode_set(mode=mode)
 
main()
 
#
blender/python/addons/vertexdistribute.txt · Last modified: 2022/02/20 02:11 by dwheele