Basic Relations

The library supports relations between points, points and intervals & relations between intervals (famous Allen's interval algebra).

  • Point-Point (PP) relations between a pair of points.
  • Point-Interval (PI) relations that between a point and an interval.
  • Interval-Interval (II) relations that between a pair of intervals.

In Allen's interval algebra there are 13 basic relations between time intervals; these relations are distinct, exhaustive, and qualitative:

  • Distinct because no pair of definite intervals can be related by more than one of the relationships.
  • Exhaustive because any pair of definite intervals are described by one of the relations.
  • Qualitative because no specific time spans are considered.

13 basic relations can be split in 6 pairs of converse relations and one relation that converse to itself. For example a before b and b after a is a pair of converse relations. Whenever the first relation is true, the converse relation is true as well.

For convenience, each relation has an associated symbol with it, e.g. b for the relation before. The converse relation is represented by the same symbol, but in the upper case, e.g. B for the relation after, that is a converse of before, b.

Note, that the relations are defined on non-empty intervals.

relations.svg

Before / After

a before b means that interval a ends before interval b begins, with a gap separating 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 at the same point where a ends. The converse of 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 right boundary of the interval a is inside of the interval b. The converse of 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 a and b have the same left boundary, and interval a is inside an the interval b, however not equal to it. The converse of 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 during b when the interval a lies inside of the interval b. The converse of 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 a and b have the same right boundary, and interval a is inside an the interval b, however not equal to it. The converse of 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 the left and right boundaries of the intervals a and b are matching. 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 are composed of several basic relations.

relations-ext.svg

IsSubset

a is a subset of b when the interval a starts, during, finishes or equals to the 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 the interval a is started by, contains, is finished by or equals to 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

a and b are disjoint if a does not intersect b. It means a before b or a 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

Two intervals a and b are adjacent if they are disjoint and the successor of the right boundary of a equals to the left boundary of b or the successor of the right boundary of b equals to the left boundary of a.

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

Two intervals a and b are intersecting if a is not before b and a is not after b. It means that if any of the remaining 11 basic relations holds, the intervals are intersecting.

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

a is less than b when the left boundary of the interval a is less than the left boundary of the interval b or if left boundaries are equal, then right boundary of the interval a should be less than the right boundary of the interval b.

Condition: (a- < b-) OR ((a- == b-) AND (a+ < b-))

isLess.svg

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

IsGreater

a is greater than b when interval b is less than interval a.

Condition: (a- > b-) OR ((a- == b-) AND (a+ > b-))

isGreater.svg

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