aims_project_windows 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +5 -0
 - data/bin/AimsCalc +367 -0
 - data/bin/AimsProject +88 -0
 - data/bin/AimsProjectManager +39 -0
 - data/lib/aims_project/aims_project_exception.rb +42 -0
 - data/lib/aims_project/aims_project_geometry.rb +52 -0
 - data/lib/aims_project/app_controller.rb +245 -0
 - data/lib/aims_project/atom.rb +95 -0
 - data/lib/aims_project/calculation.rb +406 -0
 - data/lib/aims_project/calculation_tree.rb +65 -0
 - data/lib/aims_project/calculation_window.rb +141 -0
 - data/lib/aims_project/crystal_viewer.rb +994 -0
 - data/lib/aims_project/crystal_viewer_options.rb +103 -0
 - data/lib/aims_project/geometry_console.rb +155 -0
 - data/lib/aims_project/geometry_editor.rb +83 -0
 - data/lib/aims_project/geometry_file.rb +183 -0
 - data/lib/aims_project/geometry_window.rb +160 -0
 - data/lib/aims_project/green_arrow.jpg +0 -0
 - data/lib/aims_project/inspector.rb +183 -0
 - data/lib/aims_project/material.rb +30 -0
 - data/lib/aims_project/octree.rb +5 -0
 - data/lib/aims_project/pan.gif +0 -0
 - data/lib/aims_project/project.rb +102 -0
 - data/lib/aims_project/project_tree.rb +62 -0
 - data/lib/aims_project/rotate.gif +0 -0
 - data/lib/aims_project/thread_callback_event.rb +19 -0
 - data/lib/aims_project/zoom.gif +0 -0
 - data/lib/aims_project.rb +158 -0
 - data/skeleton/Capfile +37 -0
 - data/skeleton/config/aims.sh +58 -0
 - data/skeleton/config/tasks.rb +145 -0
 - data/skeleton/config/user_variables.rb +37 -0
 - data/skeleton/control/example.erb +41 -0
 - data/skeleton/geometry/example +1 -0
 - metadata +137 -0
 
| 
         @@ -0,0 +1,994 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module AimsProject
         
     | 
| 
      
 2 
     | 
    
         
            +
            class CrystalViewer < Wx::Panel
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              include Wx
         
     | 
| 
      
 5 
     | 
    
         
            +
              include Math
         
     | 
| 
      
 6 
     | 
    
         
            +
              include Gl
         
     | 
| 
      
 7 
     | 
    
         
            +
              include Glu
         
     | 
| 
      
 8 
     | 
    
         
            +
              include Aims
         
     | 
| 
      
 9 
     | 
    
         
            +
              
         
     | 
| 
      
 10 
     | 
    
         
            +
              ID_ROTATE = 100
         
     | 
| 
      
 11 
     | 
    
         
            +
              ID_PAN = 101
         
     | 
| 
      
 12 
     | 
    
         
            +
              ID_ZOOM = 102
         
     | 
| 
      
 13 
     | 
    
         
            +
              
         
     | 
| 
      
 14 
     | 
    
         
            +
              PICK_ID_ATOM  = 0x10000000
         
     | 
| 
      
 15 
     | 
    
         
            +
              PICK_ID_PLANE = 0x20000000
         
     | 
| 
      
 16 
     | 
    
         
            +
              PICK_ID_BOND  = 0x30000000
         
     | 
| 
      
 17 
     | 
    
         
            +
              
         
     | 
| 
      
 18 
     | 
    
         
            +
              # An array of Aims::UnitCell's to display
         
     | 
| 
      
 19 
     | 
    
         
            +
              attr_reader :unit_cell
         
     | 
| 
      
 20 
     | 
    
         
            +
              attr_reader :unit_cell_corrected
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              # How many times to repeat the unit cell
         
     | 
| 
      
 23 
     | 
    
         
            +
              # A three element vector
         
     | 
| 
      
 24 
     | 
    
         
            +
              attr_accessor :repeat
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              # If displaying multiple, then the current cell
         
     | 
| 
      
 27 
     | 
    
         
            +
              attr_accessor :current_cell
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              # The keyboard actions
         
     | 
| 
      
 30 
     | 
    
         
            +
              attr_accessor :mouse_motion_func # a string "rotate", "pan" or "zoom"
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              # The background color (glClearColor)
         
     | 
| 
      
 33 
     | 
    
         
            +
              attr_accessor :background
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              attr_accessor :ortho_side, :ortho_zmin, :ortho_zmax
         
     | 
| 
      
 36 
     | 
    
         
            +
              attr_accessor :x_down, :y_down, :alt, :az, :offx, :offy, :offz
         
     | 
| 
      
 37 
     | 
    
         
            +
              attr_accessor :orthographic, :width, :height, :picking, :atom, :x_last, :y_last, :z_last
         
     | 
| 
      
 38 
     | 
    
         
            +
              attr_accessor :render_mode
         
     | 
| 
      
 39 
     | 
    
         
            +
              
         
     | 
| 
      
 40 
     | 
    
         
            +
              attr_accessor :xmax_plane, :xmin_plane
         
     | 
| 
      
 41 
     | 
    
         
            +
              attr_accessor :ymax_plane, :ymin_plane
         
     | 
| 
      
 42 
     | 
    
         
            +
              attr_accessor :zmax_plane, :zmin_plane
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              attr_accessor :slices, :stacks
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              attr_accessor :atoms_changed
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              attr_accessor :selection
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              def initialize(controller, parent, options = nil)
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                super(parent)
         
     | 
| 
      
 53 
     | 
    
         
            +
                @controller = controller
         
     | 
| 
      
 54 
     | 
    
         
            +
                
         
     | 
| 
      
 55 
     | 
    
         
            +
                # Register self as an observer of the options
         
     | 
| 
      
 56 
     | 
    
         
            +
                if options
         
     | 
| 
      
 57 
     | 
    
         
            +
                  @options = options
         
     | 
| 
      
 58 
     | 
    
         
            +
                else
         
     | 
| 
      
 59 
     | 
    
         
            +
                  @options = CrystalViewerOptions.new(parent)
         
     | 
| 
      
 60 
     | 
    
         
            +
                end 
         
     | 
| 
      
 61 
     | 
    
         
            +
                @options.add_observer(self)
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                # Toolbar for the GL Canvas
         
     | 
| 
      
 64 
     | 
    
         
            +
                basedir = File.dirname(__FILE__)
         
     | 
| 
      
 65 
     | 
    
         
            +
                rotate_icon = Image.new(File.join(basedir,"rotate.gif"), BITMAP_TYPE_GIF)
         
     | 
| 
      
 66 
     | 
    
         
            +
                @rotate_tool = BitmapButton.new(self, :id => ID_ROTATE, :bitmap => rotate_icon.rescale(16,15).convert_to_bitmap,:name => "rotate")
         
     | 
| 
      
 67 
     | 
    
         
            +
                
         
     | 
| 
      
 68 
     | 
    
         
            +
                zoom_icon = Image.new(File.join(basedir,"zoom.gif"), BITMAP_TYPE_GIF)
         
     | 
| 
      
 69 
     | 
    
         
            +
                @zoom_tool = BitmapButton.new(self, :id => ID_ZOOM, :bitmap => zoom_icon.rescale(16,15).convert_to_bitmap, :name => "zoom")
         
     | 
| 
      
 70 
     | 
    
         
            +
                
         
     | 
| 
      
 71 
     | 
    
         
            +
                pan_icon = Image.new(File.join(basedir,"pan.gif"), BITMAP_TYPE_GIF)
         
     | 
| 
      
 72 
     | 
    
         
            +
                @pan_tool = BitmapButton.new(self, :id => ID_PAN, :bitmap => pan_icon.rescale(16,15).convert_to_bitmap, :name => "pan")
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                evt_button(@rotate_tool) {|evt|
         
     | 
| 
      
 75 
     | 
    
         
            +
                  set_mouse_motion_function(:rotate)
         
     | 
| 
      
 76 
     | 
    
         
            +
                }
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                evt_button(@zoom_tool) {|evt|
         
     | 
| 
      
 79 
     | 
    
         
            +
                  set_mouse_motion_function(:zoom)
         
     | 
| 
      
 80 
     | 
    
         
            +
                }
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                evt_button(@pan_tool) {|evt|
         
     | 
| 
      
 83 
     | 
    
         
            +
                  set_mouse_motion_function(:pan)
         
     | 
| 
      
 84 
     | 
    
         
            +
                }
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                @buttonSizer = HBoxSizer.new
         
     | 
| 
      
 87 
     | 
    
         
            +
                @buttonSizer.add_item(@rotate_tool)
         
     | 
| 
      
 88 
     | 
    
         
            +
                @buttonSizer.add_item(@zoom_tool)
         
     | 
| 
      
 89 
     | 
    
         
            +
                @buttonSizer.add_item(@pan_tool)
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                #@glPanel = CalendarCtrl.new(self)
         
     | 
| 
      
 93 
     | 
    
         
            +
                attrib = [Wx::GL_RGBA, Wx::GL_DOUBLEBUFFER, Wx::GL_DEPTH_SIZE, 24]
         
     | 
| 
      
 94 
     | 
    
         
            +
                @glPanel = GLCanvas.new(self, -1, [-1, -1], [-1, -1],
         
     | 
| 
      
 95 
     | 
    
         
            +
                                           Wx::FULL_REPAINT_ON_RESIZE, "GLCanvas", attrib)
         
     | 
| 
      
 96 
     | 
    
         
            +
                
         
     | 
| 
      
 97 
     | 
    
         
            +
                vbox_sizer = VBoxSizer.new
         
     | 
| 
      
 98 
     | 
    
         
            +
                vbox_sizer.add_item(@buttonSizer, :flag => EXPAND)
         
     | 
| 
      
 99 
     | 
    
         
            +
                vbox_sizer.add_item(@glPanel, :proportion => 1, :flag => EXPAND)
         
     | 
| 
      
 100 
     | 
    
         
            +
                set_sizer(vbox_sizer)
         
     | 
| 
      
 101 
     | 
    
         
            +
                
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                set_defaults
         
     | 
| 
      
 104 
     | 
    
         
            +
                
         
     | 
| 
      
 105 
     | 
    
         
            +
                # Define the method to call for paint requests
         
     | 
| 
      
 106 
     | 
    
         
            +
                evt_paint { @glPanel.paint { draw_scene }}
         
     | 
| 
      
 107 
     | 
    
         
            +
                # Create the graphics view and define event handlers
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                # For some reason, not all left-clicks are captured, 
         
     | 
| 
      
 110 
     | 
    
         
            +
                # so we include this catchall as well, to prevent odd
         
     | 
| 
      
 111 
     | 
    
         
            +
                # behavior when rotating
         
     | 
| 
      
 112 
     | 
    
         
            +
                @glPanel.evt_mouse_events {|evt|
         
     | 
| 
      
 113 
     | 
    
         
            +
                  if evt.button_down
         
     | 
| 
      
 114 
     | 
    
         
            +
                    self.set_focus
         
     | 
| 
      
 115 
     | 
    
         
            +
                    mouse_down(evt.get_x, evt.get_y)
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
                }
         
     | 
| 
      
 118 
     | 
    
         
            +
                
         
     | 
| 
      
 119 
     | 
    
         
            +
                @glPanel.evt_left_up {|evt|
         
     | 
| 
      
 120 
     | 
    
         
            +
                  mouse_up(evt.get_x, evt.get_y)
         
     | 
| 
      
 121 
     | 
    
         
            +
                  draw_scene
         
     | 
| 
      
 122 
     | 
    
         
            +
                }
         
     | 
| 
      
 123 
     | 
    
         
            +
                
         
     | 
| 
      
 124 
     | 
    
         
            +
                @glPanel.evt_motion {|evt|
         
     | 
| 
      
 125 
     | 
    
         
            +
                  if evt.dragging
         
     | 
| 
      
 126 
     | 
    
         
            +
                    mouse_dragged(evt.get_x, evt.get_y)
         
     | 
| 
      
 127 
     | 
    
         
            +
                    draw_scene
         
     | 
| 
      
 128 
     | 
    
         
            +
                  end
         
     | 
| 
      
 129 
     | 
    
         
            +
                }
         
     | 
| 
      
 130 
     | 
    
         
            +
                
         
     | 
| 
      
 131 
     | 
    
         
            +
                @glPanel.evt_char {|evt| 
         
     | 
| 
      
 132 
     | 
    
         
            +
                  nudge_dir = case evt.get_key_code
         
     | 
| 
      
 133 
     | 
    
         
            +
                      when K_LEFT
         
     | 
| 
      
 134 
     | 
    
         
            +
                        [-1,0,0]
         
     | 
| 
      
 135 
     | 
    
         
            +
                      when K_RIGHT
         
     | 
| 
      
 136 
     | 
    
         
            +
                        [1,0,0]
         
     | 
| 
      
 137 
     | 
    
         
            +
                      when K_UP
         
     | 
| 
      
 138 
     | 
    
         
            +
                        [0,1,0]
         
     | 
| 
      
 139 
     | 
    
         
            +
                      when K_DOWN
         
     | 
| 
      
 140 
     | 
    
         
            +
                        [0,-1,0]
         
     | 
| 
      
 141 
     | 
    
         
            +
                      else
         
     | 
| 
      
 142 
     | 
    
         
            +
                        [0,0,0]
         
     | 
| 
      
 143 
     | 
    
         
            +
                      end
         
     | 
| 
      
 144 
     | 
    
         
            +
                    nudge(nudge_dir)
         
     | 
| 
      
 145 
     | 
    
         
            +
                }
         
     | 
| 
      
 146 
     | 
    
         
            +
                
         
     | 
| 
      
 147 
     | 
    
         
            +
                  # What to do when worker threads return
         
     | 
| 
      
 148 
     | 
    
         
            +
                  evt_thread_callback {|evt|
         
     | 
| 
      
 149 
     | 
    
         
            +
                    self.draw_scene
         
     | 
| 
      
 150 
     | 
    
         
            +
                  }
         
     | 
| 
      
 151 
     | 
    
         
            +
              end
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
              # Called when the options changes
         
     | 
| 
      
 154 
     | 
    
         
            +
              def update
         
     | 
| 
      
 155 
     | 
    
         
            +
                self.draw_scene
         
     | 
| 
      
 156 
     | 
    
         
            +
              end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
              def set_defaults
         
     | 
| 
      
 159 
     | 
    
         
            +
                self.current_cell = 0
         
     | 
| 
      
 160 
     | 
    
         
            +
                self.background = Material.new(0.7, 0.7, 1.0, 1)
         
     | 
| 
      
 161 
     | 
    
         
            +
                self.x_down = 0
         
     | 
| 
      
 162 
     | 
    
         
            +
                self.y_down = 0
         
     | 
| 
      
 163 
     | 
    
         
            +
                self.x_last = 0
         
     | 
| 
      
 164 
     | 
    
         
            +
                self.y_last = 0
         
     | 
| 
      
 165 
     | 
    
         
            +
                self.z_last = 0
         
     | 
| 
      
 166 
     | 
    
         
            +
                self.alt = 0
         
     | 
| 
      
 167 
     | 
    
         
            +
                self.az = 0
         
     | 
| 
      
 168 
     | 
    
         
            +
                self.offx = 0
         
     | 
| 
      
 169 
     | 
    
         
            +
                self.offy = 0
         
     | 
| 
      
 170 
     | 
    
         
            +
                self.offz = -20
         
     | 
| 
      
 171 
     | 
    
         
            +
                self.orthographic = true
         
     | 
| 
      
 172 
     | 
    
         
            +
                self.ortho_side = 15
         
     | 
| 
      
 173 
     | 
    
         
            +
                self.ortho_zmin = -1
         
     | 
| 
      
 174 
     | 
    
         
            +
                self.ortho_zmax = 50
         
     | 
| 
      
 175 
     | 
    
         
            +
                self.width = 500
         
     | 
| 
      
 176 
     | 
    
         
            +
                self.height = 500
         
     | 
| 
      
 177 
     | 
    
         
            +
                self.picking =false      
         
     | 
| 
      
 178 
     | 
    
         
            +
                # The last clicked atom
         
     | 
| 
      
 179 
     | 
    
         
            +
                self.atom = nil
         
     | 
| 
      
 180 
     | 
    
         
            +
                self.atoms_changed = true
         
     | 
| 
      
 181 
     | 
    
         
            +
                self.hiRes
         
     | 
| 
      
 182 
     | 
    
         
            +
                self.mouse_motion_func = :rotate
         
     | 
| 
      
 183 
     | 
    
         
            +
                self.repeat = Vector[1,1,1]
         
     | 
| 
      
 184 
     | 
    
         
            +
                self.render_mode = :ball_stick
         
     | 
| 
      
 185 
     | 
    
         
            +
                @options.set_properties(
         
     | 
| 
      
 186 
     | 
    
         
            +
                  :bond_length => 3,
         
     | 
| 
      
 187 
     | 
    
         
            +
                  :show_bonds => true,
         
     | 
| 
      
 188 
     | 
    
         
            +
                  :show_lighting => true,
         
     | 
| 
      
 189 
     | 
    
         
            +
                  :show_xclip => false,
         
     | 
| 
      
 190 
     | 
    
         
            +
                  :show_yclip => false,
         
     | 
| 
      
 191 
     | 
    
         
            +
                  :show_zclip => true,
         
     | 
| 
      
 192 
     | 
    
         
            +
                  :show_supercell => true
         
     | 
| 
      
 193 
     | 
    
         
            +
                )
         
     | 
| 
      
 194 
     | 
    
         
            +
              end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
              def nudge(dir)
         
     | 
| 
      
 198 
     | 
    
         
            +
                @controller.nudge_selected_atoms(dir[0]*0.5, dir[1]*0.5, 0)
         
     | 
| 
      
 199 
     | 
    
         
            +
              end
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
            =begin
         
     | 
| 
      
 203 
     | 
    
         
            +
              Set the unit cell to display. 
         
     | 
| 
      
 204 
     | 
    
         
            +
            =end
         
     | 
| 
      
 205 
     | 
    
         
            +
              def unit_cell=(uc)
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
                if @unit_cell
         
     | 
| 
      
 208 
     | 
    
         
            +
                  @unit_cell.delete_observer(self)
         
     | 
| 
      
 209 
     | 
    
         
            +
                end
         
     | 
| 
      
 210 
     | 
    
         
            +
                
         
     | 
| 
      
 211 
     | 
    
         
            +
                @unit_cell = uc
         
     | 
| 
      
 212 
     | 
    
         
            +
                @unit_cell_corrected = nil
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
                init_clip_planes
         
     | 
| 
      
 215 
     | 
    
         
            +
                
         
     | 
| 
      
 216 
     | 
    
         
            +
                @unit_cell.add_observer(self, :unit_cell_changed)
         
     | 
| 
      
 217 
     | 
    
         
            +
                draw_scene
         
     | 
| 
      
 218 
     | 
    
         
            +
                
         
     | 
| 
      
 219 
     | 
    
         
            +
              end
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
              def unit_cell_changed
         
     | 
| 
      
 222 
     | 
    
         
            +
                init_clip_planes
         
     | 
| 
      
 223 
     | 
    
         
            +
                draw_scene
         
     | 
| 
      
 224 
     | 
    
         
            +
              end
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
              def init_clip_planes
         
     | 
| 
      
 227 
     | 
    
         
            +
                  
         
     | 
| 
      
 228 
     | 
    
         
            +
                  Thread.new(self) { |evtHandler|
         
     | 
| 
      
 229 
     | 
    
         
            +
                    @unit_cell_corrected = @unit_cell.correct
         
     | 
| 
      
 230 
     | 
    
         
            +
                    evt = ThreadCallbackEvent.new
         
     | 
| 
      
 231 
     | 
    
         
            +
                    evtHandler.add_pending_event(evt)
         
     | 
| 
      
 232 
     | 
    
         
            +
                  }
         
     | 
| 
      
 233 
     | 
    
         
            +
                
         
     | 
| 
      
 234 
     | 
    
         
            +
                  return unless (@unit_cell and @unit_cell.is_valid?) 
         
     | 
| 
      
 235 
     | 
    
         
            +
                
         
     | 
| 
      
 236 
     | 
    
         
            +
                  # each bounding box is a 2 element array [max, min]
         
     | 
| 
      
 237 
     | 
    
         
            +
                  bounding_box = @unit_cell.bounding_box(false)
         
     | 
| 
      
 238 
     | 
    
         
            +
                  xmax = bounding_box[0].x
         
     | 
| 
      
 239 
     | 
    
         
            +
                  xmin = bounding_box[1].x
         
     | 
| 
      
 240 
     | 
    
         
            +
                  ymax = bounding_box[0].y
         
     | 
| 
      
 241 
     | 
    
         
            +
                  ymin = bounding_box[1].y
         
     | 
| 
      
 242 
     | 
    
         
            +
                  zmax = bounding_box[0].z
         
     | 
| 
      
 243 
     | 
    
         
            +
                  zmin = bounding_box[1].z
         
     | 
| 
      
 244 
     | 
    
         
            +
             
     | 
| 
      
 245 
     | 
    
         
            +
                  @xmax_plane = Plane.new( 1, 0, 0, xmax, 0, 0)
         
     | 
| 
      
 246 
     | 
    
         
            +
                  @xmin_plane = Plane.new(-1, 0, 0, xmin, 0, 0)
         
     | 
| 
      
 247 
     | 
    
         
            +
                  @ymax_plane = Plane.new( 0, 1, 0, 0, ymax, 0)
         
     | 
| 
      
 248 
     | 
    
         
            +
                  @ymin_plane = Plane.new( 0,-1, 0, 0, ymin, 0)
         
     | 
| 
      
 249 
     | 
    
         
            +
                  @zmax_plane = Plane.new( 0, 0, 1, 0, 0, zmax)
         
     | 
| 
      
 250 
     | 
    
         
            +
                  @zmin_plane = Plane.new( 0, 0,-1, 0, 0, zmin)
         
     | 
| 
      
 251 
     | 
    
         
            +
             
     | 
| 
      
 252 
     | 
    
         
            +
                  # Add clip-planes to each unit cell
         
     | 
| 
      
 253 
     | 
    
         
            +
                  @unit_cell.clear_planes
         
     | 
| 
      
 254 
     | 
    
         
            +
                  @unit_cell.add_plane(@xmax_plane, false)
         
     | 
| 
      
 255 
     | 
    
         
            +
                  @unit_cell.add_plane(@xmin_plane, false)
         
     | 
| 
      
 256 
     | 
    
         
            +
                  @unit_cell.add_plane(@ymax_plane, false)
         
     | 
| 
      
 257 
     | 
    
         
            +
                  @unit_cell.add_plane(@ymin_plane, false)
         
     | 
| 
      
 258 
     | 
    
         
            +
                  @unit_cell.add_plane(@zmax_plane, false)
         
     | 
| 
      
 259 
     | 
    
         
            +
                  @unit_cell.add_plane(@zmin_plane, false)
         
     | 
| 
      
 260 
     | 
    
         
            +
                  @unit_cell.recache_visible_atoms
         
     | 
| 
      
 261 
     | 
    
         
            +
                  @unit_cell.make_bonds(@options.bond_length)
         
     | 
| 
      
 262 
     | 
    
         
            +
                
         
     | 
| 
      
 263 
     | 
    
         
            +
              end
         
     | 
| 
      
 264 
     | 
    
         
            +
             
     | 
| 
      
 265 
     | 
    
         
            +
              def dump_properties
         
     | 
| 
      
 266 
     | 
    
         
            +
                self.instance_variables.each{|v|
         
     | 
| 
      
 267 
     | 
    
         
            +
                  puts "#{v} = #{self.instance_variable_get(v)}"
         
     | 
| 
      
 268 
     | 
    
         
            +
                }
         
     | 
| 
      
 269 
     | 
    
         
            +
              end
         
     | 
| 
      
 270 
     | 
    
         
            +
             
     | 
| 
      
 271 
     | 
    
         
            +
              # The currently displayed unit cell
         
     | 
| 
      
 272 
     | 
    
         
            +
              def current_unit_cell
         
     | 
| 
      
 273 
     | 
    
         
            +
                self.unit_cell
         
     | 
| 
      
 274 
     | 
    
         
            +
              end
         
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
              def dump_geometry
         
     | 
| 
      
 277 
     | 
    
         
            +
                atoms = self.unit_cell
         
     | 
| 
      
 278 
     | 
    
         
            +
                if atoms
         
     | 
| 
      
 279 
     | 
    
         
            +
                  puts atoms.format_geometry_in
         
     | 
| 
      
 280 
     | 
    
         
            +
                end
         
     | 
| 
      
 281 
     | 
    
         
            +
              end
         
     | 
| 
      
 282 
     | 
    
         
            +
             
     | 
| 
      
 283 
     | 
    
         
            +
              def bond_length=(l)
         
     | 
| 
      
 284 
     | 
    
         
            +
                @options.bond_length = l
         
     | 
| 
      
 285 
     | 
    
         
            +
                # FIXME The bonds should be made in the controller
         
     | 
| 
      
 286 
     | 
    
         
            +
                # self.unit_cell.each{|uc| uc.make_bonds(l)} if self.unit_cell
         
     | 
| 
      
 287 
     | 
    
         
            +
              end
         
     | 
| 
      
 288 
     | 
    
         
            +
             
     | 
| 
      
 289 
     | 
    
         
            +
              def mouse_down(x,y)
         
     | 
| 
      
 290 
     | 
    
         
            +
                self.x_down = x
         
     | 
| 
      
 291 
     | 
    
         
            +
                self.y_down = y
         
     | 
| 
      
 292 
     | 
    
         
            +
                self.x_last = x
         
     | 
| 
      
 293 
     | 
    
         
            +
                self.y_last = y	  
         
     | 
| 
      
 294 
     | 
    
         
            +
                self.loRes
         
     | 
| 
      
 295 
     | 
    
         
            +
              end
         
     | 
| 
      
 296 
     | 
    
         
            +
             
     | 
| 
      
 297 
     | 
    
         
            +
              def mouse_up(x,y)
         
     | 
| 
      
 298 
     | 
    
         
            +
                return unless self.unit_cell
         
     | 
| 
      
 299 
     | 
    
         
            +
                @picked = pick_object(x,y)
         
     | 
| 
      
 300 
     | 
    
         
            +
                self.atom = self.unit_cell.atoms.find{|a| a.id == @picked[:atoms].last}
         
     | 
| 
      
 301 
     | 
    
         
            +
                if self.atom
         
     | 
| 
      
 302 
     | 
    
         
            +
                  @controller.select_atom(self.atom)
         
     | 
| 
      
 303 
     | 
    
         
            +
                  # puts self.atom.format_geometry_in
         
     | 
| 
      
 304 
     | 
    
         
            +
                end
         
     | 
| 
      
 305 
     | 
    
         
            +
                
         
     | 
| 
      
 306 
     | 
    
         
            +
                unless @picked[:planes].empty?
         
     | 
| 
      
 307 
     | 
    
         
            +
                  clip_plane_id = @picked[:planes].first
         
     | 
| 
      
 308 
     | 
    
         
            +
                  @active_clip_plane = case clip_plane_id
         
     | 
| 
      
 309 
     | 
    
         
            +
                  when 1 
         
     | 
| 
      
 310 
     | 
    
         
            +
                    @zmax_plane
         
     | 
| 
      
 311 
     | 
    
         
            +
                  when 2
         
     | 
| 
      
 312 
     | 
    
         
            +
                    @zmin_plane
         
     | 
| 
      
 313 
     | 
    
         
            +
                  when 3
         
     | 
| 
      
 314 
     | 
    
         
            +
                    @xmax_plane
         
     | 
| 
      
 315 
     | 
    
         
            +
                  when 4
         
     | 
| 
      
 316 
     | 
    
         
            +
                    @xmin_plane
         
     | 
| 
      
 317 
     | 
    
         
            +
                  when 5
         
     | 
| 
      
 318 
     | 
    
         
            +
                    @ymax_plane
         
     | 
| 
      
 319 
     | 
    
         
            +
                  when 6
         
     | 
| 
      
 320 
     | 
    
         
            +
                    @ymin_plane
         
     | 
| 
      
 321 
     | 
    
         
            +
                  else
         
     | 
| 
      
 322 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 323 
     | 
    
         
            +
                  end
         
     | 
| 
      
 324 
     | 
    
         
            +
                  if @active_clip_plane
         
     | 
| 
      
 325 
     | 
    
         
            +
                    set_mouse_motion_function(:move_clip_plane)
         
     | 
| 
      
 326 
     | 
    
         
            +
                  end
         
     | 
| 
      
 327 
     | 
    
         
            +
                end
         
     | 
| 
      
 328 
     | 
    
         
            +
                self.hiRes
         
     | 
| 
      
 329 
     | 
    
         
            +
             
     | 
| 
      
 330 
     | 
    
         
            +
                # Harmless correction for bug in WxRuby that doesn't register all mouse down events
         
     | 
| 
      
 331 
     | 
    
         
            +
                self.x_last = nil
         
     | 
| 
      
 332 
     | 
    
         
            +
                self.y_last = nil
         
     | 
| 
      
 333 
     | 
    
         
            +
             
     | 
| 
      
 334 
     | 
    
         
            +
                glutPostRedisplay if @using_glut
         
     | 
| 
      
 335 
     | 
    
         
            +
              end
         
     | 
| 
      
 336 
     | 
    
         
            +
             
     | 
| 
      
 337 
     | 
    
         
            +
              def mouse_dragged(x, y)
         
     | 
| 
      
 338 
     | 
    
         
            +
             
     | 
| 
      
 339 
     | 
    
         
            +
                # Harmless correction for bug in WxRuby that doesn't register all mouse down events
         
     | 
| 
      
 340 
     | 
    
         
            +
                self.x_last = x if self.x_last.nil?
         
     | 
| 
      
 341 
     | 
    
         
            +
                self.y_last = y if self.y_last.nil? 
         
     | 
| 
      
 342 
     | 
    
         
            +
                self.z_last = z if self.z_last.nil?
         
     | 
| 
      
 343 
     | 
    
         
            +
                
         
     | 
| 
      
 344 
     | 
    
         
            +
                case self.mouse_motion_func
         
     | 
| 
      
 345 
     | 
    
         
            +
                when :rotate 
         
     | 
| 
      
 346 
     | 
    
         
            +
                  rotate(x,y)
         
     | 
| 
      
 347 
     | 
    
         
            +
                when :zoom
         
     | 
| 
      
 348 
     | 
    
         
            +
                  zoom(x,y)
         
     | 
| 
      
 349 
     | 
    
         
            +
                when :pan
         
     | 
| 
      
 350 
     | 
    
         
            +
                  pan(x,y)
         
     | 
| 
      
 351 
     | 
    
         
            +
                when :move_clip_plane
         
     | 
| 
      
 352 
     | 
    
         
            +
                  move_clip_plane(x,y)
         
     | 
| 
      
 353 
     | 
    
         
            +
                else
         
     | 
| 
      
 354 
     | 
    
         
            +
                  rotate(x,y)
         
     | 
| 
      
 355 
     | 
    
         
            +
                end
         
     | 
| 
      
 356 
     | 
    
         
            +
                glutPostRedisplay if @using_glut
         
     | 
| 
      
 357 
     | 
    
         
            +
              end
         
     | 
| 
      
 358 
     | 
    
         
            +
             
     | 
| 
      
 359 
     | 
    
         
            +
              def delete_atom
         
     | 
| 
      
 360 
     | 
    
         
            +
                if self.atom
         
     | 
| 
      
 361 
     | 
    
         
            +
                  # Remove 
         
     | 
| 
      
 362 
     | 
    
         
            +
                  self.unit_cell.remove_atom(self.atom)
         
     | 
| 
      
 363 
     | 
    
         
            +
                end
         
     | 
| 
      
 364 
     | 
    
         
            +
              end
         
     | 
| 
      
 365 
     | 
    
         
            +
             
     | 
| 
      
 366 
     | 
    
         
            +
              # Unproject the mouse coordinates to model space
         
     | 
| 
      
 367 
     | 
    
         
            +
              # Handles the flipping of the y-coordinate
         
     | 
| 
      
 368 
     | 
    
         
            +
              def unproject(x,y,z)
         
     | 
| 
      
 369 
     | 
    
         
            +
                model = glGetDoublev(GL_MODELVIEW_MATRIX)
         
     | 
| 
      
 370 
     | 
    
         
            +
                proj = glGetDoublev(GL_PROJECTION_MATRIX)
         
     | 
| 
      
 371 
     | 
    
         
            +
                viewport = glGetIntegerv(GL_VIEWPORT);
         
     | 
| 
      
 372 
     | 
    
         
            +
             
     | 
| 
      
 373 
     | 
    
         
            +
                gluUnProject(x, viewport[3]-y, z, model, proj, viewport)
         
     | 
| 
      
 374 
     | 
    
         
            +
              end
         
     | 
| 
      
 375 
     | 
    
         
            +
             
     | 
| 
      
 376 
     | 
    
         
            +
              # Cast a ray from the near clip-plane to the far clip-plane through the point x,y
         
     | 
| 
      
 377 
     | 
    
         
            +
              # return a two element array
         
     | 
| 
      
 378 
     | 
    
         
            +
              #   element 0 is the model space coordinates of (x,y) on the near clip plane 
         
     | 
| 
      
 379 
     | 
    
         
            +
              #   element 1 is the direction of the ray
         
     | 
| 
      
 380 
     | 
    
         
            +
              def cast_ray_to(x,y)
         
     | 
| 
      
 381 
     | 
    
         
            +
                x1,y1,z1 = unproject(x,y,0)
         
     | 
| 
      
 382 
     | 
    
         
            +
                x2,y2,z2 = unproject(x,y,1)
         
     | 
| 
      
 383 
     | 
    
         
            +
                [ Vector[x1, y1, z1], Vector[x2-x1, y2-y1, z2-z1] ]
         
     | 
| 
      
 384 
     | 
    
         
            +
              end
         
     | 
| 
      
 385 
     | 
    
         
            +
             
     | 
| 
      
 386 
     | 
    
         
            +
              def move_clip_plane(x,y)
         
     | 
| 
      
 387 
     | 
    
         
            +
                
         
     | 
| 
      
 388 
     | 
    
         
            +
                x_obj_last, y_obj_last, z_obj_last = unproject(x_last, y_last, 0)
         
     | 
| 
      
 389 
     | 
    
         
            +
                x_obj, y_obj, z_obj = unproject(x,y,0)
         
     | 
| 
      
 390 
     | 
    
         
            +
             
     | 
| 
      
 391 
     | 
    
         
            +
                w = [x_obj - x_obj_last, y_obj - y_obj_last, z_obj - z_obj_last]
         
     | 
| 
      
 392 
     | 
    
         
            +
                n = @active_clip_plane.unit_normal
         
     | 
| 
      
 393 
     | 
    
         
            +
                d = w[0]*n[0] + w[1]*n[1] + w[2]*n[2]
         
     | 
| 
      
 394 
     | 
    
         
            +
                
         
     | 
| 
      
 395 
     | 
    
         
            +
                # scale = 0.1
         
     | 
| 
      
 396 
     | 
    
         
            +
                # dx = (x - self.x_last)
         
     | 
| 
      
 397 
     | 
    
         
            +
                # dy = (y - self.y_last)
         
     | 
| 
      
 398 
     | 
    
         
            +
                # dr = sqrt(dx*dx + dy*dy)*(0 > dy ? -1 : 1)*scale
         
     | 
| 
      
 399 
     | 
    
         
            +
                self.x_last = x
         
     | 
| 
      
 400 
     | 
    
         
            +
                self.y_last = y
         
     | 
| 
      
 401 
     | 
    
         
            +
             
     | 
| 
      
 402 
     | 
    
         
            +
                @active_clip_plane.displace_along_normal(d)
         
     | 
| 
      
 403 
     | 
    
         
            +
                self.atoms_changed = true
         
     | 
| 
      
 404 
     | 
    
         
            +
              end
         
     | 
| 
      
 405 
     | 
    
         
            +
             
     | 
| 
      
 406 
     | 
    
         
            +
              def rotate(x,y)
         
     | 
| 
      
 407 
     | 
    
         
            +
                self.az += 5*(x - self.x_last)
         
     | 
| 
      
 408 
     | 
    
         
            +
                self.alt += 5*(y - self.y_last)
         
     | 
| 
      
 409 
     | 
    
         
            +
                self.x_last = x
         
     | 
| 
      
 410 
     | 
    
         
            +
                self.y_last = y
         
     | 
| 
      
 411 
     | 
    
         
            +
              end
         
     | 
| 
      
 412 
     | 
    
         
            +
             
     | 
| 
      
 413 
     | 
    
         
            +
              def zoom(x,y)
         
     | 
| 
      
 414 
     | 
    
         
            +
                if self.orthographic
         
     | 
| 
      
 415 
     | 
    
         
            +
                  self.ortho_side -= (y - self.y_last)*0.1
         
     | 
| 
      
 416 
     | 
    
         
            +
                else
         
     | 
| 
      
 417 
     | 
    
         
            +
                  self.offz -= (y - self.y_last)*0.1
         
     | 
| 
      
 418 
     | 
    
         
            +
                end
         
     | 
| 
      
 419 
     | 
    
         
            +
                self.x_last = x
         
     | 
| 
      
 420 
     | 
    
         
            +
                self.y_last = y
         
     | 
| 
      
 421 
     | 
    
         
            +
              end
         
     | 
| 
      
 422 
     | 
    
         
            +
             
     | 
| 
      
 423 
     | 
    
         
            +
              def pan(x,y)
         
     | 
| 
      
 424 
     | 
    
         
            +
                
         
     | 
| 
      
 425 
     | 
    
         
            +
                z = 0.0 # This value is normalized with respect to the near and far clip planes
         
     | 
| 
      
 426 
     | 
    
         
            +
             
     | 
| 
      
 427 
     | 
    
         
            +
                obj_x, obj_y, obj_z = unproject(x, y, z)
         
     | 
| 
      
 428 
     | 
    
         
            +
                obj_x_last, obj_y_last, obj_z_last = unproject(x_last, y_last, z_last)
         
     | 
| 
      
 429 
     | 
    
         
            +
                @center.x += obj_x_last - obj_x
         
     | 
| 
      
 430 
     | 
    
         
            +
                @center.y += obj_y_last - obj_y
         
     | 
| 
      
 431 
     | 
    
         
            +
                @center.z += obj_z_last - obj_z
         
     | 
| 
      
 432 
     | 
    
         
            +
                
         
     | 
| 
      
 433 
     | 
    
         
            +
                self.x_last = x
         
     | 
| 
      
 434 
     | 
    
         
            +
                self.y_last = y
         
     | 
| 
      
 435 
     | 
    
         
            +
                self.z_last = z
         
     | 
| 
      
 436 
     | 
    
         
            +
              end
         
     | 
| 
      
 437 
     | 
    
         
            +
             
     | 
| 
      
 438 
     | 
    
         
            +
              def loRes
         
     | 
| 
      
 439 
     | 
    
         
            +
                self.slices = 5
         
     | 
| 
      
 440 
     | 
    
         
            +
                self.stacks = 5
         
     | 
| 
      
 441 
     | 
    
         
            +
              end
         
     | 
| 
      
 442 
     | 
    
         
            +
             
     | 
| 
      
 443 
     | 
    
         
            +
              def hiRes
         
     | 
| 
      
 444 
     | 
    
         
            +
                self.slices = 20
         
     | 
| 
      
 445 
     | 
    
         
            +
                self.stacks = 20
         
     | 
| 
      
 446 
     | 
    
         
            +
              end
         
     | 
| 
      
 447 
     | 
    
         
            +
             
     | 
| 
      
 448 
     | 
    
         
            +
              def set_view(offset_x, offset_y, offset_z, alt, az)
         
     | 
| 
      
 449 
     | 
    
         
            +
                self.offx = offset_x
         
     | 
| 
      
 450 
     | 
    
         
            +
                self.offy = offset_y
         
     | 
| 
      
 451 
     | 
    
         
            +
                self.offz = offset_z
         
     | 
| 
      
 452 
     | 
    
         
            +
                self.alt = alt
         
     | 
| 
      
 453 
     | 
    
         
            +
                self.az = az
         
     | 
| 
      
 454 
     | 
    
         
            +
              end
         
     | 
| 
      
 455 
     | 
    
         
            +
             
     | 
| 
      
 456 
     | 
    
         
            +
              # Executes the named method when the mouse is dragged
         
     | 
| 
      
 457 
     | 
    
         
            +
              def set_mouse_motion_function(method_name)
         
     | 
| 
      
 458 
     | 
    
         
            +
                self.mouse_motion_func = method_name.to_sym
         
     | 
| 
      
 459 
     | 
    
         
            +
              end
         
     | 
| 
      
 460 
     | 
    
         
            +
             
     | 
| 
      
 461 
     | 
    
         
            +
              def draw_scene
         
     | 
| 
      
 462 
     | 
    
         
            +
                
         
     | 
| 
      
 463 
     | 
    
         
            +
                @glPanel.set_current
         
     | 
| 
      
 464 
     | 
    
         
            +
                sz = @glPanel.size
         
     | 
| 
      
 465 
     | 
    
         
            +
                viewport_setup(sz.width, sz.height)    
         
     | 
| 
      
 466 
     | 
    
         
            +
                
         
     | 
| 
      
 467 
     | 
    
         
            +
                
         
     | 
| 
      
 468 
     | 
    
         
            +
                begin
         
     | 
| 
      
 469 
     | 
    
         
            +
                  draw_init
         
     | 
| 
      
 470 
     | 
    
         
            +
                  apply_projection
         
     | 
| 
      
 471 
     | 
    
         
            +
                  position_camera
         
     | 
| 
      
 472 
     | 
    
         
            +
                  add_lights if @options.show_lighting
         
     | 
| 
      
 473 
     | 
    
         
            +
                  outline_supercell if @options.show_supercell
         
     | 
| 
      
 474 
     | 
    
         
            +
                  
         
     | 
| 
      
 475 
     | 
    
         
            +
                  if self.unit_cell
         
     | 
| 
      
 476 
     | 
    
         
            +
                    atoms = self.unit_cell
         
     | 
| 
      
 477 
     | 
    
         
            +
                    @options.x_repeat.times do |i|
         
     | 
| 
      
 478 
     | 
    
         
            +
                      @options.y_repeat.times do |j|
         
     | 
| 
      
 479 
     | 
    
         
            +
                        @options.z_repeat.times do |k|
         
     | 
| 
      
 480 
     | 
    
         
            +
                        
         
     | 
| 
      
 481 
     | 
    
         
            +
                          origin = if self.unit_cell.lattice_vectors
         
     | 
| 
      
 482 
     | 
    
         
            +
                            atoms.lattice_vectors[0]*i + atoms.lattice_vectors[1]*j + atoms.lattice_vectors[2]*k
         
     | 
| 
      
 483 
     | 
    
         
            +
                          else
         
     | 
| 
      
 484 
     | 
    
         
            +
                            Vector[0, 0, 0]
         
     | 
| 
      
 485 
     | 
    
         
            +
                          end
         
     | 
| 
      
 486 
     | 
    
         
            +
                          
         
     | 
| 
      
 487 
     | 
    
         
            +
                          draw_bonds(origin) if @options.show_bonds
         
     | 
| 
      
 488 
     | 
    
         
            +
                          draw_lattice(origin)
         
     | 
| 
      
 489 
     | 
    
         
            +
                        end
         
     | 
| 
      
 490 
     | 
    
         
            +
                      end
         
     | 
| 
      
 491 
     | 
    
         
            +
                    end
         
     | 
| 
      
 492 
     | 
    
         
            +
                  end
         
     | 
| 
      
 493 
     | 
    
         
            +
                  draw_clip_planes
         
     | 
| 
      
 494 
     | 
    
         
            +
                rescue GeometryEvaluationException => e
         
     | 
| 
      
 495 
     | 
    
         
            +
                rescue AimsProjectException => e
         
     | 
| 
      
 496 
     | 
    
         
            +
                  puts e.message
         
     | 
| 
      
 497 
     | 
    
         
            +
                  puts e.backtrace.join("\n")
         
     | 
| 
      
 498 
     | 
    
         
            +
                end
         
     | 
| 
      
 499 
     | 
    
         
            +
                
         
     | 
| 
      
 500 
     | 
    
         
            +
                @glPanel.swap_buffers
         
     | 
| 
      
 501 
     | 
    
         
            +
              end
         
     | 
| 
      
 502 
     | 
    
         
            +
             
     | 
| 
      
 503 
     | 
    
         
            +
              def viewport_setup(width, height)
         
     | 
| 
      
 504 
     | 
    
         
            +
                self.width = width
         
     | 
| 
      
 505 
     | 
    
         
            +
                self.height = height
         
     | 
| 
      
 506 
     | 
    
         
            +
                glViewport(0, 0, self.width, self.height)
         
     | 
| 
      
 507 
     | 
    
         
            +
              end
         
     | 
| 
      
 508 
     | 
    
         
            +
             
     | 
| 
      
 509 
     | 
    
         
            +
              def apply_projection
         
     | 
| 
      
 510 
     | 
    
         
            +
                glMatrixMode(GL_PROJECTION)
         
     | 
| 
      
 511 
     | 
    
         
            +
                glLoadIdentity()
         
     | 
| 
      
 512 
     | 
    
         
            +
                if self.orthographic
         
     | 
| 
      
 513 
     | 
    
         
            +
                  glOrtho(-self.ortho_side, self.ortho_side, -self.ortho_side,self.ortho_side, self.ortho_zmin, self.ortho_zmax)
         
     | 
| 
      
 514 
     | 
    
         
            +
                else
         
     | 
| 
      
 515 
     | 
    
         
            +
                  gluPerspective(60, self.width/self.height, 1, 120)
         
     | 
| 
      
 516 
     | 
    
         
            +
                end
         
     | 
| 
      
 517 
     | 
    
         
            +
                glMatrixMode(GL_MODELVIEW)
         
     | 
| 
      
 518 
     | 
    
         
            +
              end
         
     | 
| 
      
 519 
     | 
    
         
            +
             
     | 
| 
      
 520 
     | 
    
         
            +
              def draw_init
         
     | 
| 
      
 521 
     | 
    
         
            +
                glClearColor(background.r,background.g,background.b,@options.solid_bg)
         
     | 
| 
      
 522 
     | 
    
         
            +
                glEnable(GL_DEPTH_TEST)
         
     | 
| 
      
 523 
     | 
    
         
            +
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
         
     | 
| 
      
 524 
     | 
    
         
            +
             
     | 
| 
      
 525 
     | 
    
         
            +
             
     | 
| 
      
 526 
     | 
    
         
            +
                # Antialiasing
         
     | 
| 
      
 527 
     | 
    
         
            +
                glEnable(GL_LINE_SMOOTH)
         
     | 
| 
      
 528 
     | 
    
         
            +
                glEnable(GL_BLEND)
         
     | 
| 
      
 529 
     | 
    
         
            +
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
         
     | 
| 
      
 530 
     | 
    
         
            +
                glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
         
     | 
| 
      
 531 
     | 
    
         
            +
                glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST)
         
     | 
| 
      
 532 
     | 
    
         
            +
             
     | 
| 
      
 533 
     | 
    
         
            +
                if @options.show_lighting
         
     | 
| 
      
 534 
     | 
    
         
            +
                  glEnable(GL_LIGHTING)
         
     | 
| 
      
 535 
     | 
    
         
            +
                  glEnable(GL_LIGHT0)
         
     | 
| 
      
 536 
     | 
    
         
            +
                else
         
     | 
| 
      
 537 
     | 
    
         
            +
                  glDisable(GL_LIGHTING)
         
     | 
| 
      
 538 
     | 
    
         
            +
                end
         
     | 
| 
      
 539 
     | 
    
         
            +
             
     | 
| 
      
 540 
     | 
    
         
            +
                # Point size
         
     | 
| 
      
 541 
     | 
    
         
            +
                glPointSize(5)
         
     | 
| 
      
 542 
     | 
    
         
            +
                glLineWidth(2)
         
     | 
| 
      
 543 
     | 
    
         
            +
              end
         
     | 
| 
      
 544 
     | 
    
         
            +
             
     | 
| 
      
 545 
     | 
    
         
            +
              def pick_object(x,y)
         
     | 
| 
      
 546 
     | 
    
         
            +
             
     | 
| 
      
 547 
     | 
    
         
            +
                buf = glSelectBuffer(512)
         
     | 
| 
      
 548 
     | 
    
         
            +
                glRenderMode(GL_SELECT)
         
     | 
| 
      
 549 
     | 
    
         
            +
                model = glGetDoublev(GL_MODELVIEW_MATRIX)
         
     | 
| 
      
 550 
     | 
    
         
            +
                proj = glGetDoublev(GL_PROJECTION_MATRIX)
         
     | 
| 
      
 551 
     | 
    
         
            +
                viewport = glGetIntegerv(GL_VIEWPORT);
         
     | 
| 
      
 552 
     | 
    
         
            +
                
         
     | 
| 
      
 553 
     | 
    
         
            +
                self.picking = true
         
     | 
| 
      
 554 
     | 
    
         
            +
                glMatrixMode(GL_PROJECTION)
         
     | 
| 
      
 555 
     | 
    
         
            +
                glLoadIdentity()
         
     | 
| 
      
 556 
     | 
    
         
            +
                gluPickMatrix(x,viewport[3]-y,5,5,viewport)
         
     | 
| 
      
 557 
     | 
    
         
            +
                if self.orthographic
         
     | 
| 
      
 558 
     | 
    
         
            +
                  glOrtho(-self.ortho_side, self.ortho_side, -self.ortho_side,self.ortho_side, self.ortho_zmin, self.ortho_zmax)
         
     | 
| 
      
 559 
     | 
    
         
            +
                else
         
     | 
| 
      
 560 
     | 
    
         
            +
                  gluPerspective(60, self.width/self.height, 1, 60)
         
     | 
| 
      
 561 
     | 
    
         
            +
                end
         
     | 
| 
      
 562 
     | 
    
         
            +
                
         
     | 
| 
      
 563 
     | 
    
         
            +
                z = 0.0 # This value is normalized with respect to the near and far clip planes
         
     | 
| 
      
 564 
     | 
    
         
            +
                obj_x, obj_y, obj_z = gluUnProject(x, viewport[3]-y, z, model, proj, viewport)
         
     | 
| 
      
 565 
     | 
    
         
            +
                
         
     | 
| 
      
 566 
     | 
    
         
            +
                glMatrixMode(GL_MODELVIEW)
         
     | 
| 
      
 567 
     | 
    
         
            +
             
     | 
| 
      
 568 
     | 
    
         
            +
                glInitNames
         
     | 
| 
      
 569 
     | 
    
         
            +
                if self.unit_cell 
         
     | 
| 
      
 570 
     | 
    
         
            +
                  atoms = self.unit_cell
         
     | 
| 
      
 571 
     | 
    
         
            +
                  @options.x_repeat.times do |i|
         
     | 
| 
      
 572 
     | 
    
         
            +
                    @options.y_repeat.times do |j|
         
     | 
| 
      
 573 
     | 
    
         
            +
                      @options.z_repeat.times do |k|
         
     | 
| 
      
 574 
     | 
    
         
            +
                        
         
     | 
| 
      
 575 
     | 
    
         
            +
                        # Hack to display non-periodic systems
         
     | 
| 
      
 576 
     | 
    
         
            +
                        origin = if self.unit_cell.lattice_vectors
         
     | 
| 
      
 577 
     | 
    
         
            +
                          atoms.lattice_vectors[0]*i + atoms.lattice_vectors[1]*j + atoms.lattice_vectors[2]*k
         
     | 
| 
      
 578 
     | 
    
         
            +
                        else
         
     | 
| 
      
 579 
     | 
    
         
            +
                          Vector[0,0,0]
         
     | 
| 
      
 580 
     | 
    
         
            +
                        end
         
     | 
| 
      
 581 
     | 
    
         
            +
                        
         
     | 
| 
      
 582 
     | 
    
         
            +
                        self.draw_lattice(origin)
         
     | 
| 
      
 583 
     | 
    
         
            +
                      end
         
     | 
| 
      
 584 
     | 
    
         
            +
                    end
         
     | 
| 
      
 585 
     | 
    
         
            +
                  end
         
     | 
| 
      
 586 
     | 
    
         
            +
                end
         
     | 
| 
      
 587 
     | 
    
         
            +
                self.draw_clip_planes
         
     | 
| 
      
 588 
     | 
    
         
            +
             
     | 
| 
      
 589 
     | 
    
         
            +
                self.picking = false
         
     | 
| 
      
 590 
     | 
    
         
            +
             
     | 
| 
      
 591 
     | 
    
         
            +
                glMatrixMode(GL_MODELVIEW);
         
     | 
| 
      
 592 
     | 
    
         
            +
                glFlush();
         
     | 
| 
      
 593 
     | 
    
         
            +
             
     | 
| 
      
 594 
     | 
    
         
            +
                count = glRenderMode(GL_RENDER)
         
     | 
| 
      
 595 
     | 
    
         
            +
                data = buf.unpack("L!*")
         
     | 
| 
      
 596 
     | 
    
         
            +
                names = []
         
     | 
| 
      
 597 
     | 
    
         
            +
                count.times do 
         
     | 
| 
      
 598 
     | 
    
         
            +
                  num_names = data.shift
         
     | 
| 
      
 599 
     | 
    
         
            +
                  min_depth = data.shift
         
     | 
| 
      
 600 
     | 
    
         
            +
                  max_depth = data.shift
         
     | 
| 
      
 601 
     | 
    
         
            +
                  num_names.times do 
         
     | 
| 
      
 602 
     | 
    
         
            +
                    names << data.shift
         
     | 
| 
      
 603 
     | 
    
         
            +
                  end
         
     | 
| 
      
 604 
     | 
    
         
            +
                end
         
     | 
| 
      
 605 
     | 
    
         
            +
             
     | 
| 
      
 606 
     | 
    
         
            +
                picked_objects = {:atoms => [], :planes => [], :bonds => []}
         
     | 
| 
      
 607 
     | 
    
         
            +
                names.each{|n|
         
     | 
| 
      
 608 
     | 
    
         
            +
                  if (n & PICK_ID_ATOM) == PICK_ID_ATOM
         
     | 
| 
      
 609 
     | 
    
         
            +
                    picked_objects[:atoms] << (n ^ PICK_ID_ATOM)
         
     | 
| 
      
 610 
     | 
    
         
            +
                  end
         
     | 
| 
      
 611 
     | 
    
         
            +
                  if (n & PICK_ID_PLANE) == PICK_ID_PLANE
         
     | 
| 
      
 612 
     | 
    
         
            +
                    picked_objects[:planes] << (n ^ PICK_ID_PLANE)
         
     | 
| 
      
 613 
     | 
    
         
            +
                  end
         
     | 
| 
      
 614 
     | 
    
         
            +
                }
         
     | 
| 
      
 615 
     | 
    
         
            +
             
     | 
| 
      
 616 
     | 
    
         
            +
                picked_objects
         
     | 
| 
      
 617 
     | 
    
         
            +
              end
         
     | 
| 
      
 618 
     | 
    
         
            +
             
     | 
| 
      
 619 
     | 
    
         
            +
              def position_camera
         
     | 
| 
      
 620 
     | 
    
         
            +
                return unless self.unit_cell
         
     | 
| 
      
 621 
     | 
    
         
            +
                atoms = self.unit_cell
         
     | 
| 
      
 622 
     | 
    
         
            +
                
         
     | 
| 
      
 623 
     | 
    
         
            +
                # Find the center of all atoms, not just visible ones.
         
     | 
| 
      
 624 
     | 
    
         
            +
                @center = atoms.center unless @center
         
     | 
| 
      
 625 
     | 
    
         
            +
                
         
     | 
| 
      
 626 
     | 
    
         
            +
                # Move camera out along z-axis
         
     | 
| 
      
 627 
     | 
    
         
            +
                glMatrixMode(GL_MODELVIEW)
         
     | 
| 
      
 628 
     | 
    
         
            +
                glLoadIdentity()
         
     | 
| 
      
 629 
     | 
    
         
            +
             
     | 
| 
      
 630 
     | 
    
         
            +
                glTranslatef(self.offx,self.offy,self.offz)
         
     | 
| 
      
 631 
     | 
    
         
            +
                glRotatef(self.alt, 1, 0, 0)
         
     | 
| 
      
 632 
     | 
    
         
            +
                glRotatef(self.az, 0, 0, 1)
         
     | 
| 
      
 633 
     | 
    
         
            +
                glTranslatef(-@center.x, -@center.y, -@center.z)
         
     | 
| 
      
 634 
     | 
    
         
            +
              end
         
     | 
| 
      
 635 
     | 
    
         
            +
             
     | 
| 
      
 636 
     | 
    
         
            +
              def add_lights
         
     | 
| 
      
 637 
     | 
    
         
            +
                light0_position = [1,1,1,0]
         
     | 
| 
      
 638 
     | 
    
         
            +
                light1_position = [-1,-1,1,1]
         
     | 
| 
      
 639 
     | 
    
         
            +
                glLightModel(GL_LIGHT_MODEL_AMBIENT, [0.6, 0.6, 0.6 ,1.0])
         
     | 
| 
      
 640 
     | 
    
         
            +
                # glLightModel(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE)
         
     | 
| 
      
 641 
     | 
    
         
            +
                glLightfv(GL_LIGHT0, GL_POSITION, light0_position)              
         
     | 
| 
      
 642 
     | 
    
         
            +
                glLightfv(GL_LIGHT1, GL_POSITION, light1_position)
         
     | 
| 
      
 643 
     | 
    
         
            +
              end
         
     | 
| 
      
 644 
     | 
    
         
            +
             
     | 
| 
      
 645 
     | 
    
         
            +
              def outline_supercell
         
     | 
| 
      
 646 
     | 
    
         
            +
                return unless self.unit_cell
         
     | 
| 
      
 647 
     | 
    
         
            +
                uc = self.unit_cell
         
     | 
| 
      
 648 
     | 
    
         
            +
             
     | 
| 
      
 649 
     | 
    
         
            +
                vecs = uc.lattice_vectors
         
     | 
| 
      
 650 
     | 
    
         
            +
                return unless vecs
         
     | 
| 
      
 651 
     | 
    
         
            +
             
     | 
| 
      
 652 
     | 
    
         
            +
                origin = [0, 0, 0]
         
     | 
| 
      
 653 
     | 
    
         
            +
                v1 = vecs[0]
         
     | 
| 
      
 654 
     | 
    
         
            +
                v2 = vecs[1]
         
     | 
| 
      
 655 
     | 
    
         
            +
                v3 = vecs[2]
         
     | 
| 
      
 656 
     | 
    
         
            +
             
     | 
| 
      
 657 
     | 
    
         
            +
                # Corner #1
         
     | 
| 
      
 658 
     | 
    
         
            +
                c1 = v1 + v3
         
     | 
| 
      
 659 
     | 
    
         
            +
             
     | 
| 
      
 660 
     | 
    
         
            +
                # Corner #2
         
     | 
| 
      
 661 
     | 
    
         
            +
                c2 = v2 + v3
         
     | 
| 
      
 662 
     | 
    
         
            +
             
     | 
| 
      
 663 
     | 
    
         
            +
                # Corner #3
         
     | 
| 
      
 664 
     | 
    
         
            +
                c3 = v1 + v2
         
     | 
| 
      
 665 
     | 
    
         
            +
             
     | 
| 
      
 666 
     | 
    
         
            +
                # Corner #4
         
     | 
| 
      
 667 
     | 
    
         
            +
                c4 = v1 + v2 + v3
         
     | 
| 
      
 668 
     | 
    
         
            +
             
     | 
| 
      
 669 
     | 
    
         
            +
                Material.black.apply
         
     | 
| 
      
 670 
     | 
    
         
            +
                glLineWidth(1.0)
         
     | 
| 
      
 671 
     | 
    
         
            +
             
     | 
| 
      
 672 
     | 
    
         
            +
                glBegin(GL_LINES)
         
     | 
| 
      
 673 
     | 
    
         
            +
             
     | 
| 
      
 674 
     | 
    
         
            +
                glVertex3f(origin[0], origin[1], origin[2])
         
     | 
| 
      
 675 
     | 
    
         
            +
                glVertex3f(v1[0], v1[1], v1[2])				
         
     | 
| 
      
 676 
     | 
    
         
            +
             
     | 
| 
      
 677 
     | 
    
         
            +
                glVertex3f(origin[0], origin[1], origin[2])
         
     | 
| 
      
 678 
     | 
    
         
            +
                glVertex3f(v2[0], v2[1], v2[2])       
         
     | 
| 
      
 679 
     | 
    
         
            +
             
     | 
| 
      
 680 
     | 
    
         
            +
                glVertex3f(origin[0], origin[1], origin[2])
         
     | 
| 
      
 681 
     | 
    
         
            +
                glVertex3f(v3[0], v3[1], v3[2])       
         
     | 
| 
      
 682 
     | 
    
         
            +
             
     | 
| 
      
 683 
     | 
    
         
            +
                glVertex3f(v1[0], v1[1], v1[2])
         
     | 
| 
      
 684 
     | 
    
         
            +
                glVertex3f(c3[0], c3[1], c3[2])       
         
     | 
| 
      
 685 
     | 
    
         
            +
             
     | 
| 
      
 686 
     | 
    
         
            +
                glVertex3f(v2[0], v2[1], v2[2])
         
     | 
| 
      
 687 
     | 
    
         
            +
                glVertex3f(c3[0], c3[1], c3[2])       
         
     | 
| 
      
 688 
     | 
    
         
            +
             
     | 
| 
      
 689 
     | 
    
         
            +
                glVertex3f(c3[0], c3[1], c3[2])       
         
     | 
| 
      
 690 
     | 
    
         
            +
                glVertex3f(c4[0], c4[1], c4[2])       
         
     | 
| 
      
 691 
     | 
    
         
            +
             
     | 
| 
      
 692 
     | 
    
         
            +
                glVertex3f(v1[0], v1[1], v1[2])
         
     | 
| 
      
 693 
     | 
    
         
            +
                glVertex3f(c1[0], c1[1], c1[2])       
         
     | 
| 
      
 694 
     | 
    
         
            +
             
     | 
| 
      
 695 
     | 
    
         
            +
                glVertex3f(v2[0], v2[1], v2[2])
         
     | 
| 
      
 696 
     | 
    
         
            +
                glVertex3f(c2[0], c2[1], c2[2])       
         
     | 
| 
      
 697 
     | 
    
         
            +
             
     | 
| 
      
 698 
     | 
    
         
            +
                glVertex3f(c1[0], c1[1], c1[2])       
         
     | 
| 
      
 699 
     | 
    
         
            +
                glVertex3f(c4[0], c4[1], c4[2])       
         
     | 
| 
      
 700 
     | 
    
         
            +
             
     | 
| 
      
 701 
     | 
    
         
            +
                glVertex3f(c2[0], c2[1], c2[2])       
         
     | 
| 
      
 702 
     | 
    
         
            +
                glVertex3f(c4[0], c4[1], c4[2])       
         
     | 
| 
      
 703 
     | 
    
         
            +
             
     | 
| 
      
 704 
     | 
    
         
            +
                glVertex3f(v3[0], v3[1], v3[2])
         
     | 
| 
      
 705 
     | 
    
         
            +
                glVertex3f(c1[0], c1[1], c1[2])       
         
     | 
| 
      
 706 
     | 
    
         
            +
             
     | 
| 
      
 707 
     | 
    
         
            +
                glVertex3f(v3[0], v3[1], v3[2])
         
     | 
| 
      
 708 
     | 
    
         
            +
                glVertex3f(c2[0], c2[1], c2[2])       
         
     | 
| 
      
 709 
     | 
    
         
            +
             
     | 
| 
      
 710 
     | 
    
         
            +
                glEnd()        
         
     | 
| 
      
 711 
     | 
    
         
            +
              end
         
     | 
| 
      
 712 
     | 
    
         
            +
             
     | 
| 
      
 713 
     | 
    
         
            +
              def draw_bonds(origin = [0,0,0])
         
     | 
| 
      
 714 
     | 
    
         
            +
                return unless self.unit_cell
         
     | 
| 
      
 715 
     | 
    
         
            +
                atoms = if @options.correct
         
     | 
| 
      
 716 
     | 
    
         
            +
                  @unit_cell_corrected
         
     | 
| 
      
 717 
     | 
    
         
            +
                else
         
     | 
| 
      
 718 
     | 
    
         
            +
                    @unit_cell
         
     | 
| 
      
 719 
     | 
    
         
            +
                end
         
     | 
| 
      
 720 
     | 
    
         
            +
                return unless atoms.bonds
         
     | 
| 
      
 721 
     | 
    
         
            +
             
     | 
| 
      
 722 
     | 
    
         
            +
                Material.black.apply
         
     | 
| 
      
 723 
     | 
    
         
            +
                glLineWidth(1.0)
         
     | 
| 
      
 724 
     | 
    
         
            +
                glBegin(GL_LINES)
         
     | 
| 
      
 725 
     | 
    
         
            +
                atoms.bonds.each{|b|
         
     | 
| 
      
 726 
     | 
    
         
            +
                  glVertex3f(origin[0] + b[0].x, origin[1] + b[0].y, origin[2] + b[0].z)
         
     | 
| 
      
 727 
     | 
    
         
            +
                  glVertex3f(origin[0] + b[1].x, origin[1] + b[1].y, origin[2] + b[1].z)				
         
     | 
| 
      
 728 
     | 
    
         
            +
                }
         
     | 
| 
      
 729 
     | 
    
         
            +
                glEnd()
         
     | 
| 
      
 730 
     | 
    
         
            +
              end
         
     | 
| 
      
 731 
     | 
    
         
            +
              
         
     | 
| 
      
 732 
     | 
    
         
            +
              # 
         
     | 
| 
      
 733 
     | 
    
         
            +
              # Draw an atom 
         
     | 
| 
      
 734 
     | 
    
         
            +
              # @param x The x-coordinate
         
     | 
| 
      
 735 
     | 
    
         
            +
              # @param y The y-coordinate
         
     | 
| 
      
 736 
     | 
    
         
            +
              # @param z The z-coordinate
         
     | 
| 
      
 737 
     | 
    
         
            +
              # @param r The radius
         
     | 
| 
      
 738 
     | 
    
         
            +
              # @param name The name of the sphere (for picking)
         
     | 
| 
      
 739 
     | 
    
         
            +
              # @return a sphere_quadric for reuse if desired. Make sure to delete it when done
         
     | 
| 
      
 740 
     | 
    
         
            +
              def draw_sphere(x,y,z,r, name, sphere_quadric=nil)
         
     | 
| 
      
 741 
     | 
    
         
            +
             
     | 
| 
      
 742 
     | 
    
         
            +
                unless sphere_quadric 
         
     | 
| 
      
 743 
     | 
    
         
            +
                  sphere_quadric = gluNewQuadric()
         
     | 
| 
      
 744 
     | 
    
         
            +
                  gluQuadricDrawStyle(sphere_quadric, GLU_FILL)
         
     | 
| 
      
 745 
     | 
    
         
            +
                  gluQuadricNormals(sphere_quadric, GLU_SMOOTH)
         
     | 
| 
      
 746 
     | 
    
         
            +
                  gluQuadricOrientation(sphere_quadric, GLU_OUTSIDE)
         
     | 
| 
      
 747 
     | 
    
         
            +
                end
         
     | 
| 
      
 748 
     | 
    
         
            +
             
     | 
| 
      
 749 
     | 
    
         
            +
                # Load a new matrix onto the stack
         
     | 
| 
      
 750 
     | 
    
         
            +
                glPushMatrix()
         
     | 
| 
      
 751 
     | 
    
         
            +
                glPushName(name | PICK_ID_ATOM) if self.picking
         
     | 
| 
      
 752 
     | 
    
         
            +
                glTranslatef(x, y, z)
         
     | 
| 
      
 753 
     | 
    
         
            +
                gluSphere(sphere_quadric, r, slices, stacks)            
         
     | 
| 
      
 754 
     | 
    
         
            +
                glPopName() if picking
         
     | 
| 
      
 755 
     | 
    
         
            +
                glPopMatrix()
         
     | 
| 
      
 756 
     | 
    
         
            +
                
         
     | 
| 
      
 757 
     | 
    
         
            +
                sphere_quadric
         
     | 
| 
      
 758 
     | 
    
         
            +
              end
         
     | 
| 
      
 759 
     | 
    
         
            +
             
     | 
| 
      
 760 
     | 
    
         
            +
              def draw_lattice(origin = [0,0,0])
         
     | 
| 
      
 761 
     | 
    
         
            +
             
     | 
| 
      
 762 
     | 
    
         
            +
                return unless self.unit_cell
         
     | 
| 
      
 763 
     | 
    
         
            +
                
         
     | 
| 
      
 764 
     | 
    
         
            +
                atoms = if @options.correct
         
     | 
| 
      
 765 
     | 
    
         
            +
                  @unit_cell_corrected
         
     | 
| 
      
 766 
     | 
    
         
            +
                else
         
     | 
| 
      
 767 
     | 
    
         
            +
                  @unit_cell
         
     | 
| 
      
 768 
     | 
    
         
            +
                end
         
     | 
| 
      
 769 
     | 
    
         
            +
                
         
     | 
| 
      
 770 
     | 
    
         
            +
                return unless atoms
         
     | 
| 
      
 771 
     | 
    
         
            +
                
         
     | 
| 
      
 772 
     | 
    
         
            +
                # Create sphere object
         
     | 
| 
      
 773 
     | 
    
         
            +
                rmin = 0.2
         
     | 
| 
      
 774 
     | 
    
         
            +
                rmax = 0.5
         
     | 
| 
      
 775 
     | 
    
         
            +
             
     | 
| 
      
 776 
     | 
    
         
            +
                if self.atoms_changed
         
     | 
| 
      
 777 
     | 
    
         
            +
                  atoms.recache_visible_atoms 
         
     | 
| 
      
 778 
     | 
    
         
            +
                  self.atoms_changed = false
         
     | 
| 
      
 779 
     | 
    
         
            +
                end
         
     | 
| 
      
 780 
     | 
    
         
            +
                
         
     | 
| 
      
 781 
     | 
    
         
            +
                # Calculate radius scaling factor vs. depth
         
     | 
| 
      
 782 
     | 
    
         
            +
                rrange = rmax - rmin
         
     | 
| 
      
 783 
     | 
    
         
            +
                # bb = atoms.bounding_box
         
     | 
| 
      
 784 
     | 
    
         
            +
                zmin = atoms.min{|a,b| a.z <=> b.z}.z
         
     | 
| 
      
 785 
     | 
    
         
            +
                zmax = atoms.max{|a,b| a.z <=> b.z}.z
         
     | 
| 
      
 786 
     | 
    
         
            +
                zrange = zmax - zmin
         
     | 
| 
      
 787 
     | 
    
         
            +
                if zrange == 0
         
     | 
| 
      
 788 
     | 
    
         
            +
                  rscale = 0
         
     | 
| 
      
 789 
     | 
    
         
            +
                else
         
     | 
| 
      
 790 
     | 
    
         
            +
                  rscale = rrange/zrange
         
     | 
| 
      
 791 
     | 
    
         
            +
                end
         
     | 
| 
      
 792 
     | 
    
         
            +
             
     | 
| 
      
 793 
     | 
    
         
            +
             
     | 
| 
      
 794 
     | 
    
         
            +
             
     | 
| 
      
 795 
     | 
    
         
            +
                sphere_quadric = nil
         
     | 
| 
      
 796 
     | 
    
         
            +
                for a in atoms
         
     | 
| 
      
 797 
     | 
    
         
            +
                  a.material.apply(@options.show_lighting)
         
     | 
| 
      
 798 
     | 
    
         
            +
                  case self.render_mode 
         
     | 
| 
      
 799 
     | 
    
         
            +
                  when :ball_stick
         
     | 
| 
      
 800 
     | 
    
         
            +
                    r = rmin+(a.z - zmin)*rscale
         
     | 
| 
      
 801 
     | 
    
         
            +
                  else
         
     | 
| 
      
 802 
     | 
    
         
            +
                    r = 2.0
         
     | 
| 
      
 803 
     | 
    
         
            +
                  end
         
     | 
| 
      
 804 
     | 
    
         
            +
                  
         
     | 
| 
      
 805 
     | 
    
         
            +
                  sphere_quadric = draw_sphere(origin[0] + a.x, origin[1] + a.y, origin[2] + a.z, r, a.id, sphere_quadric)
         
     | 
| 
      
 806 
     | 
    
         
            +
                  
         
     | 
| 
      
 807 
     | 
    
         
            +
                end
         
     | 
| 
      
 808 
     | 
    
         
            +
                gluDeleteQuadric(sphere_quadric) if sphere_quadric
         
     | 
| 
      
 809 
     | 
    
         
            +
             
     | 
| 
      
 810 
     | 
    
         
            +
              end
         
     | 
| 
      
 811 
     | 
    
         
            +
             
     | 
| 
      
 812 
     | 
    
         
            +
              # a test method to see of an object of a particular type was picked.
         
     | 
| 
      
 813 
     | 
    
         
            +
              # valid types are :atom, :plane 
         
     | 
| 
      
 814 
     | 
    
         
            +
              def is_picked?(type, id)
         
     | 
| 
      
 815 
     | 
    
         
            +
                if @picked
         
     | 
| 
      
 816 
     | 
    
         
            +
                case type
         
     | 
| 
      
 817 
     | 
    
         
            +
                  when :atom
         
     | 
| 
      
 818 
     | 
    
         
            +
                    @picked[:atoms].member? id
         
     | 
| 
      
 819 
     | 
    
         
            +
                  when :plane
         
     | 
| 
      
 820 
     | 
    
         
            +
                    @picked[:planes].member? id
         
     | 
| 
      
 821 
     | 
    
         
            +
                  when :bond
         
     | 
| 
      
 822 
     | 
    
         
            +
                    @picked[:bonds].member? id
         
     | 
| 
      
 823 
     | 
    
         
            +
                  else
         
     | 
| 
      
 824 
     | 
    
         
            +
                    false
         
     | 
| 
      
 825 
     | 
    
         
            +
                  end
         
     | 
| 
      
 826 
     | 
    
         
            +
                else
         
     | 
| 
      
 827 
     | 
    
         
            +
                  false
         
     | 
| 
      
 828 
     | 
    
         
            +
                end
         
     | 
| 
      
 829 
     | 
    
         
            +
              end
         
     | 
| 
      
 830 
     | 
    
         
            +
             
     | 
| 
      
 831 
     | 
    
         
            +
              #
         
     | 
| 
      
 832 
     | 
    
         
            +
              # Draw a plane
         
     | 
| 
      
 833 
     | 
    
         
            +
              # use the vertices defined in lineLoop as the boundary of the plane
         
     | 
| 
      
 834 
     | 
    
         
            +
              def draw_plane(plane, lineLoop, pickid)
         
     | 
| 
      
 835 
     | 
    
         
            +
             
     | 
| 
      
 836 
     | 
    
         
            +
                glPushName(pickid | PICK_ID_PLANE) if self.picking
         
     | 
| 
      
 837 
     | 
    
         
            +
                
         
     | 
| 
      
 838 
     | 
    
         
            +
                # if is_picked?(:plane, pickid)
         
     | 
| 
      
 839 
     | 
    
         
            +
                #   Material.black.apply
         
     | 
| 
      
 840 
     | 
    
         
            +
                #   glLineWidth(3.0)
         
     | 
| 
      
 841 
     | 
    
         
            +
                #   glEdgeFlag(GL_TRUE)
         
     | 
| 
      
 842 
     | 
    
         
            +
                # end
         
     | 
| 
      
 843 
     | 
    
         
            +
                glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
         
     | 
| 
      
 844 
     | 
    
         
            +
             
     | 
| 
      
 845 
     | 
    
         
            +
                Material.new(0.9, 0.9, 0.0, 0.5).apply
         
     | 
| 
      
 846 
     | 
    
         
            +
                glBegin(GL_TRIANGLE_FAN)
         
     | 
| 
      
 847 
     | 
    
         
            +
                glNormal3f(plane.a, plane.b, plane.c)
         
     | 
| 
      
 848 
     | 
    
         
            +
                lineLoop.each{|p| 
         
     | 
| 
      
 849 
     | 
    
         
            +
                    glVertex3f(p[0], p[1], p[2])
         
     | 
| 
      
 850 
     | 
    
         
            +
                }
         
     | 
| 
      
 851 
     | 
    
         
            +
                glEnd()
         
     | 
| 
      
 852 
     | 
    
         
            +
                
         
     | 
| 
      
 853 
     | 
    
         
            +
                glEdgeFlag(GL_FALSE)
         
     | 
| 
      
 854 
     | 
    
         
            +
                glPopName() if picking
         
     | 
| 
      
 855 
     | 
    
         
            +
                
         
     | 
| 
      
 856 
     | 
    
         
            +
                if (is_picked?(:plane, pickid))
         
     | 
| 
      
 857 
     | 
    
         
            +
                  Material.black.apply
         
     | 
| 
      
 858 
     | 
    
         
            +
                  glLineWidth(3.0)
         
     | 
| 
      
 859 
     | 
    
         
            +
                  glBegin(GL_LINE_LOOP)
         
     | 
| 
      
 860 
     | 
    
         
            +
                  lineLoop.each{|p|
         
     | 
| 
      
 861 
     | 
    
         
            +
                    glVertex3f(p[0], p[1], p[2])
         
     | 
| 
      
 862 
     | 
    
         
            +
                  }
         
     | 
| 
      
 863 
     | 
    
         
            +
                  glEnd()
         
     | 
| 
      
 864 
     | 
    
         
            +
                  glLineWidth(1.0)
         
     | 
| 
      
 865 
     | 
    
         
            +
                end
         
     | 
| 
      
 866 
     | 
    
         
            +
                
         
     | 
| 
      
 867 
     | 
    
         
            +
              end
         
     | 
| 
      
 868 
     | 
    
         
            +
             
     | 
| 
      
 869 
     | 
    
         
            +
              def draw_clip_planes
         
     | 
| 
      
 870 
     | 
    
         
            +
                return unless self.unit_cell
         
     | 
| 
      
 871 
     | 
    
         
            +
                atoms = self.unit_cell
         
     | 
| 
      
 872 
     | 
    
         
            +
             
     | 
| 
      
 873 
     | 
    
         
            +
                bb = atoms.bounding_box
         
     | 
| 
      
 874 
     | 
    
         
            +
                bbx1 = bb[0].x
         
     | 
| 
      
 875 
     | 
    
         
            +
                bbx2 = bb[1].x
         
     | 
| 
      
 876 
     | 
    
         
            +
                bby1 = bb[0].y
         
     | 
| 
      
 877 
     | 
    
         
            +
                bby2 = bb[1].y
         
     | 
| 
      
 878 
     | 
    
         
            +
                bbz1 = bb[0].z
         
     | 
| 
      
 879 
     | 
    
         
            +
                bbz2 = bb[1].z
         
     | 
| 
      
 880 
     | 
    
         
            +
             
     | 
| 
      
 881 
     | 
    
         
            +
                # draw z_planes
         
     | 
| 
      
 882 
     | 
    
         
            +
                # The are bounded by the min and max points in the x-y plane
         
     | 
| 
      
 883 
     | 
    
         
            +
             
     | 
| 
      
 884 
     | 
    
         
            +
                if @options.show_zclip and @zmax_plane and @zmin_plane
         
     | 
| 
      
 885 
     | 
    
         
            +
                  z = -1*@zmax_plane.distance_to_point(0,0,0)
         
     | 
| 
      
 886 
     | 
    
         
            +
                  draw_plane(@zmax_plane, [[bbx1, bby1, z],
         
     | 
| 
      
 887 
     | 
    
         
            +
                                           [bbx2, bby1, z],
         
     | 
| 
      
 888 
     | 
    
         
            +
                                           [bbx2, bby2, z], 
         
     | 
| 
      
 889 
     | 
    
         
            +
                                           [bbx1, bby2, z]],1)
         
     | 
| 
      
 890 
     | 
    
         
            +
             
     | 
| 
      
 891 
     | 
    
         
            +
                   z = @zmin_plane.distance_to_point(0,0,0)
         
     | 
| 
      
 892 
     | 
    
         
            +
                   draw_plane(@zmin_plane, [[bbx1, bby1, z],
         
     | 
| 
      
 893 
     | 
    
         
            +
                                            [bbx2, bby1, z],
         
     | 
| 
      
 894 
     | 
    
         
            +
                                            [bbx2, bby2, z], 
         
     | 
| 
      
 895 
     | 
    
         
            +
                                            [bbx1, bby2, z]],2)
         
     | 
| 
      
 896 
     | 
    
         
            +
                end
         
     | 
| 
      
 897 
     | 
    
         
            +
             
     | 
| 
      
 898 
     | 
    
         
            +
                if @options.show_xclip and @xmax_plane and @xmin_plane
         
     | 
| 
      
 899 
     | 
    
         
            +
                  x = -1*@xmax_plane.distance_to_point(0,0,0)
         
     | 
| 
      
 900 
     | 
    
         
            +
                  draw_plane(@xmax_plane, [[x, bby1, bbz1],
         
     | 
| 
      
 901 
     | 
    
         
            +
                                           [x, bby1, bbz2],
         
     | 
| 
      
 902 
     | 
    
         
            +
                                           [x, bby2, bbz2], 
         
     | 
| 
      
 903 
     | 
    
         
            +
                                           [x, bby2, bbz1]],3)
         
     | 
| 
      
 904 
     | 
    
         
            +
             
     | 
| 
      
 905 
     | 
    
         
            +
                   x = @xmin_plane.distance_to_point(0,0,0)
         
     | 
| 
      
 906 
     | 
    
         
            +
                   draw_plane(@xmin_plane, [[x, bby1, bbz1],
         
     | 
| 
      
 907 
     | 
    
         
            +
                                            [x, bby1, bbz2],
         
     | 
| 
      
 908 
     | 
    
         
            +
                                            [x, bby2, bbz2], 
         
     | 
| 
      
 909 
     | 
    
         
            +
                                            [x, bby2, bbz1]],4)
         
     | 
| 
      
 910 
     | 
    
         
            +
                end
         
     | 
| 
      
 911 
     | 
    
         
            +
             
     | 
| 
      
 912 
     | 
    
         
            +
                if @options.show_yclip and @ymax_plane and @ymin_plane
         
     | 
| 
      
 913 
     | 
    
         
            +
                  y = -1*@ymax_plane.distance_to_point(0,0,0)
         
     | 
| 
      
 914 
     | 
    
         
            +
                  draw_plane(@ymax_plane, [[bbx1, y, bbz1],
         
     | 
| 
      
 915 
     | 
    
         
            +
                                           [bbx1, y, bbz2],
         
     | 
| 
      
 916 
     | 
    
         
            +
                                           [bbx2, y, bbz2], 
         
     | 
| 
      
 917 
     | 
    
         
            +
                                           [bbx2, y, bbz1]],5)
         
     | 
| 
      
 918 
     | 
    
         
            +
             
     | 
| 
      
 919 
     | 
    
         
            +
                   y = @ymin_plane.distance_to_point(0,0,0)
         
     | 
| 
      
 920 
     | 
    
         
            +
                   draw_plane(@ymin_plane, [[bbx1, y, bbz1],
         
     | 
| 
      
 921 
     | 
    
         
            +
                                            [bbx1, y, bbz2],
         
     | 
| 
      
 922 
     | 
    
         
            +
                                            [bbx2, y, bbz2], 
         
     | 
| 
      
 923 
     | 
    
         
            +
                                            [bbx2, y, bbz1]],6)
         
     | 
| 
      
 924 
     | 
    
         
            +
                end
         
     | 
| 
      
 925 
     | 
    
         
            +
             
     | 
| 
      
 926 
     | 
    
         
            +
              end
         
     | 
| 
      
 927 
     | 
    
         
            +
             
     | 
| 
      
 928 
     | 
    
         
            +
              def rgba_image_data
         
     | 
| 
      
 929 
     | 
    
         
            +
             
     | 
| 
      
 930 
     | 
    
         
            +
                # 4 bytes/pixel
         
     | 
| 
      
 931 
     | 
    
         
            +
                bytewidth = self.width*4
         
     | 
| 
      
 932 
     | 
    
         
            +
                bytewidth = (bytewidth.to_i + 3) & ~3 # Align to 4 bytes
         
     | 
| 
      
 933 
     | 
    
         
            +
                bytes = bytewidth * self.height
         
     | 
| 
      
 934 
     | 
    
         
            +
             
     | 
| 
      
 935 
     | 
    
         
            +
                # Finish any pending Commands
         
     | 
| 
      
 936 
     | 
    
         
            +
                @glPanel.set_current
         
     | 
| 
      
 937 
     | 
    
         
            +
                glFinish
         
     | 
| 
      
 938 
     | 
    
         
            +
             
     | 
| 
      
 939 
     | 
    
         
            +
                # Setup pixel store
         
     | 
| 
      
 940 
     | 
    
         
            +
                glPixelStorei(Gl::GL_PACK_ALIGNMENT, 4) # Force 4-byte alignment
         
     | 
| 
      
 941 
     | 
    
         
            +
                glPixelStorei(Gl::GL_PACK_ROW_LENGTH, 0)
         
     | 
| 
      
 942 
     | 
    
         
            +
                glPixelStorei(Gl::GL_PACK_SKIP_ROWS, 0)
         
     | 
| 
      
 943 
     | 
    
         
            +
                glPixelStorei(Gl::GL_PACK_SKIP_PIXELS, 0)
         
     | 
| 
      
 944 
     | 
    
         
            +
             
     | 
| 
      
 945 
     | 
    
         
            +
                glReadPixels(0, 0, self.width, self.height, Gl::GL_RGBA, Gl::GL_UNSIGNED_BYTE)
         
     | 
| 
      
 946 
     | 
    
         
            +
             
     | 
| 
      
 947 
     | 
    
         
            +
              end
         
     | 
| 
      
 948 
     | 
    
         
            +
             
     | 
| 
      
 949 
     | 
    
         
            +
              def image
         
     | 
| 
      
 950 
     | 
    
         
            +
                image = Image.new(self.width, self.height)
         
     | 
| 
      
 951 
     | 
    
         
            +
                image.set_rgb_data(self.rgb_image_data)
         
     | 
| 
      
 952 
     | 
    
         
            +
                image.set_alpha_data(self.alpha_image_data)
         
     | 
| 
      
 953 
     | 
    
         
            +
             		image
         
     | 
| 
      
 954 
     | 
    
         
            +
              end
         
     | 
| 
      
 955 
     | 
    
         
            +
             
     | 
| 
      
 956 
     | 
    
         
            +
              def rgb_image_data
         
     | 
| 
      
 957 
     | 
    
         
            +
             
     | 
| 
      
 958 
     | 
    
         
            +
                # 3 bytes/pixel
         
     | 
| 
      
 959 
     | 
    
         
            +
                bytewidth = self.width*3
         
     | 
| 
      
 960 
     | 
    
         
            +
                bytes = bytewidth * self.height
         
     | 
| 
      
 961 
     | 
    
         
            +
             
     | 
| 
      
 962 
     | 
    
         
            +
                # Finish any pending Commands
         
     | 
| 
      
 963 
     | 
    
         
            +
                @glPanel.set_current
         
     | 
| 
      
 964 
     | 
    
         
            +
                glFinish
         
     | 
| 
      
 965 
     | 
    
         
            +
             
     | 
| 
      
 966 
     | 
    
         
            +
                # Setup pixel store
         
     | 
| 
      
 967 
     | 
    
         
            +
                glPixelStorei(Gl::GL_PACK_ALIGNMENT, 1) # Force byte alignment
         
     | 
| 
      
 968 
     | 
    
         
            +
                glPixelStorei(Gl::GL_PACK_ROW_LENGTH, 0)
         
     | 
| 
      
 969 
     | 
    
         
            +
                glPixelStorei(Gl::GL_PACK_SKIP_ROWS, 0)
         
     | 
| 
      
 970 
     | 
    
         
            +
                glPixelStorei(Gl::GL_PACK_SKIP_PIXELS, 0)
         
     | 
| 
      
 971 
     | 
    
         
            +
             
     | 
| 
      
 972 
     | 
    
         
            +
                glReadPixels(0, 0, self.width, self.height, Gl::GL_RGB, Gl::GL_UNSIGNED_BYTE)
         
     | 
| 
      
 973 
     | 
    
         
            +
             
     | 
| 
      
 974 
     | 
    
         
            +
              end
         
     | 
| 
      
 975 
     | 
    
         
            +
              
         
     | 
| 
      
 976 
     | 
    
         
            +
              def alpha_image_data
         
     | 
| 
      
 977 
     | 
    
         
            +
                # 1 byte/pixel
         
     | 
| 
      
 978 
     | 
    
         
            +
                bytewidth = self.width;
         
     | 
| 
      
 979 
     | 
    
         
            +
                
         
     | 
| 
      
 980 
     | 
    
         
            +
                bytes = bytewidth*height;
         
     | 
| 
      
 981 
     | 
    
         
            +
                @glPanel.set_current
         
     | 
| 
      
 982 
     | 
    
         
            +
                glFinish
         
     | 
| 
      
 983 
     | 
    
         
            +
             
     | 
| 
      
 984 
     | 
    
         
            +
                # Setup pixel store
         
     | 
| 
      
 985 
     | 
    
         
            +
                glPixelStorei(Gl::GL_PACK_ALIGNMENT, 1) # Force byte alignment
         
     | 
| 
      
 986 
     | 
    
         
            +
                glPixelStorei(Gl::GL_PACK_ROW_LENGTH, 0)
         
     | 
| 
      
 987 
     | 
    
         
            +
                glPixelStorei(Gl::GL_PACK_SKIP_ROWS, 0)
         
     | 
| 
      
 988 
     | 
    
         
            +
                glPixelStorei(Gl::GL_PACK_SKIP_PIXELS, 0)
         
     | 
| 
      
 989 
     | 
    
         
            +
                
         
     | 
| 
      
 990 
     | 
    
         
            +
                glReadPixels(0, 0, self.width, self.height, Gl::GL_ALPHA, Gl::GL_UNSIGNED_BYTE)
         
     | 
| 
      
 991 
     | 
    
         
            +
              end
         
     | 
| 
      
 992 
     | 
    
         
            +
             
     | 
| 
      
 993 
     | 
    
         
            +
            end
         
     | 
| 
      
 994 
     | 
    
         
            +
            end
         
     |