Basic Relations
This library supports relations between points, points and intervals, and between intervals themselves, including Allen's famous interval algebra.
- Point-Point (PP) relations: between two points.
- Point-Interval (PI) relations: between a point and an interval.
- Interval-Interval (II) relations: between two intervals.
In Allen's interval algebra, there are 13 basic relations between time intervals. These relations are distinct, exhaustive, and qualitative:
- Distinct: No pair of definite intervals can be related by more than one relation.
- Exhaustive: Every pair of definite intervals is described by one of the relations.
- Qualitative: No specific time spans are considered.
These 13 basic relations can be grouped into 6 pairs of converse relations and one relation that is its own converse.
For example, a
before b
and b
after a
form a pair of converse relations.
Whenever the first relation is true, the converse relation is also true.
For convenience, each relation has an associated symbol. For instance, b
denotes the relation before, and B
represents its converse relation after.
Note: These relations apply to non-empty intervals.
Before / After
a
before b
means that interval a
ends before interval b
begins, with a gap between them.
The converse relation is b
after a
.
Condition: a+ < b-
// before (b), after (B)
Interval.closed(1, 4).before(Interval.closed(5, 8)) // true
Interval.closed(5, 8).after(Interval.closed(1, 4)) // true
Meets / IsMetBy
a
meets b
means that b
begins exactly where a
ends.
The converse relation is b
is met by a
.
Condition: a+ = b-
// meets (m), isMetBy (M)
Interval.closed(1, 5).meets(Interval.closed(5, 10)) // true
Interval.closed(5, 10).isMetBy(Interval.closed(1, 5)) // true
Overlaps / IsOverlappedBy
a
overlaps b
when the right boundary of interval a
is within interval b
.
The converse relation is b
is overlapped by a
.
Condition: a- < b- < a+ < b+
// overlaps (o), isOverlappedBy (O)
Interval.closed(1, 10).overlaps(Interval.closed(5, 15)) // true
Interval.closed(5, 15).isOverlappedBy(Interval.closed(1, 10)) // true
Starts / IsStartedBy
a
starts b
when both intervals have the same left boundary, but interval a
lies inside b
without being equal to it.
The converse relation is b
is started by a
.
Condition: (a- = b-) AND (a+ < b+)
// starts (s), isStartedBy (S)
Interval.closed(1, 4).starts(Interval.closed(1, 6)) // true
Interval.closed(1, 6).isStartedBy(Interval.closed(1, 4)) // true
During / Contains
a
is during b
when interval a
lies entirely within interval b
.
The converse relation is b
contains a
.
Condition: (a- > b-) AND (a+ < b+)
// during (d), contains (D)
Interval.closed(3, 7).during(Interval.closed(1, 10)) // true
Interval.closed(1, 10).contains(Interval.closed(3, 7)) // true
Finishes / IsFinishedBy
a
finishes b
when both intervals have the same right boundary, but interval a
lies inside b
without being equal to it.
The converse relation is b
is finished by a
.
Condition: (a+ = b+) AND (a- > b-)
// finishes (f), isFinishedBy (F)
Interval.closed(3, 6).finishes(Interval.closed(1, 6)) // true
Interval.closed(1, 6).isFinishedBy(Interval.closed(3, 6)) // true
EqualsTo
a
equals to b
when both intervals share the same left and right boundaries.
It is its own converse.
Condition: (a- = b-) AND (a+ = b+)
// equalsTo (e)
Interval.closed(1, 5).equalsTo(Interval.closed(1, 5)) // true
Extended Relations
For convenience, the library defines extended relations that combine multiple basic relations.
IsSubset
a
is a subset of b
when interval a
is either starts, during, finishes or equals to interval b
.
Condition: (a- >= b-) AND (a+ <= b+)
Interval.closed(4, 7).isSubset(Interval.closed(4, 10)) // true
Interval.closed(4, 7).isSubset(Interval.closed(2, 10)) // true
Interval.closed(4, 7).isSubset(Interval.closed(2, 7)) // true
Interval.closed(4, 7).isSubset(Interval.closed(4, 7)) // true
IsSuperset
a
is a superset of b
when interval a
is started by, contains, is finished by or equals to interval b
.
Condition: (b- >= a-) AND (b+ <= a+)
Interval.closed(4, 10).isSuperset(Interval.closed(4, 7)) // true
Interval.closed(2, 10).isSuperset(Interval.closed(4, 7)) // true
Interval.closed(2, 7).isSuperset(Interval.closed(4, 7)) // true
Interval.closed(4, 7).isSuperset(Interval.closed(4, 7)) // true
IsDisjoint
Intervals a
and b
are disjoint if they do not intersect.
This means that a
is either before or after b
.
Condition: (a+ < b-) OR (a- > b+)
Interval.closed(5, 7).isDisjoint(Interval.closed(1, 3)) // true
Interval.closed(5, 7).isDisjoint(Interval.closed(8, 10)) // true
IsAdjacent
Intervals a
and b
are adjacent if they are disjoint and the successor of the right boundary of a
equals the left boundary of b
, or vice versa.
Condition: (succ(a+) = b-) OR (succ(b+) = a-)
Interval.closed(5, 7).isAdjacent(Interval.closed(8, 10)) // true
Interval.closed(1, 4).isAdjacent(Interval.closed(5, 7)) // true
Intersects
Intervals a
and b
intersect if neither is before nor after the other.
If any of the other 11 basic relations holds, the intervals intersect.
Condition: (a- <= b+) AND (b- <= a+)
Interval.empty.intersects(Interval.empty) // false
Interval.point(5).intersects(Interval.point(5)) // true
Interval.closed(0, 5).intersects(Interval.closed(1, 6)) // true
Merges
Two intervals a
and b
can be merged if they are either adjacent or intersect.
Condition: intersects(a, b) OR isAdjacent(a, b)
Interval.point(5).merges(Interval.point(6)) // true
Interval.closed(4, 10).merges(Interval.closed(5, 12)) // true
IsLess
Interval a
is less than b
when the left boundary of a
is less than that of b
, or if their left boundaries are equal, the right boundary of a
must be less than that of b
.
Condition: (a- < b-) OR ((a- == b-) AND (a+ < b+))
Interval.closed(1, 5).isLess(Interval.closed(5, 10)) // true
IsGreater
Interval a
is greater than b
when the relation b.isLess(a)
is true.
Condition: (a- > b-) OR ((a- == b-) AND (a+ > b+))
Interval.closed(5, 10).isGreater(Interval.closed(1, 5)) // true