105 lines
5.1 KiB
Plaintext
105 lines
5.1 KiB
Plaintext
################################################################################
|
|
## Example on Creating User-Defined Functions for Moving Objects ##
|
|
## Author: Christian Duentgen ##
|
|
## Date: 9/23/2011 ##
|
|
################################################################################
|
|
#
|
|
# Using the following operator, it has become quite easy to implement user
|
|
# defined functions dealing with several moving objects at once:
|
|
#
|
|
# Name: getRefinementPartion
|
|
# Signature: {mT1|uT1} x {mT2|uT2} -> stream(tuple((Tstart instant)(Tend
|
|
# instant)(Tlc bool)(Trc bool)(Unit1 uT1)(Unit2 uT2)(UnitNo1
|
|
# int)(UnitNo2 int))); T1, T2 in {point, real, int, bool,
|
|
# string}
|
|
# Syntax: getRefinementPartion( M1, M2 )
|
|
# Meaning: Creates a stream representing the temporal refinement
|
|
# partion of the two arguments as a stream of tuples. Each
|
|
# result tuple contains a temporal interval (represented by
|
|
# starting instant Tstart, ending instant Tend, and closedness
|
|
# parameters Tlc (Tstart included), Trc (Tend includes)),
|
|
# restrictions of both arguments, M1 and M2, to this interval,
|
|
# and the position indexes of the according original units
|
|
# within M1 (UnitNo1), M2 (UnitNo2). If for a given interval
|
|
# one of the arguments is not defined, the according result
|
|
# unit is set to UNDEFINED. If one argument is UNDEFINED, the
|
|
# result contains the original units of the other, defined,
|
|
# argument. If M1 and M2 are both undefined, or both are empty
|
|
# (do not contain any unit) the result stream is empty.
|
|
# Example: query getRefinementPartion(train1, train5) count
|
|
#
|
|
# As an example, we provide a small function, that will do a vectorial summation
|
|
# of two moving point objects. The result is a moving point, where for each
|
|
# instant where both arguments, M1 and M2, are defined, the position is the
|
|
# vectorial sum of the current position of M1 and M2:
|
|
|
|
close database;
|
|
open database berlintest:
|
|
|
|
let mpplus = fun(M1: mpoint, M2: mpoint)
|
|
getRefinementPartion( M1, M2 )
|
|
filter[isdefined(.Unit1) and isdefined(.Unit2)]
|
|
projectextend[Tstart, Tend, Tlc, Trc ; P1:
|
|
val(initial(.Unit1))
|
|
+ val(initial(.Unit2)), P2:val(final(.Unit1)) + val(final(.Unit2))]
|
|
projectextend[;U: the_unit( .P1, .P2, .Tstart, .Tend, .Tlc, .Trc )]
|
|
makemvalue[U];
|
|
|
|
# The function can be called as follows:
|
|
|
|
query mpplus(train1, train7);
|
|
query Trains feed projectextend[; Trip: mpplus(train1,.Trip)] tconsume count;
|
|
|
|
# You can easily extend this method, e.g. in order to explicitely deal with
|
|
# periods, where only one of the objects (M1 or M2) is defined. The following
|
|
# variant creates a mpoint, that is defined whereever at least one of the
|
|
# arguments M1, M2 is defined. If only one argument is defined, the position of
|
|
# the defined argument is forwarded (by substituting the position of the other
|
|
# object with point (0,0):
|
|
|
|
let mpplus2 = fun(M1: mpoint, M2: mpoint)
|
|
getRefinementPartion( M1, M2 )
|
|
filter[isdefined(.Unit1) or isdefined(.Unit2)]
|
|
projectextend[Tstart, Tend, Tlc, Trc ; P1:
|
|
ifthenelse(isdefined(.Unit1),val(initial(.Unit1)),makepoint(0,0))
|
|
+ ifthenelse(isdefined(.Unit2),val(initial(.Unit2)),makepoint(0,0)),
|
|
P2: ifthenelse(isdefined(.Unit1),val(final(.Unit1)),makepoint(0,0))
|
|
+ ifthenelse(isdefined(.Unit2),val(final(.Unit2)),makepoint(0,0))]
|
|
projectextend[;U: the_unit( .P1, .P2, .Tstart, .Tend, .Tlc, .Trc )]
|
|
makemvalue[U];
|
|
|
|
# It can be used the same way:
|
|
|
|
query mpplus2(train1, train7);
|
|
query Trains feed projectextend[; Trip: mpplus2(train1,.Trip)] tconsume count;
|
|
|
|
# You can also think about passing additional arguments, telling the function
|
|
# how to deal with instants not covered by both arguments, M1 and M2. The
|
|
# following variant uses different 'offsets', SP1 and SP2, depending on whether
|
|
# the 'missing' unit is from M1 or M2:
|
|
|
|
let mpplus3 = fun(M1: mpoint, M2: mpoint, SP1: point, SP2: point)
|
|
getRefinementPartion( M1, M2 )
|
|
filter[isdefined(.Unit1) or isdefined(.Unit2)]
|
|
projectextend[Tstart, Tend, Tlc, Trc ; P1:
|
|
ifthenelse(isdefined(.Unit1),val(initial(.Unit1)),SP1)
|
|
+ ifthenelse(isdefined(.Unit2),val(initial(.Unit2)),SP1),
|
|
P2: ifthenelse(isdefined(.Unit1),val(final(.Unit1)),SP2)
|
|
+ ifthenelse(isdefined(.Unit2),val(final(.Unit2)),SP2)]
|
|
projectextend[;U: the_unit( .P1, .P2, .Tstart, .Tend, .Tlc, .Trc )]
|
|
makemvalue[U];
|
|
|
|
# It's used like this:
|
|
|
|
query mpplus3(train1, train7, makepoint(-1000,-1000), makepoint(10000,10000));
|
|
|
|
# The quintessence is, that you do not need to implement new operators to
|
|
# provide new methods of combining temporal data requiring a refinement of
|
|
# the moving objects.
|
|
# In the same way, you may also test the concept of a new functionality before
|
|
# implementing it as a Secondo operator.
|
|
################################################################################
|
|
close database;
|
|
quit;
|
|
|