Пример #1
0
    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'}
Пример #2
0
    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'}
Пример #3
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

        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'}
Пример #4
0
    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'}
Пример #5
0
    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")
Пример #6
0
 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'}
Пример #7
0
    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'}
Пример #8
0
    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
Пример #9
0
    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'}
Пример #10
0
    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'}
Пример #11
0
    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'}
Пример #12
0
    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'}
Пример #13
0
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)
Пример #14
0
    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")
Пример #15
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
Пример #16
0
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
Пример #17
0
    def execute(self, context):
        settings = get_settings()
        dbg = settings.debug
        bridge_methods.bridge_from_selection(context, debug=dbg)

        return {'FINISHED'}
Пример #18
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.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'}
Пример #19
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.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'}
Пример #20
0
    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'}
Пример #21
0
    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'}
Пример #22
0
    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'}
Пример #23
0
    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'}