class Capybara::Queries::SelectorQuery::Rectangle

Attributes

bottom[R]
left[R]
right[R]
top[R]

Public Class Methods

new(position) click to toggle source
# File lib/capybara/queries/selector_query.rb, line 584
def initialize(position)
  # rubocop:disable Style/RescueModifier
  @top = position['top'] rescue position['y']
  @bottom = position['bottom'] rescue (@top + position['height'])
  @left = position['left'] rescue position['x']
  @right = position['right'] rescue (@left + position['width'])
  # rubocop:enable Style/RescueModifier
end

Public Instance Methods

above?(other) click to toggle source
# File lib/capybara/queries/selector_query.rb, line 608
def above?(other)
  bottom <= other.top
end
below?(other) click to toggle source
# File lib/capybara/queries/selector_query.rb, line 612
def below?(other)
  top >= other.bottom
end
distance(other) click to toggle source
# File lib/capybara/queries/selector_query.rb, line 593
def distance(other)
  distance = Float::INFINITY

  line_segments.each do |ls1|
    other.line_segments.each do |ls2|
      distance = [
        distance,
        distance_segment_segment(*ls1, *ls2)
      ].min
    end
  end

  distance
end
left_of?(other) click to toggle source
# File lib/capybara/queries/selector_query.rb, line 616
def left_of?(other)
  right <= other.left
end
near?(other) click to toggle source
# File lib/capybara/queries/selector_query.rb, line 624
def near?(other)
  distance(other) <= 50
end
right_of?(other) click to toggle source
# File lib/capybara/queries/selector_query.rb, line 620
def right_of?(other)
  left >= other.right
end

Protected Instance Methods

line_segments() click to toggle source
# File lib/capybara/queries/selector_query.rb, line 630
def line_segments
  [
    [Vector[top, left], Vector[top, right]],
    [Vector[top, right], Vector[bottom, left]],
    [Vector[bottom, left], Vector[bottom, right]],
    [Vector[bottom, right], Vector[top, left]]
  ]
end

Private Instance Methods

distance_segment_segment(l1p1, l1p2, l2p1, l2p2) click to toggle source
# File lib/capybara/queries/selector_query.rb, line 641
def distance_segment_segment(l1p1, l1p2, l2p1, l2p2)
  # See http://geomalgorithms.com/a07-_distance.html
  # rubocop:disable Naming/VariableName
  u = l1p2 - l1p1
  v = l2p2 - l2p1
  w = l1p1 - l2p1

  a = u.dot u
  b = u.dot v
  c = v.dot v

  d = u.dot w
  e = v.dot w
  cap_d = (a * c) - (b**2)
  sD = tD = cap_d

  # compute the line parameters of the two closest points
  if cap_d < Float::EPSILON # the lines are almost parallel
    sN = 0.0 # force using point P0 on segment S1
    sD = 1.0 # to prevent possible division by 0.0 later
    tN = e
    tD = c
  else # get the closest points on the infinite lines
    sN = (b * e) - (c * d)
    tN = (a * e) - (b * d)
    if sN.negative? # sc < 0 => the s=0 edge is visible
      sN = 0
      tN = e
      tD = c
    elsif sN > sD # sc > 1 => the s=1 edge is visible
      sN = sD
      tN = e + b
      tD = c
    end
  end

  if tN.negative? # tc < 0 => the t=0 edge is visible
    tN = 0
    # recompute sc for this edge
    if (-d).negative?
      sN = 0.0
    elsif -d > a
      sN = sD
    else
      sN = -d
      sD = a
    end
  elsif tN > tD # tc > 1 => the t=1 edge is visible
    tN = tD
    # recompute sc for this edge
    if (-d + b).negative?
      sN = 0.0
    elsif (-d + b) > a
      sN = sD
    else
      sN = (-d + b)
      sD = a
    end
  end

  # finally do the division to get sc and tc
  sc = sN.abs < Float::EPSILON ? 0.0 : sN / sD
  tc = tN.abs < Float::EPSILON ? 0.0 : tN / tD

  # difference of the two closest points
  dP = w + (u * sc) - (v * tc)

  Math.sqrt(dP.dot(dP))
  # rubocop:enable Naming/VariableName
end