Class: CTioga::Curve2D
- Inherits:
-
TiogaElement
- Object
- TiogaElement
- CTioga::Curve2D
- Includes:
- Dobjects
- Defined in:
- lib/CTioga/elements/curves.rb
Overview
The class Curve2D stores both the data and the way it should be plotted, such as it’s legend, it’s color, it’s line style and so on…
Direct Known Subclasses
Instance Attribute Summary collapse
-
#function ⇒ Object
readonly
The underlying Function object:.
-
#style ⇒ Object
readonly
The CurveStyle object representing the curve’s style.
Attributes inherited from TiogaElement
Class Method Summary collapse
-
.compute_boundaries(bounds) ⇒ Object
Computes the outmost boundaries of the given boundaries.
Instance Method Summary collapse
-
#close_path(t, y) ⇒ Object
A function to close the path created by make_path.
-
#draw_error_bars(t = nil) ⇒ Object
The function that plots error bars.
-
#draw_fill(t) ⇒ Object
Draws the filled region according to the :fill_type element of the style pseudo-hash.
- #draw_markers(t) ⇒ Object
-
#draw_path(t) ⇒ Object
Draw the path.
-
#get_boundaries ⇒ Object
This function returns the bouding box of the specified graphes No margin adjustment is done here, as it can lead to very uneven graphs.
- #has_legend? ⇒ Boolean
-
#initialize(style = nil, data = nil) ⇒ Curve2D
constructor
A new instance of Curve2D.
-
#make_path(t) ⇒ Object
Creates a path for the given curve.
- #need_style? ⇒ Boolean
-
#parse_position(spec) ⇒ Object
This function returns the index of a point from the curve according to the given spec, a string.
- #plot(t = nil) ⇒ Object (also: #do)
-
#set_data(ar) ⇒ Object
Sets the data for the curve.
- #set_style(style) ⇒ Object
-
#tangent(index, dir = :both) ⇒ Object
Returns the tangent of the curve at the given point, that is a vector parallel to it.
-
#y_value(spec) ⇒ Object
Returns a y value suitable for fills/histograms or other kinds of stuff based on a specification: * false/nil: returns nil * to_y_axis: y = 0 * to_bottom: the bottom of the plot * to_top: the top of the plot * “y = .…”: the given value.
Methods inherited from TiogaElement
Methods included from Log
#identify, #init_logger, #logger, #logger_options, #spawn
Methods included from Debug
#debug_figmaker, #debug_patterns, #debug_puts, #figmaker_options, #test_pattern, #test_pattern_right
Constructor Details
#initialize(style = nil, data = nil) ⇒ Curve2D
Returns a new instance of Curve2D.
45 46 47 48 49 50 |
# File 'lib/CTioga/elements/curves.rb', line 45 def initialize(style = nil, data = nil) # style is a CurveStyle object set_style(style) if style set_data(data) if data @line_cap = nil end |
Instance Attribute Details
#function ⇒ Object (readonly)
The underlying Function object:
35 36 37 |
# File 'lib/CTioga/elements/curves.rb', line 35 def function @function end |
#style ⇒ Object (readonly)
The CurveStyle object representing the curve’s style.
32 33 34 |
# File 'lib/CTioga/elements/curves.rb', line 32 def style @style end |
Class Method Details
.compute_boundaries(bounds) ⇒ Object
Computes the outmost boundaries of the given boundaries. Any NaN in here will happily get ignored.
124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/CTioga/elements/curves.rb', line 124 def Curve2D.compute_boundaries(bounds) left = Dvector.new right = Dvector.new top = Dvector.new bottom = Dvector.new bounds.each do |a| left.push(a[0]) right.push(a[1]) top.push(a[2]) bottom.push(a[3]) end return [left.min, right.max, top.max, bottom.min] end |
Instance Method Details
#close_path(t, y) ⇒ Object
A function to close the path created by make_path. Overridden in the histogram code.
215 216 217 218 219 |
# File 'lib/CTioga/elements/curves.rb', line 215 def close_path(t, y) t.append_point_to_path(@function.x.last, y) t.append_point_to_path(@function.x.first, y) t.close_path end |
#draw_error_bars(t = nil) ⇒ Object
The function that plots error bars.
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/CTioga/elements/curves.rb', line 255 def (t = nil) # We first check that we actually need to do anything t.context do t.stroke_transparency = @style. || 0 if @function.errors.key?(:xmin) or @function.errors.key?(:ymin) = {} # Just create it once, anyway ['color'] = @style. errors = @function.errors # So we won't have to worry # some data should be shared @function.errors[:x].each_index do |i| ['x'] = errors[:x][i] if errors.key?(:xmin) && ((errors[:xmax][i] - errors[:xmin][i]) != 0) ['dx_plus'] = errors[:xmax][i] - errors[:x][i] ['dx_minus'] = errors[:x][i] - errors[:xmin][i] .delete('dx') else %w(dx_plus dx_minus).each do |el| .delete(el) end ['dx'] = 0 end ['y'] = errors[:y][i] if errors.key?(:ymin) && ((errors[:ymax][i] - errors[:ymin][i]) != 0) ['dy_plus'] = errors[:ymax][i] - errors[:y][i] ['dy_minus'] = errors[:y][i] - errors[:ymin][i] .delete('dy') else %w(dy_plus dy_minus).each do |el| .delete(el) end ['dy'] = 0 end if (['dx'] != 0 || ['dy'] != 0) t.() end end end end end |
#draw_fill(t) ⇒ Object
Draws the filled region according to the :fill_type element of the style pseudo-hash. It can be:
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/CTioga/elements/curves.rb', line 223 def draw_fill(t) y = y_value(@style.fill_type) return unless y t.fill_transparency = @style.fill_transparency || 0 # Now is the tricky part. To do the actual fill, we first make a # path according to the make_path function. make_path(t) # Then we add two line segments that go from the end to the # beginning. close_path(t, y) # Now the path is ready. Just strike -- or, rather, fill ! t.fill_color = @style.fill_color t.fill end |
#draw_markers(t) ⇒ Object
171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/CTioga/elements/curves.rb', line 171 def draw_markers(t) xs = @function.x ys = @function.y if @style.marker t.line_type = [[], 0] # Always solid for striking markers t.stroke_transparency = @style.marker_transparency || 0 t.fill_transparency = @style.marker_transparency || 0 t.show_marker('Xs' => xs, 'Ys' => ys, 'marker' => @style.marker, 'scale' => @style.marker_scale, 'color' => @style.marker_color) end end |
#draw_path(t) ⇒ Object
Draw the path
157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/CTioga/elements/curves.rb', line 157 def draw_path(t) t.line_width = @style.linewidth if @style.linewidth if @style.color && @style.line_style t.line_type = @style.line_style t.stroke_transparency = @style.transparency || 0 t.stroke_color = @style.color if @line_cap t.line_cap = @line_cap end make_path(t) t.stroke end end |
#get_boundaries ⇒ Object
This function returns the bouding box of the specified graphes No margin adjustment is done here, as it can lead to very uneven graphs
110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/CTioga/elements/curves.rb', line 110 def get_boundaries top = @function.y.max bottom = @function.y.min left = @function.x.min right = @function.x.max width = (left == right) ? 1 : right - left height = (top == bottom) ? 1 : top - bottom return [left,right,top,bottom] end |
#has_legend? ⇒ Boolean
52 53 54 55 56 57 58 |
# File 'lib/CTioga/elements/curves.rb', line 52 def has_legend? if @style.legend return true else return false end end |
#make_path(t) ⇒ Object
Creates a path for the given curve. This should be defined with care, as it will be used for instance for region coloring and stroking. The function should only append to the current path, not attempt to create a new path or empty what was done before.
143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/CTioga/elements/curves.rb', line 143 def make_path(t) bnds = Utils::Boundaries.new(parent.effective_bounds) if @style.interpolate for f in @function.split_monotonic new_f = f.bound_values(*bnds.real_bounds) t.append_interpolant_to_path(f.make_interpolant) end else f = @function.bound_values(*bnds.real_bounds) t.append_points_to_path(f.x, f.y) end end |
#need_style? ⇒ Boolean
37 38 39 |
# File 'lib/CTioga/elements/curves.rb', line 37 def need_style? return true end |
#parse_position(spec) ⇒ Object
This function returns the index of a point from the curve according to the given spec, a string.
-
if spec is a number >= 1, it represents the index of the point in the Function object.
-
if spec is a number <1, it represents the relative position of the point in the object (it is then multiplied by the size to get the actual index).
-
if spec is of the form ‘x,y’, the closest point belonging to the function is taken. Not implemented yet.
74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/CTioga/elements/curves.rb', line 74 def parse_position(spec) if spec =~ /(.+),(.+)/ raise "The (x,y) point position is not implemented yet" else val = Float(spec) if val < 1 index = (@function.size * val).round else index = val.round end index end end |
#plot(t = nil) ⇒ Object Also known as: do
241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/CTioga/elements/curves.rb', line 241 def plot(t = nil) debug "Plotting curve #{inspect}" t.context do # The fill is always first draw_fill(t) for op in CurveStyle::DrawingOrder[@style[:drawing_order]] self.send("draw_#{op}".to_sym, t) end end end |
#set_data(ar) ⇒ Object
Sets the data for the curve
61 62 63 |
# File 'lib/CTioga/elements/curves.rb', line 61 def set_data(ar) @function = ar end |
#set_style(style) ⇒ Object
41 42 43 |
# File 'lib/CTioga/elements/curves.rb', line 41 def set_style(style) @style = style.dup end |
#tangent(index, dir = :both) ⇒ Object
Returns the tangent of the curve at the given point, that is a vector parallel to it. dir specifies if it is a left tangent or a right tangent or an average of both. Nothing else than the latter is implemented for now.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/CTioga/elements/curves.rb', line 92 def tangent(index, dir = :both) before = @function.point(index - 1) point = @function.point(index) after = @function.point(index + 1) raise "Point invalid" unless point tangent = Dvector[0,0] if index > 0 tangent += (point - before) end if index < (@function.size - 1) tangent += (after - point) end return tangent end |
#y_value(spec) ⇒ Object
Returns a y value suitable for fills/histograms or other kinds of stuff based on a specification:
-
false/nil: returns nil
-
to_y_axis: y = 0
-
to_bottom: the bottom of the plot
-
to_top: the top of the plot
-
“y = .…”: the given value.
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/CTioga/elements/curves.rb', line 193 def y_value(spec) case spec when false, nil, :old_style return false when Float # If that is already a Float, fine ! return spec when :to_y_axis return 0.0 when :to_bottom return parent.effective_bounds[3] # bottom when :to_top return parent.effective_bounds[2] # top when /y\s*=\s*(.*)/ return Float($1) else warn "Y value #{spec} not understood" return false # We don't have anything to do, then. end end |