lib/PDB.rb
#
# select random extrema points
# first three points maximize area of a triangle
# fourth point maximizes distance from a point ot the triangular plane
# additional points are taken at random
select random extrema points
first three points maximize area of a triangle
fourth point maximizes distance from a point ot the triangular plane
additional points are taken at random
select random extrema points first three points maximize area of a triangle fourth point maximizes distance from a point ot the triangular plane additional points are taken at random
def select_random_extrema(total_to_select)
      begin
        if total_to_select < 3 || total_to_select > 12
          raise "Total number of random points must be > 3 and < 12"
        end
      rescue => error
        PDB::report_error("#{error.class} and #{error.message} : #{total_to_select} ")
      end
      @extrema.shuffle!
      points=Array.new(total_to_select)
      points[0] = @extrema[0].dup
      prior = 0
      for i in 1...@extrema.size
        anchor = @extrema[i]
        delx = points[0].xpos - anchor.xpos
        dely = points[0].ypos - anchor.ypos
        delz = points[0].zpos - anchor.zpos
        dis2 = delx*delx + dely*dely + delz*delz
        if dis2 > prior
          points[1] = @extrema[i].dup
          prior = dis2
        end
      end
      prior = 0
      for i in 1...@extrema.size
        anchor = @extrema[i]
        delx = points[0].xpos - anchor.xpos
        dely = points[0].ypos - anchor.ypos
        delz = points[0].zpos - anchor.zpos
        delx2 = points[1].xpos - anchor.xpos
        dely2 = points[1].ypos - anchor.ypos
        delz2 = points[1].zpos - anchor.zpos
        dis2 = Math::sqrt(delx*delx + dely*dely + delz*delz) + Math::sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2)
        if dis2 > prior
          points[2] = @extrema[i].dup
          prior = dis2
        end
      end
      vec1 = GSL::Vector[points[0].xpos - points[2].xpos, points[0].ypos - points[2].ypos, points[0].zpos - points[2].zpos]
      vec2 = GSL::Vector[points[1].xpos - points[2].xpos, points[1].ypos - points[2].ypos, points[1].zpos - points[2].zpos]
      a_coeff = vec1[1]*vec2[2] - vec1[2]*vec2[1]
      b_coeff = vec1[2]*vec2[0] - vec1[0]*vec2[2]
      c_coeff = vec1[0]*vec2[1] - vec1[1]*vec2[0]
      d_coeff = a_coeff*points[2].xpos + b_coeff*points[2].ypos + c_coeff*points[2].zpos
      inv_coeff = 1.0/Math::sqrt(a_coeff*a_coeff + b_coeff*b_coeff + c_coeff*c_coeff)
      prior = 0
      for i in 1...@extrema.size
        anchor = @extrema[i]
        dis = (anchor.xpos*a_coeff + anchor.ypos*b_coeff + anchor.zpos*c_coeff - d_coeff).abs * inv_coeff
        if (dis > prior)
          points[3] = @extrema[i].dup
          prior = dis
        end
      end
      if total_to_select > 4
        for i in 4...total_to_select
            for j in 0...14
              temp = points.select{|p| p.xpos == @extrema[j].xpos}
              if temp.size == 0
                @points[i] = @extrema[j].dup
                break
              end
            end
        end
      end
      @random_extrema = points
    end
def select_random_extrema ( total_to_select ) begin if total_to_select < 3 || total_to_select > 12 raise "Total number of random points must be > 3 and < 12" end rescue => error PDB :: report_error ( "#{error.class} and #{error.message} : #{total_to_select} " ) end @extrema . shuffle! points = Array . new ( total_to_select ) points [ 0 ] = @extrema [ 0 ] . dup prior = 0 for i in 1 ... @extrema . size anchor = @extrema [ i ] delx = points [ 0 ] . xpos - anchor . xpos dely = points [ 0 ] . ypos - anchor . ypos delz = points [ 0 ] . zpos - anchor . zpos dis2 = delx * delx + dely * dely + delz * delz if dis2 > prior points [ 1 ] = @extrema [ i ] . dup prior = dis2 end end prior = 0 for i in 1 ... @extrema . size anchor = @extrema [ i ] delx = points [ 0 ] . xpos - anchor . xpos dely = points [ 0 ] . ypos - anchor . ypos delz = points [ 0 ] . zpos - anchor . zpos delx2 = points [ 1 ] . xpos - anchor . xpos dely2 = points [ 1 ] . ypos - anchor . ypos delz2 = points [ 1 ] . zpos - anchor . zpos dis2 = Math :: sqrt ( delx * delx + dely * dely + delz * delz ) + Math :: sqrt ( delx2 * delx2 + dely2 * dely2 + delz2 * delz2 ) if dis2 > prior points [ 2 ] = @extrema [ i ] . dup prior = dis2 end end vec1 = GSL :: Vector [ points [ 0 ] . xpos - points [ 2 ] . xpos , points [ 0 ] . ypos - points [ 2 ] . ypos , points [ 0 ] . zpos - points [ 2 ] . zpos ] vec2 = GSL :: Vector [ points [ 1 ] . xpos - points [ 2 ] . xpos , points [ 1 ] . ypos - points [ 2 ] . ypos , points [ 1 ] . zpos - points [ 2 ] . zpos ] a_coeff = vec1 [ 1 ] * vec2 [ 2 ] - vec1 [ 2 ] * vec2 [ 1 ] b_coeff = vec1 [ 2 ] * vec2 [ 0 ] - vec1 [ 0 ] * vec2 [ 2 ] c_coeff = vec1 [ 0 ] * vec2 [ 1 ] - vec1 [ 1 ] * vec2 [ 0 ] d_coeff = a_coeff * points [ 2 ] . xpos + b_coeff * points [ 2 ] . ypos + c_coeff * points [ 2 ] . zpos inv_coeff = 1.0 / Math :: sqrt ( a_coeff * a_coeff + b_coeff * b_coeff + c_coeff * c_coeff ) prior = 0 for i in 1 ... @extrema . size anchor = @extrema [ i ] dis = ( anchor . xpos * a_coeff + anchor . ypos * b_coeff + anchor . zpos * c_coeff - d_coeff ) . abs * inv_coeff if ( dis > prior ) points [ 3 ] = @extrema [ i ] . dup prior = dis end end if total_to_select > 4 for i in 4 ... total_to_select for j in 0 ... 14 temp = points . select { | p | p . xpos == @extrema [ j ] . xpos } if temp . size == 0 @points [ i ] = @extrema [ j ] . dup break end end end end @random_extrema = points end
select random extrema points
first three points maximize area of a triangle
fourth point maximizes distance from a point ot the triangular plane
additional points are taken at random
select random extrema points first three points maximize area of a triangle fourth point maximizes distance from a point ot the triangular plane additional points are taken at random
# select longest distance # find the next point that maximizes distance between first two select points # find fourth point as a non-planar point (distances between point and plane is maximized) # cross-product - get parameters for a plane # find the next point that maximizes distance between first two select points #end # add additional points from random selection
total_to_select
<not_specific>