Bläddra i källkod

Added modified temporal vector algebra code from GSoC 2013 student Thomas Leppelt.

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@58807 15284696-431f-4ddb-bdfa-cd5b030d7da7
Soeren Gebbert 11 år sedan
förälder
incheckning
1755b6b243

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
lib/python/temporal/Makefile


+ 2 - 0
lib/python/temporal/__init__.py

@@ -26,3 +26,5 @@ from mapcalc import *
 from univar_statistics import *
 from c_libraries_interface import *
 from temporal_algebra import *
+from temporal_vector_algebra import *
+from temporal_vector_operator import *

+ 6 - 0
lib/python/temporal/register.py

@@ -172,6 +172,12 @@ def register_maps_in_space_time_dataset(
 
         # Get a new instance of the map type
         map = dataset_factory(type, maplist[count]["id"])
+        
+        if map.map_exists() is not True:
+            msgr.fatal(_("Unable to update %(t)s map <%(id)s>. "
+                            "The map does not exists.") %
+                            {'t': map.get_type(),
+                            'id': map.get_map_id()})
 
         # Use the time data from file
         if "start" in maplist[count]:

+ 19 - 18
lib/python/temporal/temporal_algebra.py

@@ -2,12 +2,12 @@
 
 Temporal algebra parser class
 
-(C) 2013 by the GRASS Development Team
+(C) 2014 by the GRASS Development Team
 This program is free software under the GNU General Public
 License (>=v2). Read the file COPYING that comes with GRASS
 for details.
 
-@author Thomas Leppelt and Soeren Gebbert
+@authors Thomas Leppelt and Soeren Gebbert
 
 @code
 
@@ -659,13 +659,9 @@ class TemporalAlgebraParser(object):
         self.run = run
         self.debug = debug
         self.pid = pid
-        self.lexer = TemporalAlgebraLexer()
-        self.lexer.build()
         # Intermediate vector map names
         self.names = {}
         # Count map names
-        self.count = 0
-        self.parser = yacc.yacc(module=self, debug=False)
         self.spatial = spatial
         self.null = null
         self.mapset = get_current_mapset()
@@ -679,6 +675,10 @@ class TemporalAlgebraParser(object):
             self.dbif.close()
 
     def parse(self, expression, stdstype = 'strds', basename = None):
+        self.lexer = TemporalAlgebraLexer()
+        self.lexer.build()
+        self.parser = yacc.yacc(module=self, debug=self.debug)
+
         self.count = 0
         self.stdstype = stdstype
         self.basename = basename
@@ -1685,19 +1685,21 @@ class TemporalAlgebraParser(object):
                                                         'mean', None, \
                                                         overwrite = grass.overwrite())
             if isinstance(t[3], list):
-                dbif, connect = init_dbif(None)
                 num = len(t[3])
                 count = 0
-                for map in t[3]:
-                    map.select()
-                    #map.update()
-                    resultstds.register_map(map, dbif)
-                    count += 1
-                    if count % 10 == 0:
-                        self.msgr.percent(count, num, 1)
-
-                resultstds.update_from_registered_maps(dbif)
-                dbif.close()
+                if num > 0:
+                    dbif, connected = init_dbif(None)
+                    for map in t[3]:
+                        map.select(dbif=dbif)
+                        #map.update()
+                        resultstds.register_map(map, dbif=dbif)
+                        count += 1
+                        if count % 10 == 0:
+                            self.msgr.percent(count, num, 1)
+
+                    resultstds.update_from_registered_maps(dbif=dbif)
+                    if connected:
+                        dbif.close()
             t[0] = t[3]
 
         if self.debug:
@@ -2249,7 +2251,6 @@ class TemporalAlgebraParser(object):
                 print t[3] + "* = tshift(", t[3], ",", t[5], ")"
             t[0] = t[3] + "*"
 
-
     # Handle errors.
     def p_error(self, t):
         raise SyntaxError("syntax error on line %d near '%s' expression '%s'" %

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1013 - 0
lib/python/temporal/temporal_vector_algebra.py


+ 349 - 0
lib/python/temporal/temporal_vector_operator.py

@@ -0,0 +1,349 @@
+"""!@package grass.temporal
+
+Temporal vector operator evaluation with PLY
+
+(C) 2014 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+@authors Thomas Leppelt and Soeren Gebbert
+
+@code
+    >>> import grass.temporal as tgis
+    >>> tgis.init(True)
+    >>> p = tgis.TemporalVectorOperatorParser()
+    >>> expression =  "{equal| during,&&}"
+    >>> p.parse(expression, True)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during'], '=', '&&')
+    >>> expression =  "{equal| during | follows,&&}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during', 'follows'], '&', '&')
+    >>> expression =  "{equal| during | follows,+!:}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during', 'follows'], '+', '!:')
+    >>> expression =  "{equal| during,!:}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during'], '=', '!:')
+    >>> expression =  "{!:}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal'], '=', '!:')
+    >>> expression =  "{&&}"
+    >>> p.parse(expression, True)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal'], '=', '&&')
+    >>> expression =  "{&&}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal'], '&', '&')
+    >>> expression =  "{|#}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal'], '|', '#')
+    >>> expression =  "{equal,||}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal'], '|', '|')
+    >>> expression =  "{equal|during,=!:}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during'], '=', '!:')
+    >>> expression =  "{equal|during|starts}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    (['equal', 'during', 'starts'], None, None)
+    >>> expression =  "{over| equal,||}"
+    >>> p.parse(expression)
+    >>> print(p.relations, p.temporal, p.function)
+    ([['overlaps', 'overlapped'], 'equal'], '|', '|')
+    
+@endcode
+"""
+try:
+    import ply.lex as lex
+    import ply.yacc as yacc
+except:
+    pass
+
+class TemporalVectorOperatorLexer(object):
+    """!Lexical analyzer for the GRASS GIS temporal vector operators"""
+    
+    # Functions that defines topological relations.
+    relations = {
+        'equal'      : "EQUAL",
+        'follows'    : "FOLLOWS",
+        'precedes'   : "PRECEDES",
+        'overlaps'   : "OVERLAPS",
+        'overlapped' : "OVERLAPPED",
+        'during'     : "DURING",
+        'starts'     : "STARTS",
+        'finishes'   : "FINISHES",
+        'contains'   : "CONTAINS",
+        'started'    : "STARTED",
+        'finished'   : "FINISHED",
+        'over'       : "OVER"
+        }
+        
+    # This is the list of token names.
+    tokens = (
+        'COMMA',
+        'LEFTREF',
+        'HASH',
+        'OR',
+        'AND',
+        'DISOR',
+        'XOR',
+        'NOT',
+        'T_SELECT',
+        'T_NOT_SELECT',
+        'CLPAREN',
+        'CRPAREN',
+    )
+    
+    # Build the token list
+    tokens = tokens + tuple(relations.values())
+
+    # Regular expression rules for simple tokens
+    t_T_SELECT           = r':'
+    t_T_NOT_SELECT       = r'!:'
+    t_COMMA              = r','
+    t_LEFTREF             = r'='
+    t_HASH               = r'\#'
+    t_OR                 = r'[\|]'
+    t_AND                = r'[&]'
+    t_DISOR              = r'\+'
+    t_XOR                = r'\^'
+    t_NOT                = r'\~'
+    t_CLPAREN             = r'\{'
+    t_CRPAREN             = r'\}'
+    
+    # These are the things that should be ignored.
+    t_ignore = ' \t'
+
+    # Track line numbers.
+    def t_newline(self, t):
+        r'\n+'
+        t.lineno += len(t.value)
+        
+    def t_NAME(self, t):
+        r'[a-zA-Z_][a-zA-Z_0-9]*'
+        self.temporal_symbol(t)
+        return t
+        
+    # Parse symbols
+    def temporal_symbol(self, t):
+        # Check for reserved words
+        if t.value in TemporalVectorOperatorLexer.relations.keys():
+            t.type = TemporalVectorOperatorLexer.relations.get(t.value)
+        #else:
+        #    t.type = 'NAME'
+        return(t)
+
+    # Handle errors.
+    def t_error(self, t):
+        raise SyntaxError("syntax error on line %d near '%s'" % 
+            (t.lineno, t.value))
+
+    # Build the lexer
+    def build(self,**kwargs):
+        self.lexer = lex.lex(module=self, **kwargs)
+        
+    # Just for testing
+    def test(self,data):
+        self.name_list = {}
+        print(data)
+        self.lexer.input(data)
+        while True:
+             tok = self.lexer.token()
+             if not tok: break
+             print tok
+             
+class TemporalVectorOperatorParser(object):
+    """!The parser for the GRASS GIS temporal vector operators"""
+    
+    def __init__(self):
+        self.lexer = TemporalVectorOperatorLexer()
+        self.lexer.build()
+        self.parser = yacc.yacc(module=self)
+
+    def parse(self, expression, comparison = False):
+        self.comparison = comparison
+        self.parser.parse(expression)
+        
+    # Error rule for syntax errors.
+    def p_error(self, t):
+        raise SyntaxError("invalid syntax")
+
+    # Get the tokens from the lexer class
+    tokens = TemporalVectorOperatorLexer.tokens
+
+    def p_relation_only(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN relation CRPAREN
+                 | CLPAREN relationlist CRPAREN
+        """
+        # Set three operator components.
+        if isinstance(t[2], list):
+            self.relations = t[2]
+        else:
+            self.relations = [t[2]]
+        self.temporal  = None 
+        self.function  = None
+        
+        t[0] = t[2]
+
+
+    def p_operator(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN select CRPAREN
+                 | CLPAREN HASH CRPAREN
+                 | CLPAREN overlay CRPAREN
+        """
+        # Set three operator components.
+        self.relations = ['equal']
+        self.temporal  = "=" 
+        self.function  = t[2]
+        
+        t[0] = t[2]
+        
+    def p_operator_temporal(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN temporal select CRPAREN
+                 | CLPAREN temporal HASH CRPAREN
+                 | CLPAREN temporal overlay CRPAREN
+        """
+        # Set three operator components.
+        self.relations = ['equal']
+        if self.comparison:
+            self.temporal = "="
+            self.function = t[2] + t[3]
+        else:
+            self.temporal = t[2]
+            self.function = t[3]
+        
+        t[0] = t[3]
+
+    def p_operator_relation(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN relation COMMA select CRPAREN
+                 | CLPAREN relationlist COMMA select CRPAREN
+                 | CLPAREN relation COMMA HASH CRPAREN
+                 | CLPAREN relationlist COMMA HASH CRPAREN
+                 | CLPAREN relation COMMA overlay CRPAREN
+                 | CLPAREN relationlist COMMA overlay CRPAREN
+        """
+        # Set three operator components.
+        if isinstance(t[2], list):
+            self.relations = t[2]
+        else:
+            self.relations = [t[2]]
+        self.temporal  = "=" 
+        self.function  = t[4]
+        
+        t[0] = t[4]
+
+    def p_operator_relation_temporal(self, t):
+        # The expression should always return a list of maps.
+        """
+        operator : CLPAREN relation COMMA temporal select CRPAREN
+                 | CLPAREN relationlist COMMA temporal select CRPAREN
+                 | CLPAREN relation COMMA temporal HASH CRPAREN
+                 | CLPAREN relationlist COMMA temporal HASH CRPAREN
+                 | CLPAREN relation COMMA temporal overlay CRPAREN
+                 | CLPAREN relationlist COMMA temporal overlay CRPAREN
+        """
+        # Set three operator components.
+        if isinstance(t[2], list):
+            self.relations = t[2]
+        else:
+            self.relations = [t[2]]
+        if self.comparison:
+            self.temporal = "="
+            self.function = t[4] + t[5]
+        else:
+            self.temporal = t[4]
+            self.function = t[5]
+        t[0] = t[5]
+        
+    def p_relation(self, t):
+        # The list of relations.
+        """
+        relation : EQUAL
+                 | FOLLOWS
+                 | PRECEDES
+                 | OVERLAPS
+                 | OVERLAPPED
+                 | DURING
+                 | STARTS
+                 | FINISHES
+                 | CONTAINS
+                 | STARTED
+                 | FINISHED
+        """
+        t[0] = t[1]
+        
+    def p_over(self, t):
+        # The list of relations.
+        """
+        relation : OVER
+        """
+        over_list = ["overlaps", "overlapped"]
+        t[0] = over_list
+
+    def p_relationlist(self, t):
+        # The list of relations.
+        """
+        relationlist : relation OR relation
+                     | relation OR relationlist
+        """
+        rel_list = []
+        rel_list.append(t[1])
+        if isinstance(t[3], list):
+            rel_list = rel_list + t[3]
+        else:
+            rel_list.append(t[3])
+        t[0] =  rel_list
+
+    def p_temporal_operator(self, t):
+        # The list of relations.
+        """
+        temporal : LEFTREF
+                 | OR
+                 | AND
+                 | DISOR
+        """
+        t[0] = t[1]
+
+    def p_select_operator(self, t):
+        # The list of relations.
+        """
+        select : T_SELECT
+               | T_NOT_SELECT
+        """
+        t[0] = t[1]
+
+    def p_overlay_operator(self, t):
+        # The list of relations.
+        """
+        overlay : OR
+                | AND
+                | DISOR
+                | XOR
+                | NOT
+        """
+        t[0] = t[1]
+###############################################################################             
+        
+if __name__ == "__main__":
+    import doctest
+    doctest.testmod()
+    

+ 7 - 0
temporal/t.vect.mapcalc/Makefile

@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../../
+
+PGM = t.vect.mapcalc
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script

+ 340 - 0
temporal/t.vect.mapcalc/t.vect.mapcalc.html

@@ -0,0 +1,340 @@
+<h2>DESCRIPTION</h2> 
+
+t.vect.mapcalc performs temporal and spatial overlay and buffer functions on space time vector datasets (STVDS)
+by using the temporal vector algebra. New STVDS can be created, which are expressions of existing STVDS.
+
+<h3>PROGRAM USE</h3> 
+The module expects an <b>expression</b> as input parameter in the following form: <br>
+<br>
+<b> "result = expression" </b>
+<br>
+<br>
+
+The statement structure is similar to r.mapcalc, see <a href="r.mapcalc.html">r.mapcalc</a>.
+Where <b>result</b> represents the name of a space time vector dataset (STVDS)that will 
+contain the result of the calculation that is given as <b>expression</b> 
+on the right side of the equality sign. 
+These expression can be any valid or nested combination of temporal 
+operations and spatial overlay or buffer functions that are provided by the temporal algebra.  <br>
+The temporal vector algebra works with space time vector datasets only (STVDS).
+The algebra provides methods for map selection from STVDS based on their temporal relations. 
+It is also possible to temporally shift maps, to create temporal buffer and to snap time 
+instances to create a valid temporal topology. Furthermore expressions can be nested and 
+evaluated in conditional statements (if, else statements). Within if-statements the algebra 
+provides temporal variables like start time, end time, day of year, time differences or 
+number of maps per time interval to build up conditions. In addition the algebra provides 
+the spatial operations for vector overlay and buffering. All these operations can be assigned 
+to STVDS or to the resulting map lists of operations between STVDS. 
+<br>
+<br>
+As default, topological relationships between space time datasets will be 
+evaluated only temporal. Use the <b>s</b> flag to activate the 
+additionally evaluate the spatial topology based on the spatial extents of maps.
+<br>
+<br>
+The expression option must be passed as <b>quoted</b> 
+expression, for example: <br>
+<div class="code"><pre>t.vect.mapcalc expression="C = A & B" basename=result</pre></div> 
+Where <b>C</b> is the new space time vector dataset that will contain maps
+with the basename "result" that represent the intersection of maps from STVDS <b>A</b> and 
+equally temporal related maps from STVDS <b>B</b>.
+<br>
+<br>
+The map basename for the result STVDS must always be specified.
+
+<h2>Temporal vector algebra</h2>
+
+The temporal vector algebra provides a wide range of temporal and spatial operators and 
+functions that will be presented in the following section. <br>
+<br>
+
+<h3>Temporal relations</h3>
+
+Several temporal topology relations between space 
+time datasets are supported: <br>
+<div class="code"><pre>
+equals            A ------
+                  B ------
+
+during            A  ---- 
+                  B ------
+
+contains          A ------
+                  B  ---- 
+
+starts            A ----
+                  B ------
+
+started           A ------
+                  B ----
+
+finishs           A   ---- 
+                  B ------
+
+finished          A ------
+                  B   ----
+
+precedes          A ----
+                  B     ----
+
+follows           A     ----
+                  B ----
+
+overlapped        A   ------
+                  B ------
+
+overlaps          A ------
+                  B   ------
+
+over              booth overlaps and overlapped
+
+</pre></div>
+The relations must be read as: A is related to B, like - A equals B - A is 
+during B - A contains B <br>
+<br>
+Topological relations must be specified in {} parentheses. <br>
+
+<h3>Temporal Selection</h3>
+
+The temporal selection simply selects parts of a space time dataset without 
+processing raster or vector data.
+
+The algebra provides a selection operator <b>:</b> that selects parts 
+of a space time dataset that are temporally equal to parts of a second one 
+by default. The following expression
+<div class="code"><pre>
+C = A : B
+</pre></div>
+means: Select all parts of space time dataset A that are equal to B and store 
+it in space time dataset C. The parts are time stamped maps. <br>
+<br>
+In addition the inverse selection operator <b>!:</b> is defined as the complement of 
+the selection operator, hence the following expression
+<div class="code"><pre>
+C = A !: B
+</pre></div>
+means: select all parts of space time time dataset A that are not equal to B 
+and store it in space time dataset (STDS) C. <br>
+<br>
+To select parts of a STDS by different topological relations to other STDS, 
+the temporal topology selection operator can be used. The operator consists of 
+topological relations, that must be separated by the logical OR operator 
+<b>|</b> and the temporal selection operator. Both parts are separated by 
+comma and surrounded by curly braces: 
+{"topological relations", "temporal selection operator"}  <br>
+<br>
+Examples:
+<div class="code"><pre>
+C = A {equals,:} B
+C = A {equals,!:} B
+</pre></div>
+We can now define arbitrary topological relations using logical OR operator 
+to connect them:
+<div class="code"><pre>
+C = A {equals|during|overlaps,:} B
+</pre></div>
+Select all parts of A that are equal to B, during B or overlaps B. <br>
+<br>
+The selection operator is implicitly contained in the temporal topology 
+selection operator, so that the following statements are exactly the same:
+<div class="code"><pre>
+C = A : B
+C = A {:} B
+C = A {equal,:} B
+</pre></div>
+
+Same for the complementary selection:
+<div class="code"><pre>
+C = A !: B
+C = A {!:} B
+C = A {equal,!:} B
+</pre></div>
+
+<h3>Conditional statements</h3>
+
+Selection operations can be evaluated within conditional statements.
+<br>
+<div class="code"><pre>
+Note A and B can either be space time datasets or expressions.
+
+if statement                         decision option                        temporal relations
+  if(if, then, else)
+  if(conditions, A)                    A if conditions are True;              temporal topological relation between if and then is equal.
+  if(conditions, A, B)                 A if conditions are True, B otherwise; temporal topological relation between if, then and else is equal.
+  if(topologies, conditions, A)        A if conditions are True;              temporal topological relation between if and then is explicit specified by topologies.
+  if(topologies, conditions, A, B)     A if conditions are True, B otherwise; temporal topological relation between if, then and else is explicit specified by topologies.
+</pre></div>
+The conditions are comparison expressions that are used to evaluate 
+space time datasets. Specific values of temporal variables are 
+compared by logical operators and evaluated for each map of the STDS.
+<br>
+<br>
+The supported logical operators:
+<div class="code"><pre>
+Symbol  description
+
+  ==    equal
+  !=    not equal
+  >     greater than
+  >=    greater than or equal
+  <     less than
+  <=    less than or equal
+  &&    and
+  ||    or
+</pre></div>
+
+Temporal functions: <br>
+<div class="code"><pre>
+
+td(A)                   Returns a list of time intervals of STDS A
+
+start_time()            Start time as HH::MM:SS
+start_date()            Start date as yyyy-mm-DD
+start_datetime()        Start datetime as yyyy-mm-DD HH:MM:SS
+end_time()              End time as HH:MM:SS
+end_date()              End date as yyyy-mm-DD
+end_datetime()          End datetime as  yyyy-mm-DD HH:MM
+
+start_doy()             Day of year (doy) from the start time [1 - 366]
+start_dow()             Day of week (dow) from the start time [1 - 7], the start of the week is Monday == 1
+start_year()            The year of the start time [0 - 9999]
+start_month()           The month of the start time [1 - 12]
+start_week()            Week of year of the start time [1 - 54]
+start_day()             Day of month from the start time [1 - 31]
+start_hour()            The hour of the start time [0 - 23]
+start_minute()          The minute of the start time [0 - 59]
+start_second()          The second of the start time [0 - 59]
+end_doy()               Day of year (doy) from the end time [1 - 366]
+end_dow()               Day of week (dow) from the end time [1 - 7], the start of the week is Monday == 1
+end_year()              The year of the end time [0 - 9999]
+end_month()             The month of the end time [1 - 12]
+end_week()              Week of year of the end time [1 - 54]
+end_day()               Day of month from the start time [1 - 31]
+end_hour()              The hour of the end time [0 - 23]
+end_minute()            The minute of the end time [0 - 59]
+end_second()            The second of the end time [0 - 59]            
+</pre></div>
+
+Additionally the number of maps in intervals can be computed and 
+used in conditional statements. <br>
+The operator to count the number of maps 
+is the hash <b>#</b>. 
+<div class="code"><pre>
+A{contains,#}B
+</pre></div>
+This expression computes the number of maps from space 
+time dataset B which are during the time intervals of maps from 
+space time dataset A.<br>
+A list of integers (scalars) corresponding to the maps of A 
+that contain maps from B will be returned. <br>
+<br>
+
+Furthermore the temporal algebra allows temporal buffering, shifting 
+and snapping with the functions buff_t(), tshift() and tsnap()
+respectively.
+<div class="code"><pre>
+buff_t(A, size)         Buffer STDS A with granule ("1 month" or 5)
+tshift(A, size)         Shift STDS A with granule ("1 month" or 5)
+tsnap(A)                Snap time instances and intervals of STDS A
+</pre></div>
+
+<h3>Temporal Operators</h3>
+<p>
+The temporal algebra defines temporal operators that can be combined 
+later with spatial operators to perform spatio-temporal operations. 
+The temporal operators process the time instances and intervals of temporal related maps. 
+</p>
+<div class="code"><pre>
+AND             &amp;       Intersection 
+OR              |       Union
+DISJOINT OR     +       Disjoint union
+LEFT REFERENCE  =       Use the time stamp of the left space time dataset
+</pre></div><p>
+For example we can compute the intersection, union or disjoint union from time stamps of maps 
+that temporally overlap, or we can just keep the time stamp of the left STDS.
+</p>
+
+<h3>Spatial vector operators</h3>
+
+The module supports the following boolean vector operations: <br>
+<div class="code"><pre>
+ Boolean Name   Operator Meaning         Precedence   Correspondent function 
+---------------------------------------------------------------------------------- 
+ AND            &        Intersection          1      (v.overlay operator=and) 
+ OR             |        Union                 1      (v.overlay operator=or)  
+ DISJOINT OR    +        Disjoint union        1      (v.patch)              
+ XOR            ^        Symmetric difference  1      (v.overlay operator=xor) 
+ NOT            ~        Complement            1      (v.overlay operator=not) 
+
+</pre></div>
+
+And vector functions:
+<div class="code"><pre>
+ buff_p(A, size)    	  Buffer the points of vector map layer A with size
+ buff_l(A, size)    	  Buffer the lines of vector map layer A with size
+ buff_a(A, size)    	  Buffer the areas of vector map layer A with size
+</pre></div>
+<br>
+
+<p>
+<h3>Combinations of temporal, vector and select operators</h3>
+
+We combine the temporal topology relations, the temporal operators and the spatial/select operators to create spatio-temporal operators:
+
+<pre class="code">
+{"list of temporal relations", "temporal operator" "spatial or select operator"} 
+</pre><p>
+The spatial and the select operators can be used stand-alone. In this case the temporal topology relation "equal" and the temporal operator "left reference =" is assumed and used as default. This allows the convenient use of the spatial and select 
+operators in case of space time vector datasets with equal time stamps.
+</p>
+<div class="code"> <pre>
+ ---------------------------------------
+|   |  &amp; |  | |  ^ |  ~ |  + |  : |  !: |
+|---|----|----|----|----|----|----|-----|
+| &amp; | &amp;&amp; | &amp;| | &amp;^ | &amp;~ | &amp;+ | &amp;: | &amp;!: |
+| | | |&amp; | || | |^ | |~ | |+ | |: | |!: |
+| + | +&amp; | +| | +^ | +~ | ++ | +: | +!: |
+| = | =&amp; | =| | =^ | =~ | =+ | =: | =!: |
+ ---------------------------------------
+</pre></div>
+
+<h3>Examples: </h3>
+
+Spatio-temporal intersect all maps from space time dataset A with all maps from space time dataset 
+B which have equal time stamps and are temporary before Jan. 1. 2005 and 
+store them in space time dataset D.
+<div class="code"><pre>
+D = if(start_date() < "2005-01-01", A & B)
+</pre></div>
+
+Buffer all vector points from space time vector dataset A and B with a distance of one and
+intersect the results with overlapping, containing, during and equal temporal relations
+to store the result in space time vector dataset D with intersected time stamps.
+<div class="code"><pre>
+D = buff_p(A, 1) {overlaps|overlapped|equal|during|contains,&&} buff_p(B, 1)
+</pre></div>
+
+Select all maps from space time dataset B which are during the temporal 
+buffered space time dataset A with a map interval of three days, else
+select maps from C and store them in space time dataset D.
+<div class="code"><pre>
+D = if(contain, td(buff_t(A, "1 days")) == 3, B, C)
+</pre></div>
+
+<h2>REFERENCES</h2>
+
+<tt><a href="http://www.dabeaz.com/ply/">PLY(Python-Lex-Yacc)</a></tt>
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="t.select.html">t.select</a>
+</em>
+
+
+<h2>AUTHOR</h2>
+
+Thomas Leppelt, Soeren Gebbert, Thuenen Institut, Germany <br>
+
+<p><i>Last changed: $Date: 2013-07-24 17:35:20 +0100 (Thu, 24 Jul 2013) $</i>
+

+ 70 - 0
temporal/t.vect.mapcalc/t.vect.mapcalc.py

@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+############################################################################
+#
+# MODULE:       t.vect.mapcalc
+# AUTHOR(S):    Thomas Leppelt, Soeren Gebbert
+#
+# PURPOSE:      Provide temporal vector algebra to perform spatial an temporal operations
+#               for space time datasets by topological relationships to other space time
+#               datasets.
+# COPYRIGHT:    (C) 2014 by the GRASS Development Team
+#
+#               This program is free software under the GNU General Public
+#               License (version 2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+#%module
+#% description: Apply temporal and spatial oeprations on space time vector datasets using temporal vector algebra.
+#% keywords: temporal
+#% keywords: mapalgebra
+#%end
+
+#%option
+#% key: expression
+#% type: string
+#% description: The mapcalc expression for temporal and spatial analysis of space time vector datasets.
+#% key_desc: expression
+#% required : yes
+#%end
+
+#%option
+#% key: basename
+#% type: string
+#% description: The basename of vector maps that are stored within the result space time vector dataset.
+#% key_desc: basename
+#% required : yes
+#%end
+
+#%flag
+#% key: s
+#% description: Activate spatial topology.
+#%end
+
+import grass.script as grass
+import grass.temporal as tgis
+import sys
+
+def main():
+    expression = options['expression']
+    basename = options['basename']
+    spatial = flags["s"]
+    stdstype = "stvds"
+
+    # Check for PLY istallation
+    try:
+        import ply.lex as lex
+        import ply.yacc as yacc
+    except:
+        grass.fatal(_("Please install PLY (Lex and Yacc Python implementation) to use the temporal algebra modules."))
+
+    tgis.init(True)
+    p = tgis.TemporalVectorAlgebraParser(run = True, debug=False, spatial = spatial)
+    p.parse(expression, stdstype, basename)
+
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    sys.exit(main())
+

+ 77 - 0
temporal/t.vect.mapcalc/test_suite/test.t.vect.mapcalc.sh

@@ -0,0 +1,77 @@
+#!/usr/bin/sh
+
+g.region s=0 n=80 w=0 e=120 b=0 t=50 res=10 -p
+
+export GRASS_OVERWRITE=1
+
+# Test for temporal algebra in LatLon location.
+rm /tmp/vinput1_point_test.txt
+rm /tmp/vinput2_point_test.txt
+rm /tmp/vinput3_point_test.txt
+rm /tmp/vinput4_point_test.txt
+rm /tmp/vinput1_area_test.txt
+rm /tmp/vinput2_area_test.txt
+rm /tmp/vinput3_area_test.txt
+rm /tmp/vinput4_area_test.txt
+
+# Create random area test maps.
+for i in {1..60}
+  do
+    if [[ "$i" -le 20 ]]; then
+      echo vtestpoint1_$i >> /tmp/vinput1_point_test.txt
+      echo vtestarea1_$i  >> /tmp/vinput1_area_test.txt
+      v.random --o -z output=vtestpoint1_$i n=3 seed=$i+1
+      v.voronoi --o input=vtestpoint1_$i output=vtestarea1_$i
+    elif [ "$i" -gt 20 ] && [ "$i" -le 40 ]; then
+      echo vtestpoint2_$i >> /tmp/vinput2_point_test.txt
+      echo vtestarea2_$i  >> /tmp/vinput2_area_test.txt
+      v.random --o -z output=vtestpoint2_$i n=3 seed=$i+1
+      v.voronoi --o input=vtestpoint2_$i output=vtestarea2_$i
+    else
+      echo vtestpoint3_$i >> /tmp/vinput3_point_test.txt
+      echo vtestpoint4_$i >> /tmp/vinput4_point_test.txt
+      echo vtestarea3_$i  >> /tmp/vinput3_area_test.txt
+      echo vtestarea4_$i  >> /tmp/vinput4_area_test.txt
+      v.random --o -z output=vtestpoint3_$i n=3 seed=$i+1
+      v.voronoi --o input=vtestpoint3_$i output=vtestarea3_$i
+      v.random --o -z output=vtestpoint4_$i n=3 seed=$i+1
+      v.voronoi --o input=vtestpoint4_$i output=vtestarea4_$i
+    fi
+  done
+
+# Create STVDS and register test maps.
+t.create output=A1 type=stvds title="Area test dataset" descr="Area test dataset"
+t.create output=A2 type=stvds title="Area test dataset" descr="Area test dataset"
+t.create output=A3 type=stvds title="Area test dataset" descr="Area test dataset"
+t.create output=A4 type=stvds title="Area test dataset" descr="Area test dataset"
+t.create output=P1 type=stvds title="Point test dataset" descr="Point test dataset"
+t.create output=P2 type=stvds title="Point test dataset" descr="Point test dataset"
+t.create output=P3 type=stvds title="Point test dataset" descr="Point test dataset"
+t.create output=P4 type=stvds title="Point test dataset" descr="Point test dataset"
+
+t.register -i type=vect input=A1 file=/tmp/vinput1_area_test.txt increment="1 days" start="2013-01-01"
+t.register -i type=vect input=A2 file=/tmp/vinput2_area_test.txt increment="1 days" start="2013-01-10"
+t.register -i type=vect input=A3 file=/tmp/vinput3_area_test.txt increment="3 days" start="2013-01-01"
+t.register -i type=vect input=A4 file=/tmp/vinput4_area_test.txt increment="3 days" start="2013-01-10"
+t.register -i type=vect input=P1 file=/tmp/vinput1_point_test.txt increment="1 days" start="2013-01-01"
+t.register -i type=vect input=P2 file=/tmp/vinput2_point_test.txt increment="1 days" start="2013-01-10"
+t.register -i type=vect input=P3 file=/tmp/vinput3_point_test.txt increment="3 days" start="2013-01-01"
+t.register -i type=vect input=P4 file=/tmp/vinput4_point_test.txt increment="3 days" start="2013-01-10"
+
+# Test different options.
+t.vect.mapcalc expression='B1 = A1 & A2' basename="bmap1"
+t.vect.list input=B1 column=name,start_time,end_time
+t.vect.mapcalc expression='B2 = A1 {equal|during,+&} A3' basename="bmap2"
+t.vect.list input=B2 column=name,start_time,end_time
+t.vect.mapcalc expression='B3 = buff_p(P1,10)' basename="bmap3"
+t.vect.list input=B3 column=name,start_time,end_time
+t.vect.mapcalc expression='B4 = buff_p(P2,30) {equal|during,|^} A4' basename="bmap4"
+t.vect.list input=B4 column=name,start_time,end_time
+t.vect.mapcalc expression='B5 = if(td(A1) == 1 || start_date() >= "2010-01-10", A2)' basename="bmap5"
+t.vect.list input=B5 column=name,start_time,end_time
+t.vect.mapcalc expression='B6 = buff_p(P2,30) {equal|during|started,&^} buff_p(P3,30)' basename="bmap6"
+t.vect.list input=B6 column=name,start_time,end_time
+t.vect.mapcalc expression='B7 = buff_p(P2,30) {starts,&^} buff_p(P3,30)' basename="bmap7"
+t.vect.list input=B8 column=name,start_time,end_time
+t.vect.mapcalc expression='B8 = buff_p(P2,30) {starts,|^} buff_p(P3,30)' basename="bmap8"
+t.vect.list input=B8 column=name,start_time,end_time