1
$\begingroup$

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?

$\endgroup$
3
$\begingroup$

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)
| improve this answer | |
$\endgroup$
  • $\begingroup$ And CTRL+T will re-triangulate -- nice! $\endgroup$ – P i Feb 10 '14 at 10:46
  • 2
    $\begingroup$ You can do that with bmesh.ops.triangulate(bm, faces=bm.faces, use_beauty=True) $\endgroup$ – CodeManX Feb 10 '14 at 11:20
0
$\begingroup$

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( )
| 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.