Class: UOM::CompositeUnit

Inherits:
Unit
  • Object
show all
Defined in:
lib/uom/composite_unit.rb

Overview

A CompositeUnit represents a measurement unit across more than one dimension, e.g. :gram_per_liter.

Constant Summary collapse

SUPPORTED_OPERATORS =
[:/, :*]

Instance Attribute Summary collapse

Attributes inherited from Unit

#abbreviations, #axis, #dimension, #label, #permissible_factors, #scalar

Instance Method Summary collapse

Methods inherited from Unit

#*, #/, #add_abbreviation, #add_converter, #basic?, #basis

Constructor Details

#initialize(u1, u2, operator, *params) ⇒ CompositeUnit

Creates a CompositeUnit from the given units u1 and u2 and operator symbol :/ or :*. Each unit can be either a Unit or another CompositeUnit. The remaining parameters are described in Unit.

The CompositeUnit label is inferred from the operator constituent units, e.g.:

CompositeUnit.new(Unit.for(:gram), Unit.for(:liter), :/) #=> grams_per_liter

Raises:



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/uom/composite_unit.rb', line 31

def initialize(u1, u2, operator, *params)
  @axes = [u1, u2]
  @operator = operator
  raise MeasurementError.new("Unit composition operator unsupported - expected #{SUPPORTED_OPERATORS.join(' or ')}, found #{operator}") unless SUPPORTED_OPERATORS.include?(operator)
  # make the composite dimension parameter
  dims = @axes.map { |axis| axis.dimension }
  # Add the first axis and the dimension to the parameters. The first axis is designated
  # the axis in Unit; the second axis is a qualifier.
  params << CompositeDimension.for([dims, @operator])
  # call the Unit initializer with the parameters except for the axes
  super(*params)
  # add to the extent
  CompositeUnit << self
end

Instance Attribute Details

#axesObject (readonly)

Returns the value of attribute axes.



23
24
25
# File 'lib/uom/composite_unit.rb', line 23

def axes
  @axes
end

#operatorObject (readonly)

Returns the value of attribute operator.



23
24
25
# File 'lib/uom/composite_unit.rb', line 23

def operator
  @operator
end

Instance Method Details

#as(quantity, unit) ⇒ Object

Returns the the given quantity converted from this Unit into the given unit.

Raises:



47
48
49
50
51
52
53
54
55
56
57
# File 'lib/uom/composite_unit.rb', line 47

def as(quantity, unit)
  # if unit wraps a composite unit axis, then convert unit => axis => self and invert
  return 1.0 / unit.as(1.0 / quantity, self) unless CompositeUnit === unit
  raise MeasurementError.new("No conversion from #{self} to #{unit}") unless unit.axes.size == axes.size and unit.operator == operator
  # convert the the first axis quantity to the first unit axis
  first = axes[0].as(quantity, unit.axes[0])
  # convert the remaining units
  vector = REXML::SyncEnumerator.new(axes[1..-1], unit.axes[1..-1]).map { |from, to| from.as(1, to).to_f }
  # apply the operator
  vector.inject(first) { |q, item| q.send(@operator, item) }
end

#composition_to_sObject

Returns a string representation of this CompositeUnit’s composition, e.g.

((UOM::METER * UOM::SECOND) / UOM::GRAM).composition_to_s #=> (meter * second) / gram


69
70
71
# File 'lib/uom/composite_unit.rb', line 69

def composition_to_s
  axes.map { |axis| CompositeUnit === axis ? "(#{axis.composition_to_s})" : axis.label.to_s }.join(" #{operator} ")
end

#inspectObject



63
64
65
# File 'lib/uom/composite_unit.rb', line 63

def inspect
  "#{self.class.name}@#{self.object_id}[#{([label] + abbreviations).join(', ')}: #{composition_to_s}]"
end

#to_s(quantity = nil) ⇒ Object



59
60
61
# File 'lib/uom/composite_unit.rb', line 59

def to_s(quantity=nil)
  @operator == :* ? super : [axes.first.to_s(quantity)].concat(axes[1..-1]).join('_per_')
end