class VectorBeWinding::Segment

Attributes

control[R]
control_1[R]
direction[R]
end_point[R]
large_arc[R]
radius[R]
rotation[R]
start_point[R]
sweep[R]

Public Class Methods

new(direction, start_point, end_point_hint, prev_segment = nil) click to toggle source
# File lib/vector_be_winding/segment.rb, line 7
def initialize(direction, start_point, end_point_hint, prev_segment = nil)
  @direction = direction
  @start_point = start_point
  @end_point =
    if @direction.kind_of?(::Savage::Directions::PointTarget)
      create_vector(@direction.target.x, @direction.target.y, @direction.absolute?)
    elsif @direction.kind_of?(::Savage::Directions::HorizontalTo)
      create_vector(@direction.target, nil, @direction.absolute?)
    elsif @direction.kind_of?(::Savage::Directions::VerticalTo)
      create_vector(nil, @direction.target, @direction.absolute?)
    elsif @direction.kind_of?(::Savage::Directions::ClosePath)
      end_point_hint
    else
      raise "Unknown direction: #{@direction}"
    end

  if @direction.instance_of?(::Savage::Directions::QuadraticCurveTo)
    control = @direction.control ||
              prev_segment.control&.reflect(start_point) ||
              start_point
    @control = create_vector(control.x, control.y, @direction.absolute?)
  elsif @direction.instance_of?(::Savage::Directions::CubicCurveTo)
    control = @direction.control
    control_1 = @direction.control_1 ||
              prev_segment.control&.reflect(start_point) ||
              start_point
    @control = create_vector(control.x, control.y, @direction.absolute?)
    @control_1 = create_vector(control_1.x, control_1.y, @direction.absolute?)
  elsif @direction.instance_of?(::Savage::Directions::ArcTo)
    @radius = @direction.radius
    @rotation = @direction.rotation
    @large_arc = @direction.large_arc
    @sweep = @direction.sweep
  end
end

Public Instance Methods

area(p) click to toggle source

Calculate direction area of the triangle (p, start_point, end_point) It must be positive iff the three points forms clockwise order.

# File lib/vector_be_winding/segment.rb, line 62
def area(p)
  if @direction.kind_of?(::Savage::Directions::QuadraticCurveTo)
    # Approximate with triangle
    (start_point - p).cross(control - start_point) +
      (control - p).cross(end_point - control)
  elsif @direction.kind_of?(::Savage::Directions::CubicCurveTo)
    # Approximate with quadrangle
    (start_point - p).cross(control_1 - start_point) +
      (control_1 - p).cross(control_2 - control_1) +
      (control_2 - p).cross(end_point - control_2)
  elsif @direction.kind_of?(::Savage::Directions::ArcTo)
    # Very rough approximation. TODO: Be more precise
    (start_point - p).cross(end_point - start_point) / 2.0 + (sweep ? 1 : -1)
  else
    (start_point - p).cross(end_point - start_point) / 2.0
  end
end
bounding_rect() click to toggle source
# File lib/vector_be_winding/segment.rb, line 55
def bounding_rect
  @bounding_rect ||=
    Rect.new(start_point.x, start_point.y, end_point.x, end_point.y)
end
control_2() click to toggle source
# File lib/vector_be_winding/segment.rb, line 43
def control_2
  control
end
create_vector(x, y, absolute) click to toggle source
# File lib/vector_be_winding/segment.rb, line 47
def create_vector(x, y, absolute)
  if absolute
    Vector.new(x || start_point.x, y || start_point.y)
  else
    start_point + Vector.new(x || 0, y || 0)
  end
end
reverse() click to toggle source
# File lib/vector_be_winding/segment.rb, line 80
def reverse
  Segment.new(reverse_dir, end_point, start_point)
end
reverse_dir() click to toggle source
# File lib/vector_be_winding/segment.rb, line 84
def reverse_dir
  case @direction.command_code.upcase
  when 'Z', 'L'
    ::Savage::Directions::LineTo.new(start_point.x, start_point.y, true)
  when 'M'
    nil  # Unable to reverse
  when 'H'
    ::Savage::Directions::HorizontalTo.new(start_point.x, true)
  when 'V'
    ::Savage::Directions::VerticalTo.new(start_point.y, true)
  when 'Q', 'T'
    ::Savage::Directions::QuadraticCurveTo.new(
      control.x, control.y, start_point.x, start_point.y, true)
  when 'C', 'S'
    ::Savage::Directions::CubicCurveTo.new(
      control.x, control.y, control_1.x, control_1.y,
      start_point.x, start_point.y, true)
  when 'A'
    ::Savage::Directions::ArcTo.new(
      radius.x, radius.y, rotation, large_arc, !sweep, start_point.x, start_point.y, true)
  else
    raise "Unknown direction: #{@direction}"
  end
end