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.

relations.svg

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.svg

// 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.svg

// 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.svg

// 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.svg

// 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.svg

// 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.svg

// 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.svg

// 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.

relations-ext.svg

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+)

isSubset.svg

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+)

isSuperset.svg

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+)

isDisjoint.svg

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-)

isAdjacent.svg

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+)

intersects.svg

Interval.empty[Int].intersects(Interval.empty[Int])     // 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)

merges.svg

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+))

isLess.svg

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+))

isGreater.svg

Interval.closed(5, 10).isGreater(Interval.closed(1, 5)) // true