class RSVGR::Samples::Plot

Public Class Methods

new(*args) click to toggle source
Calls superclass method
# File lib/rsvgr.rb, line 284
def initialize *args
  # @stroke_width = 0.002
  # @fill_color = "white"
  super
end

Public Instance Methods

add_dots(array) click to toggle source
# File lib/rsvgr.rb, line 419
def add_dots array
  add_array array, false
end
add_line(array) click to toggle source
# File lib/rsvgr.rb, line 416
def add_line array
  add_array array, true
end
to_s() click to toggle source
Calls superclass method RSVGR::Group#to_s
# File lib/rsvgr.rb, line 289
def to_s
  return @to_s_cached if @to_s_cached
  # maybe start all #to_s with "super \" and implement caching crutch in Node#to_s
  left = 0.2
  text_size = 0.03
  self << field = Group.new(id:"TODOfield", x: left, y: 0.05, scale: 0.7)
  field << Rect.new(fill_color: "none")
  ticks = lambda do |values, forced_ticks = nil|
    if values.all?{ |i| i.is_a? Numeric }
      min, max = values.minmax
      @log ? [
        forced_ticks || [min, *(1...8).map{ |i| Math.exp(Math.log(min - min + 1) + (Math.log(max - min + 1) - Math.log(min - min + 1)) * i * 0.125) + min - 1 }, max],
        -> x { (Math.log(x - min + 1) - Math.log(min - min + 1)) * 1.0 / (Math.log(max - min + 1) - Math.log(min - min + 1)) }
      ] : [
        forced_ticks || [min, *(1...8).map{ |i|                   min            + (         max            -          min           ) * i * 0.125            }, max],
        -> x { (         x            -          min           ) * 1.0 / (         max            -          min           ) }
      ]
    else
      unique_values = forced_ticks || values.uniq
      [
        unique_values,
        -> x { unique_values.index(x) * 1.0 / (unique_values.size - 1) }
      ]
    end
  end
  ticks_x, f_x = ticks[ arrays.flat_map{ |array| array[:data].transpose[0] }, @ticks_x ]
  ticks_y, f_y = ticks[ arrays.flat_map{ |array| array[:data].transpose[1] }, @ticks_y ]
  ticks_x.each do |tick|
    field << Line.new(
      y1: 1.025, x1: f_x[tick], x2: f_x[tick]
    ) << Line.new(
      x1: f_x[tick], x2: f_x[tick], stroke_color: "silver"
    ) << (Group.new(
      y:  1.025, x:  f_x[tick], rotate: 90
        ) << (Text.new(x: 0, y: 0, size: text_size,
        #baseline: "text-before-edge",
        anchor: "begin",
        #style: "writing-mode: tb;",
        ) << tick.to_s)
    )
  end
  ticks_y.each do |tick|
    field << Line.new(
      x2: -0.025, y1: 1 - f_y[tick], y2: 1 - f_y[tick]
    ) << Line.new(
      y1: 1 - f_y[tick], y2: 1 - f_y[tick], stroke_color: "silver"
    ) << (Text.new(
      y: 1 - f_y[tick], x: -left * 0.2, size: text_size, anchor: "end"
        ) << tick.to_s
    )
  end
  (0...arrays.size).map do |i|
    ?# + lambda do |h,s,v|
      vmin = (100 - s) * v / 100
      a = (v - vmin) * (h % 60) / 60.0
      vinc = vmin + a
      vdec = v - a
      case h / 60
      when 0 ; [v, vinc, vmin]
      when 1 ; [vdec, v, vmin]
      when 2 ; [vmin, v, vinc]
      when 3 ; [vmin, vdec, v]
      when 4 ; [vinc, vmin, v]
      when 5 ; [v, vmin, vdec]
      end.map{ |i| (2.55 * i).floor }
    end.call(i * 360 / arrays.size, 100, 100).pack("C*").unpack("H*").first
  end.zip(arrays).each_with_index do |(color, line), i|
    #@@id = defined?(@@id) ? @@id + 1 : 0
    field << (Text.new(                         # Legend text
      #id: @@id,
      # fill_color: color.tr("0123456789abcdef", "fedcba9876543210"),
      size: text_size,
      x: 0.12,
      y: (0.025 + i * 0.03),
      anchor: "begin",
      baseline: "text-before-edge",
    ) << line[:title]) << Rect.new(             # Legend rectangle
      x: 0.05,
      y: 0.035 + i * 0.03,
      width: 0.05,
      height: 0.03,
      fill_color: line[:color] || color,
    ) if arrays.size > 1
    line[:data].each do |x, y, info|            # Line verticles
      cx = f_x[x]
      cy = 1 - f_y[y]
      require "cgi"
      field << Circle.new(
        cx: cx.round(3),
        cy: cy.round(3),
        r: 0.005 * (line[:r] || 1),
        stroke_width: line[:verticles_stroke_width],
        fill_color: line[:color] || color,
        # stroke_color: color,
        onmousemove: "s(evt,"                                   +
          " '(#{x}, #{y})#{" #{CGI.escapeHTML info}" if info}"  \
            "#{" \\'#{line[:title]}\\'" if arrays.size > 1}',"  +
          " #{(DEFAULT_SIZE *  cx         ).round(3)},"         +
          " #{(DEFAULT_SIZE * (cy - 0.025)).round(3)})",
        onmouseout: "h(evt)",
      )
    end
    field << Path.new(                            # Line itself
      stroke_color: line[:color] || color,
      stroke_width: line[:edges_stroke_width],
      points: line[:data].map{ |k, v, | [f_x[k], 1 - f_y[v]] }
    ) if line[:connected]
  end
  field << Text.new(
    id: "tooltip",
    visibility: "hidden",
    baseline: "before-edge",
    size: text_size,
  ) << (Script.new(id: "TODOscript") << "
    var svg = document.getElementById(\"TODOscript\").ownerSVGElement;
    svg.tooltip = svg.getElementById(\"tooltip\");
    function s(evt, text, x, y) {
      var tooltip = evt.target.ownerSVGElement.tooltip;
      tooltip.setAttributeNS(null, \"x\", x);
      tooltip.setAttributeNS(null, \"y\", y);
      tooltip.textContent = text;
      tooltip.setAttributeNS(null, \"visibility\", \"visible\");
    }
    function h(evt) { evt.target.ownerSVGElement.tooltip.setAttributeNS(null, \"visibility\", \"hidden\"); }
  ")
  @to_s_cached = super
end

Private Instance Methods

add_array(array, connected) click to toggle source
# File lib/rsvgr.rb, line 423
def add_array array, connected
  # array[:data] =
  array[:connected] = connected
  # array[:data] = Hash[array[:data]]
  arrays << array
  self
end
arrays() click to toggle source
# File lib/rsvgr.rb, line 430
def arrays
  @arrays ||= []
end