1:- module(spacetimeindex,
    2          [ spacetime_candidate/2,
    3            spacetime_index/1,
    4            spacetime_clear/1,
    5            spacetime_clear/0,
    6            spacetime_assert/4,
    7            spacetime_assert/3,
    8            spacetime_bulkload/3,
    9            spacetime_bulkload/2,
   10            spacetime_index_all/2,
   11            spacetime_index_all/1,
   12            spacetime_within_range/5,
   13            spacetime_within_range/4,
   14            spacetime_intersects/3,
   15            spacetime_intersects/2,
   16            bucket/3,
   17            buckets/3
   18          ]
   19         ).   20
   21:- use_module(library(semweb/rdf_db)).   22:- use_module(library(space/space)).   23:- use_module(library(space/timeindex)).   24
   25:- dynamic spacetime_index/4.   26:- multifile spacetime_candidate/2.   27
   28spacetime_index(I) :- spacetime_index(_,_,_,I).
   29
   30spacetime_candidate(URI, time_shape(Time,Shape)) :-
   31    uri_time(URI,Time),
   32    uri_shape(URI,Shape).
   33
   34bucket(Time,IntervalSize,Bucket) :-
   35    Bucket is floor(Time/IntervalSize) * IntervalSize.
   36
   37buckets(point(T),IS,BS) :- buckets(T,T,IS,BS).
   38buckets(interval(T1,T2),IS,BS) :- buckets(T1,T2,IS,BS).
   39buckets(T1,T2,IntervalSize,[]) :- T1 >= T2 + IntervalSize, !.
   40buckets(T0,T2,IntervalSize,[Bucket|Tail]) :-
   41    bucket(T0,IntervalSize,Bucket),
   42    T1 is T0 + IntervalSize,
   43    buckets(T1,T2,IntervalSize,Tail).
   44
   45bucket_indexname(Bucket,BaseName,IndexName) :-
   46    atom_number(BucketAtom,Bucket),
   47    atomic_list_concat([BaseName,BucketAtom],'_',IndexName).
   48
   49spacetime_index_in_interval(point(T),spacetime_index(Bucket,IS,BN,IndexName)) :-
   50    spacetime_index_in_interval(interval(T,T),spacetime_index(Bucket,IS,BN,IndexName)).
   51spacetime_index_in_interval(interval(From,To),spacetime_index(Bucket,IS,BN,IndexName)) :-
   52    spacetime_index(Bucket,IS,BN,IndexName),
   53    UBND is Bucket + IS,
   54    Bucket =< To,
   55    UBND >= From.
   56
   57spacetime_clear :- spacetime_clear(st_default).
   58spacetime_clear(BaseName) :-
   59    findall(spacetime_index(B,I,BaseName,IndexName),
   60            spacetime_index(B,I,BaseName,IndexName),
   61            Indices),
   62    forall(member(spacetime_index(B,I,BN,Index), Indices),
   63           (   space_clear(Index),
   64               retractall(spacetime_index(B,I,BN,Index))
   65           )).
   66
   67spacetime_assert(URI,TS,IS) :- spacetime_assert(URI,TS,IS,st_default).
   68spacetime_assert(URI,time_shape(Time,Shape),IntervalSize,BaseName) :-
   69    buckets(Time,IntervalSize,Buckets),
   70    forall(member(Bucket,Buckets),
   71           (   bucket_indexname(Bucket,BaseName,IndexName),
   72               space_assert(URI,Shape,IndexName),
   73               (   \+spacetime_index(Bucket,IntervalSize,BaseName,IndexName)
   74               ->  assert(spacetime_index(Bucket,IntervalSize,BaseName,IndexName))
   75               ;   true
   76               )
   77           )).
   78
   79spacetime_bulkload(Candidate,IntervalSize) :-
   80    spacetime_bulkload(Candidate,IntervalSize,st_default).
   81spacetime_bulkload(Candidate,IntervalSize,BaseName) :-
   82    empty_nb_set(Assertions),
   83    forall(call(Candidate, URI, TimeShape),
   84           (   spacetime_assert(URI, TimeShape, IntervalSize, BaseName),
   85               add_nb_set(space_assert(URI,TimeShape),Assertions)
   86           )),
   87    forall(spacetime_index(_,_,_,I),
   88           space_index(I)),
   89    size_nb_set(Assertions,N),
   90    format('% Added ~w URI-Time/Shape pairs to ~w\n',[N,BaseName]).
   91
   92spacetime_index_all(IntervalSize) :- spacetime_index_all(IntervalSize,st_default).
   93spacetime_index_all(IntervalSize,BaseName) :-
   94    spacetime_bulkload(spacetime_candidate,IntervalSize,BaseName).
   95
   96
   97spacetime_within_range(time_shape(Time,Shape),Target,TimeInterval,SpaceRadius) :-
   98    spacetime_within_range(time_shape(Time,Shape),Target,TimeInterval,SpaceRadius,st_default).
   99spacetime_within_range(time_shape(Time,Shape),Target,TimeInterval,SpaceRadius,BaseName) :-
  100    time_expand(Time,TimeInterval,Time2),
  101    spacetime_index_in_interval(Time2,spacetime_index(_Bucket,_IntervalSize,BaseName,IndexName)),
  102    space_within_range(Shape,Target,SpaceRadius,IndexName),
  103    once((   spacetime_candidate(Target,time_shape(Time3,_)),
  104             time_overlaps(Time2,Time3)
  105         )).
  106
  107
  108spacetime_intersects(time_shape(Time,Shape), Target) :-
  109    spacetime_intersects(time_shape(Time,Shape), Target, st_default).
  110spacetime_intersects(time_shape(Time,Shape), Target, BaseName) :-
  111    spacetime_index_in_interval(Time,spacetime_index(_Bucket,_IntervalSize,BaseName,IndexName)),
  112    space_intersects(Shape,Target,IndexName),
  113    once((   spacetime_candidate(Target,time_shape(Time2,_)),
  114             time_overlaps(Time,Time2)
  115         ))