indexing description: "[ Objects that describe an interval bounded by a minimum and a maximum value. ]" author: "" date: "$Date$" revision: "$Revision$" class EM_INTERVAL_REF inherit EM_ALIGNMENT_CONSTANTS create make_from_reference, make_from_tuple, make_from_min_max, make, default_create convert make_from_tuple ({TUPLE [DOUBLE, DOUBLE]}) feature -- Initialization make_from_reference (ref: EM_INTERVAL_REF) is -- Make from reference do make_from_min_max (ref.min, ref.max) end make_from_tuple (t: TUPLE [DOUBLE, DOUBLE]) is -- Make from tuple containing boundary points do make (t.double_item (1), t.double_item (2)) end make_from_min_max (vmin: like min; vmax: like max) -- Set `min' / `max' to `vmin' / `vmax' directly require constraint: vmin <= vmax do min := vmin max := vmax ensure set: min = vmin and max = vmax end make (v1, v2: like min) -- Set boundaries to `v1' and `v2' do if v1 < v2 then make_from_min_max (v1, v2) else make_from_min_max (v2, v1) end end feature -- Access min: DOUBLE -- Lower boundary of interval max: like min -- Upper boundary of interval feature -- Measurement size: like min is -- Size of interval do Result := max - min ensure -- definition: Result = max - min end center: like min is -- Midpoint between `min' and `max' do Result := (max + min) / 2 ensure -- definition: Result = (max + min) / 2 end feature -- Element Change set_min (value: like min) is -- Set `min' to `value' require constraint: value <= max do min := value ensure set: min = value end set_max (value: like max) is -- Set `max' to `value', must be greater than `min' require constraint: value >= min do max := value ensure set: max = value end feature -- Basic queries contains_value (value: like min): BOOLEAN is -- Is `value' contained within current interval? do Result := min <= value and value <= max ensure end fully_contains_interval (other: like Current): BOOLEAN is -- Is `other' interval fully contained within current interval? do Result := contains_value (other.min) and contains_value (other.max) ensure end intersects_interval, partially_contains_interval (other: like Current): BOOLEAN is -- Does `other' interval intersect with current? do Result := not (other.max < min or max < other.min) ensure end feature -- Basic operations align_value (value: like min; alignment: EM_ALIGNMENT): like min is -- Aligned `value' with `other' interval according to alignment do inspect alignment.value when Align_lower then Result := min when Align_center then Result := center when Align_upper then Result := max when Align_user_specified then Result := value else check false end end end clamp_value (value: like min): like min is -- Return element of interval with shortest distance to `value' do Result := max.min( min.max(value) ) ensure contains_result: contains_value (Result) end feature -- Transformation accommodate_value (value: like min) is -- Expand current interval by as much as needed to accomodate -- `value'. No shrinking is allowed do min := min.min (value) max := max.max (value) ensure no_shrinking: size >= old size containment: contains_value (value) tight_fit: (value < old min implies min = value) and (value > old max implies max = value) and (value >= old min implies min = old min) and (value <= old max implies max = old max) end accommodate_interval (other: like Current) is -- Expand current interval by as much as needed to accomodate -- `other' interval. No shrinking is allowed do accommodate_value (other.min) accommodate_value (other.max) ensure no_shrinking: size >= old size containment: fully_contains_interval (other) end align_with (other: like Current; alignment: EM_ALIGNMENT) is -- Align current interval with `other' interval according to -- `alignment' local omin, omax, omid, csize: DOUBLE do omin := other.min omax := other.max omid := other.center csize := size inspect alignment.value when Align_lower then make (omin, omin + csize) when Align_center then make (omid - csize / 2, omid + csize / 2) when Align_upper then make (omax - csize, omax) when Align_user_specified then -- Do not change anything else check false end end ensure -- same_size: size = old size end align_with_value (value: like min; alignment: EM_ALIGNMENT) is -- Align current interval with `value' according to `alignment' local point_interval: EM_INTERVAL do point_interval.set (value, value) align_with (point_interval, alignment) end clamp_with (other: like Current) is -- Clamp boundaries of current interval to fit within `other' -- interval. May result in empty interval with size = 0 if -- `current' lies completely outside `other' interval. do make_from_min_max ( other.clamp_value (min), other.clamp_value (max) ) ensure no_growing: old size >= size containment: other.fully_contains_interval (Current) -- zero_product: not (old Current).intersects_interval (other) implies size = 0 end resize (new_size: like size) is -- Set `size' to absolute value of `new_size' do make_from_min_max (min, min + new_size) ensure -- set_to_absolute: size = new_size.abs end pad (a_padding: like size) is -- Add `a_padding' to both sides of interval by adjusting -- both `min' and `max' such that `size' will always be positive do make (min - a_padding, max + a_padding) ensure -- padded: size = (old size + a_padding).abs end aligned_resize (new_size: like size; alignment: EM_ALIGNMENT) is -- Resize current interval to `new_size', and align result with -- old boundaries according to `alignment'. -- If `alignment'.is_user_specified, this operation is equal -- to a normal resize local old_self: EM_INTERVAL_REF do old_self := Current.twin resize (new_size) align_with (old_self, alignment) end translate (distance: like min) -- Translate current interval by `distance' do min := min + distance max := max + distance ensure -- same_size: old size = size -- definition: min = old min + distance and max = old max + distance end invariant definition: max >= min end