1
# axes.rb: the style of one axis or edge
2
# copyright (c) 2009 by Vincent Fourmond
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details (in the COPYING file).
14
require 'ctioga2/utils'
17
# This module contains all the classes used by ctioga
20
Version::register_svn_info('$Revision: 202 $', '$Date: 2010-11-30 22:21:17 +0100 (Tue, 30 Nov 2010) $')
26
# The style of an axis or an egde of the plot. Unlike tioga,
27
# ctioga2 does not make any difference.
28
class AxisStyle < BasicStyle
29
include Tioga::FigureConstants
31
# The type of the edge/axis. Any of the Tioga constants:
32
# AXIS_HIDDEN, AXIS_LINE_ONLY, AXIS_WITH_MAJOR_TICKS_ONLY,
33
# AXIS_WITH_TICKS_ONLY,
34
# AXIS_WITH_MAJOR_TICKS_AND_NUMERIC_LABELS, and
35
# AXIS_WITH_TICKS_AND_NUMERIC_LABELS.
36
attr_accessor :decoration
38
# The position of the axis. Can be one of :left, :right, :top,
39
# :bottom, :at_y_origin or :at_x_origin.
40
attr_accessor :location
42
# Offset of the axis with respect to its normal position. It
43
# is counted *away* from the graph. It is either a
44
# Types::Dimension object or _nil_.
47
# The background lines for the given axis. _nil_ for nothing,
48
# or a StrokeStyle object if we want to draw something.
49
attr_accessor :background_lines
51
# The style of the tick labels
52
attr_accessor :tick_label_style
54
# The label of the axis, if there is one
55
attr_accessor :axis_label
57
# Whether the axis should be log scale or not
60
# Transform: a Types::Bijection object specifying a coordinate
61
# transformation for the axis.
62
attr_accessor :transform
64
# The color of the stroke for the lines of the axis
65
attr_accessor :stroke_color
68
# Creates a new AxisStyle object at the given location with
70
def initialize(location = nil, decoration = nil, label = nil)
71
@location = Types::PlotLocation.new(location)
72
@decoration = decoration
74
@tick_label_style = FullTextStyle.new
75
@axis_label = TextLabel.new(label)
79
# Draws the axis within the current plot. Boundaries are the
80
# current plot boundaries. Also draw the #axis_label, if there
84
# * the offset mechanism, to place the axis away from the place
85
# where it should be...
86
# * non-linear axes (or linear, for that matter, but with
89
spec = get_axis_specification(t)
90
# Add tick label style:
91
spec.merge!(@tick_label_style.to_hash)
93
spec['stroke_color'] = @stroke_color
96
@axis_label.loc = @location
97
default = vertical? ? 'ylabel' : 'xlabel'
98
@axis_label.draw(t, default)
101
# Sets the current boundaries of the _t_ object to the _range_
102
# SimpleRange object for the direction handled by the
103
# AxisStyle, without touching the rest.
104
def set_bounds_for_axis(t, range = nil)
108
l,r,top,b = t.bounds_left, t.bounds_right,
109
t.bounds_top, t.bounds_bottom
118
t.set_bounds([l,r,top,b])
121
# Draw the axis background lines:
122
def draw_background_lines(t)
124
# First, getting major ticks location from tioga
125
info = t.axis_information(get_axis_specification(t))
135
@background_lines.set_stroke_style(t)
136
values = info['major_ticks'] || info['major']
139
t.stroke_line(x0, val, x1, val)
141
t.stroke_line(val, y0, val, y1)
148
# Returns the AxisStyle object corresponding to the named axis
149
# in the current plot.
150
def self.current_axis_style(plotmaker, spec)
151
return PlotStyle.current_plot_style(plotmaker).
155
# Returns the part of the #extension only due to the labels
156
# (ticks and standard label).
158
# For now, it returns the same value as #extension, but that
160
def labels_only_extension(t, style = nil)
161
ticks_shift, ticks_scale = *get_ticks_parameters(t)
162
default = vertical? ? 'ylabel' : 'xlabel'
163
le = @axis_label.label_extension(t, default, @location)
166
when AXIS_WITH_MAJOR_TICKS_AND_NUMERIC_LABELS,
167
AXIS_WITH_TICKS_AND_NUMERIC_LABELS
168
te = ticks_shift * ticks_scale
172
return Dobjects::Dvector[le,te].max *
173
(style ? style.text_scale || 1 : 1)
176
# Returns the extension of the axis (including tick labels and
177
# labels if applicable) perpendicular to itself, in units of
178
# text height (at scale = current text scale when drawing
181
# _style_ is a PlotStyle object containing the style
182
# information for the target plot.
184
# \todo handle offset axes when that is implemented.
185
def extension(t, style = nil)
186
return labels_only_extension(t, style)
191
# Whether the axis is vertical or not
193
return @location.vertical?
196
# Returns: _ticks_shift_, _ticks_scale_ for the axis.
198
# \todo try something clever with the angles ?
199
def get_ticks_parameters(t)
200
i = t.axis_information({'location' => @location.tioga_location})
202
retval << (@tick_label_style.shift || i['shift'])
203
retval << (@tick_label_style.scale || i['scale'])
209
# Returns an argument suitable for use for
210
# FigureMaker#show_axis or FigureMaker#axis_information.
212
# For the log axis scale to work, tioga revision 543 is
213
# absolutely necessary. It won't fail, though, without it.
214
def get_axis_specification(t)
216
retval = compute_coordinate_transforms(t)
221
raise YetUnimplemented, "This has not been implemented yet"
224
update({'location' => @location.tioga_location,
225
'type' => @decoration, 'log' => @log})
230
# Setup coordinate transformations
231
def compute_coordinate_transforms(t)
232
return unless @transform
233
# We'll proceed by steps...
234
i = t.axis_information({'location' => @location.tioga_location})
237
top,b = @transform.convert_to([t.bounds_top, t.bounds_bottom])
238
l,r = t.bounds_left, t.bounds_right
240
top,b = t.bounds_top, t.bounds_bottom
241
l,r = @transform.convert_to([t.bounds_left, t.bounds_right])
243
t.set_bounds([l,r,top,b])
244
i = t.axis_information({'location' => @location.tioga_location})
245
# Now, we have the location of everything we need.
247
# In the following, the || are because of a fix in Tioga
249
return { 'labels' => i['labels'],
250
'major_ticks' => @transform.
251
convert_from(i['major_ticks'] || i['major']),
252
'minor_ticks' => @transform.
253
convert_from(i['minor_ticks'] || i['minor'] )
262
'transform' => CmdArg.new('bijection'),
263
'location' => CmdArg.new('location'),
264
'stroke_color' => CmdArg.new('color')
267
FullAxisStyle = PartialAxisStyle.dup
268
FullAxisStyle['decoration'] = CmdArg.new('axis-decoration')