Featured post

new redirect for blender.org bpy docs.

http://www.blender.org/api/blender_python_api_current/ As of 10/11 november 2015 we can now link to the current api docs and not be worr...

Showing posts with label random. Show all posts
Showing posts with label random. Show all posts

July 11, 2012

randomize geometry

This snippet randomizes the z value of all vertices by a given amount. (be in object mode, with a mesh object selected)
import bpy
import random

verts = bpy.context.active_object.data.vertices

for i in verts:
    i.co.z *= random.uniform(0.7, 1.3) 
        
In combination with the separation script from a previous post you can get some neat effects, maybe this will plant some seeds

June 27, 2011

randomizing geometry

this code randomizes all internal vertices on a surface of faces, it takes into account the shortest edge connected to each vertex. What it doesn't do is store the initial vertex position, so any consecutive randomize will random atop of the newly randomized coordinate

# must be in object mode
# with no verts selected on the object.

import bpy
import random
from mathutils import Vector

index_list = []
tracker_list = []

for i in bpy.context.active_object.data.edges:
index_list.append(i.vertices[0])
index_list.append(i.vertices[1])
tracker_list.append([i.vertices[0], i.vertices[1]])

# rudimentary numeric sorting, came in handy for debugging, but
# not essential for operational code.
sorted_list = sorted(index_list)

# use a set to eliminate multiples fast
sorted_set = set(sorted_list)

# track all verts with 4 or more other verts attached, store as list_internals
list_internals = []
for num in sorted_set:
if sorted_list.count(num) >= 4: # quad mesh only.
list_internals.append(num)

'''
# this selects all internal geometry.
for i in list_internals:
bpy.context.active_object.data.vertices[i].select = True
'''
print("="*20)

# store the length of the shortest connected edge, for each internal vertex
min_length_list = []
meshdata = bpy.context.active_object.data.vertices
for vert in list_internals:

# find each edge that uses this vert
# print(vert, "used in")
temp_storage = []
for pair in tracker_list:
if vert in pair:
vec1 = meshdata[pair[0]].co
vec2 = meshdata[pair[1]].co
dist = (vec1-vec2).length
temp_storage.append(dist)
# print(pair, "length is", dist)

shortest_attached_edge = min(temp_storage)
# print("shorted length is: ", shortest_attached_edge)

# store [vertnum, shortest_attached_edge]
min_length_list.append([vert, shortest_attached_edge])

for i in min_length_list:
print(i)

# randomize to .4 or shortest edge.
def randomize_vector(vector_in, amount):
amount = amount * 0.2
# random.uniform(0.7, 1.3)
vecx = random.uniform(vector_in.x-amount, vector_in.x+amount)
vecy = random.uniform(vector_in.y-amount, vector_in.y+amount)
vecz = random.uniform(vector_in.z-amount, vector_in.z+amount)

return Vector((vecx, vecy, vecz))

for i in min_length_list:
print(meshdata[i[0]].co, "randomize by ", 0.4*i[1] )
newvec = randomize_vector(meshdata[i[0]].co, 0.4*i[1])
print(newvec)
meshdata[i[0]].co = newvec


becomes

randomly placing vertices around a spherical surface

import bpy
import time
from math import radians
from random import randint
from mathutils import Vector, Euler

# constants
SPHERE_RADIUS = 0.7
NUM_VERTS = 116
MIN_DISTANCE = 0.19

# ttime in seconds beyond which iteration will be cancelled.
MAX_TIME = 20 

# consumable
Verts = []

# get start time
a_time = time.time()


def make_vertgon(Verts, object_name):
    object_mesh = object_name + "_mesh"
    mesh = bpy.data.meshes.new(object_mesh)
    mesh.from_pydata(Verts, [], [])
    mesh.update()
    new_object = bpy.data.objects.new(object_name, mesh)
    new_object.data = mesh
    
    scene = bpy.context.scene
    scene.objects.link(new_object)
    return


# populate the Verts list with verts randomly positioned around the radius
while(len(Verts)<=NUM_VERTS):
            
    ax_x = radians(randint(0, 360))
    ax_y = radians(randint(0, 360))
    ax_z = radians(randint(0, 360))
    myEul = Euler((ax_x, ax_y, ax_z), 'XYZ')
    
    outVec = Vector((SPHERE_RADIUS, 0.0, 0.0))
    outVec.rotate(myEul)

    # get current time
    b_time = time.time()
    
    # check time difference between current and start.
    elapsed_time = abs(a_time - b_time)    
    if elapsed_time > MAX_TIME:
        # breaking instead of running something that might be shy of infinite.
        break

    myToken = False    
    for B in Verts:       
        if (outVec-B).length < MIN_DISTANCE:
            myToken = True
            break
        
    if myToken == True:
        continue    
   
    Verts.append(outVec)
    
        
# draw verts randomly around the radius
make_vertgon(Verts, "stix")


'''
code notes:
    
this approach makes it obvious that SPHERE_RADIUS, NUM_VERTS and MIN_DISTANCE 
will reach equilibrium if their ratio approaches the optimal spread that 
NUM_VERTS has on the surface of the sphere.

The random nature of establishing vertex coordinates will often make it 
unlikely that any precise geometric distribution can be achieved.
'''