Exemple #1
0
    def execute(self, context):
        settings = get_settings()
        dbg = settings.debug
        #if bpy.context.mode != 'OBJECT':
        #    bpy.ops.object.mode_set(mode = 'OBJECT')

        sce = context.scene
        n = sce.odc_implant_index
        implant_space = sce.odc_implants[n]

        implants = odcutils.implant_selection(context)
        layers_copy = [layer for layer in context.scene.layers]
        context.scene.layers[0]

        if implants != []:

            for implant_space in implants:
                #check if space already has an implant object.
                #if so, delete, replace, print warning
                if implant_space.implant and implant_space.implant in bpy.data.objects:
                    self.report({
                        'WARNING'
                    }, "replacing the existing implant with the one you chose")
                    Implant = bpy.data.objects[implant_space.implant]

                    #the origin/location of the implant is it's apex
                    L = Implant.location.copy()

                    world_mx = Implant.matrix_world.copy()

                    #the platorm is the length of the implant above the apex, in the local Z direction
                    #local Z positive is out the apex, soit's negative.
                    #Put the cursor there
                    sce.cursor_location = L - Implant.dimensions[
                        2] * world_mx.to_3x3() * Vector((0, 0, 1))

                    #first get rid of children...so we can use the
                    #parent to find out who the children are
                    if Implant.children:
                        for child in Implant.children:
                            sce.objects.unlink(child)
                            child.user_clear()
                            bpy.data.objects.remove(child)

                    #unlink it from the scene, clear it's users, remove it.
                    sce.objects.unlink(Implant)
                    Implant.user_clear()
                    #remove the object
                    bpy.data.objects.remove(Implant)

                #TDOD what about the children/hardwares?
                else:
                    world_mx = Matrix.Identity(4)

                world_mx[0][3] = sce.cursor_location[0]
                world_mx[1][3] = sce.cursor_location[1]
                world_mx[2][3] = sce.cursor_location[2]

                #is this more memory friendly than listing all objects?
                current_obs = [ob.name for ob in bpy.data.objects]

                #link the new implant from the library
                odcutils.obj_from_lib(settings.imp_lib, self.imp)

                #this is slightly more robust than trusting we don't have duplicate names.
                for ob in bpy.data.objects:
                    if ob.name not in current_obs:
                        Implant = ob

                sce.objects.link(Implant)

                #this relies on the associated hardware objects having the parent implant
                #name inside them
                if self.hardware:
                    current_obs = [ob.name for ob in bpy.data.objects]

                    inc = self.imp + '_'
                    hardware_list = odcutils.obj_list_from_lib(
                        settings.imp_lib, include=inc)
                    print(hardware_list)
                    for ob in hardware_list:
                        odcutils.obj_from_lib(settings.imp_lib, ob)

                    for ob in bpy.data.objects:
                        if ob.name not in current_obs:
                            sce.objects.link(ob)
                            ob.parent = Implant
                            ob.layers[11] = True

                delta = Implant.dimensions[2] * world_mx.to_3x3() * Vector(
                    (0, 0, 1))
                print(delta.length)
                world_mx[0][3] += delta[0]
                world_mx[1][3] += delta[1]
                world_mx[2][3] += delta[2]

                Implant.matrix_world = world_mx

                if sce.odc_props.master:
                    Master = bpy.data.objects[sce.odc_props.master]
                    odcutils.parent_in_place(Implant, Master)
                else:
                    self.report({
                        'WARNING'
                    }, 'No Master Model, placing implant anyway, moving objects may not preserve spatial relationships'
                                )

                #looks a little redundant, but it ensure if any
                #duplicates exist our referencing stays accurate
                Implant.name = implant_space.name + '_' + Implant.name
                implant_space.implant = Implant.name

                odcutils.layer_management(sce.odc_implants, debug=dbg)

        for i, layer in enumerate(layers_copy):
            context.scene.layers[i] = layer
        context.scene.layers[11] = True
        return {'FINISHED'}
Exemple #2
0
    def execute(self, context):
        settings = get_settings()
        dbg = settings.debug
        #if bpy.context.mode != 'OBJECT':
        #    bpy.ops.object.mode_set(mode = 'OBJECT')

        sce = context.scene
        implants = odcutils.implant_selection(context)

        layers_copy = [layer for layer in context.scene.layers]
        context.scene.layers[0] = True

        if implants != []:

            for implant_space in implants:
                #check if space already has an implant object.
                #if so, delete, replace, print warning
                Implant = bpy.data.objects[implant_space.implant]

                if Implant.rotation_mode != 'QUATERNION':
                    Implant.rotation_mode = 'QUATERNION'
                    Implant.update_tag()
                    sce.update()

                if bpy.data.objects.get(implant_space.drill):
                    self.report(
                        {'WARNING'},
                        "replacing the existing drill with the one you chose")
                    Sleeve = bpy.data.objects[implant_space.drill]
                    #unlink it from the scene, clear it's users, remove it.
                    sce.objects.unlink(Sleeve)
                    Implant.user_clear()
                    #remove the object
                    bpy.data.objects.remove(Sleeve)

                current_obs = [ob.name for ob in bpy.data.objects]

                #link the new implant from the library
                settings = get_settings()
                odcutils.obj_from_lib(settings.drill_lib, self.drill)

                #this is slightly more robust than trusting we don't have duplicate names.
                for ob in bpy.data.objects:
                    if ob.name not in current_obs:
                        Sleeve = ob

                sce.objects.link(Sleeve)
                Sleeve.layers[19] = True
                mx_w = Implant.matrix_world.copy()
                #point the right direction
                Sleeve.rotation_mode = 'QUATERNION'
                Sleeve.rotation_quaternion = mx_w.to_quaternion()
                Sleeve.update_tag()
                context.scene.update()
                Trans = Sleeve.rotation_quaternion * Vector(
                    (0, 0, -self.depth))
                Sleeve.matrix_world[0][3] = mx_w[0][3] + Trans[0]
                Sleeve.matrix_world[1][3] = mx_w[1][3] + Trans[1]
                Sleeve.matrix_world[2][3] = mx_w[2][3] + Trans[2]

                Sleeve.name = implant_space.name + '_' + Sleeve.name
                implant_space.drill = Sleeve.name
                Sleeve.update_tag()
                context.scene.update()
                odcutils.parent_in_place(Sleeve, Implant)
                odcutils.layer_management(sce.odc_implants, debug=dbg)
        for i, layer in enumerate(layers_copy):
            context.scene.layers[i] = layer
        context.scene.layers[19] = True
        return {'FINISHED'}
def cloth_fill_main(context, loop_obj, oct, smooth, debug = False):
    '''
    notes:
       make sure the user view is such that you can see the entire ring with
       out any corosses (knots)
       
       if calling from script not in 3dview, you can override the view
       
    args:
        context - blender context
        loop_obj:  blender curve object or mesh object representing just a loop
        oct - octree depth for the grid to fill.
        smooth - iteartions to smooth the surface (soap bubble effect)
    return:
        CurveMesh :  The filled looop object type Blender Object (Mesh) 
    '''
    
    #selection mode = verts
    sce = context.scene
    context.tool_settings.mesh_select_mode = [True,False,False]
    
    #get the space data
    v3d = bpy.context.space_data
    v3d.transform_orientation = 'GLOBAL'
    v3d.pivot_point = 'MEDIAN_POINT'
    
    region = v3d.region_3d        
    vrot = region.view_rotation #this is a quat
    
    #set object mode...force selection
    if context.mode != 'OBJECT':
        bpy.ops.object.mode_set(mode='OBJECT')
    
    bpy.ops.object.select_all(action='DESELECT')
    context.scene.objects.active = loop_obj
    loop_obj.select = True
    
    #change the mesh orientation to align with view..for blockout
    odcutils.reorient_object(loop_obj, vrot) #TODO test this
    sce.update()
        
    if loop_obj.type in {'CURVE','MESH'}:
        if loop_obj.type == 'CURVE':
            #check if cyclic
            if not loop_obj.data.splines[0].use_cyclic_u:
                loop_obj.data.splines[0].use_cyclic_u = True #TODO: add this over to margin

            #convert the curve to a mesh...so we can use it.
            bpy.ops.object.duplicate()
            bpy.ops.object.convert(target='MESH', keep_original = False)
            #active object is now the mesh version of the curve
            
        else:
            #make sure it's a loop
            if len(loop_obj.data.vertices) != len(loop_obj.data.edges):
                print('this is not a loop')
                return
            else:
                bpy.ops.object.duplicate()
                #active object is now the mesh duplicate
    
    #this will become our final cloth filled objec
    CurveMesh = context.object
    CurveMesh.name = "Cloth Tray Mesh"
    
    #do some size estimation
    size = max(list(CurveMesh.dimensions))
    grid_predict = size * 0.9 / pow(oct,2)
    print("grid prediction is:  " + str(grid_predict))
     
                    
    #make a duplicate...
    current_objects = list(bpy.data.objects) #remember current objects to ID new ones later
    bpy.ops.object.duplicate()
    for obj in sce.objects:
        if obj not in current_objects:
            obj.name = "cloth_temp"
            Temp = obj
    
    #fill the the surface of the temp
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_all(action='SELECT')       
    bpy.ops.mesh.fill()
    
    #stretch it out a little
    bpy.ops.mesh.select_all(action = 'DESELECT')
    bpy.context.tool_settings.mesh_select_mode = [False,True,False]
    bpy.ops.mesh.select_non_manifold()
    bpy.ops.object.editmode_toggle()
    
    eds = [ed for ed in Temp.data.edges if ed.select]
    barrier = .05 * min(Temp.dimensions)
    odcutils.extrude_edges_out_view(Temp.data, eds, Temp.matrix_world, barrier/5, debug = debug)
    bpy.ops.object.editmode_toggle()
    
    bpy.context.tool_settings.mesh_select_mode = [False,True,False]
    bpy.ops.mesh.select_non_manifold()
    bpy.ops.mesh.extrude_edges_move()
    bpy.ops.object.editmode_toggle()
    
    eds = [ed for ed in Temp.data.edges if ed.select]
    odcutils.extrude_edges_out_view(Temp.data, eds, Temp.matrix_world, barrier, debug = debug)
    bpy.ops.object.editmode_toggle()
    bpy.context.tool_settings.mesh_select_mode = [True,False,False]
    
    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.ops.object.select_all(action='DESELECT')
    
    CurveMesh.select = True
    sce.objects.active = CurveMesh
    CurveMesh.rotation_mode = 'QUATERNION'
    
    #make the origin the same as the bez curve?
    sce.cursor_location = loop_obj.location
    bpy.ops.object.origin_set(type = 'ORIGIN_CURSOR')
    
    if CurveMesh.parent:
        Parent = CurveMesh.parent
        reparent = True
        wmx = CurveMesh.matrix_world.copy()
        CurveMesh.parent = None
        CurveMesh.matrix_world = wmx
    else:
        wmx = Matrix.Identity(4)
        reparent = False
    #unrotate it so we can make a nice remesh surface
    #although why this doesn't work with local coords I dunno
    bpy.ops.object.rotation_clear()

    
    #flatten to view...fill in the loop
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_all(action='SELECT')
    #get the space data
    v3d = bpy.context.space_data
    v3d.transform_orientation = 'LOCAL'
    v3d.pivot_point = 'MEDIAN_POINT'
    bpy.ops.transform.resize(value=(1, 1, 0), constraint_orientation='LOCAL')
    bpy.ops.mesh.looptools_space()
    bpy.ops.mesh.fill()

    #add modifiers
    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.ops.object.modifier_add(type='SOLIDIFY')
    bpy.ops.object.modifier_add(type='REMESH')
    
    solmod = CurveMesh.modifiers["Solidify"]
    solmod.thickness = grid_predict * .75
    
    remod = CurveMesh.modifiers["Remesh"]
    remod.octree_depth = oct
    remod.scale = .9
    
    #for some reason the modifier weren't updating
    bpy.ops.object.editmode_toggle()
    bpy.ops.object.editmode_toggle()
    

    #problem with applying modifiers...new method.
    mesh = CurveMesh.to_mesh(bpy.context.scene, True, 'RENDER')
    new_obj = bpy.data.objects.new(CurveMesh.name, mesh)
    bpy.context.scene.objects.link(new_obj)
    new_obj.matrix_world = wmx
    
    bpy.context.scene.objects.active = new_obj
    
    CurveMesh.select = True
    bpy.context.scene.objects.active = CurveMesh
    bpy.ops.object.delete()
    
    new_obj.select = True
    CurveMesh = new_obj
    bpy.context.scene.objects.active = CurveMesh
    '''
    bpy.ops.object.modifier_apply(modifier="Solidify")
    
    bpy.ops.object.editmode_toggle()
    bpy.ops.object.editmode_toggle()
    
    bpy.ops.object.modifier_apply(modifier="Remesh")
    '''

    
    bpy.ops.object.mode_set(mode='EDIT')        
    bpy.ops.mesh.select_all(action = 'DESELECT')
    bpy.ops.object.mode_set(mode = 'OBJECT')
    
    #make it a 2d obejct
    bpy.context.tool_settings.mesh_select_mode = [False,False,True]
    flat = False
    n = 0
    while not flat:
        
        #hope to select a polygon not on the border
        CurveMesh.data.polygons[n].select = True
        bpy.ops.object.mode_set(mode = 'EDIT')
        bpy.ops.mesh.faces_select_linked_flat()
        bpy.ops.object.mode_set(mode = 'OBJECT')
        
        sel_faces = [poly for poly in CurveMesh.data.polygons if poly.select]
        if len(sel_faces) > len(CurveMesh.data.polygons)/3:
            flat = True
        
        if n > 100:
            break
        n+= 1
    bpy.ops.object.mode_set(mode='EDIT')       
    bpy.ops.mesh.delete()
    bpy.context.tool_settings.mesh_select_mode = [False,True,False]
    bpy.ops.mesh.select_loose()
    bpy.ops.mesh.delete(type='EDGE')
    bpy.ops.mesh.select_non_manifold()
    bpy.context.tool_settings.mesh_select_mode = [True,False,False]
    bpy.ops.mesh.select_all(action='INVERT')
    bpy.ops.mesh.vertices_smooth(repeat = smooth)         
    
    bpy.ops.object.mode_set(mode='OBJECT')
    

    bpy.ops.object.modifier_add(type='SHRINKWRAP')
    swrap = CurveMesh.modifiers["Shrinkwrap"]
    swrap.wrap_method = 'PROJECT'
    swrap.use_project_z = True
    swrap.use_negative_direction = True
    swrap.use_positive_direction = True
    swrap.target = Temp
    
    CurveMesh.rotation_quaternion = vrot
    bpy.ops.object.modifier_apply(modifier="Shrinkwrap")
    
    
    if reparent:
        CurveMesh.update_tag()
        sce.update()
        odcutils.parent_in_place(CurveMesh, Parent)
        
    
    bpy.ops.object.select_all(action='DESELECT')

    if debug < 3:
        Temp.select = True
        sce.objects.active=Temp
        bpy.ops.object.delete()

    CurveMesh.select = True
    sce.objects.active = CurveMesh
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_all(action='DESELECT')
    
    bpy.context.tool_settings.mesh_select_mode = [False,True,False]
    bpy.ops.mesh.select_loose()
    bpy.ops.mesh.delete(type='EDGE')
    bpy.context.tool_settings.mesh_select_mode = [True,False,False]
    bpy.ops.object.mode_set(mode='OBJECT')
    
    mx = CurveMesh.matrix_world
    sum_edges = 0
    if len(CurveMesh.data.edges) != 0:
        for ed in CurveMesh.data.edges:
            v0 = CurveMesh.data.vertices[ed.vertices[0]]
            v1 = CurveMesh.data.vertices[ed.vertices[1]]
            V = mx*v1.co - mx*v0.co
            sum_edges += V.length
            
        avg_edge = sum_edges/len(CurveMesh.data.edges)
            
        if debug:
            print("average grid size: " + str(avg_edge))
        
    return CurveMesh
def cloth_fill_main2(context, loop_obj, oct, smooth, debug = False):
    '''
    notes:
       make sure the user view is such that you can see the entire ring with
       out any corosses (knots)
       
       if calling from script not in 3dview, you can override the view
       
    args:
        context - blender context
        loop_obj:  blender curve object or mesh object representing just a loop
        oct - octree depth for the grid to fill.
        smooth - iteartions to smooth the surface (soap bubble effect)
    return:
        CurveMesh :  The filled looop object type Blender Object (Mesh) 
    '''
    
    #selection mode = verts
    sce = context.scene
 
    if context.area.type != 'VIEW_3D':
        # Py cant access notifers
        for area in context.window.screen.areas:
            if area.type == 'VIEW_3D':
            #    for reg in area.regions:
            #        if reg.type == 'WINDOW':
            #            region = reg

                for spc in area.spaces:
                    if spc.type == 'VIEW_3D':
                        v3d = spc
                        region = spc.region_3d
    else:
        #get the space data
        v3d = bpy.context.space_data
        #v3d.transform_orientation = 'GLOBAL'
        #v3d.pivot_point = 'MEDIAN_POINT'
        region = v3d.region_3d     
           
    vrot = region.view_rotation #this is a quat
    Z = vrot * Vector((0,0,1))
    
    #change the mesh orientation to align with view..for blockout
    odcutils.reorient_object(loop_obj, vrot) #TODO test this
    sce.update()
    
    if loop_obj.parent:
        reparent = True
    else:
        reparent = False
        
    if loop_obj.type not in {'CURVE', 'MESH'}: return
    
    me = loop_obj.to_mesh(context.scene, True, 'PREVIEW')
    tray_bme = bmesh.new()
    tray_bme.from_mesh(me)
    
    tray_me = bpy.data.meshes.new('cloth tray')
    TrayOb = bpy.data.objects.new('Cloth Tray', tray_me)
    TrayOb.matrix_world = loop_obj.matrix_world
        
    #do some size estimation
    min_size = min(loop_obj.dimensions)
    size = max(list(loop_obj.dimensions))
    grid_predict = size * 0.9 / pow(oct,2)
    print("grid prediction is:  " + str(grid_predict))
            
    #make a 2nd object to project down on...
    tmp_bme = bmesh.new()
    tmp_bme.from_mesh(me)
    temp_me = bpy.data.meshes.new('cloth temp')
    TempOb = bpy.data.objects.new('Cloth Temp', temp_me)
    TempOb.matrix_world = loop_obj.matrix_world
    context.scene.objects.link(TempOb)
    
    #fill the the surface of the temp
    geom = bmesh.ops.triangle_fill(tmp_bme, use_beauty = True, edges = tmp_bme.edges)    
    tmp_bme.edges.ensure_lookup_table()
    tmp_bme.verts.ensure_lookup_table()
    
    #move edges outward a little
    perim_eds = [ed for ed in tmp_bme.edges if not ed.is_manifold]
    odcutils.extrude_bmesh_loop(tmp_bme, perim_eds, loop_obj.matrix_world, Z, -.001 * min_size, move_only = True)
    
    #This time add an extrusion
    odcutils.extrude_bmesh_loop(tmp_bme, perim_eds, loop_obj.matrix_world, Z, -.05 * min_size, move_only = False)
    
    #put the data in
    tmp_bme.to_mesh(TempOb.data)
    tmp_bme.free()
    
    #Now deal with the tray which is to be remeshed.
    #first, solidify all of their
    
    #flatten. Since oriented into view, this flattens it
    for v in tray_bme.verts:
        v.co[2] = 0.00
    
    #triangle fill
    geom = bmesh.ops.triangle_fill(tray_bme, use_beauty = True, edges = tray_bme.edges)
    
    solid_geom = [f for f in tray_bme.faces] + [v for v in tray_bme.verts] + [ed for ed in tray_bme.edges]
    new_geom = bmesh.ops.solidify(tray_bme, geom = solid_geom, thickness = grid_predict * 0.75)
    
    
    tray_bme.to_mesh(tray_me)
    tray_bme.free()
    
    context.scene.objects.link(TrayOb)
    mod = TrayOb.modifiers.new('Remesh', type = 'REMESH')
    mod.octree_depth = oct
    mod.scale = .9
    
    tray_bme = bmesh.new()
    final_me = TrayOb.to_mesh(context.scene, apply_modifiers = True, settings = 'PREVIEW')
    tray_bme.from_mesh(final_me)
    tray_bme.verts.ensure_lookup_table()
    to_delete = []
    for v in tray_bme.verts:
        if v.co[2] > .0001 or v.co[2] < -.0001:
            to_delete.append(v)
    
    bmesh.ops.delete(tray_bme, geom = to_delete, context = 1)
    
    TrayOb.modifiers.remove(modifier = mod)
    tray_bme.to_mesh(TrayOb.data)
    tray_bme.free()
       
    #TODOD, manually with ray cast
    swrap = TrayOb.modifiers.new('Shrinkwrap', type = 'SHRINKWRAP')
    swrap.wrap_method = 'PROJECT'
    swrap.use_project_z = True
    swrap.use_negative_direction = True
    swrap.use_positive_direction = True
    swrap.target = TempOb
    

    #tray_me = TrayOb.to_mesh(context.scene, apply_modifiers = True, settings = 'PREVIEW')
    
    #TrayOb.data = tray_me
    #TrayOb.modifiers.remove(modifier = swrap)
    if reparent:
        TrayOb.update_tag()
        sce.update()
        odcutils.parent_in_place(TrayOb, loop_obj.parent)

    return TrayOb
Exemple #5
0
def place_implant(context, implant_space, location,orientation,imp, hardware = True):
    '''
    
    args:
        context
        implant_space - ODC Implant Space type
        location - Vector
        orientation - Matrix or Quaternion
        lib_implants - 
        imp - string representing implant object name in link library
    '''
    #check if space already has an implant object.
    #if so, delete, replace, print warning
    sce = context.scene
    if implant_space.implant and implant_space.implant in bpy.data.objects:
        print("replacing the existing implant with the one you chose")
        Implant = bpy.data.objects[implant_space.implant]
        #unlink it from the scene, clear it's useres, remove it.
        
        
        if Implant.children:
            for child in Implant.children:
                sce.objects.unlink(child)
                child.user_clear
                bpy.data.objects.remove(child)
                            
        sce.objects.unlink(Implant)
        implant_mesh = Implant.data
        
        Implant.user_clear()
        #remove the object
        bpy.data.objects.remove(Implant)
        implant_mesh.user_clear()
        bpy.data.meshes.remove(implant_mesh)
        
        sce.update()
        #TDOD what about the children/hardwares?
   
    world_mx = Matrix.Identity(4)
    world_mx[0][3]=location[0]
    world_mx[1][3]=location[1]
    world_mx[2][3]=location[2]
        
        #mx_b = Matrix.Identity(4)
        #mx_l = Matrix.Identity(4)
    #is this more memory friendly than listing all objects?
    current_obs = [ob.name for ob in bpy.data.objects]
    
    #link the new implant from the library
    settings = get_settings()
    odcutils.obj_from_lib(settings.imp_lib, imp)
    
    #this is slightly more robust than trusting we don't have duplicate names.
    for ob in bpy.data.objects:
        if ob.name not in current_obs:
            Implant = ob
    
    
    sce.objects.link(Implant)
    #Implant.matrix_basis = mx_b
    Implant.matrix_world = world_mx
    Implant.update_tag()
    sce.update()
    Implant.rotation_mode = 'QUATERNION'
    Implant.rotation_quaternion = orientation
    sce.update()
    #Implant.matrix_local = mx_l
    #Implant.location = L
    
    if sce.odc_props.master:
        Master = bpy.data.objects[sce.odc_props.master]
        odcutils.parent_in_place(Implant, Master)
    else:
        print('No Master Model, placing implant anyway, moving objects may not preserve spatial relationships')
    
    #looks a little redundant, but it ensure if any
    #duplicates exist our referencing stays accurate
    Implant.name = implant_space.name + "_" + Implant.name
    implant_space.implant = Implant.name
    
    if hardware:
        current_obs = [ob.name for ob in bpy.data.objects]
                    
        inc = imp + '_'
        
        settings = get_settings()
        hardware_list = odcutils.obj_list_from_lib(settings.imp_lib, include = inc)
        print(hardware_list)
        for ob in hardware_list:
            odcutils.obj_from_lib(settings.imp_lib,ob)
                
        for ob in bpy.data.objects:
            if ob.name not in current_obs:
                sce.objects.link(ob)
                ob.parent = Implant
                ob.layers[11] = True  #TODO: put this in layer management.
                                           
    return Implant
Exemple #6
0
def implant_inner_cylinder(context, space, thickness = None, debug = False):
    
    if debug:
        start_time = time.time()
    sce = context.scene
    Implant = sce.objects[space.implant]
    mx_w = Implant.matrix_world.copy()
    
    if thickness:
        D = thickness
    else:
        D = Implant.dimensions[0]
        
    #create a bmesh cylinder
    R = D/2
    bm = odcutils.primitive_flattened_cylinder(R, R, 64, 30)
    
    if Implant.rotation_mode != 'QUATERNION':
        Implant.rotation_mode = 'QUATERNION'
        Implant.update_tag()
        context.scene.update()

    if space.inner and space.inner in bpy.data.objects:
        Cylinder = bpy.data.objects[space.inner]
        me = Cylinder.data
        
    else:
        me = bpy.data.meshes.new(Implant.name + '_GC')
        Cylinder = bpy.data.objects.new(Implant.name + '_IC', me)
        # Add the mesh to the scene
        scene = bpy.context.scene
        scene.objects.link(Cylinder)
        
        #point the right direction
        Cylinder.rotation_mode = 'QUATERNION'
        Cylinder.rotation_quaternion = mx_w.to_quaternion()
    
        #now we must update to propagate changes to the
        #world matrix.  Otherwise, when we access matrix_world
        #it will not have the new information about scale and
        #rotation...and they changes will be lost when we access
        #the matrix to assign different values to other elements
        Cylinder.update_tag()
        context.scene.update()
    
        Trans = Implant.rotation_quaternion * Vector((0,0,- (30 + Implant.dimensions[2])))
        Cylinder.matrix_world[0][3] = mx_w[0][3] + Trans[0]
        Cylinder.matrix_world[1][3] = mx_w[1][3] + Trans[1]
        Cylinder.matrix_world[2][3] = mx_w[2][3] + Trans[2]

    #Write the bmesh into a new mesh or replace the old mesh?
    bm.to_mesh(me)
    bm.free()

    Cylinder.vertex_groups.clear()        
    Cylinder.vertex_groups.new("Project")
    
    #rodd verts added to the "Project Group"
    vert_inds = [v.index for v in Cylinder.data.vertices if v.index%2]
    Cylinder.vertex_groups["Project"].add(vert_inds, 1,'REPLACE')
        
    Cylinder.update_tag()
    context.scene.update()
    
    space.inner = Cylinder.name
    
    odcutils.parent_in_place(Cylinder, Implant)
    if debug:
        print('finished inner cylinder for %s in %f seconds' % (space.name, time.time() - start_time))
Exemple #7
0
def implant_outer_cylinder(context, space, 
                           width, depth, trim = 0, 
                           wedge = False, wedge_pct = .7,
                           debug = False):
    
    if debug:
        start_time = time.time()
    
    scene = bpy.context.scene
    Implant = scene.objects[space.implant]
    mx_w = Implant.matrix_world.copy()
    
    if Implant.rotation_mode != 'QUATERNION':
        Implant.rotation_mode = 'QUATERNION'
        Implant.update_tag()
        context.scene.update()
    
    R = width/2
    H = .1
    if wedge:
        bm = odcutils.primitive_wedge_cylinder(R, wedge_pct, 64, H)
        
    else:
        bm = odcutils.primitive_flattened_cylinder(R, R-trim, 64, H)

    if space.outer and space.outer in bpy.data.objects:
        Cylinder = bpy.data.objects[space.outer]
        me = Cylinder.data
        if len(Cylinder.modifiers):
            for mod in Cylinder.modifiers:
                Cylinder.modifiers.remove(mod)
    
    else:
        me = bpy.data.meshes.new(Implant.name + '_GC')
        Cylinder = bpy.data.objects.new(Implant.name + '_GC', me)
        scene.objects.link(Cylinder)
        name = Implant.name + '_GC'
        Cylinder.name = name
    
        #point the right direction
        Cylinder.rotation_mode = 'QUATERNION'
        Cylinder.rotation_quaternion = mx_w.to_quaternion()
        
        Cylinder.update_tag()
        context.scene.update()
    
        Trans = Implant.rotation_quaternion * Vector((0,0,-depth))
        Cylinder.matrix_world[0][3] = mx_w[0][3] + Trans[0]
        Cylinder.matrix_world[1][3] = mx_w[1][3] + Trans[1]
        Cylinder.matrix_world[2][3] = mx_w[2][3] + Trans[2]
    
    bm.to_mesh(me)
    bm.free()

    #vert group    
    Cylinder.vertex_groups.clear() 
    Cylinder.vertex_groups.new("Project")
    vert_inds = [v.index for v in Cylinder.data.vertices if v.index%2]
    Cylinder.vertex_groups["Project"].add(vert_inds, 1,'REPLACE')

    Cylinder.update_tag()
    context.scene.update()

    if len(scene.odc_splints):
        splint = scene.odc_splints[scene.odc_splint_index]
        if splint.splint in bpy.data.objects:
            Splint = bpy.data.objects[splint.splint]
        
            mod = Cylinder.modifiers.new('Project','SHRINKWRAP')
            mod.wrap_method = 'PROJECT'
            mod.use_project_z = True
            mod.use_project_y = False
            mod.use_project_x = False
            mod.offset = .5
            mod.target = Splint
            mod.vertex_group = 'Project'
    

    space.outer = Cylinder.name
    
    odcutils.parent_in_place(Cylinder, Implant)
    if debug:
        print('finished outer cylinder for %s in %f seconds' % (space.name, time.time() - start_time))
Exemple #8
0
 def execute(self, context):
     settings = get_settings()
     dbg = settings.debug
     #if bpy.context.mode != 'OBJECT':
     #    bpy.ops.object.mode_set(mode = 'OBJECT')
     
     sce = context.scene
     implants = odcutils.implant_selection(context)
     
     layers_copy = [layer for layer in context.scene.layers]
     context.scene.layers[0] = True
     
     if implants != []:
     
         for implant_space in implants:
             #check if space already has an implant object.
             #if so, delete, replace, print warning
             Implant = bpy.data.objects[implant_space.implant]
             
             if Implant.rotation_mode != 'QUATERNION':
                 Implant.rotation_mode = 'QUATERNION'
                 Implant.update_tag()
                 sce.update()
                 
             if bpy.data.objects.get(implant_space.drill):
                 self.report({'WARNING'}, "replacing the existing drill with the one you chose")
                 Sleeve = bpy.data.objects[implant_space.drill]
                 #unlink it from the scene, clear it's users, remove it.
                 sce.objects.unlink(Sleeve)
                 Implant.user_clear()
                 #remove the object
                 bpy.data.objects.remove(Sleeve)
                 
             current_obs = [ob.name for ob in bpy.data.objects]
             
             #link the new implant from the library
             settings = get_settings()
             odcutils.obj_from_lib(settings.drill_lib,self.drill)
             
             #this is slightly more robust than trusting we don't have duplicate names.
             for ob in bpy.data.objects:
                 if ob.name not in current_obs:
                     Sleeve = ob
                     
             sce.objects.link(Sleeve)
             Sleeve.layers[19] = True
             mx_w = Implant.matrix_world.copy()
             #point the right direction
             Sleeve.rotation_mode = 'QUATERNION'
             Sleeve.rotation_quaternion = mx_w.to_quaternion()          
             Sleeve.update_tag()
             context.scene.update()   
             Trans = Sleeve.rotation_quaternion * Vector((0,0,-self.depth))
             Sleeve.matrix_world[0][3] = mx_w[0][3] + Trans[0]
             Sleeve.matrix_world[1][3] = mx_w[1][3] + Trans[1]
             Sleeve.matrix_world[2][3] = mx_w[2][3] + Trans[2]
             
             Sleeve.name = implant_space.name + '_' + Sleeve.name
             implant_space.drill = Sleeve.name
             Sleeve.update_tag()
             context.scene.update()    
             odcutils.parent_in_place(Sleeve, Implant)
             odcutils.layer_management(sce.odc_implants, debug = dbg)
     for i, layer in enumerate(layers_copy):
         context.scene.layers[i] = layer
     context.scene.layers[19] = True                
     return {'FINISHED'}
Exemple #9
0
    def execute(self, context):
        settings = get_settings()
        dbg = settings.debug
        #if bpy.context.mode != 'OBJECT':
        #    bpy.ops.object.mode_set(mode = 'OBJECT')
        
        sce = context.scene
        n = sce.odc_implant_index
        implant_space = sce.odc_implants[n]
        
        implants = odcutils.implant_selection(context)
        layers_copy = [layer for layer in context.scene.layers]
        context.scene.layers[0] 
        
        if implants != []:
        
            for implant_space in implants:
                #check if space already has an implant object.
                #if so, delete, replace, print warning
                if implant_space.implant and implant_space.implant in bpy.data.objects:
                    self.report({'WARNING'}, "replacing the existing implant with the one you chose")
                    Implant = bpy.data.objects[implant_space.implant]
                    
                    
                    #the origin/location of the implant is it's apex
                    L = Implant.location.copy()  

                    world_mx = Implant.matrix_world.copy()
                    
                    #the platorm is the length of the implant above the apex, in the local Z direction
                    #local Z positive is out the apex, soit's negative.
                    #Put the cursor there
                    sce.cursor_location = L - Implant.dimensions[2] * world_mx.to_3x3() *  Vector((0,0,1))
                                        
                    #first get rid of children...so we can use the
                    #parent to find out who the children are
                    if Implant.children:
                        for child in Implant.children:
                            sce.objects.unlink(child)
                            child.user_clear()
                            bpy.data.objects.remove(child)
                            
                    #unlink it from the scene, clear it's users, remove it.
                    sce.objects.unlink(Implant)
                    Implant.user_clear()
                    #remove the object
                    bpy.data.objects.remove(Implant)
                    
                    
                    
                #TDOD what about the children/hardwares?
                else:
                    world_mx = Matrix.Identity(4)
                    
                world_mx[0][3]=sce.cursor_location[0]
                world_mx[1][3]=sce.cursor_location[1]
                world_mx[2][3]=sce.cursor_location[2]
                                        
                #is this more memory friendly than listing all objects?
                current_obs = [ob.name for ob in bpy.data.objects]
                
                #link the new implant from the library
                odcutils.obj_from_lib(settings.imp_lib,self.imp)
                
                #this is slightly more robust than trusting we don't have duplicate names.
                for ob in bpy.data.objects:
                    if ob.name not in current_obs:
                        Implant = ob
                        
                sce.objects.link(Implant)
                
                #this relies on the associated hardware objects having the parent implant
                #name inside them
                if self.hardware:
                    current_obs = [ob.name for ob in bpy.data.objects]
                    
                    inc = self.imp + '_'
                    hardware_list = odcutils.obj_list_from_lib(settings.imp_lib, include = inc)
                    print(hardware_list)
                    for ob in hardware_list:
                        odcutils.obj_from_lib(settings.imp_lib,ob)
                
                    for ob in bpy.data.objects:
                        if ob.name not in current_obs:
                            sce.objects.link(ob)
                            ob.parent = Implant
                            ob.layers[11] = True
                

                delta =  Implant.dimensions[2] * world_mx.to_3x3() * Vector((0,0,1))
                print(delta.length)
                world_mx[0][3] += delta[0]
                world_mx[1][3] += delta[1]
                world_mx[2][3] += delta[2]
                    

                Implant.matrix_world = world_mx

                
                if sce.odc_props.master:
                    Master = bpy.data.objects[sce.odc_props.master]
                    odcutils.parent_in_place(Implant, Master)
                else:
                    self.report({'WARNING'}, 'No Master Model, placing implant anyway, moving objects may not preserve spatial relationships')
                
                #looks a little redundant, but it ensure if any
                #duplicates exist our referencing stays accurate
                Implant.name = implant_space.name + '_' + Implant.name
                implant_space.implant = Implant.name
                    
                odcutils.layer_management(sce.odc_implants, debug = dbg)
        
        for i, layer in enumerate(layers_copy):
            context.scene.layers[i] = layer
        context.scene.layers[11] = True           
        return {'FINISHED'}
def cloth_fill_main2(context, loop_obj, oct, smooth, debug=False):
    '''
    notes:
       make sure the user view is such that you can see the entire ring with
       out any corosses (knots)
       
       if calling from script not in 3dview, you can override the view
       
    args:
        context - blender context
        loop_obj:  blender curve object or mesh object representing just a loop
        oct - octree depth for the grid to fill.
        smooth - iteartions to smooth the surface (soap bubble effect)
    return:
        CurveMesh :  The filled looop object type Blender Object (Mesh) 
    '''

    #selection mode = verts
    sce = context.scene

    if context.area.type != 'VIEW_3D':
        # Py cant access notifers
        for area in context.window.screen.areas:
            if area.type == 'VIEW_3D':
                #    for reg in area.regions:
                #        if reg.type == 'WINDOW':
                #            region = reg

                for spc in area.spaces:
                    if spc.type == 'VIEW_3D':
                        v3d = spc
                        region = spc.region_3d
    else:
        #get the space data
        v3d = bpy.context.space_data
        #v3d.transform_orientation = 'GLOBAL'
        #v3d.pivot_point = 'MEDIAN_POINT'
        region = v3d.region_3d

    vrot = region.view_rotation  #this is a quat
    Z = vrot * Vector((0, 0, 1))

    #change the mesh orientation to align with view..for blockout
    odcutils.reorient_object(loop_obj, vrot)  #TODO test this
    sce.update()

    if loop_obj.parent:
        reparent = True
    else:
        reparent = False

    if loop_obj.type not in {'CURVE', 'MESH'}: return

    me = loop_obj.to_mesh(context.scene, True, 'PREVIEW')
    tray_bme = bmesh.new()
    tray_bme.from_mesh(me)

    tray_me = bpy.data.meshes.new('cloth tray')
    TrayOb = bpy.data.objects.new('Cloth Tray', tray_me)
    TrayOb.matrix_world = loop_obj.matrix_world

    #do some size estimation
    min_size = min(loop_obj.dimensions)
    size = max(list(loop_obj.dimensions))
    grid_predict = size * 0.9 / pow(oct, 2)
    print("grid prediction is:  " + str(grid_predict))

    #make a 2nd object to project down on...
    tmp_bme = bmesh.new()
    tmp_bme.from_mesh(me)
    temp_me = bpy.data.meshes.new('cloth temp')
    TempOb = bpy.data.objects.new('Cloth Temp', temp_me)
    TempOb.matrix_world = loop_obj.matrix_world
    context.scene.objects.link(TempOb)

    #fill the the surface of the temp
    geom = bmesh.ops.triangle_fill(tmp_bme,
                                   use_beauty=True,
                                   edges=tmp_bme.edges)
    tmp_bme.edges.ensure_lookup_table()
    tmp_bme.verts.ensure_lookup_table()

    #move edges outward a little
    perim_eds = [ed for ed in tmp_bme.edges if not ed.is_manifold]
    odcutils.extrude_bmesh_loop(tmp_bme,
                                perim_eds,
                                loop_obj.matrix_world,
                                Z,
                                -.001 * min_size,
                                move_only=True)

    #This time add an extrusion
    odcutils.extrude_bmesh_loop(tmp_bme,
                                perim_eds,
                                loop_obj.matrix_world,
                                Z,
                                -.05 * min_size,
                                move_only=False)

    #put the data in
    tmp_bme.to_mesh(TempOb.data)
    tmp_bme.free()

    #Now deal with the tray which is to be remeshed.
    #first, solidify all of their

    #flatten. Since oriented into view, this flattens it
    for v in tray_bme.verts:
        v.co[2] = 0.00

    #triangle fill
    geom = bmesh.ops.triangle_fill(tray_bme,
                                   use_beauty=True,
                                   edges=tray_bme.edges)

    solid_geom = [f for f in tray_bme.faces] + [v for v in tray_bme.verts] + [
        ed for ed in tray_bme.edges
    ]
    new_geom = bmesh.ops.solidify(tray_bme,
                                  geom=solid_geom,
                                  thickness=grid_predict * 0.75)

    tray_bme.to_mesh(tray_me)
    tray_bme.free()

    context.scene.objects.link(TrayOb)
    mod = TrayOb.modifiers.new('Remesh', type='REMESH')
    mod.octree_depth = oct
    mod.scale = .9

    tray_bme = bmesh.new()
    final_me = TrayOb.to_mesh(context.scene,
                              apply_modifiers=True,
                              settings='PREVIEW')
    tray_bme.from_mesh(final_me)
    tray_bme.verts.ensure_lookup_table()
    to_delete = []
    for v in tray_bme.verts:
        if v.co[2] > .0001 or v.co[2] < -.0001:
            to_delete.append(v)

    bmesh.ops.delete(tray_bme, geom=to_delete, context=1)

    TrayOb.modifiers.remove(modifier=mod)
    tray_bme.to_mesh(TrayOb.data)
    tray_bme.free()

    #TODOD, manually with ray cast
    swrap = TrayOb.modifiers.new('Shrinkwrap', type='SHRINKWRAP')
    swrap.wrap_method = 'PROJECT'
    swrap.use_project_z = True
    swrap.use_negative_direction = True
    swrap.use_positive_direction = True
    swrap.target = TempOb

    #tray_me = TrayOb.to_mesh(context.scene, apply_modifiers = True, settings = 'PREVIEW')

    #TrayOb.data = tray_me
    #TrayOb.modifiers.remove(modifier = swrap)
    if reparent:
        TrayOb.update_tag()
        sce.update()
        odcutils.parent_in_place(TrayOb, loop_obj.parent)

    return TrayOb
def cloth_fill_main(context, loop_obj, oct, smooth, debug=False):
    '''
    notes:
       make sure the user view is such that you can see the entire ring with
       out any corosses (knots)
       
       if calling from script not in 3dview, you can override the view
       
    args:
        context - blender context
        loop_obj:  blender curve object or mesh object representing just a loop
        oct - octree depth for the grid to fill.
        smooth - iteartions to smooth the surface (soap bubble effect)
    return:
        CurveMesh :  The filled looop object type Blender Object (Mesh) 
    '''

    #selection mode = verts
    sce = context.scene
    context.tool_settings.mesh_select_mode = [True, False, False]

    #get the space data
    v3d = bpy.context.space_data
    v3d.transform_orientation = 'GLOBAL'
    v3d.pivot_point = 'MEDIAN_POINT'

    region = v3d.region_3d
    vrot = region.view_rotation  #this is a quat

    #set object mode...force selection
    if context.mode != 'OBJECT':
        bpy.ops.object.mode_set(mode='OBJECT')

    bpy.ops.object.select_all(action='DESELECT')
    context.scene.objects.active = loop_obj
    loop_obj.select = True

    #change the mesh orientation to align with view..for blockout
    odcutils.reorient_object(loop_obj, vrot)  #TODO test this
    sce.update()

    if loop_obj.type in {'CURVE', 'MESH'}:
        if loop_obj.type == 'CURVE':
            #check if cyclic
            if not loop_obj.data.splines[0].use_cyclic_u:
                loop_obj.data.splines[
                    0].use_cyclic_u = True  #TODO: add this over to margin

            #convert the curve to a mesh...so we can use it.
            bpy.ops.object.duplicate()
            bpy.ops.object.convert(target='MESH', keep_original=False)
            #active object is now the mesh version of the curve

        else:
            #make sure it's a loop
            if len(loop_obj.data.vertices) != len(loop_obj.data.edges):
                print('this is not a loop')
                return
            else:
                bpy.ops.object.duplicate()
                #active object is now the mesh duplicate

    #this will become our final cloth filled objec
    CurveMesh = context.object
    CurveMesh.name = "Cloth Tray Mesh"

    #do some size estimation
    size = max(list(CurveMesh.dimensions))
    grid_predict = size * 0.9 / pow(oct, 2)
    print("grid prediction is:  " + str(grid_predict))

    #make a duplicate...
    current_objects = list(
        bpy.data.objects)  #remember current objects to ID new ones later
    bpy.ops.object.duplicate()
    for obj in sce.objects:
        if obj not in current_objects:
            obj.name = "cloth_temp"
            Temp = obj

    #fill the the surface of the temp
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_all(action='SELECT')
    bpy.ops.mesh.fill()

    #stretch it out a little
    bpy.ops.mesh.select_all(action='DESELECT')
    bpy.context.tool_settings.mesh_select_mode = [False, True, False]
    bpy.ops.mesh.select_non_manifold()
    bpy.ops.object.editmode_toggle()

    eds = [ed for ed in Temp.data.edges if ed.select]
    barrier = .05 * min(Temp.dimensions)
    odcutils.extrude_edges_out_view(Temp.data,
                                    eds,
                                    Temp.matrix_world,
                                    barrier / 5,
                                    debug=debug)
    bpy.ops.object.editmode_toggle()

    bpy.context.tool_settings.mesh_select_mode = [False, True, False]
    bpy.ops.mesh.select_non_manifold()
    bpy.ops.mesh.extrude_edges_move()
    bpy.ops.object.editmode_toggle()

    eds = [ed for ed in Temp.data.edges if ed.select]
    odcutils.extrude_edges_out_view(Temp.data,
                                    eds,
                                    Temp.matrix_world,
                                    barrier,
                                    debug=debug)
    bpy.ops.object.editmode_toggle()
    bpy.context.tool_settings.mesh_select_mode = [True, False, False]

    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.ops.object.select_all(action='DESELECT')

    CurveMesh.select = True
    sce.objects.active = CurveMesh
    CurveMesh.rotation_mode = 'QUATERNION'

    #make the origin the same as the bez curve?
    sce.cursor_location = loop_obj.location
    bpy.ops.object.origin_set(type='ORIGIN_CURSOR')

    if CurveMesh.parent:
        Parent = CurveMesh.parent
        reparent = True
        wmx = CurveMesh.matrix_world.copy()
        CurveMesh.parent = None
        CurveMesh.matrix_world = wmx
    else:
        wmx = Matrix.Identity(4)
        reparent = False
    #unrotate it so we can make a nice remesh surface
    #although why this doesn't work with local coords I dunno
    bpy.ops.object.rotation_clear()

    #flatten to view...fill in the loop
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_all(action='SELECT')
    #get the space data
    v3d = bpy.context.space_data
    v3d.transform_orientation = 'LOCAL'
    v3d.pivot_point = 'MEDIAN_POINT'
    bpy.ops.transform.resize(value=(1, 1, 0), constraint_orientation='LOCAL')
    bpy.ops.mesh.looptools_space()
    bpy.ops.mesh.fill()

    #add modifiers
    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.ops.object.modifier_add(type='SOLIDIFY')
    bpy.ops.object.modifier_add(type='REMESH')

    solmod = CurveMesh.modifiers["Solidify"]
    solmod.thickness = grid_predict * .75

    remod = CurveMesh.modifiers["Remesh"]
    remod.octree_depth = oct
    remod.scale = .9

    #for some reason the modifier weren't updating
    bpy.ops.object.editmode_toggle()
    bpy.ops.object.editmode_toggle()

    #problem with applying modifiers...new method.
    mesh = CurveMesh.to_mesh(bpy.context.scene, True, 'RENDER')
    new_obj = bpy.data.objects.new(CurveMesh.name, mesh)
    bpy.context.scene.objects.link(new_obj)
    new_obj.matrix_world = wmx

    bpy.context.scene.objects.active = new_obj

    CurveMesh.select = True
    bpy.context.scene.objects.active = CurveMesh
    bpy.ops.object.delete()

    new_obj.select = True
    CurveMesh = new_obj
    bpy.context.scene.objects.active = CurveMesh
    '''
    bpy.ops.object.modifier_apply(modifier="Solidify")
    
    bpy.ops.object.editmode_toggle()
    bpy.ops.object.editmode_toggle()
    
    bpy.ops.object.modifier_apply(modifier="Remesh")
    '''

    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_all(action='DESELECT')
    bpy.ops.object.mode_set(mode='OBJECT')

    #make it a 2d obejct
    bpy.context.tool_settings.mesh_select_mode = [False, False, True]
    flat = False
    n = 0
    while not flat:

        #hope to select a polygon not on the border
        CurveMesh.data.polygons[n].select = True
        bpy.ops.object.mode_set(mode='EDIT')
        bpy.ops.mesh.faces_select_linked_flat()
        bpy.ops.object.mode_set(mode='OBJECT')

        sel_faces = [poly for poly in CurveMesh.data.polygons if poly.select]
        if len(sel_faces) > len(CurveMesh.data.polygons) / 3:
            flat = True

        if n > 100:
            break
        n += 1
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.delete()
    bpy.context.tool_settings.mesh_select_mode = [False, True, False]
    bpy.ops.mesh.select_loose()
    bpy.ops.mesh.delete(type='EDGE')
    bpy.ops.mesh.select_non_manifold()
    bpy.context.tool_settings.mesh_select_mode = [True, False, False]
    bpy.ops.mesh.select_all(action='INVERT')
    bpy.ops.mesh.vertices_smooth(repeat=smooth)

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

    bpy.ops.object.modifier_add(type='SHRINKWRAP')
    swrap = CurveMesh.modifiers["Shrinkwrap"]
    swrap.wrap_method = 'PROJECT'
    swrap.use_project_z = True
    swrap.use_negative_direction = True
    swrap.use_positive_direction = True
    swrap.target = Temp

    CurveMesh.rotation_quaternion = vrot
    bpy.ops.object.modifier_apply(modifier="Shrinkwrap")

    if reparent:
        CurveMesh.update_tag()
        sce.update()
        odcutils.parent_in_place(CurveMesh, Parent)

    bpy.ops.object.select_all(action='DESELECT')

    if debug < 3:
        Temp.select = True
        sce.objects.active = Temp
        bpy.ops.object.delete()

    CurveMesh.select = True
    sce.objects.active = CurveMesh
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_all(action='DESELECT')

    bpy.context.tool_settings.mesh_select_mode = [False, True, False]
    bpy.ops.mesh.select_loose()
    bpy.ops.mesh.delete(type='EDGE')
    bpy.context.tool_settings.mesh_select_mode = [True, False, False]
    bpy.ops.object.mode_set(mode='OBJECT')

    mx = CurveMesh.matrix_world
    sum_edges = 0
    if len(CurveMesh.data.edges) != 0:
        for ed in CurveMesh.data.edges:
            v0 = CurveMesh.data.vertices[ed.vertices[0]]
            v1 = CurveMesh.data.vertices[ed.vertices[1]]
            V = mx * v1.co - mx * v0.co
            sum_edges += V.length

        avg_edge = sum_edges / len(CurveMesh.data.edges)

        if debug:
            print("average grid size: " + str(avg_edge))

    return CurveMesh