def execute(self, context): settings = get_settings() dbg = settings.debug Bridge = bpy.data.objects[self.odc_bridge.bridge] mes_tooth_distal_connector = self.b + self.b_group dis_tooth_mesial_connector = self.a + self.a_group [ob_sets, tool_sets, space_sets] = odcutils.scene_preserv(context, debug=dbg) #TODO: global debug bridge_methods.bridge_loop(context, Bridge, mes_tooth_distal_connector, dis_tooth_mesial_connector, 2, self.twist, self.bulbous, group3="Connectors", debug=True) odcutils.scene_reconstruct(context, ob_sets, tool_sets, space_sets, debug=dbg) return {'FINISHED'}
def execute(self, context): curve = context.object settings = get_settings() dbg = settings.debug full_arch_methods.keep_arch_plan(context, curve, debug=dbg) return {'FINISHED'}
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 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 obj_from_lib(settings.ortho_lib, self.ob) #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: Bracket = ob sce.objects.link(Bracket) rv3d = context.region_data view_mx = rv3d.view_rotation.to_matrix() Bracket.matrix_world = world_mx * view_mx.to_4x4() return {'FINISHED'}
def execute(self, context): settings = get_settings() dbg = settings.debug odcutils.scene_verification(context.scene, debug=dbg) spaces = odcutils.implant_selection(context) layers_copy = [layer for layer in context.scene.collection.all_objects] context.scene.collection.all_objects[0] = True if context.mode != 'OBJECT': bpy.ops.object.mode_set(mode='OBJECT') for space in spaces: if not space.implant: self.report( {'WARNING'}, "It seems you have not yet placed an implant for %s" % space.name) else: if self.use_thickness: thickness = self.thickness else: thickness = None implant_utils.implant_inner_cylinder(context, space, thickness=thickness, debug=dbg) odcutils.material_management(context, context.scene.odc_implants) odcutils.layer_management(context.scene.odc_implants, debug=dbg) for i, layer in enumerate(layers_copy): context.scene.collection.all_objects[i] = layer context.scene.collection.all_objects[9] = True return {'FINISHED'}
def draw(self, context): if not context.scene.odc_props.show_dentures: return sce = bpy.context.scene layout = self.layout addon_prefs = get_settings() row = layout.row() row.label(text="Dentures") row.operator( "wm.url_open", text="", icon="INFO").url = "https://github.com/patmo141/odc_public/wiki" row = layout.row() col = row.column(align=True) # col.operator("opendental.add_implant_restoration", text = "Add a Space") col.operator("opendental.meta_scaffold_create", text="Make Baseplate/Tray Scaffold") col.operator("opendental.meta_custom_tray", text="Make Meta Custom Tray") col.operator("opendental.meta_offset_surface", text="Make Meta Baseplate") col.operator("opendental.meta_rim_from_curve", text="Make Meta Wax Rim") if context.object and context.object.type == "META": col.operator("object.convert", text="Convert Meta Baseplate to Mesh") col.operator("opendental.denture_boolean_intaglio", text="Boolean with Master Cast")
def invoke(self, context, event): self.objs.clear() #here we grab the asset library from the addon prefs settings = get_settings() libpath = settings.imp_lib assets = odcutils.obj_list_from_lib(libpath, exclude='_') for asset_object_name in assets: self.objs.add().name = asset_object_name #context.window_manager.invoke_search_popup(self.ob_list) context.window_manager.invoke_search_popup(self) return {'FINISHED'}
def invoke(self, context, event): self.objs.clear() settings = get_settings() libpath = settings.drill_lib assets = odcutils.obj_list_from_lib(libpath, exclude='Drill') for asset_object_name in assets: self.objs.add().name = asset_object_name context.window_manager.invoke_search_popup(self) return {'FINISHED'}
def __init__(self, context, bracket_data_manager): ''' Gets info from bracket manager and siplays orthogonal slices on the snap object ''' if not bracket_data_manager.bracket_obj: return None elif not bracket_data_manager.snap_ob: return None self.bracket_data = bracket_data_manager ob = self.bracket_data.snap_ob bme = bmesh.new() bme.from_object(ob, context.scene) self.snap_ob = ob self.bme = bme self.bvh = BVHTree.FromBMesh(self.bme) self.cut_pt = None self.cut_no_x = None self.cut_no_y = None self.slice_points_x = [] self.slice_points_y = [] self.reference_L = [] self.points_2d = [] self.active_point_2d = Vector((0, 0, 0)) self.mx = self.bracket_data.bracket_obj.matrix_world.to_3x3() b_gauge = self.bracket_data.bracket_obj.get('bracket_gauge') if b_gauge and not get_settings().bgauge_override: #read the prescription value from the objects self.b_gauge = b_gauge else: #override the rx value self.b_gauge = get_settings().bracket_gauge
def execute(self, context): loop_obj = context.object oct = self.oct smooth = self.smooth settings = get_settings() dbg = settings.debug full_arch_methods.cloth_fill_main(context, loop_obj, oct, smooth, debug=dbg) return {'FINISHED'}
def execute(self, context): settings = get_settings() dbg = settings.debug layers_copy = [layer for layer in context.scene.layers] context.scene.layers[0] = True odc_bridge = bridge_methods.active_spanning_restoration(context)[0] bridge_methods.make_pre_bridge(context, odc_bridge, debug=dbg) #TODO: debug settings for i, layer in enumerate(layers_copy): context.scene.layers[i] = layer context.scene.layers[5] = True odcutils.layer_management(context.scene.odc_bridges, debug=dbg) return {'FINISHED'}
def invoke(self, context, event): settings = get_settings() libpath = settings.ortho_lib assets = obj_list_from_lib(libpath) if settings.bracket in assets: current_obs = [ob.name for ob in bpy.data.objects] obj_from_lib(settings.ortho_lib, settings.bracket) for ob in bpy.data.objects: if ob.name not in current_obs: Bracket = ob Bracket.hide = False context.scene.objects.link(Bracket) else: Bracket = None if context.object and context.object.type == 'MESH': self.bracket_manager = BracketDataManager( context, snap_type='OBJECT', snap_object=context.object, name='Bracket', bracket=Bracket) self.bracket_slicer = BracektSlicer(context, self.bracket_manager) else: self.bracket_manager = BracketDataManager(context, snap_type='SCENE', snap_object=None, name='Bracket', bracket=Bracket) self.bracket_slicer = None help_txt = "DRAW MARGIN OUTLINE\n\nLeft Click on model to place bracket.\n G to grab \n S to show slice \n ENTER to confirm \n ESC to cancel" self.help_box = TextBox(context, 500, 500, 300, 200, 10, 20, help_txt) self.help_box.snap_to_corner(context, corner=[1, 1]) self.mode = 'start' self._handle = bpy.types.SpaceView3D.draw_handler_add( bracket_placement_draw_callback, (self, context), 'WINDOW', 'POST_PIXEL') context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'}
def invoke(self, context, event): settings = get_settings() dbg = settings.debug if context.space_data.region_3d.is_perspective: #context.space_data.region_3d.is_perspective = False bpy.ops.view3d.view_persportho() if context.space_data.type != 'VIEW_3D': self.report({'WARNING'}, "Active space must be a View3d") return {'CANCELLED'} #gather all the teeth in the scene TODO, keep better track self.target = 11 self.message = "Set axis for " + str(self.target) if context.mode != 'OBJECT': bpy.ops.object.mode_set(mode='OBJECT') #check for an armature bpy.ops.object.select_all(action='DESELECT') help_txt = "Left click on the tooth indicated to label it. Right click skip a tooth \n Up or Dn Arrow to change label\n Enter to finish \n ESC to cancel" self.help_box = TextBox(context, 500, 500, 300, 200, 10, 20, help_txt) self.help_box.fit_box_width_to_text_lines() self.help_box.fit_box_height_to_text_lines() self.help_box.snap_to_corner(context, corner=[1, 1]) aspect, mid = menu_utils.view3d_get_size_and_mid(context) self.target_box = TextBox(context, mid[0], aspect[1] - 20, 300, 200, 10, 20, self.message) self.target_box.format_and_wrap_text() self.target_box.fit_box_width_to_text_lines() self.target_box.fit_box_height_to_text_lines() self.mode = 'main' context.window_manager.modal_handler_add(self) self._handle = bpy.types.SpaceView3D.draw_handler_add( rapid_label_teeth_callback, (self, context), 'WINDOW', 'POST_PIXEL') return {'RUNNING_MODAL'}
def update_link_operators(): #unregister get crown bpy.utils.unregister_class(OPENDENTAL_OT_place_implant) bpy.utils.unregister_class(OPENDENTAL_OT_implant_from_contour) #redefinte list from user prefs prop global lib_teeth_enum global lib_teeth lib_teeth_enum = [] lib_teeth = [] settings = get_settings() dbg = settings.debug lib_teeth = odcutils.obj_list_from_lib(settings.tooth_lib, exclude='_', debug=dbg) for ind, obj in enumerate(lib_teeth): lib_teeth_enum.append((str(ind), obj, str(ind))) #reregister. bpy.utils.register_class(OPENDENTAL_OT_place_implant) bpy.utils.register_class(OPENDENTAL_OT_implant_from_contour)
def draw(self, context): if not context.scene.odc_props.show_ortho: return sce = bpy.context.scene layout = self.layout addon_prefs = get_settings() row = layout.row() row.label(text="Orthodontics") row.operator( "wm.url_open", text="", icon="INFO").url = "https://github.com/patmo141/odc_public/wiki" layout.label(text="Brackets") row = layout.row() row.prop(addon_prefs, "ortho_lib", text="") row = layout.row() row.prop(addon_prefs, "bracket", text="Bracket") row = layout.row() row.prop(addon_prefs, "bgauge_override", text="") row.prop(addon_prefs, "bracket_gauge", text="") row = layout.row() row.operator("opendental.place_ortho_bracket", text="Place Bracket Guide") row = layout.row() row.operator("opendental.place_static_bracket", text="Place Bracket at Cursor") layout.label(text="Treatment Animation/Setup") row = layout.row() row.operator("opendental.show_max_teeth", text="Upper") row.operator("opendental.show_man_teeth", text="Lower") row = layout.row() row.operator("opendental.show_left_teeth", text="Left") row.operator("opendental.show_right_teeth", text="Right") row = layout.row() col = row.column(align=True) col.operator("opendental.add_bone_roots", "Add roots") if context.mode == "OBJECT": col.operator("opendental.adjust_bone_roots", "Adjust Roots") elif context.mode == "EDIT_ARMATURE" and context.object.type == "ARMATURE": col.operator("object.mode_set", "Finish Roots").mode = "OBJECT" col.operator("opendental.set_roots_parents", "Set Root Parents") if context.scene.frame_current != 0 and not any( [ob.animation_data for ob in context.scene.objects]): row = layout.row() row.label("Initial position not captured!", icon="ERROR") row = layout.row() row.label("Set Frame to 0 and record initial position") else: row = layout.row() row.operator("opendental.set_treatment_keyframe", "Capture Positions") row = layout.row() row.prop(context.scene, "frame_current", text="") layout.label(text="Physics Simulation Tools") row = layout.row() col = row.column(align=True) col.operator("opendental.add_physics_scene", "Add Physics Scene") col.operator("opendental.physics_sim_setup", "Setup Physics Simulation") col.operator("opendental.add_forcefields", "Add Forcefields") col.operator("opendental.limit_physics_movements", "Limit Movement") col.operator("opendental.unlimit_physics_movements", "Unlimit Movement") col.operator("opendental.lock_physics_movements", "Lock Tooth") col.operator("opendental.unlock_physics_movements", "Unlock Tooth") layout.label(text="Simulation Timeline") row = layout.row() row.operator("screen.animation_play", icon="PLAY") row.prop(context.scene, "frame_current") row.operator("screen.frame_jump", icon="FILE_REFRESH").end = False # Big render button row = layout.row() row.scale_y = 1.5 row.operator("opendental.keep_simulation_results", "Keep Simulation")
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
def active_spanning_restoration(context, exclude=[], debug=False): ''' TODO: test robustness and implications of this logic looks at addon preferences returns a list, ''' sce = context.scene bridges = [] if not hasattr(context.scene, 'odc_props'): return [None] if len(context.scene.odc_bridges) == 0: return [None] settings = get_settings() b = settings.behavior behave_mode = settings.behavior_modes[int(b)] if behave_mode == 'LIST': #choose just one tooth in the list if len(sce.odc_bridges): bridge = sce.odc_bridges[sce.odc_bridge_index] bridges.append(bridge) elif behave_mode == 'ACTIVE': if len(sce.odc_bridges): for bridge in context.scene.odc_bridges: prop_keys = bridge.keys() prop_vals = bridge.values() if debug > 1: print(prop_keys) print(prop_vals) ob = context.object if ob.name in prop_vals: n = prop_vals.index(ob.name) this_key = prop_keys[n] if debug: print( "found the object named %s as the property value: %s in bridge: %s" % (ob.name, this_key, bridge.name)) if this_key and (this_key not in exclude): bridges.append(bridge) tooth = odcutils.tooth_selection(context)[0] for bridge in sce.odc_bridges: if tooth.name in bridge.tooth_string.split(sep=":"): if debug: print('found tooth %s in bridge: %s' % (tooth.name, bridge.name)) bridges.append(bridge) elif behave_mode == 'ACTIVE_SELECTED': #make sure the active object has priority by checking that first. if len(sce.odc_bridges): for bridge in context.scene.odc_bridges: prop_keys = bridge.keys() prop_vals = bridge.values() if context.object: if context.object.name in prop_vals: n = prop_vals.index(context.object.name) this_key = prop_keys[n] if debug: print( "found the object named %s as the property value: %s in bridge: %s" % (ob.name, this_key, bridge.name)) bridges.append(bridge) teeth = odcutils.tooth_selection(context) if teeth: for tooth in teeth: for bridge in sce.odc_bridges: if tooth.name in bridge.tooth_string.split(sep=":"): if debug: print('found tooth %s in bridge: %s' % (tooth.name, bridge.name)) if bridge not in bridges: bridges.append(bridge) if debug > 1: print(bridges) return bridges
def execute(self, context): settings = get_settings() dbg = settings.debug bridge_methods.bridge_from_selection(context, debug=dbg) return {'FINISHED'}
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.collection.all_objects] context.scene.collection.all_objects[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 context.collection.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.collection.all_objects[i] = layer context.scene.collection.all_objects[19] = True return {'FINISHED'}
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.collection.all_objects] context.scene.collection.all_objects[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 context.collection.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: context.collection.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) 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 context.collection.objects.link(Implant) Implant.matrix_world = world_mx for i, layer in enumerate(layers_copy): context.scene.collection.all_objects[i] = layer context.scene.collection.all_objects[11] = True return {'FINISHED'}
def execute(self, context): settings = get_settings() dbg = settings.debug odc_bridge = bridge_methods.active_spanning_restoration(context)[0] sce = context.scene Bridge = bpy.data.objects.get(odc_bridge.bridge) if not Bridge: self.report({ 'ERROR' }, 'Use "Boolean Bridge" to join individual units to an outer shell first' ) go_local = False if context.space_data.local_view: go_local = True bpy.ops.view3d.localview() if len(Bridge.modifiers): me = Bridge.to_mesh(context.scene, True, 'PREVIEW') mods = [mod for mod in Bridge.modifiers] for mod in mods: Bridge.modifiers.remove(mod) Bridge.data = me ### Remove the bottom 3 edge loops bridge_bme = bmesh.new() bridge_bme.from_object(Bridge, context.scene) bridge_bme.edges.ensure_lookup_table() bridge_bme.verts.ensure_lookup_table() bridge_bme.faces.ensure_lookup_table() for i in range(0, 3): non_man_eds = [ed for ed in bridge_bme.edges if not ed.is_manifold] bmesh.ops.delete(bridge_bme, geom=non_man_eds, context=2) non_man_vs = [v for v in bridge_bme.verts if not v.is_manifold] bmesh.ops.delete(bridge_bme, geom=non_man_vs, context=1) bridge_bme.edges.ensure_lookup_table() bridge_bme.verts.ensure_lookup_table() bridge_bme.faces.ensure_lookup_table() bridge_bme.to_mesh(Bridge.data) ### DONE Removing bottom 3 edge loops ### bridge_teeth = [ context.scene.odc_teeth[name] for name in odc_bridge.tooth_string.split(sep=":") ] intag_objects = [ bpy.data.objects.get(tooth.intaglio) for tooth in bridge_teeth if tooth.rest_type != '1' ] if None in intag_objects: self.report({'ERROR'}, 'Missing Intaglio for some abutments') bpy.ops.object.select_all(action='DESELECT') join_obs = [] for ob in intag_objects: new_me = ob.to_mesh(context.scene, True, 'PREVIEW') new_ob = bpy.data.objects.new(ob.name + ' dupli', new_me) new_ob.matrix_world = ob.matrix_world context.scene.objects.link(new_ob) join_obs.append(new_ob) print(join_obs) bpy.ops.object.select_all(action='DESELECT') for ob in join_obs: ob.select = True Bridge.hide = False Bridge.select = True context.scene.objects.active = Bridge Bridge.name += '_solid' bpy.ops.object.join() bridge_bme.free() bridge_bme = bmesh.new() bridge_bme.from_mesh(Bridge.data, True) bridge_bme.edges.ensure_lookup_table() bridge_bme.verts.ensure_lookup_table() bridge_bme.faces.ensure_lookup_table() non_man = [ed for ed in bridge_bme.edges if not ed.is_manifold] bmesh.ops.bridge_loops(bridge_bme, edges=non_man, use_pairs=True) #non_man = [ed.index for ed in bridge_bme.edges if not ed.is_manifold] #loops = mesh_cut.edge_loops_from_bmedges(bridge_bme, non_man) #for loop in loops: #for i in loop: #bridge_bme.verts[i].select_set(True) bmesh.ops.recalc_face_normals(bridge_bme, faces=bridge_bme.faces[:]) bridge_bme.to_mesh(Bridge.data) #bridge_bme.transform(Bridge.matrix_world) #new_me = bpy.data.meshes.new(odc_bridge.name + '_solid') #bridge_bme.to_mesh(new_me) bridge_bme.free() #new_ob = bpy.data.objects.new(odc_bridge.name + '_solid', new_me) #context.scene.objects.link(new_ob) if go_local: bpy.ops.view3d.localview() return {'FINISHED'}
def invoke(self, context, event): settings = get_settings() dbg = settings.debug if context.space_data.region_3d.is_perspective: #context.space_data.region_3d.is_perspective = False bpy.ops.view3d.view_persportho() if context.space_data.type != 'VIEW_3D': self.report({'WARNING'}, "Active space must be a View3d") return {'CANCELLED'} #gather all the teeth in the scene TODO, keep better track self.units = [] for i in TOOTH_NUMBERS: ob = context.scene.objects.get(str(i)) if ob != None and not ob.hide: self.units.append(ob) if not len(self.units): self.report({ 'ERROR' }, "There are no teeth in the scene!, Teeth must be named 2 digits eg 11 or 46" ) return {'CANCELLED'} self.target = self.units[0] self.message = "Set axis for %s" % self.target.name #check for an armature bpy.ops.object.select_all(action='DESELECT') if context.mode != 'OBJECT': bpy.ops.object.mode_set(mode='OBJECT') if context.scene.objects.get('Roots'): root_arm = context.scene.objects.get('Roots') root_arm.select = True root_arm.hide = False context.scene.objects.active = root_arm bpy.ops.object.mode_set(mode='EDIT') for ob in self.units: if ob.name + 'root' not in root_arm.data.bones: bpy.ops.armature.bone_primitive_add(name=ob.name + 'root') else: root_data = bpy.data.armatures.new('Roots') root_arm = bpy.data.objects.new('Roots', root_data) context.scene.objects.link(root_arm) root_arm.select = True context.scene.objects.active = root_arm bpy.ops.object.mode_set(mode='EDIT') for ob in self.units: bpy.ops.armature.bone_primitive_add(name=ob.name + 'root') bpy.ops.object.mode_set(mode='OBJECT') root_arm.select = False self.units[0].select = True help_txt = "Right click to select a tooth \n Align View with root, mes and distal\n Up Arrow and Dn Arrow to select different units \n Left click in middle of prep to set axis \n Enter to finish \n ESC to cancel" self.help_box = TextBox(context, 500, 500, 300, 200, 10, 20, help_txt) self.help_box.fit_box_width_to_text_lines() self.help_box.fit_box_height_to_text_lines() self.help_box.snap_to_corner(context, corner=[1, 1]) aspect, mid = menu_utils.view3d_get_size_and_mid(context) self.target_box = TextBox(context, mid[0], aspect[1] - 20, 300, 200, 10, 20, self.message) self.target_box.format_and_wrap_text() self.target_box.fit_box_width_to_text_lines() self.target_box.fit_box_height_to_text_lines() self.mode = 'main' context.window_manager.modal_handler_add(self) self._handle = bpy.types.SpaceView3D.draw_handler_add( insertion_axis_draw_callback, (self, context), 'WINDOW', 'POST_PIXEL') return {'RUNNING_MODAL'}
def execute(self, context): settings = get_settings() dbg = settings.debug #TODO: Scene Preservation recording teeth = odcutils.tooth_selection(context) sce = bpy.context.scene layers_copy = [layer for layer in context.scene.collection.all_objects] context.scene.collection.all_objects[0] for tooth in teeth: #see if there is a corresponding implant if tooth.name in sce.odc_implants: contour = bpy.data.objects.get(tooth.contour) Z = Vector((0, 0, -1)) if contour: if tooth.axis: Axis = bpy.data.objects.get(tooth.axis) if Axis: neg_z = Axis.matrix_world.to_quaternion() @ Z rot_diff = odcutils.rot_between_vecs( Vector((0, 0, 1)), neg_z) else: neg_z = contour.matrix_world.to_quaternion() @ Z rot_diff = odcutils.rot_between_vecs( Vector((0, 0, 1)), neg_z) else: neg_z = contour.matrix_world.to_quaternion() @ Z rot_diff = odcutils.rot_between_vecs( Vector((0, 0, 1)), neg_z) mx = contour.matrix_world x = mx[0][3] y = mx[1][3] z = mx[2][3] #CEJ Location new_loc = odcutils.box_feature_locations( contour, Vector((0, 0, -1))) Imp = implant_utils.place_implant( context, sce.odc_implants[tooth.name], new_loc, rot_diff, self.imp, hardware=self.hardware) #reposition platform below CEJ world_mx = Imp.matrix_world delta = Imp.dimensions[2] * world_mx.to_3x3() @ Vector( (0, 0, 1)) + self.depth @ world_mx.to_3x3() @ Vector( (0, 0, 1)) world_mx[0][3] += delta[0] world_mx[1][3] += delta[1] world_mx[2][3] += delta[2] #odcutils.reorient_object(Imp, rot_diff) odcutils.layer_management(sce.odc_implants, debug=False) for i, layer in enumerate(layers_copy): context.scene.collection.all_objects[i] = layer context.scene.collection.all_objects[11] = True return {'FINISHED'}
def execute(self, context): settings = get_settings() dbg = settings.debug odc_bridge = bridge_methods.active_spanning_restoration(context)[0] layers_copy = [layer for layer in context.scene.layers] context.scene.layers[0] = True bridge_teeth = [ context.scene.odc_teeth[name] for name in odc_bridge.tooth_string.split(sep=":") ] contour_obs = [ bpy.data.objects.get(tooth.contour) for tooth in bridge_teeth ] if None in contour_obs: bad_unit = contour_obs.index(None) bad_tooth = bridge_teeth[bad_unit].name self.report({'ERROR'}, 'Full Contour design missing for ' + bad_tooth) return {'CANCELLED'} left_teeth = [] right_teeth = [] for tooth in bridge_teeth: if tooth.name.startswith('2') or tooth.name.startswith('3'): left_teeth.append(tooth) else: right_teeth.append(tooth) print('left teeth') print([tooth.name for tooth in left_teeth]) def get_key(tooth): return tooth.name print([ tooth.name for tooth in sorted(left_teeth, key=get_key, reverse=True) ]) if len(left_teeth): left_teeth_sorted = [ tooth for tooth in sorted(left_teeth, key=get_key, reverse=True) ] left_contours = [ bpy.data.objects.get(tooth.contour) for tooth in left_teeth_sorted ] left_base_ob = left_contours[0] print(left_base_ob.name) left_bridge_me = left_base_ob.to_mesh(context.scene, apply_modifiers=True, settings='PREVIEW') left_bridge_ob = bpy.data.objects.new(odc_bridge.name, left_bridge_me) left_bridge_ob.matrix_world = left_base_ob.matrix_world context.scene.objects.link(left_bridge_ob) print(left_bridge_ob.name) for i in range(1, len(left_contours)): print('adding boolean modifier') mod = left_bridge_ob.modifiers.new(str(i), 'BOOLEAN') mod.operation = 'UNION' mod.object = left_contours[i] print(left_contours[i].name) left_final_me = left_bridge_ob.to_mesh(context.scene, apply_modifiers=True, settings='PREVIEW') mods = [mod for mod in left_bridge_ob.modifiers] for mod in mods: left_bridge_ob.modifiers.remove(mod) left_bridge_ob.data = left_final_me odc_bridge.bridge = left_bridge_ob.name if len(right_teeth): right_teeth_sorted = [ tooth for tooth in sorted(right_teeth, key=get_key, reverse=True) ] right_contours = [ bpy.data.objects.get(tooth.contour) for tooth in right_teeth_sorted ] right_base_ob = right_contours[0] right_bridge_me = right_base_ob.to_mesh(context.scene, apply_modifiers=True, settings='PREVIEW') right_bridge_ob = bpy.data.objects.new(odc_bridge.name, right_bridge_me) right_bridge_ob.matrix_world = right_base_ob.matrix_world context.scene.objects.link(right_bridge_ob) for i in range(1, len(right_contours)): mod = right_bridge_ob.modifiers.new(str(i), 'BOOLEAN') mod.operation = 'UNION' mod.object = right_contours[i] right_final_me = right_bridge_ob.to_mesh(context.scene, apply_modifiers=True, settings='PREVIEW') mods = [mod for mod in right_bridge_ob.modifiers] for mod in mods: right_bridge_ob.modifiers.remove(mod) right_bridge_ob.data = right_final_me odc_bridge.bridge = right_bridge_ob.name if len(left_teeth) and len(right_teeth): mod = left_bridge_ob.modifiers.new('Midline', 'BOOLEAN') mod.operation = 'UNION' mod.object = right_bridge_ob left_bridge_ob.update_tag() context.scene.update() final_me = left_bridge_ob.to_mesh(context.scene, apply_modifiers=True, settings='PREVIEW') mods = [mod for mod in left_bridge_ob.modifiers] for mod in mods: left_bridge_ob.modifiers.remove(mod) left_bridge_ob.data = final_me context.scene.objects.unlink(right_bridge_ob) bpy.data.objects.remove(right_bridge_ob) bpy.data.meshes.remove(right_bridge_me) odc_bridge.bridge = left_bridge_ob.name return {'FINISHED'}