class TaskJuggler::CollisionDetector

Public Class Methods

new(width, height) click to toggle source
# File lib/taskjuggler/reports/CollisionDetector.rb, line 21
def initialize(width, height)
  @width = width
  @height = height

  # The zones are stored as Arrays of line segments. Horizontal blocks are
  # stored separately from vertical blocks. Blocked segments for a
  # particular x coordinate are stored in @vLines, for y coordinates in
  # @hLines. Each entry is an Array of [ start, end ] values that describe
  # the blocked segments of that particular line. Start and end point are
  # part of the segment. A listed segment will not be overwritten during
  # routing.
  @hLines = Array.new(@height) { |i| i = [] }
  @vLines = Array.new(@width) { |i| i = [] }
end

Public Instance Methods

addBlockedZone(x, y, w, h, horiz, vert) click to toggle source

This function registers an area as don't-cross-zone. The rectangular zone is described by x, y, w and h. If horiz is true, the zone will be blocked for horizontal lines, if vert is true the zone will be blocked for vertical lines.

# File lib/taskjuggler/reports/CollisionDetector.rb, line 40
def addBlockedZone(x, y, w, h, horiz, vert)
  # Clip the input rectangle to fit within the handled area of this router.
  x = clip(x.to_i, @width - 1)
  y = clip(y.to_i, @height - 1)
  w = clip(w.to_i, @width - x)
  h = clip(h.to_i, @height - y)

  # We can ignore empty zones.
  return if w == 0 || h == 0

  # Break the rectangle into line segments and add them to the appropriate
  # line Arrays.
  if horiz
    y.upto(y + h - 1) do |i|
      addSegment(@hLines[i], [ x, x + w - 1 ])
    end
  end
  if vert
    x.upto(x + w - 1) do |i|
      addSegment(@vLines[i], [ y, y + h - 1 ])
    end
  end
end
collision?(pos, segment, horizontal) click to toggle source

Find out if there is a block at line pos for the start/end coordinates given by segment. If horizontal is true, we are looking for a horizontal block, otherwise a vertical.

# File lib/taskjuggler/reports/CollisionDetector.rb, line 67
def collision?(pos, segment, horizontal)
  line = (horizontal ? @hLines : @vLines)[pos]

  # For complex charts, the segment lists can be rather long. We use a
  # binary search to be fairly efficient.
  l = 0
  u = line.length - 1
  while l <= u
    # Look at the element in the middle between l and u.
    p = l + ((u - l) / 2).to_i
    return true if overlaps?(line[p], segment)

    if segment[0] > line[p][1]
      # The potential target is above p. Adjust lower bound.
      l = p + 1
    else
      # The potential target is below p. Adjust upper bound.
      u = p - 1
    end
  end
  false
end
to_html() click to toggle source
# File lib/taskjuggler/reports/CollisionDetector.rb, line 90
def to_html
  html = []
  # Change this to determine what zones you want to see.
  if true
    # Show vertical blocks
    x = 0
    @vLines.each do |line|
      line.each do |segment|
        html << lineToHTML(x, segment[0], x, segment[1], 'white')
      end
      x += 1
    end
  else
    # Show horizontal blocks
    y = 0
    @hLines.each do |line|
      line.each do |segment|
        html << lineToHTML(segment[0], y, segment[1], y, 'white')
      end
      y += 1
    end
  end
  html
end