Class: Sevgi::Sundries::Ruler

Inherits:
Interval
  • Object
show all
Defined in:
lib/sevgi/sundries/ruler.rb

Overview

Fits a repeated interval into a broader span with computed margins.

A ruler stores both the fitted major interval and the source subinterval. brut is the full available span. unit * multiple becomes the major interval, and sd/su/sn describe that source subinterval. Requested margins are minimums: leftover space is split between them while their start/end difference is preserved. The fitted d excludes those margins; waste includes them and any remainder.

Examples:

Ruler geometry

ruler = Sevgi::Sundries::Ruler.new(unit: 1, multiple: 10, brut: 150)
ruler.su # => 1.0
ruler.sn # => 10
ruler.u  # => 10.0
ruler.n  # => 15
ruler.d  # => 150.0

Fit whole major intervals inside minimum margins

ruler = Sevgi::Sundries::Ruler.new(brut: 103, unit: 1, multiple: 10, margins: [5])
ruler.n       # => 9
ruler.margins # => [6.5, 6.5]
ruler.waste   # => 13.0

Preserve an asymmetric margin difference

ruler = Sevgi::Sundries::Ruler.new(brut: 100, unit: 1, multiple: 10, margins: [5, 15])
ruler.margins # => [5.0, 15.0]
ruler.ds.last # => 80.0

See Also:

Direct Known Subclasses

Grid::Axis, RulerEven

Instance Attribute Summary collapse

Attributes inherited from Interval

#n, #u

Instance Method Summary collapse

Methods inherited from Interval

[], #[], #count, #d, #ds, #h, #hs, #nds, #nhs

Constructor Details

#initialize(brut:, unit:, multiple:, margins: [0.0]) ⇒ void

Creates a ruler fitted into the given span.

Parameters:

  • brut (Numeric)

    full available span

  • unit (Numeric)

    subinterval unit length

  • multiple (Integer)

    number of subinterval units per major interval

  • margins (Array<Numeric>) (defaults to: [0.0])

    one symmetric or two start/end minimum margins

Raises:

  • (Sevgi::ArgumentError)

    when brut is not numeric

  • (Sevgi::ArgumentError)

    when brut is not finite

  • (Sevgi::ArgumentError)

    when brut is negative

  • (Sevgi::ArgumentError)

    when unit is not numeric

  • (Sevgi::ArgumentError)

    when unit is not finite

  • (Sevgi::ArgumentError)

    when unit is not positive

  • (Sevgi::ArgumentError)

    when multiple is not a positive integer

  • (Sevgi::ArgumentError)

    when margins does not contain one or two values

  • (Sevgi::ArgumentError)

    when a margin is not numeric

  • (Sevgi::ArgumentError)

    when a margin is not finite

  • (Sevgi::ArgumentError)

    when a margin is negative

  • (Sevgi::ArgumentError)

    when the fitting span is negative



215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/sevgi/sundries/ruler.rb', line 215

def initialize(brut:, unit:, multiple:, margins: [0.0])
  @brut = non_negative_number(brut, "Ruler brut")
  unit = positive_number(unit, "Ruler unit")
  multiple = positive_integer(multiple, "Ruler multiple")
  @sub = Interval.new(unit, multiple)
  span, start, finish = fitting_span(margins)

  n = divide(unit:, multiple:, span:)

  super(@sub, n)
  @start, @finish = fitted_margins(start, finish, span)
end

Instance Attribute Details

#brutFloat (readonly)

Returns the full available span before fitting.

Returns:

  • (Float)


183
184
185
# File 'lib/sevgi/sundries/ruler.rb', line 183

def brut
  @brut
end

#finishFloat (readonly)

Returns the fitted margin after the interval.

Returns:

  • (Float)


187
188
189
# File 'lib/sevgi/sundries/ruler.rb', line 187

def finish
  @finish
end

#startFloat (readonly)

Returns the fitted margin before the interval.

Returns:

  • (Float)


191
192
193
# File 'lib/sevgi/sundries/ruler.rb', line 191

def start
  @start
end

#subSevgi::Sundries::Interval (readonly)

Returns the source subinterval.



195
196
197
# File 'lib/sevgi/sundries/ruler.rb', line 195

def sub
  @sub
end

Instance Method Details

#expandSevgi::Sundries::Ruler

Returns a ruler where the source subinterval is flattened into units.

Examples:

Expand major intervals into individual units

ruler = Sevgi::Sundries::Ruler.new(brut: 103, unit: 1, multiple: 10, margins: [5])
ruler.expand.n # => 90
ruler.ms.size  # => 91

Returns:



234
# File 'lib/sevgi/sundries/ruler.rb', line 234

def expand = self.class.new(unit: sub.u, multiple: 1, brut: d + waste, margins:)

#marginsArray<Float>

Returns fitted start and finish margins.

Returns:

  • (Array<Float>)

    frozen margin pair



238
# File 'lib/sevgi/sundries/ruler.rb', line 238

def margins = @margins ||= [start, finish].freeze

#msArray<Float>

Returns minor tick distances across the fitted span. The memoized collection is frozen and must be treated as immutable.

Returns:

  • (Array<Float>)

    frozen minor tick distances



243
# File 'lib/sevgi/sundries/ruler.rb', line 243

def ms = @ms ||= expand.ds

#sdFloat

Returns the source subinterval distance.

Returns:

  • (Float)


255
# File 'lib/sevgi/sundries/ruler.rb', line 255

def sd = @sub.d

#snInteger

Returns the source subinterval count.

Returns:

  • (Integer)


251
# File 'lib/sevgi/sundries/ruler.rb', line 251

def sn = @sub.n

#suFloat

Returns the source subinterval unit length.

Returns:

  • (Float)


259
# File 'lib/sevgi/sundries/ruler.rb', line 259

def su = @sub.u

#wasteFloat

Returns the unfitted distance distributed outside the fitted span.

Returns:

  • (Float)


247
# File 'lib/sevgi/sundries/ruler.rb', line 247

def waste = @waste ||= brut - d