1

I need to process a mesh so that all of the edges are below a certain threshold, say x units.

(I am throwing a mesh into an acoustic simulator, which requires the longest edge length to be < 1/3 of the maximum wavelength)

How can accomplish this with a Python script?

P i
  • 3,921
  • 9
  • 34
  • 53

2 Answers2

3

Example subdividing the default cube.

import bpy
import bmesh

threshold = 0.1
obj = bpy.data.objects['Cube']
bm = bmesh.from_edit_mesh(obj.data)

#do ... while
while True:
    edges = [e for e in bm.edges if e.calc_length() > threshold]
    if not edges:
        break
    bmesh.ops.subdivide_edges(
        bm,
        edges=edges,
        cuts=1
        #use_single_edge=True,
        #use_grid_fill=True
        )
    #triangulate
    bmesh.ops.triangulate(bm, faces=bm.faces, use_beauty=True)  

bmesh.update_edit_mesh(obj.data)
pink vertex
  • 9,896
  • 1
  • 25
  • 44
0

Here is a full implication of pink vertex's solution:

(Thanks to CoDEmanX!)

enter image description here

enter image description here

# Edge-Splitter
#
# π 11.2.2014
#
# Repeatedly splits all edges with length > max_threshold and re-triangulates
#
#   To load, one of the following:
#      1) paste into blender's inbuilt text editor, which has a menu option for "run script", which you need to do.
#      2) type into blender python prompt:
#        f='/path/to/???.py'; exec(   compile( open(f).read(), f, 'exec' )   )
#      3) Place in Blender's Addons folder (on my Mac it is /Applications/Blender.app/Contents/MacOS/2.69/scripts/addons/)
#          and InfoBar -> File -> User Prefs -> Addons -> (find and check it)
#
# NOTE: You can also make your own scripts folder and InfoBar -> File -> User Prefs -> File -> Scripts -> [ type it here ]
# 
# To use:
#    * With target object selected
#    * in edit mode
#    * with the mouse over the 3-D view
#   Hit SpaceBar
#
#   ...and search for "LimitEdgeLen"
#
#   Adjust the max edge length in the panel

bl_info = {
    "name"        : "Limit Edge Length",
    "author"      : "pi",
    "version"     : (1, 0),
    "blender"     : (2, 67, 0),
    "location"    : "View3D > T-panel > Object Tools",
    "description" : "foo",
    "warning"     : "",
    "wiki_url"    : "",
    "tracker_url" : "",
    "category"    : "Add Mesh"
    }

import bpy, bmesh

from mathutils import Vector

# http://blenderscripting.blogspot.co.uk/2013/05/adding-geometry-to-existing-geometry.html

def main( context, maxlen ):
    obj = bpy.context.object
    me = obj.data

    bpy.ops.object.mode_set( mode = 'EDIT' )

    bm = bmesh.from_edit_mesh( me )


    #do ... while
    while( True ):

        long_edges = [ e for e in bm.edges if e.calc_length() > maxlen ]

        if not long_edges:
            break

        bmesh.ops.subdivide_edges(
            bm,
            edges=long_edges,
            cuts=1
            #use_single_edge=True,
            #use_grid_fill=True
           )

        bmesh.ops.triangulate( bm, faces=bm.faces, use_beauty=True )

    # update, while in edit mode  
    # thanks to ideasman42 for making this clear  
    # http://blender.stackexchange.com/questions/414/  
    bmesh.update_edit_mesh( me )

    # bpy.context.scene.update()


class MESH_OT_limit_edge_length( bpy.types.Operator ):
    """Tooltip"""
    bl_idname = "mesh.limit_edge_length"
    bl_label = "Limit Edge Length"
    bl_options = {'REGISTER', 'UNDO'}

    maxlen = bpy.props.FloatProperty(
        name        = "Max Length",
        description = "Subdivide edges until below this value",
        default     = 0.5,
        min         = 0.001, 
        max         = 999
        )

    @classmethod
    def poll( cls, context ):
        return ( context.object is not None  and
                context.object.type == 'MESH' )

    def invoke( self, context, event ):
        return context.window_manager.invoke_props_dialog( self )

    def execute( self, context ):
        main( context, self.maxlen )
        return {'FINISHED'}


def draw_func( self, context ):
    layout = self.layout
    layout.operator( MESH_OT_limit_edge_length.bl_idname )


def register( ):
    bpy.utils.register_class( MESH_OT_limit_edge_length )
    bpy.types.VIEW3D_PT_tools_objectmode.prepend( draw_func )


def unregister( ):
    bpy.utils.unregister_class( MESH_OT_limit_edge_length )
    bpy.types.VIEW3D_PT_tools_objectmode.remove( draw_func )


if __name__ == "__main__":
    register( )
P i
  • 3,921
  • 9
  • 34
  • 53