示例#1
0
    def execute(self, context):
        keywords = self.as_keywords(ignore=("axis_forward",
                                            "axis_up",
                                            "use_selection",
                                            "global_scale",
                                            "check_existing",
                                            "filter_glob",
                                            "use_scene_unit",
                                            "use_mesh_modifiers",
                                            "batch_mode"
                                            ))

        scene = context.scene
        
        Block = bpy.data.objects.get('Templates Base')
        if not Block:
            self.report({'ERROR'}, 'You have not created your block yet')
            return {'CANCEL'}
        
        
        #TODO, maybe give option to export the sweep surface or convex surface
        data_seq = [Block]

        # Take into account scene's unit scale, so that 1 inch in Blender gives 1 inch elsewhere! See T42000.
        global_scale = self.global_scale
        if scene.unit_settings.system != 'NONE' and self.use_scene_unit:
            global_scale *= scene.unit_settings.scale_length

        global_matrix = axis_conversion(from_forward=self.axis_forward,
                                        from_up=self.axis_up,
                                        ).to_4x4() * Matrix.Scale(global_scale, 4)

        if self.batch_mode == 'OFF':
            faces = itertools.chain.from_iterable(
                    blender_utils.faces_from_mesh(ob, global_matrix, self.use_mesh_modifiers)
                    for ob in data_seq)

            stl_utils.write_stl(faces=faces, **keywords)
        elif self.batch_mode == 'OBJECT':
            prefix = os.path.splitext(self.filepath)[0]
            keywords_temp = keywords.copy()
            for ob in data_seq:
                faces = blender_utils.faces_from_mesh(ob, global_matrix, self.use_mesh_modifiers)
                keywords_temp["filepath"] = prefix + bpy.path.clean_name(ob.name) + ".stl"
                stl_utils.write_stl(faces=faces, **keywords_temp)
        
        filename = os.path.basename(self.filepath).split('.')[0]
        tracking.trackUsage("apgExportBlock", param = filename)
        return {'FINISHED'}
示例#2
0
    def execute(self, context):
        tracking.trackUsage("D3Splint:StopFunctionalSurface", None)
        print('removing the handler')

        handlers = [
            hand.__name__ for hand in bpy.app.handlers.frame_change_pre
        ]

        if occlusal_surface_frame_change.__name__ in handlers:

            bpy.app.handlers.frame_change_pre.remove(
                occlusal_surface_frame_change)

        else:
            print('alrady removed')

        return {'FINISHED'}
示例#3
0
 def execute(self, context):
     
     n = context.scene.odc_splint_index
     splint = context.scene.odc_splints[n]
     prefs = get_settings()
     
     start = time.time()
     
     Shell = bpy.data.objects.get('Final Splint')
    
     
     
     if Shell == None:
         self.report({'ERROR'}, 'Need to calculate the finalize the splint first')
         return {'CANCELLED'}
     
     bme = bmesh.new()
     bme.from_object(Shell, context.scene)
     bme.verts.ensure_lookup_table()
     bme.edges.ensure_lookup_table()
     bme.faces.ensure_lookup_table()
     
     
     islands = bmesh_loose_parts(bme, selected_faces = None, max_iters = 100)
     
     if len(islands) == 1:
         print('there is only one solid part')
         Shell.modifiers.clear()
         bme.to_mesh(Shell.data)
         bme.free()
         return {'FINISHED'}
         
     best_island = max(islands, key = len)
     to_keep = set(best_island)
     
     total_faces = set(bme.faces[:])
     del_faces = total_faces - to_keep
     bmesh.ops.delete(bme, geom = list(del_faces), context = 3)
     del_verts = []  #There has GOT to be a smarter way.  Maybe by iterating over del_faces?
     for v in bme.verts:
         if all([f in del_faces for f in v.link_faces]):
             del_verts += [v]        
     
     bmesh.ops.delete(bme, geom = del_verts, context = 1)
     del_edges = []
     for ed in bme.edges:
         if len(ed.link_faces) == 0:
             del_edges += [ed]
             
     bmesh.ops.delete(bme, geom = del_edges, context = 4)
     
     
     Shell.modifiers.clear()
     bme.to_mesh(Shell.data)
     
     bme.free()
     
     finish = time.time()
     print('took %f seconds to clean islands' % (finish - start))
     
     
     completion_time = time.time() - start
     print('Applied all modifiers and removed islands in %f seconds' % completion_time)   
    
     tracking.trackUsage("D3Splint:RemoveIslands",str(completion_time)[0:4])
     return {'FINISHED'}  
示例#4
0
    def execute(self, context):
        
        n = context.scene.odc_splint_index
        splint = context.scene.odc_splints[n]
        
        prefs = get_settings()
        if not prefs.non_clinical_use:
            self.report({'ERROR'}, 'You must certify non-clinical use in your addon preferences or in the panel')
            return {'CANCELLED'}
        
        if splint.finalize_splint:
            self.report({'WARNING'}, 'You have already finalized, this will remove or alter existing modifiers and try again')
         
        if splint.workflow_type != 'BITE_POSITIONER':
            self.report({'ERROR'}, 'This splint is not a bite positioner workflow, change it to use this function')
            return {'CANCELLED'}
        
        Shell = bpy.data.objects.get('Splint Shell')
        Maxilla = bpy.data.objects.get(splint.get_maxilla())
        Mandible = bpy.data.objects.get(splint.get_mandible())
        
        
        if Shell == None:
            self.report({'ERROR'}, 'Need to calculate the bite wafer first')
            return {'CANCELLED'}
        
        if Maxilla == None:
            self.report({'ERROR'}, 'Need to mark the maxillary modelfirst')    
            return {'CANCELLED'}
        
        if Mandible == None:
            self.report({'ERROR'}, 'Need to mark the mandible first')    
            return {'CANCELLED'}
        
        if context.mode != 'OBJECT':
            bpy.ops.object.mode_set(mode = 'OBJECT')
        
        start = time.time()
        #don't add multiple boolean modifiers
        
        if 'Final Splint' not in bpy.data.objects:
            me = Shell.to_mesh(context.scene, apply_modifiers = True, settings = 'PREVIEW')
            ob = bpy.data.objects.new('Final Splint', me)
            context.scene.objects.link(ob)
            ob.matrix_world = Shell.matrix_world
        else:
            ob = bpy.data.objects.get('Final Splint')
            me = ob.data
        
            
        #Blockout Wax Needs a union modifier
        if 'Subtract Mandible' in ob.modifiers:
            mod = ob.modifiers.get('Subtract Mandible')
            mod.object = Mandible
            mod.operation = 'DIFFERENCE'
            mod.solver = self.solver
        else:
            mod = ob.modifiers.new('Subtract Mandible', type = 'BOOLEAN')
            mod.object = Mandible
            mod.operation = 'DIFFERENCE'
            mod.solver = self.solver
            
            
        if 'Subtract Maxilla' in ob.modifiers:
            mod = ob.modifiers.get('Subtract Maxilla')
            mod.object = Maxilla
            mod.operation = 'DIFFERENCE'
            mod.solver = self.solver
        else:
            mod = ob.modifiers.new('Subtract Maxilla', type = 'BOOLEAN')
            mod.object = Maxilla
            mod.operation = 'DIFFERENCE'
            mod.solver = self.solver
            
        

        for obj in context.scene.objects:
            obj.hide = True
            
        context.scene.objects.active = ob
        ob.select = True
        ob.hide = False
         
        completion_time = time.time() - start
        print('competed the boolean subtraction in %f seconds' % completion_time)   
        splint.finalize_splint = True
        tracking.trackUsage("D3Splint:FinishBiteBoolean",(self.solver, str(completion_time)[0:4]))
        return {'FINISHED'}    
示例#5
0
 def execute(self, context):
     
     n = context.scene.odc_splint_index
     splint = context.scene.odc_splints[n]
     prefs = get_settings()
     if not prefs.non_clinical_use:
         self.report({'ERROR'}, 'You must certify non-clinical use in your addon preferences or in the panel')
         return {'CANCELLED'}
     
     if splint.finalize_splint:
         self.report({'WARNING'}, 'You have already finalized, this will remove or alter existing modifiers and try again')
     
     if self.solver == 'CORK':
         self.report({'ERROR'}, 'The Cork engine has not been set up with this new method')
         return {'CANCELLED'}
      
     Shell = bpy.data.objects.get('Splint Shell')
     Refractory = bpy.data.objects.get('Refractory Model')
     
     if Shell == None:
         self.report({'ERROR'}, 'Need to calculate splint shell first')
         return {'CANCELLED'}
     
     if Refractory == None:
         self.report({'ERROR'}, 'Need to make refractory model first')    
         return {'CANCELLED'}
     
     
     if context.mode != 'OBJECT':
         bpy.ops.object.mode_set(mode = 'OBJECT')
     
     start = time.time()
     #don't add multiple boolean modifiers
     
     if 'Final Splint' not in bpy.data.objects:
         me = Shell.to_mesh(context.scene, apply_modifiers = True, settings = 'PREVIEW')
         ob = bpy.data.objects.new('Final Splint', me)
         context.scene.objects.link(ob)
         ob.matrix_world = Shell.matrix_world
     else:
         ob = bpy.data.objects.get('Final Splint')
         me = ob.data
         
     a_base = bpy.data.objects.get('Auto Base')
     if 'Trim Base' in ob.modifiers and a_base != None:
         mod = ob.modifiers.get('Trim Base')
         mod.object = a_base
         mod.operation = 'DIFFERENCE'
         mod.solver = self.solver
     else:
         mod = ob.modifiers.new('Trim Base', type = 'BOOLEAN')
         mod.object = a_base
         mod.operation = 'DIFFERENCE'
         mod.solver = self.solver 
         
 
     #Final Spint need only 1 boolean operation
     if 'Refractory Model' in ob.modifiers:
         mod = ob.modifiers.get('Passive Spacer')
         
     else:
         mod = ob.modifiers.new('Refractory Model', type = 'BOOLEAN')
     mod.object = Refractory
     mod.operation = 'DIFFERENCE'
     mod.solver = self.solver
     
     for obj in context.scene.objects:
         obj.hide = True
         
     context.scene.objects.active = ob
     ob.select = True
     ob.hide = False
     ob.update_tag()
     context.scene.update()
         
     completion_time = time.time() - start
     print('competed the boolean subtraction in %f seconds' % completion_time)   
     splint.finalize_splint = True
     splint.ops_string += 'Finalize Splint:'
     tracking.trackUsage("D3Splint:FinishBoolean3",(self.solver, str(completion_time)[0:4]))
     
     tmodel = bpy.data.objects.get('Trimmed_Model')
     #make sure user can verify no intersections
     if tmodel:
         tmodel.hide = False
 
     context.space_data.show_backface_culling = False
     return {'FINISHED'}
示例#6
0
 def execute(self, context):
     
     n = context.scene.odc_splint_index
     splint = context.scene.odc_splints[n]
     prefs = get_settings()
     if not prefs.non_clinical_use:
         self.report({'ERROR'}, 'You must certify non-clinical use in your addon preferences or in the panel')
         return {'CANCELLED'}
     
     if splint.finalize_splint:
         self.report({'WARNING'}, 'You have already finalized, this will remove or alter existing modifiers and try again')
         
     Shell = bpy.data.objects.get('Splint Shell')
     Passive = bpy.data.objects.get('Passive Spacer')
     Blockout = bpy.data.objects.get('Blockout Wax')
     
     
     if Shell == None:
         self.report({'ERROR'}, 'Need to calculate splint shell first')
         return {'CANCELLED'}
     
     if Passive == None:
         self.report({'ERROR'}, 'Need to make passive spacer first')    
         return {'CANCELLED'}
     
     if Blockout == None and self.use_blockout == True:
         self.report({'ERROR'}, 'Need to blockout trimmed model first')    
         return {'CANCELLED'}
     
     if context.mode != 'OBJECT':
         bpy.ops.object.mode_set(mode = 'OBJECT')
     
     start = time.time()
     #don't add multiple boolean modifiers
     
     
     
     if 'Final Splint' not in bpy.data.objects:
         me = Shell.to_mesh(context.scene, apply_modifiers = True, settings = 'PREVIEW')
         ob = bpy.data.objects.new('Final Splint', me)
         context.scene.objects.link(ob)
         ob.matrix_world = Shell.matrix_world
     else:
         ob = bpy.data.objects.get('Final Splint')
         me = ob.data
         
     a_base = bpy.data.objects.get('Auto Base')
     if 'Trim Base' in ob.modifiers and a_base != None:
         mod = ob.modifiers.get('Trim Base')
         mod.object = a_base
         mod.operation = 'DIFFERENCE'
         mod.solver = self.solver1
     else:
         mod = ob.modifiers.new('Trim Base', type = 'BOOLEAN')
         mod.object = a_base
         mod.operation = 'DIFFERENCE'
         mod.solver = self.solver1  
         
     if self.method_order == 'JOIN':
         #Structure is   Shell - (Blockout + Passive)
         
         #Blockout Wax Needs a union modifier
         if 'Join Passive' in Blockout.modifiers:
             mod = Blockout.modifiers.get('Join Passive')
             mod.object = Passive
             mod.operation = 'UNION'
             mod.solver = self.solver1
         else:
             mod = Blockout.modifiers.new('Join Passive', type = 'BOOLEAN')
             mod.object = Passive
             mod.operation = 'UNION'
             mod.solver = self.solver1
         
         
         #Final Spint need only 1 boolean operation
         if 'Passive Spacer' in ob.modifiers:
             mod = ob.modifiers.get('Passive Spacer')
             ob.modifiers.remove(mod)
             
         if 'Subtract Blockout' in ob.modifiers:
             mod = ob.modifiers.get('Subtract Blockout')
             mod.object = Blockout
             mod.operation = 'DIFFERENCE'
             mod.solver = self.solver2
         else:
             mod = ob.modifiers.new('Subtract Blockout', type = 'BOOLEAN')
             mod.object = Blockout
             mod.operation = 'DIFFERENCE'
             mod.solver = self.solver2
         
     elif self.method_order == 'SUBTRACT':
         
         #Strucure is
         #Shell - Blockout - Passive
         
         #Blockout Wax MUST NOT have modifier
         if 'Join Passive' in Blockout.modifiers:
             mod = Blockout.modifiers.get('Join Passive')
             Blockout.modifiers.remove(mod)
             Blockout.update_tag()
             
         if 'Subtract Blockout' in ob.modifiers:
             mod = ob.modifiers.get('Subtract Blockout')
             mod.object = Blockout
             mod.operation = 'DIFFERENCE'
             mod.solver = self.solver1
         else:
             mod = ob.modifiers.new('Subtract Blockout', type = 'BOOLEAN')
             mod.object = Blockout
             mod.operation = 'DIFFERENCE'
             mod.solver = self.solver1
             
         if 'Passive Spacer' not in ob.modifiers:
             bool_mod = ob.modifiers.new('Passive Spacer', type = 'BOOLEAN')
             bool_mod.operation = 'DIFFERENCE'
             bool_mod.object = Passive
             bool_mod.solver = self.solver2  #Bmesh is too likely to create bad cuts
         else:
             bool_mod = ob.modifiers.get('Passive Spacer')
             bool_mod.operation = 'DIFFERENCE'
             bool_mod.object = Passive
             bool_mod.solver = self.solver2  ##Bmesh is too likely to create bad cuts
         
     
     for obj in context.scene.objects:
         obj.hide = True
         
     context.scene.objects.active = ob
     ob.select = True
     ob.hide = False
     ob.update_tag()
     context.scene.update()
         
     completion_time = time.time() - start
     print('competed the boolean subtraction in %f seconds' % completion_time)   
     splint.finalize_splint = True
     tracking.trackUsage("D3Splint:FinishBoolean",(self.solver1,self.solver2, self.method_order, str(completion_time)[0:4]))
     
     tmodel = bpy.data.objects.get('Trimmed_Model')
     #make sure user can verify no intersections
     if tmodel:
         tmodel.hide = False
 
     
     return {'FINISHED'}
示例#7
0
    def exec(self, context):
        try:
            bme = cork_boolean(context, self._cork, "-diff", self._base, self._plane)
        except Exception as e:
            print('error in line 24')
            self.report({'ERROR'}, str(e))
            tracking.trackUsage("D3Splint:FAILEDCorkBoolean")
            return {'CANCELLED'}

        bme.verts.ensure_lookup_table()
        bme.edges.ensure_lookup_table()
        bme.faces.ensure_lookup_table()
        
        #clean loose verts
        to_delete = []
        for v in bme.verts:
            if len(v.link_edges) < 2:
                to_delete.append(v)
                
        print('deleting %i loose verts' % len(to_delete))
        bmesh.ops.delete(bme, geom = to_delete, context = 1)
        
        bme.verts.ensure_lookup_table()
        bme.edges.ensure_lookup_table()
        bme.faces.ensure_lookup_table()
        
        #delete edges without faces
        to_delete = []
        for ed in bme.edges:
            if len(ed.link_faces) == 0:
                for v in ed.verts:
                    if len(v.link_faces) == 0:
                        to_delete.append(v)

        to_delete = list(set(to_delete))
        bmesh.ops.delete(bme, geom = to_delete, context = 1)
                
        bme.verts.ensure_lookup_table()
        bme.edges.ensure_lookup_table()
        bme.faces.ensure_lookup_table()
        
        total_faces = set(bme.faces[:])
        islands = []
        iters = 0
        while len(total_faces) and iters < 100:
            iters += 1
            seed = total_faces.pop()
            island = flood_selection_faces(bme, {}, seed, max_iters = 10000)
            islands += [island]
            total_faces.difference_update(island)
            
        
        best = max(islands, key = len)
        
        total_faces = set(bme.faces[:])
        del_faces = total_faces - best
        
        bmesh.ops.delete(bme, geom = list(del_faces), context = 3)
        del_verts = []
        for v in bme.verts:
            if all([f in del_faces for f in v.link_faces]):
                del_verts += [v]        
        bmesh.ops.delete(bme, geom = del_verts, context = 1)
        
        
        del_edges = []
        for ed in bme.edges:
            if len(ed.link_faces) == 0:
                del_edges += [ed]
        bmesh.ops.delete(bme, geom = del_edges, context = 4) 
        
        if 'Final Splint' in bpy.data.objects:
            ob = bpy.data.objects.get('Final Splint')
            
            if len(ob.modifiers):
                ob.modifiers.clear()
                
            bme.to_mesh(ob.data)
            ob.data.update()
            
        else:
            me = bpy.data.meshes.new('Final Splint')
            ob = bpy.data.objects.new('Final Splint', me)
            context.scene.objects.link(ob)
        
        bme.free()
        
        for obj in context.scene.objects:
            obj.hide = True
            
        context.scene.objects.active = ob
        ob.select = True
        ob.hide = False
        
        tracking.trackUsage("D3Splint:SplintBooleanCORK")
        return {'FINISHED'}
示例#8
0
    def execute(self, context):
        
        n = context.scene.odc_splint_index
        splint = context.scene.odc_splints[n]
        
        prefs = common_utilities.get_settings()
        if not prefs.non_clinical_use:
            self.report({'ERROR'}, 'You must certify non-clinical use in your addon preferences or in the panel')
            return {'CANCELLED'}
        
        if splint.finalize_splint:
            self.report({'WARNING'}, 'You have already finalized, this will remove or alter existing modifiers and try again')
            
        Shell = bpy.data.objects.get('Splint Shell')
        Passive = bpy.data.objects.get('Passive Spacer')

        if Shell == None:
            self.report({'ERROR'}, 'Need to calculate splint shell first')
            return {'CANCELLED'}
        
        if Passive == None:
            self.report({'ERROR'}, 'Need to make passive spacer first')    
            return {'CANCELLED'}
        
        if context.mode != 'OBJECT':
            bpy.ops.object.mode_set(mode = 'OBJECT')
        
        tracking.trackUsage("D3Splint:FinishBoolean",None)    
        
        
        #don't add multiple boolean modifiers
        if 'Passive Fit' not in Shell.modifiers:
            bool_mod = Shell.modifiers.new('Passive Fit', type = 'BOOLEAN')
            bool_mod.operation = 'DIFFERENCE'
        
        bool_mod.solver = self.solver
            
        #update in case they changed the spacer
        bool_mod.object = Passive
        Passive.hide = True 
        
        bme = bmesh.new()
        bme.from_object(Shell, context.scene)
        bme.faces.ensure_lookup_table()
        bme.verts.ensure_lookup_table()
        total_faces = set(bme.faces[:])
        islands = []
        iters = 0
        while len(total_faces) and iters < 100:
            iters += 1
            seed = total_faces.pop()
            island = flood_selection_faces(bme, {}, seed, max_iters = 10000)
            islands += [island]
            total_faces.difference_update(island)
            
        best = max(islands, key = len)
        
        total_faces = set(bme.faces[:])
        del_faces = total_faces - best
        
        bmesh.ops.delete(bme, geom = list(del_faces), context = 3)
        del_verts = []
        for v in bme.verts:
            if all([f in del_faces for f in v.link_faces]):
                del_verts += [v]        
        bmesh.ops.delete(bme, geom = del_verts, context = 1)
        
        
        del_edges = []
        for ed in bme.edges:
            if len(ed.link_faces) == 0:
                del_edges += [ed]
        bmesh.ops.delete(bme, geom = del_edges, context = 4) 
        
        
        if 'Final Splint' not in bpy.data.objects:
            me = bpy.data.meshes.new('Final Splint')
            ob = bpy.data.objects.new('Final Splint', me)
            context.scene.objects.link(ob)
            ob.matrix_world = Shell.matrix_world
        else:
            ob = bpy.data.objects.get('Final Splint')
            me = ob.data
            
        bme.to_mesh(me)
        bme.free()
        
        for obj in context.scene.objects:
            obj.hide = True
            
        context.scene.objects.active = ob
        ob.select = True
        ob.hide = False
        
        tmodel = bpy.data.objects.get('Trimmed_Model')
        #make sure user can verify no intersections
        if tmodel:
            tmodel.hide = False

        splint.finalize_splint = True
        context.space_data.show_backface_culling = False
        return {'FINISHED'}
示例#9
0
 def finish(self, context):
     #settings = get_settings()
     #apply all modifiers
     context.window.cursor_modal_restore()
     tracking.trackUsage("D3Splint:PlaneCutRaw",None)
    def execute(self, context):
        
        if not len(context.scene.odc_splints):
            self.report({'ERROR'}, 'Need to start a splint by setting model first')
            return {'CANCELLED'}
        
        n = context.scene.odc_splint_index
        splint = context.scene.odc_splints[n]
        
        Model = bpy.data.objects.get(splint.model)
        Shell = bpy.data.objects.get('Splint Shell')
        Opposing = bpy.data.objects.get(splint.opposing)

        
        if Shell == None:
            self.report({'ERROR'}, 'Need to calculate splint shell first')
            return {'CANCELLED'}
        if Opposing == None:
            self.report({'ERROR'}, 'Need to indicate opposing model')
            return {'CANCELLED'}
        
        if len(Shell.modifiers):
            old_data = Shell.data
            new_data = Shell.to_mesh(context.scene, apply_modifiers = True, settings = 'PREVIEW')
            
            for mod in Shell.modifiers:
                Shell.modifiers.remove(mod)
            
            Shell.data = new_data
            bpy.data.meshes.remove(old_data)
        
        bme = bmesh.new()
        bme.from_mesh(Opposing.data)
        bme.verts.ensure_lookup_table()
        
        
        
        mx_p = Opposing.matrix_world
        imx_p = mx_p.inverted()
        
        mx_m = Model.matrix_world
        imx_m = mx_m.inverted()
        
        mx_s = Shell.matrix_world
        imx_s = mx_s.inverted()
        
        if splint.jaw_type == 'MAXILLA':
            Z = Vector((0,0,1))
        else:
            Z = Vector((0,0,-1))
            

        #Do a manual ray cast to the underlying data...use BVH in future?
        sbme = bmesh.new()
        sbme.from_mesh(Shell.data)
        sbme.verts.ensure_lookup_table()
        
        print('got the shell data')
        n_ray_casted = 0
        for v in sbme.verts:
            ray_orig = mx_s * v.co
            ray_target = mx_s * ( v.co + 5 * Z )
            ray_target2 = mx_s * (v.co - self.snap_limit * Z)
            ok, loc, no, face_ind = Opposing.ray_cast(imx_p * ray_orig, imx_p * ray_target - imx_p*ray_orig)
            
            if ok:
                v.co = imx_s * (mx_p * loc)
                n_ray_casted += 1
                
            if self.sculpt_to:
                if abs(v.normal.dot(Z)) < .2: continue
                
                
                ok, loc, no, face_ind = Opposing.ray_cast(imx_p * ray_orig, imx_p * ray_target2 - imx_p*ray_orig, distance = self.snap_limit)
                if ok:
                    v.co = imx_s * (mx_p * loc)
                    n_ray_casted += 1
                    
        sbme.to_mesh(Shell.data)
        sbme.free()
        Shell.data.update()
                
        Opposing.hide = True
        Shell.hide = False
        Model.hide = False
        

        splint.ops_string += 'MIP_Bite:'
        tracking.trackUsage("D3Splint:MIPBite", param = None, background = True)
        return {'FINISHED'}
示例#11
0
 def finish(self, context):
     #settings = get_settings()
     context.window.cursor_modal_restore()
     tracking.trackUsage("D3Splint:StencilText",None)
示例#12
0
 def invoke(self, context, event):
     tracking.trackUsage("D3Splint:ChangePinSetting", None)
     return context.window_manager.invoke_props_dialog(self)
示例#13
0
    def execute(self, context):
        tracking.trackUsage(
            "D3Tool:GenArticulator",
            str((self.intra_condyle_width, self.intra_condyle_width,
                 self.bennet_angle, self.canine_guidance,
                 self.incisal_guidance)))

        context.scene.frame_start = 0
        context.scene.frame_end = 3 * self.resolution
        context.scene.frame_set(0)

        #add 2 bezier paths named right and left condyle, move them to the condyle width
        if 'Articulator' in bpy.data.objects:
            #start fresh
            art_arm = bpy.data.objects.get('Articulator')
            n = context.scene.odc_splint_index
            splint = context.scene.odc_splints[n]
            opposing = splint.get_mandible()
            Model = bpy.data.objects.get(opposing)
            if Model:
                for cons in Model.constraints:
                    if cons.type == 'CHILD_OF' and cons.target == art_arm:
                        Model.constraints.remove(cons)

            context.scene.objects.unlink(art_arm)
            art_data = art_arm.data

            bpy.data.objects.remove(art_arm)
            bpy.data.armatures.remove(art_data)

        if 'Right Condyle Path' in bpy.data.curves:
            rcp_obj = bpy.data.objects.get("RCP")
            lcp_obj = bpy.data.objects.get("LCP")

            rcp = bpy.data.curves.get('Right Condyle Path')
            lcp = bpy.data.curves.get('Left Condyle Path')

        else:
            rcp = bpy.data.curves.new('Right Condyle Path', type='CURVE')
            lcp = bpy.data.curves.new('Left Condyle Path', type='CURVE')

            rcp.splines.new('BEZIER')
            lcp.splines.new('BEZIER')

            rcp.splines[0].bezier_points.add(count=1)
            lcp.splines[0].bezier_points.add(count=1)

            rcp_obj = bpy.data.objects.new("RCP", rcp)
            lcp_obj = bpy.data.objects.new("LCP", lcp)

            context.scene.objects.link(rcp_obj)
            context.scene.objects.link(lcp_obj)

        rcp.splines[0].bezier_points[0].handle_left_type = 'AUTO'
        rcp.splines[0].bezier_points[0].handle_right_type = 'AUTO'
        lcp.splines[0].bezier_points[0].handle_left_type = 'AUTO'
        lcp.splines[0].bezier_points[0].handle_right_type = 'AUTO'

        rcp.splines[0].bezier_points[1].handle_left_type = 'AUTO'
        rcp.splines[0].bezier_points[1].handle_right_type = 'AUTO'
        lcp.splines[0].bezier_points[1].handle_left_type = 'AUTO'
        lcp.splines[0].bezier_points[1].handle_right_type = 'AUTO'

        #track lenght
        rcp.splines[0].bezier_points[0].co = Vector((-2, 0, 0))
        lcp.splines[0].bezier_points[0].co = Vector((-2, 0, 0))

        rcp.splines[0].bezier_points[1].co = Vector((8, 0, 0))
        lcp.splines[0].bezier_points[1].co = Vector((8, 0, 0))

        rcp.dimensions = '3D'
        lcp.dimensions = '3D'

        rcp_obj.location = Vector((0, -0.5 * self.intra_condyle_width, 0))
        lcp_obj.location = Vector((0, 0.5 * self.intra_condyle_width, 0))

        lcp_obj.rotation_euler[1] = self.condyle_angle / 180 * math.pi
        rcp_obj.rotation_euler[1] = self.condyle_angle / 180 * math.pi

        lcp_obj.rotation_euler[2] = -self.bennet_angle / 180 * math.pi
        rcp_obj.rotation_euler[2] = self.bennet_angle / 180 * math.pi

        ant_guidance = Vector(
            (math.cos(self.incisal_guidance * math.pi / 180), 0,
             -math.sin(self.incisal_guidance * math.pi / 180)))
        rcan_guidance = Vector(
            (0, math.cos(self.canine_guidance * math.pi / 180),
             -math.sin(self.canine_guidance * math.pi / 180)))
        lcan_guidance = Vector(
            (0, -math.cos(self.canine_guidance * math.pi / 180),
             -math.sin(self.canine_guidance * math.pi / 180)))

        ant_guidance.normalize()
        rcan_guidance.normalize()
        lcan_guidance.normalize()

        bme = bmesh.new()

        v0 = Vector((0, -.5 * self.guidance_delay_lat, 0))
        v1 = v0 + Vector((self.guidance_delay_ant, 0, 0))
        v2 = v1 + 15 * ant_guidance

        v3 = Vector((0, .5 * self.guidance_delay_lat, 0))
        v4 = v3 + Vector((self.guidance_delay_ant, 0, 0))
        v5 = v4 + 15 * ant_guidance

        v6 = v0 + 15 * lcan_guidance
        v7 = v1 + 15 * lcan_guidance
        v8 = v2 + 15 * lcan_guidance

        v9 = v3 + 15 * rcan_guidance
        v10 = v4 + 15 * rcan_guidance
        v11 = v5 + 15 * rcan_guidance
        vecs = [v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11]

        vs = [bme.verts.new(v) for v in vecs]

        bme.faces.new((vs[0], vs[3], vs[4], vs[1]))
        bme.faces.new((vs[1], vs[4], vs[5], vs[2]))

        bme.faces.new((vs[3], vs[9], vs[10], vs[4]))
        bme.faces.new((vs[6], vs[0], vs[1], vs[7]))

        bme.faces.new((vs[4], vs[10], vs[11], vs[5]))
        bme.faces.new((vs[7], vs[1], vs[2], vs[8]))

        if 'Guide Table' in bpy.data.objects:
            guide_object = bpy.data.objects.get('Guide Table')
            guide_data = guide_object.data

        else:
            guide_data = bpy.data.meshes.new('Guide Table')
            guide_object = bpy.data.objects.new('Guide Table', guide_data)
            context.scene.objects.link(guide_object)
            guide_object.location = Vector(
                (99.9, 0, -60))  #TODO, incisal edge location

        bme.to_mesh(guide_data)

        art_data = bpy.data.armatures.new('Articulator')
        art_data.draw_type = 'STICK'
        art_arm = bpy.data.objects.new('Articulator', art_data)
        context.scene.objects.link(art_arm)

        art_arm.select = True
        context.scene.objects.active = art_arm
        bpy.ops.object.mode_set(mode='EDIT')

        bpy.ops.armature.bone_primitive_add(name="Right Condyle")
        bpy.ops.armature.bone_primitive_add(name="Left Condyle")
        bpy.ops.armature.bone_primitive_add(name="Mand Bow Silent")
        bpy.ops.armature.bone_primitive_add(name="Mandibular Bow")
        bpy.ops.armature.bone_primitive_add(name="Guide Pin")

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

        b = art_arm.data.edit_bones.get("Right Condyle")
        b.head.xyz = Vector((0, 0, 0))
        b.tail.xyz = Vector((0, 0, 10))

        b = art_arm.data.edit_bones.get("Left Condyle")
        b.head.xyz = Vector((0, 0, 0))
        b.tail.xyz = Vector((0, 0, 10))

        b = art_arm.data.edit_bones.get('Mand Bow Silent')
        b.head.xyz = Vector((0, 0, 0))
        b.tail.xyz = Vector((100, 0, 0))

        b = art_arm.data.edit_bones.get('Mandibular Bow')
        b.head.xyz = Vector((0, 0, 0))
        b.tail.xyz = Vector((100, 0, 0))

        #notice this bone points up, because the head will snap to guide plane
        b = art_arm.data.edit_bones.get('Guide Pin')
        b.head.xyz = Vector((100, 0, -60))
        b.tail.xyz = Vector((100, 0, 0))

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

        bpy.ops.object.mode_set(mode='POSE')
        #now set the pose constrints
        if 'threeway_envelope_r' not in bpy.app.driver_namespace:
            bpy.app.driver_namespace[
                'threeway_envelope_r'] = three_way_envelope_r
        if 'threeway_envelope_l' not in bpy.app.driver_namespace:
            bpy.app.driver_namespace[
                'threeway_envelope_l'] = three_way_envelope_l

        pboneR = art_arm.pose.bones.get('Right Condyle')
        cons = pboneR.constraints.new(type='FOLLOW_PATH')
        cons.target = rcp_obj
        cons.use_fixed_location = True
        d = cons.driver_add('offset_factor').driver
        v = d.variables.new()
        v.name = "frame"
        v.targets[0].id_type = 'SCENE'
        v.targets[0].id = context.scene
        v.targets[0].data_path = "frame_current"
        #d.expression = "threeway_envelope_r(frame) * " + str(self.range_of_motion)[0:3]

        cfactor = min(8.0, self.factor / 8.0)
        d.expression = 'threeway_envelope_r(frame,' + str(
            cfactor)[0:4] + ',' + str(self.resolution) + ')'

        pboneL = art_arm.pose.bones.get('Left Condyle')
        cons = pboneL.constraints.new(type='FOLLOW_PATH')
        cons.target = lcp_obj
        cons.use_fixed_location = True
        d = cons.driver_add('offset_factor').driver
        v = d.variables.new()
        v.name = "frame"
        v.targets[0].id_type = 'SCENE'
        v.targets[0].id = context.scene
        v.targets[0].data_path = "frame_current"
        #d.expression = "threeway_envelope_l(frame) * " + str(self.range_of_motion)[0:3]
        d.expression = 'threeway_envelope_l(frame,' + str(
            cfactor)[0:4] + ',' + str(self.resolution) + ')'

        cons = pboneR.constraints.new(type='LOCKED_TRACK')
        cons.target = art_arm
        cons.subtarget = "Left Condyle"
        cons.track_axis = "TRACK_NEGATIVE_Z"
        cons.lock_axis = "LOCK_Y"

        cons = pboneL.constraints.new(type='LOCKED_TRACK')
        cons.target = art_arm
        cons.subtarget = "Right Condyle"
        cons.track_axis = 'TRACK_NEGATIVE_Z'
        cons.lock_axis = "LOCK_Y"

        #update the pose posititions
        bpy.ops.object.mode_set(mode='EDIT')
        bpy.ops.object.mode_set(mode='POSE')

        pboneBow = art_arm.pose.bones.get('Mand Bow Silent')
        cons = pboneBow.constraints.new('CHILD_OF')
        cons.target = art_arm
        cons.subtarget = 'Left Condyle'
        cons.inverse_matrix = pboneL.matrix.inverted()

        bpy.ops.object.mode_set(mode='EDIT')
        cons.influence = .5
        bpy.ops.object.mode_set(mode='POSE')

        cons = pboneBow.constraints.new('CHILD_OF')
        cons.target = art_arm
        cons.subtarget = 'Right Condyle'
        cons.inverse_matrix = pboneR.matrix.inverted()

        bpy.ops.object.mode_set(mode='EDIT')
        cons.influence = .5
        bpy.ops.object.mode_set(mode='POSE')

        pbonePin = art_arm.pose.bones.get('Guide Pin')
        cons = pbonePin.constraints.new(type='CHILD_OF')
        cons.target = art_arm
        cons.use_rotation_x = False
        cons.use_rotation_y = False
        cons.subtarget = 'Mand Bow Silent'
        cons.inverse_matrix = pboneBow.matrix.inverted()

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

        cons = pbonePin.constraints.new(type='SHRINKWRAP')
        cons.target = guide_object
        cons.shrinkwrap_type = 'PROJECT'
        cons.project_axis = "NEG_Y"

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

        pboneBow2 = art_arm.pose.bones.get("Mandibular Bow")
        cons = pboneBow2.constraints.new(type='CHILD_OF')
        cons.target = art_arm
        cons.subtarget = 'Mand Bow Silent'

        cons = pboneBow2.constraints.new(type='LOCKED_TRACK')
        cons.target = art_arm
        cons.subtarget = 'Guide Pin'
        cons.head_tail = 1
        cons.track_axis = 'TRACK_Y'
        cons.lock_axis = 'LOCK_Z'

        cons = pboneBow2.constraints.new(type='TRACK_TO')
        cons.target = art_arm
        cons.subtarget = 'Guide Pin'
        cons.head_tail = 1
        cons.track_axis = 'TRACK_Y'
        cons.up_axis = 'UP_Z'
        #https://blender.stackexchange.com/questions/19602/child-of-constraint-set-inverse-with-python

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

        n = context.scene.odc_splint_index
        splint = context.scene.odc_splints[n]
        maxilla = splint.get_maxilla()
        Maxilla = bpy.data.objects.get(maxilla)
        if Maxilla:
            for ob in context.scene.objects:
                ob.select = False
            Maxilla.hide = False
            context.scene.objects.active = Maxilla
            Maxilla.select = True
        #bpy.ops.view3d.viewnumpad(type = 'RIGHT')

        bpy.ops.d3splint.enable_articulator_visualizations()

        #save settings to object
        art_arm['bennet_angle'] = self.bennet_angle
        art_arm['intra_condyle_width'] = self.intra_condyle_width
        art_arm['incisal_guidance'] = self.incisal_guidance
        art_arm['canine_guidance'] = self.canine_guidance
        art_arm['condyle_angle'] = self.condyle_angle
        art_arm['guidance_delay_ant'] = self.guidance_delay_ant
        art_arm['guidance_delay_lat'] = self.guidance_delay_ant
        splint.ops_string += 'GenArticulator:'

        if not self.auto_mount:
            return {'FINISHED'}

        n = context.scene.odc_splint_index
        splint = context.scene.odc_splints[n]
        splint.ops_string += 'Generate Articulator:'
        mandible = splint.get_mandible()
        Mandible = bpy.data.objects.get(mandible)

        if Mandible:

            Mandible.hide = False
            cons = Mandible.constraints.new(type='CHILD_OF')
            cons.target = art_arm
            cons.subtarget = 'Mandibular Bow'

            mx = art_arm.matrix_world * art_arm.pose.bones[
                'Mandibular Bow'].matrix
            cons.inverse_matrix = mx.inverted()

        #write the lower jaw BVH to cache for fast ray_casting
        OppModel = bpy.data.objects.get(splint.opposing)
        if OppModel != None:
            bme = bmesh.new()
            bme.from_mesh(OppModel.data)
            bvh = BVHTree.FromBMesh(bme)
            splint_cache.write_mesh_cache(OppModel, bme, bvh)

        return {'FINISHED'}
示例#14
0
    def execute(self, context):
        splint = context.scene.odc_splints[0]
        Model = bpy.data.objects.get(splint.opposing)
        Master = bpy.data.objects.get(splint.model)

        Art = bpy.data.objects.get('Articulator')

        if Model == None:
            self.report({'ERROR'}, 'No Opposing Model')
            return {'CANCELLED'}

        if Art == None:
            self.report({
                'ERROR'
            }, 'You need to Generate Articulator or set initial articulator values first'
                        )
            return {'CANCELLED'}

        if not splint_cache.is_object_valid(Model):
            splint_cache.clear_mesh_cache()
            bme = bmesh.new()

            bme.from_mesh(Model.data)
            bme.faces.ensure_lookup_table()
            bme.verts.ensure_lookup_table()

            bvh = BVHTree.FromBMesh(bme)
            splint_cache.write_mesh_cache(Model, bme, bvh)

        bpy.ops.d3splint.articulator_mode_set(
            mode=self.mode,
            resolution=self.resolution,
            range_of_motion=self.range_of_motion,
            use_relax=self.use_relax,
            relax_ramp_length=self.relax_ramp_length)

        #filter the occlusal surface verts
        Plane = bpy.data.objects.get('Dynamic Occlusal Surface')
        if Plane == None:
            self.report({
                'ERROR'
            }, 'Need to mark occlusal curve on opposing object to get reference plane'
                        )
            return {'CANCELLED'}

        Shell = bpy.data.objects.get('Splint Shell')
        if Shell == None:
            self.report({'WARNING'},
                        'There is no splint shell, however this OK.')

        if Shell:

            if len(Shell.modifiers):
                Shell.select = True
                Shell.hide = False
                context.scene.objects.active = Shell

                for mod in Shell.modifiers:
                    bpy.ops.object.modifier_apply(modifier=mod.name)

            bme = bmesh.new()
            bme.from_mesh(Plane.data)
            bme.verts.ensure_lookup_table()

            #reset occusal plane if animate articulator has happened already
            if "AnimateArticulator" in splint.ops_string:
                for v in bme.verts:
                    v.co[2] = 0

            mx_p = Plane.matrix_world
            imx_p = mx_p.inverted()

            mx_s = Shell.matrix_world
            imx_s = mx_s.inverted()

            keep_verts = set()
            if splint.jaw_type == 'MAXILLA':
                Z = Vector((0, 0, 1))
            else:
                Z = Vector((0, 0, -1))
            for v in bme.verts:
                ray_orig = mx_p * v.co
                ray_target = mx_p * v.co + 5 * Z
                ok, loc, no, face_ind = Shell.ray_cast(
                    imx_s * ray_orig, imx_s * ray_target - imx_s * ray_orig)

                if ok:
                    keep_verts.add(v)

            print('there are %i keep verts' % len(keep_verts))
            front = set()
            for v in keep_verts:

                immediate_neighbors = [
                    ed.other_vert(v) for ed in v.link_edges
                    if ed.other_vert(v) not in keep_verts
                ]

                front.update(immediate_neighbors)
                front.difference_update(keep_verts)

            keep_verts.update(front)

            for i in range(0, 10):
                new_neighbors = set()
                for v in front:
                    immediate_neighbors = [
                        ed.other_vert(v) for ed in v.link_edges
                        if ed.other_vert(v) not in front
                    ]
                    new_neighbors.update(immediate_neighbors)

                keep_verts.update(front)
                front = new_neighbors

            delete_verts = [v for v in bme.verts if v not in keep_verts]
            bmesh.ops.delete(bme, geom=delete_verts, context=1)
            bme.to_mesh(Plane.data)

        for ob in bpy.data.objects:
            if ob.type == 'MESH':
                ob.hide = True
            elif ob.type == 'CURVE':
                ob.hide = True

        Model.hide = False
        Master.hide = False
        Plane.hide = False

        tracking.trackUsage("D3Splint:CreateSurface", None)
        context.scene.frame_current = -1
        context.scene.frame_current = 0
        splint.ops_string += 'AnimateArticulator:'
        print('adding the handler!')

        handlers = [
            hand.__name__ for hand in bpy.app.handlers.frame_change_pre
        ]

        if occlusal_surface_frame_change.__name__ not in handlers:
            bpy.app.handlers.frame_change_pre.append(
                occlusal_surface_frame_change)

        else:
            print('handler already in there')

        context.space_data.show_backface_culling = False
        bpy.ops.screen.animation_play()

        return {'FINISHED'}