Class: CTioga2::Graphics::Types::Dimension

Inherits:
Object
  • Object
show all
Includes:
Tioga::Utils
Defined in:
lib/ctioga2/graphics/types/dimensions.rb

Overview

A Dimension is an object that represents a dimension in the different ways understood by Tioga:

  • an “absolute” dimension, ie, in real units (postscript points)

  • a “text” dimension, in units of the height of the current text object

  • a frame/page/figure dimension, in units of the current frame/page/figure coordinates

Direct Known Subclasses

BaseCoordinate

Constant Summary collapse

DimensionConversion =

Dimension conversion constants taken straight from the TeXbook

{
  "pt" => (72.0/72.27),
  "bp" => 1.0,
  "in" => 72.0,
  "cm" => (72.0/2.54),
  "mm" => (72.0/25.4),
}
DimensionRegexp =

A regular expression that matches all dimensions.

/^\s*([+-]?\s*[\d.eE+-]+)\s*([a-zA-Z]+)?\s*$/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type, value, orientation = :x) ⇒ Dimension

Creates a Dimension object of the given type, the given value oriented along the given orientation



52
53
54
55
56
57
58
59
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 52

def initialize(type, value, orientation = :x)
  @type = type
  if not @type.is_a? Symbol
    raise "Invalid value for the dimension type: '#{@type}'"
  end
  @value = value
  @orientation = orientation
end

Instance Attribute Details

#orientationObject

The orientation of the dimension: vertical (:y) or horizontal (:x) ?



44
45
46
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 44

def orientation
  @orientation
end

#typeObject

What is the underlying representation of the dimension ?

  • :bp in postscript points

  • :dy in text height units

  • :frame in frame coordinates

  • :page in page coordinates

  • :figure in figure coordinates



40
41
42
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 40

def type
  @type
end

#valueObject

The actual dimension. The interpretation depends on the value of #type.



48
49
50
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 48

def value
  @value
end

Class Method Details

.adjust_line(t, x1, y1, x2, y2, left, right) ⇒ Object

Adjusts the given line by adding the dimensions on the left and on the right (can be negative).

Returns the new [x1, y1, x2, y2]



95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 95

def self.adjust_line(t, x1, y1, x2, y2, left, right)
  dx = x2 - x1
  dy = y2 - y1
  dst = get_distance(t, x2-x1, y2-y1).to_bp(t)
  lf = left.to_bp(t)/dst
  rf = right.to_bp(t)/dst

  x1 -= lf * dx
  y1 -= lf * dy
  x2 += rf * dx
  y2 += rf * dy
  return [x1, y1, x2, y2]
end

.from_text(text, orientation, default = :figure) ⇒ Object

Creates a Dimension object from a text specification. The text should be in the forms

value unit

where unit is one of bp, pt, in, mm, cm, dy (the latter being one unit of height) f|figure, F|Frame|frame, p|page. It can be ommitted, in which case it defaults to the default parameter.



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 215

def self.from_text(text, orientation, default = :figure)
  # Absolute or :dy dimension

  if text =~ /^\s*auto\s*$/i
    Dimension.new(:frame, 1.0, orientation)
  elsif text =~ DimensionRegexp
    value = Utils::txt_to_float($1)
    unit = $2
    if ! unit
      unit = default
    elsif DimensionConversion.key?(unit.downcase)
      value *= DimensionConversion[unit.downcase]
      unit = :bp
    else
      case unit
      when /^dy$/i
        unit = :dy
      when /^F|(?i:frame)$/
        unit = :frame
      when /^f|(?i:figure)$/
        unit = :figure
      when /^p|(?i:page)$/
        unit = :page
      else
        raise "Unkown dimension unit: #{unit}"
      end
    end
    return Dimension.new(unit, value, orientation)
  else
    raise "Unknown Dimension specification: '#{text}'"
  end
end

.get_angle(t, dx, dy) ⇒ Object

Gets the angle along the given direction



70
71
72
73
74
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 70

def self.get_angle(t, dx, dy)
  dx = make_dimension(dx, :x).to_bp(t)
  dy = make_dimension(dy, :y).to_bp(t)
  return 180 * Math::atan2(dy, dx)/Math::PI
end

.get_distance(t, dx, dy) ⇒ Object

Returns a dimension corresponding to the distance.



85
86
87
88
89
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 85

def self.get_distance(t, dx, dy)
  dx = make_dimension(dx, :x).to_bp(t)
  dy = make_dimension(dy, :y).to_bp(t)
  return Dimension.new(:bp, (dx**2 + dy**2)**0.5)
end

.make_dimension(val, orient = :x, default = :figure) ⇒ Object



61
62
63
64
65
66
67
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 61

def self.make_dimension(val, orient = :x, default = :figure)
  if val.is_a? Dimension
    return val
  else
    return Dimension.new(default, val, orient)
  end
end

Instance Method Details

#*(fct) ⇒ Object



80
81
82
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 80

def *(fct)
  return Dimension.new(@type, @value*fct, @orientation)
end

#-@Object



76
77
78
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 76

def -@
  return Dimension.new(@type, -@value, @orientation)
end

#copy_from(dm, orient = false) ⇒ Object

Copy from another dimension, omitting the orientation



254
255
256
257
258
259
260
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 254

def copy_from(dm, orient = false)
  @type = dm.type
  @value = dm.value
  if orient
    @orientation = dm.orientation
  end
end

#replace_if_bigger(t, dimension) ⇒ Object

Replace this Dimension by dimension if the latter is bigger. Conserves the current orientation.



185
186
187
188
189
190
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 185

def replace_if_bigger(t, dimension)
  if self.to_figure(t) < dimension.to_figure(t, @orientation)
    @type = dimension.type
    @value = dimension.value
  end
end

#set_from_text(str, default = :figure) ⇒ Object



248
249
250
251
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 248

def set_from_text(str, default = :figure)
  dm  = Dimension.from_text(str, self.orientation, default)
  copy_from(dm)
end

#to_bp(t, orientation = nil) ⇒ Object

Converts the dimension into big points



162
163
164
165
166
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 162

def to_bp(t, orientation = nil)
  orientation ||= @orientation
  return t.send("convert_figure_to_output_d#{orientation}", 
                to_figure(t, orientation)) / t.scaling_factor
end

#to_dy(t) ⇒ Object

Return the value of the dimension in units of text height



156
157
158
159
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 156

def to_dy(t)
  fig = to_figure(t, :y)
  return fig/t.default_text_height_dy
end

#to_figure(t, orientation = nil) ⇒ Object

Converts the Dimension to the figure coordinates of the current figure in t.

An extension of this function allows one to provide an ANGLE instead of :x or :y for the orientation, in which case the return value is a [dx, dy] array. In that case, the dimension is first converted into a physical dimension in the axis closest to the orientation and then one proceeds.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 118

def to_figure(t, orientation = nil)
  orientation ||= @orientation

  if ! orientation.is_a? Symbol
    angle = orientation.to_f * Math::PI/180.0
    dim = self
    if @type != :bp
      # Must first convert to physical dimension
      closest_orient = if Math::sin(angle)**2 > 0.5
                         :y
                       else
                         :x
                       end
      vl = dim.to_bp(t, closest_orient)
      dim = Dimension.new(:bp, vl)
    end
    dx = dim.to_figure(t, :x) * Math::cos(angle)
    dy = dim.to_figure(t, :y) * Math::sin(angle)
    return [dx, dy]
  end
  
  case @type
  when :bp
    return t.send("convert_output_to_figure_d#{orientation}", @value) * t.scaling_factor
  when :dy
    return t.send("default_text_height_d#{orientation}") * @value
  when :frame
    return t.send("convert_frame_to_figure_d#{orientation}", @value)
  when :page
    return t.send("convert_page_to_figure_d#{orientation}", @value)
  when :figure
    return @value
  else
    raise "Invalid type for Dimension: #{@type}"
  end
end

#to_frame(t, orientation = nil) ⇒ Object

Converts the Dimension to the frame coordinates of the current frame in t.



170
171
172
173
174
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 170

def to_frame(t, orientation = nil)
  orientation ||= @orientation
  return t.send("convert_figure_to_frame_d#{orientation}", 
                to_figure(t, orientation))
end

#to_text_height(t, orientation = nil) ⇒ Object

Express the Dimension in units of text height (dy)



177
178
179
180
181
# File 'lib/ctioga2/graphics/types/dimensions.rb', line 177

def to_text_height(t, orientation = nil)
  orientation ||= @orientation
  return self.to_figure(t, orientation)/
    t.send("default_text_height_d#{orientation}")
end