* Integer_Geometry: Unlimited intervals
This commit is contained in:
parent
ddfc137cf5
commit
a5dc433e07
|
@ -53,10 +53,16 @@ package Video.Integer_Geometry with Pure is
|
|||
-- Scale down a vector by D
|
||||
--
|
||||
|
||||
--
|
||||
-- An Interval
|
||||
--
|
||||
|
||||
type Interval is record
|
||||
First, Last : Coordinate;
|
||||
end record;
|
||||
-- A type like an Ada range (but a type)
|
||||
-- Values Coordinate'First at First and Coordinate'Last at Last
|
||||
-- are treated specially as 'no limit'
|
||||
|
||||
function Empty_Interval return Interval is (Coordinate'Last, Coordinate'First);
|
||||
-- Interval with nothing in
|
||||
|
@ -66,10 +72,16 @@ package Video.Integer_Geometry with Pure is
|
|||
-- Note: many operations on Full_Interval could cause overflow
|
||||
|
||||
-- Note that transformations can cause overflow when applied to
|
||||
-- Empty and Full intervals. User code should detect that corner cases.
|
||||
-- Empty and Full intervals. Library should treat these corner cases correctly.
|
||||
|
||||
function Is_Empty (A : Interval) return Boolean is (A.First >= A.Last);
|
||||
-- Test is interval have nothing in
|
||||
-- Test if interval have nothing in
|
||||
|
||||
function Is_Negative_Unlimited (A : Interval) return Boolean is (A.First <= Coordinate'First);
|
||||
-- Test if there's no lower limit
|
||||
|
||||
function Is_Positive_Unlimited (A : Interval) return Boolean is (A.Last >= Coordinate'Last);
|
||||
-- Test if there's no upper limit
|
||||
|
||||
subtype Nonempty_Interval is Interval with Dynamic_Predicate => not Is_Empty (Nonempty_Interval);
|
||||
-- A type for an interval that is not empty
|
||||
|
@ -90,29 +102,42 @@ package Video.Integer_Geometry with Pure is
|
|||
-- Identity function
|
||||
|
||||
function "-" (A : Interval) return Interval
|
||||
is (if Is_Empty (A) then Empty_Interval else (-A.Last, -A.First));
|
||||
is (if Is_Empty (A) then Empty_Interval else (
|
||||
(if A.Last >= Coordinate'Last then Coordinate'First else -A.Last),
|
||||
(if A.First <= Coordinate'First then Coordinate'First else -A.First)));
|
||||
-- Negate inverval by flipping it over zero
|
||||
|
||||
function "+" (A : Interval; B : Coordinate) return Interval
|
||||
is (if Is_Empty (A) then Empty_Interval else (A.First + B, A.Last + B));
|
||||
is (if Is_Empty (A) then Empty_Interval else (
|
||||
(if A.First <= Coordinate'First then A.First else A.First + B),
|
||||
(if A.Last >= Coordinate'Last then A.Last else A.Last + B)));
|
||||
-- Translate interval
|
||||
|
||||
function "+" (A : Coordinate; B : Interval) return Interval
|
||||
is (if Is_Empty (B) then Empty_Interval else (A + B.First, A + B.Last));
|
||||
is (if Is_Empty (B) then Empty_Interval else (
|
||||
(if B.First <= Coordinate'First then B.First else A + B.First),
|
||||
(if B.Last >= Coordinate'Last then B.Last else A + B.Last)));
|
||||
-- Translate interval (other form)
|
||||
|
||||
function "+" (A, B : Interval) return Interval
|
||||
is (if Is_Empty (A) or else Is_Empty (B) then Empty_Interval else (A.First + B.First, A.Last + B.Last));
|
||||
is (if Is_Empty (A) or else Is_Empty (B) then Empty_Interval else (
|
||||
(if A.First <= Coordinate'First or B.First <= Coordinate'First then
|
||||
Coordinate'First else A.First + B.First),
|
||||
(if A.Last >= Coordinate'Last or B.Last >= Coordinate'Last then
|
||||
Coordinate'Last else A.Last + B.Last)));
|
||||
-- Minkowski sum
|
||||
-- The area sweeped by one interval when offset by values in other interval.
|
||||
|
||||
function "-" (A : Interval; B : Coordinate) return Interval
|
||||
is (if Is_Empty (A) then Empty_Interval else (A.First - B, A.Last - B));
|
||||
-- Translate interval
|
||||
|
||||
function "-" (A : Interval; B : Nonempty_Interval) return Interval
|
||||
is (if Is_Empty (A) then Empty_Interval else (A.First - B.First, A.Last - B.Last));
|
||||
is (if Is_Empty (A) then Empty_Interval else (
|
||||
(if A.First <= Coordinate'First then A.First else A.First - B.First),
|
||||
(if A.Last >= Coordinate'Last then A.Last else A.Last - B.Last)));
|
||||
-- Minkowski difference
|
||||
-- That is the result (if not empty) is the argument to minkowski sum with B to get A
|
||||
-- That is the result (if not empty) is the argument to minkowski sum with B to get A.
|
||||
-- Note: Minkowski difference is not the same as sum with negated interval
|
||||
|
||||
function "and" (A, B : Interval) return Interval
|
||||
|
@ -127,11 +152,14 @@ package Video.Integer_Geometry with Pure is
|
|||
|
||||
function Center (A : Nonempty_Interval) return Coordinate
|
||||
is (A.First / 2 + A.Last / 2 + (A.First rem 2 + A.Last rem 2) / 2);
|
||||
-- Central point (equidistant to both limits)
|
||||
|
||||
function Center (A, B : Nonempty_Interval) return Coordinate
|
||||
is ((B.First + B.Last - A.First - A.Last) / 2);
|
||||
-- Offset to translate interval A to match center of interval B
|
||||
|
||||
--
|
||||
-- Box
|
||||
--
|
||||
|
||||
type Box is record
|
||||
|
@ -196,11 +224,11 @@ package Video.Integer_Geometry with Pure is
|
|||
-- Note: Minkowski difference is not the same as sum with negated box
|
||||
|
||||
function "and" (A, B : Box) return Box
|
||||
is (A.X and B.X, A.Y and B.Y);
|
||||
is (X => A.X and B.X, Y => A.Y and B.Y);
|
||||
-- Intersection (like in sets)
|
||||
|
||||
function "or" (A, B : Box) return Box
|
||||
is (A.X or B.X, A.Y or B.Y);
|
||||
is (X => A.X or B.X, Y => A.Y or B.Y);
|
||||
-- Minimal box enclosing both arguments
|
||||
-- Note: contrary to "and" it is not an set union
|
||||
|
||||
|
@ -208,6 +236,6 @@ package Video.Integer_Geometry with Pure is
|
|||
is (X => Center (P.X), Y => Center (P.Y));
|
||||
|
||||
function Center (A, B : Nonempty_Box) return Point
|
||||
is (Center (A.X, B.X), Center (A.Y, B.Y));
|
||||
is (X => Center (A.X, B.X), Y => Center (A.Y, B.Y));
|
||||
|
||||
end Video.Integer_Geometry;
|
||||
|
|
Loading…
Reference in New Issue