ADD ON: Altitude to vertex group

Hi, here a little script to split a mesh in 5 vertex group. The group are made selecting the face distance from the center, or the face distance (along Z axis) from a plane. I think that can be usefull with landscape.

User interface (very simple):
https://lh6.googleusercontent.com/_uGKL7dhNVTY/TcbsyTbmG8I/AAAAAAAAAtA/NVCsBHRZ_JI/s800/UI.jpg

With Level 1, 2, 3, 4 you set the 5 level for vertex group.
With Sphere on/off you set the “type of the distance”: From the center of the object, or from distance from the plane along z axis.
Example 1 (Sphere uncheked)
https://lh5.googleusercontent.com/_uGKL7dhNVTY/TcbsypOkx1I/AAAAAAAAAtE/M3O6BjiXSvY/s640/Plane.jpg

Example 2 (Sphere checked)
https://lh3.googleusercontent.com/_uGKL7dhNVTY/TcbsypviynI/AAAAAAAAAtI/Ttyt6529XNs/s640/Sphere.jpg

Complete Code: http://www.pasteall.org/21460/python

I have splitted the code in 2 part.
Part 1


import bpy
import random
from mathutils import Vector
#Return the max value of the list
def Max(Dimensions):
    max=0
    for value in Dimensions:
        if value > max:
            max=value
    return max
#Return distance from 2 vertex    
def Distance(p1,p2):
    ob = bpy.context.object
    mesh = ob.data
    p1 = p1 * ob.matrix_world
    v = p1-p2
    distance=v.length
    return distance
#Return Min and Max value of faces.center of the mesh
#Maybe there is a better algo for this    
def MinMax(mesh):
    min=100000
    max=0
    #If is a sphere: distance from 0,0,0
    #else vertical distance (Z axis)
    if bpy.context.scene.Sphere:
        for face in mesh.faces:
            n=Distance(face.center,Vector((0.0,0.0,0.0)))
            if n <= min:
                min=n
            elif n>max:
                max=n
    else:
        for face in mesh.faces:
            n=(face.center.z)
            if n <= min:
                min=n
            elif n>max:
                max=n
    return (min, max)
def MakeMaterial(Name,R,G,B):
    random.seed()
    mat = bpy.data.materials.new(Name)
    mat.diffuse_color = (R, G, B)
    return mat
#Add a material to vertex group.
#Create it If material slot doesn't exist
def AddMatToVertexGroup(MaterialName,VertexGroupName,R,G,B):
    obj = bpy.context.object
    Exist=False
    for cont in range (0,  len(obj.material_slots)):
        obj.active_material_index=cont
        if obj.material_slots[cont].name==MaterialName:
            Exist=True
            break
    if Exist:
        bpy.ops.object.editmode_toggle()
        bpy.ops.mesh.select_all(action='DESELECT')
        bpy.ops.object.vertex_group_set_active(group=VertexGroupName)
        bpy.ops.object.vertex_group_select()
        bpy.ops.object.material_slot_assign()
        bpy.ops.object.editmode_toggle()
    else:
        bpy.ops.object.material_slot_add() #Add a material slot
        obj.material_slots[obj.material_slots.__len__() - 1].material = MakeMaterial(MaterialName,R,G,B) #Assign a material to the last slot
        bpy.ops.object.vertex_group_set_active(group=VertexGroupName)  #Select the vertex group
        bpy.ops.object.editmode_toggle()  #Go in edit mode
        bpy.ops.mesh.select_all(action='DESELECT') #Deselect all the vertices
        bpy.ops.object.vertex_group_select() #Select the vertices of the vertex group
        bpy.ops.object.material_slot_assign() #Assign the material on the selected vertices
        bpy.ops.object.editmode_toggle()  #Go in object mode
 
 
#Create a Vertex group and select the vertices
def AddVertexGroup(Name,Vertex):
    obj = bpy.context.object
    Group = None
    New = False
    #Better mode to test if exist a Vertex group?
    #I don't like try except
    try:
        bpy.ops.object.vertex_group_set_active(group=Name)
    except:
        New=True
 
    if New == True:
        Group = obj.vertex_groups.new(Name) #Create a Vertex Group
    else:
        bpy.ops.object.vertex_group_set_active(group=Name)
        Group=obj.vertex_groups[Name]
    #First delete all the vertex from the selected vertex group
    #then assign a new group of vertices
    bpy.ops.object.vertex_group_set_active(group=Name)
    bpy.ops.object.mode_set(mode="EDIT")
    bpy.ops.mesh.select_all(action='DESELECT')
    bpy.ops.object.vertex_group_select()
    bpy.ops.object.vertex_group_remove_from()
    bpy.ops.object.mode_set(mode="OBJECT")
    Group.add(Vertex, 1.0, 'ADD') #Add the vertices to the vertex group
    return Group
#Create the lists of the vertex for sphere type
def GroupCreateSphere():
    vgroup1 = []
    vgroup2 = []
    vgroup3 = []
    vgroup4 = []
    vgroup5 = []
    obj = bpy.context.object
    mesh = obj.data
    p2= Vector((0.0,0.0,0.0))
    for face in mesh.faces:
        if Distance(face.center,p2) <= bpy.context.scene.Level_1:
            vgroup1.append(face.vertices[0])
            vgroup1.append(face.vertices[1])
            vgroup1.append(face.vertices[2])
            if len(face.vertices) == 4: 
                vgroup1.append(face.vertices[3])
        elif Distance(face.center,p2) > bpy.context.scene.Level_1 and Distance(face.center,p2) <= bpy.context.scene.Level_2:
            vgroup2.append(face.vertices[0])
            vgroup2.append(face.vertices[1])
            vgroup2.append(face.vertices[2])
            if len(face.vertices) == 4: 
                vgroup2.append(face.vertices[3])
        elif Distance(face.center,p2) > bpy.context.scene.Level_2 and Distance(face.center,p2) <= bpy.context.scene.Level_3:
            vgroup3.append(face.vertices[0])
            vgroup3.append(face.vertices[1])
            vgroup3.append(face.vertices[2])
            if len(face.vertices) == 4: 
                vgroup3.append(face.vertices[3])
        elif Distance(face.center,p2) > bpy.context.scene.Level_3 and Distance(face.center,p2) <= bpy.context.scene.Level_4:
            vgroup4.append(face.vertices[0])
            vgroup4.append(face.vertices[1])
            vgroup4.append(face.vertices[2])
            if len(face.vertices) == 4: 
                vgroup4.append(face.vertices[3])
        elif Distance(face.center,p2) > bpy.context.scene.Level_4:
            vgroup5.append(face.vertices[0])
            vgroup5.append(face.vertices[1])
            vgroup5.append(face.vertices[2])
            if len(face.vertices) == 4: 
                vgroup5.append(face.vertices[3])
    group=AddVertexGroup("Level_1",vgroup1)
    AddMatToVertexGroup("Level_1",group.name, 0,0,1) #Blue
    group=AddVertexGroup("Level_2",vgroup2)
    AddMatToVertexGroup("Level_2",group.name,0,0.5,0) #Green dark
    group=AddVertexGroup("Level_3",vgroup3)
    AddMatToVertexGroup("Level_3",group.name,0,1,0) #Green
 
    group=AddVertexGroup("Level_4",vgroup4)
    AddMatToVertexGroup("Level_4",group.name,0.179,0.062,0.044) #Brown
 
    group=AddVertexGroup("Level_5",vgroup5)
    AddMatToVertexGroup("Level_5",group.name,1,1,1) #White
    return
#Create the lists of the vertex for plane type
def GroupsCreate():    
    vgroup1 = []
    vgroup2 = []
    vgroup3 = []
    vgroup4 = []
    vgroup5 = []
    obj = bpy.context.object
    mesh = obj.data
 
    for face in mesh.faces:
        if face.center.z <= bpy.context.scene.Level_1:
            vgroup1.append(face.vertices[0])
            vgroup1.append(face.vertices[1])
            vgroup1.append(face.vertices[2])
            if len(face.vertices)==4: 
                vgroup1.append(face.vertices[3])
        elif face.center.z > bpy.context.scene.Level_1 and face.center.z <= bpy.context.scene.Level_2:
            vgroup2.append(face.vertices[0])
            vgroup2.append(face.vertices[1])
            vgroup2.append(face.vertices[2])
            if len(face.vertices)==4: 
                vgroup2.append(face.vertices[3])
        elif face.center.z > bpy.context.scene.Level_2 and face.center.z <= bpy.context.scene.Level_3:
            vgroup3.append(face.vertices[0])
            vgroup3.append(face.vertices[1])
            vgroup3.append(face.vertices[2])
            if len(face.vertices)==4: 
                vgroup3.append(face.vertices[3])
        elif face.center.z > bpy.context.scene.Level_3 and face.center.z <= bpy.context.scene.Level_4:
            vgroup4.append(face.vertices[0])
            vgroup4.append(face.vertices[1])
            vgroup4.append(face.vertices[2])
            if len(face.vertices)==4: 
                vgroup4.append(face.vertices[3])
        elif face.center.z > bpy.context.scene.Level_4:
            vgroup5.append(face.vertices[0])
            vgroup5.append(face.vertices[1])
            vgroup5.append(face.vertices[2])
            if len(face.vertices)==4: 
                vgroup5.append(face.vertices[3])
    group=AddVertexGroup("Level_1",vgroup1)
    AddMatToVertexGroup("Level_1",group.name, 0,0,1)
    group=AddVertexGroup("Level_2",vgroup2)
    AddMatToVertexGroup("Level_2",group.name,0,0.5,0)
    group=AddVertexGroup("Level_3",vgroup3)
    AddMatToVertexGroup("Level_3",group.name,0,1,0)
 
    group=AddVertexGroup("Level_4",vgroup4)
    AddMatToVertexGroup("Level_4",group.name,0.179,0.062,0.044)
 
    group=AddVertexGroup("Level_5",vgroup5)
    AddMatToVertexGroup("Level_5",group.name,1,1,1)
    return
 #Suggest the 4 level
class SuggestOperator(bpy.types.Operator):
    bl_idname = 'suggest.altitudes'
    bl_label = 'Suggest altitude'
    bl_description = 'Suggest the four level'
    def execute(self, context):
        Min, Max = (MinMax(bpy.context.object.data))
        step = ( Max - Min) / 5
        bpy.context.scene.Level_1 = Min + step
        bpy.context.scene.Level_2 = Min + step*2
        bpy.context.scene.Level_3 = Min + step*3
        bpy.context.scene.Level_4 = Min + step*4
        return {'FINISHED'}

Part 2


#Execute
class MeshAltitudeOperator(bpy.types.Operator):
    bl_idname = 'mesh.altitude'
    bl_label = 'Start altitude'
    bl_description = 'Assign different vertex group to the high of the mesh'
    def execute(self, context):
        if bpy.context.scene.Sphere:
            GroupCreateSphere()
        else:
            GroupsCreate()
    return {'FINISHED'}
 
# Drawing the user interface
class MeshAltitudePanel(bpy.types.Panel):
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOL_PROPS"
    bl_label = "Altitude to vertex group"
    def __init__(self):        
        typ = bpy.types.Scene
        var = bpy.props
        max = Max(bpy.context.object.dimensions)
        typ.Level_1 = var.FloatProperty(description="Level 1", min=0, max=max, step=0.001, precision=5)
        typ.Level_2 = var.FloatProperty(description="Level 2", min=0, max=max, step=0.001, precision=5)
        typ.Level_3 = var.FloatProperty(description="Level 3", min=0, max=max, step=0.001, precision=5)
        typ.Level_4 = var.FloatProperty(description="Level 4", min=0, max=max, step=0.001, precision=5)
        typ.Sphere=var.BoolProperty(description="Use the distance from the center of the mesh", default=False)
    def draw(self, context):
        layout = self.layout
        col = layout.column()
        split = col.split(align=True)
        split.prop(context.scene, "Level_1", "Level 1")
        split = col.split(align=True)
        split.prop(context.scene, "Level_2", "Level 2")
        split = col.split(align=True)
        split.prop(context.scene, "Level_3", "Level 3")
        split = col.split(align=True)
        split.prop(context.scene, "Level_4", "Level 4")
        col.separator()
        split = col.split(align=True)
        split.prop(context.scene, "Sphere", "Sphere")
        split.operator('suggest.altitudes', text='Suggest')
        col.separator()
        split = col.split(align=True)
        split.operator('mesh.altitude', text='Assign')
# registering the script
def register():
    bpy.utils.register_module(__name__)
 
def unregister():
    bpy.utils.unregister_module(__name__)
    clear_properties()
if __name__ == "__main__":
    register()

Very nice!
Remove litte indent error

Should be:


    def execute(self, context):
        if bpy.context.scene.Sphere:
            GroupCreateSphere()
        else:
            GroupsCreate()
        return {'FINISHED'}

More detail, because yesterday I was a bit tired and maybe it was more understandable :eyebrowlift:

The script split the mesh in 5 level.
If I unselect “Sphere” the script take the distance from the plane 0 of the mesh along Z axis First example on first post).
If I select “Sphere” the script take the distance from the center of the mesh in every direction, useful with planet landscape (Second example on the first post).

“Suggest” button suggest the value for the Level: every level is equidistant.

The 5 level are :
<= Level 1
> Level 1 and <= Level 2
> Level 2 and <= Level 3
> Level 3 and <= Level 4
> Level 4

Work with triangles and quad face.

And naturally you can use with any mesh:

https://lh6.googleusercontent.com/_uGKL7dhNVTY/TchCfuyfNRI/AAAAAAAAAtg/o2cuoz5FOtA/s640/Monky.png