Files
secondo/Documents/HOWTO_write_UserDefinedFunctions_for_MovingObjects.SEC
2026-01-23 17:03:45 +08:00

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;