[GRASS-SVN] r67494 - in grass-addons/grass7/vector: . v.mapcalc
svn_grass at osgeo.org
svn_grass at osgeo.org
Tue Jan 5 19:05:44 PST 2016
Author: wenzeslaus
Date: 2016-01-05 19:05:44 -0800 (Tue, 05 Jan 2016)
New Revision: 67494
Added:
grass-addons/grass7/vector/v.mapcalc/
grass-addons/grass7/vector/v.mapcalc/Makefile
grass-addons/grass7/vector/v.mapcalc/v.mapcalc.html
grass-addons/grass7/vector/v.mapcalc/v.mapcalc.py
Modified:
grass-addons/grass7/vector/Makefile
Log:
v.mapcalc: vector map algebra module in Python (authors: Thomas Leppelt and Soeren Gebbert)
Code from:
https://code.google.com/p/grass-gis-temporal-algebra/source/checkout
svn checkout http://grass-gis-temporal-algebra.googlecode.com/svn/trunk/ grass-gis-temporal-algebra-read-only
Developed in GSoC 2014:
https://grasswiki.osgeo.org/wiki/GRASS_GSoC_2013_Temporal_GIS_Algebra_for_raster_and_vector_data_in_GRASS
Modified: grass-addons/grass7/vector/Makefile
===================================================================
--- grass-addons/grass7/vector/Makefile 2016-01-06 03:00:33 UTC (rev 67493)
+++ grass-addons/grass7/vector/Makefile 2016-01-06 03:05:44 UTC (rev 67494)
@@ -32,6 +32,7 @@
v.lfp \
v.lidar.mcc \
v.link.precip \
+ v.mapcalc \
v.maxent.swd \
v.median \
v.mrmr \
Added: grass-addons/grass7/vector/v.mapcalc/Makefile
===================================================================
--- grass-addons/grass7/vector/v.mapcalc/Makefile (rev 0)
+++ grass-addons/grass7/vector/v.mapcalc/Makefile 2016-01-06 03:05:44 UTC (rev 67494)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../../grass7.0/grass_trunk
+
+PGM = v.mapcalc
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script
\ No newline at end of file
Added: grass-addons/grass7/vector/v.mapcalc/v.mapcalc.html
===================================================================
--- grass-addons/grass7/vector/v.mapcalc/v.mapcalc.html (rev 0)
+++ grass-addons/grass7/vector/v.mapcalc/v.mapcalc.html 2016-01-06 03:05:44 UTC (rev 67494)
@@ -0,0 +1,113 @@
+<h2>DESCRIPTION</h2>
+
+v.mapcalc performs overlay and buffer functions on vector map layers. New vector map layers can be created which are
+expressions of existing vector map layers, boolean vector operations and buffer functions.
+
+<h3>PROGRAM USE</h3>
+The module expects its input as expression in the following form: <br>
+<br>
+<b> result = expression </b>
+<br>
+<br>
+
+This structure is similar to r.mapcalc, see <a href="r.mapcalc.html">r.mapcalc</a>.
+Where <b>result</b> is the name of a vector map layer that will contain the result of the calculation and
+<b>expression</b> is any valid combination of boolean and buffer operations for existing vector map layers. <br>
+
+The input is given by using the first module option <i>expression=</i> . This option passes a <b>quoted</b>
+expression on the command line, for example: <br>
+<div class="code"><pre>v.mapcalc expression="A = B"</pre></div>
+Where <b>A</b> is the new vector map layer that will be equal to the existing vector map layer <b>B</b> in this case. <br>
+<div class="code"><pre>v.mapcalc "A = B"</pre></div>
+Will give the same result.
+<br>
+<br>
+<h3>OPERATORS AND FUNCTIONS</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>
+
+<h2>NOTES</h2>
+As shown in the operator table above, the boolean vector operators do not have different precedence.
+In default setting the expression will be left associatively evaluated. To define specific precedence use parentheses
+around these expressions, for example: <br>
+
+<div class="code"><pre>
+ v.mapcalc expression="D = A & B | C"
+</pre></div>
+Here the first intermediate result is the intersection of vector map layers <b>A & B</b>.
+This intermediate vector map layer is taken to create the union with vector map <b>C</b> to get the final result <b>D</b>.
+It represents the default behaviour of left associativity.
+
+<div class="code"><pre>
+ v.mapcalc expression="D = A & (B | C)"
+</pre></div>
+Here the first intermediate result is taken from the parenthesized union of vector map layers <b>B | C</b>.
+Afterwards the intersection of the intermediate vector map layer and <b>A</b> will be evaluated to get the final
+result vector map layer <b>D</b>.
+<br>
+<br>
+It should be noticed, that the order in which the operations are performed does matter.
+Different order of operations can lead to a different result.
+
+<h2>EXAMPLES</h2>
+This example needed specific region setting. It should work in UTM and LL test locations. <br>
+First set the regions extent and create two vector maps with one random points, respectively:
+<div class="code"><pre>
+g.region s=0 n=80 w=0 e=120 b=0 t=50 res=10 res3=10 -p3
+
+v.random --o -z output=point_1 n=1 seed=1
+v.info point_1
+v.random --o -z output=point_2 n=1 seed=2
+v.info point_2
+</pre></div>
+
+Then the vector algebra is used to create buffers around those points, cut out a subset and apply different boolean operation on the subsets in one statement:
+<div class="code"><pre>
+v.mapcalc --o expr="buff_and = (buff_p(point_1, 30.0) ~ buff_p(point_1, 20.0)) & \
+ (buff_p(point_2, 35) ~ buff_p(point_2, 25))"
+v.mapcalc --o expr="buff_or = (buff_p(point_1, 30.0) ~ buff_p(point_1, 20.0)) | \
+ (buff_p(point_2, 35) ~ buff_p(point_2, 25))"
+v.mapcalc --o expr="buff_xor = (buff_p(point_1, 30.0) ~ buff_p(point_1, 20.0)) ^ \
+ (buff_p(point_2, 35) ~ buff_p(point_2, 25))"
+v.mapcalc --o expr="buff_not = (buff_p(point_1, 30.0) ~ buff_p(point_1, 20.0)) ~ \
+ (buff_p(point_2, 35) ~ buff_p(point_2, 25))"
+</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="v.overlay.html">v.overlay</a>,
+<a href="v.buffer.html">v.buffer</a>,
+<a href="v.patch.html">v.patch</a>,
+<a href="r.mapcalc.html">r.mapcalc</a>
+</em>
+
+
+<h2>AUTHOR</h2>
+
+Thomas Leppelt, Soeren Gebbert, Thuenen Institut, Germany <br>
+
+<p><i>Last changed: $Date: 2013-06-12 11:35:20 +0100 (Wed, 12 Jun 2013) $</i>
+
Added: grass-addons/grass7/vector/v.mapcalc/v.mapcalc.py
===================================================================
--- grass-addons/grass7/vector/v.mapcalc/v.mapcalc.py (rev 0)
+++ grass-addons/grass7/vector/v.mapcalc/v.mapcalc.py 2016-01-06 03:05:44 UTC (rev 67494)
@@ -0,0 +1,408 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+############################################################################
+#
+# MODULE: v.mapcalc
+# AUTHOR(S): Thomas Leppelt, Soeren Gebbert, Thünen Institut Germany,
+#
+# PURPOSE: Vector map algebra
+# COPYRIGHT: (C) 2011 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.
+#
+#############################################################################
+
+#%module
+#% description: Vector algebra
+#% keywords: vector, mapcalc, algebra
+#%end
+#%option
+#% key: expression
+#% type: string
+#% description: The vector mapcalc expression
+#% key_desc: expression
+#% required : yes
+#%end
+
+import ply.lex as lex
+import ply.yacc as yacc
+import sys
+import re
+import os
+from grass.script import core as grass
+import grass.pygrass.modules as mod
+
+class CmdMapList(object):
+ """Listing and execution of PyGRASS module objects"""
+ def __init__(self):
+ self.exec_list = []
+ # Execute command list.
+ def exec_cmd_list(self):
+ for cmd in self.exec_list:
+ cmd.run()
+ if cmd.popen.returncode != 0:
+ grass.ScriptError("Error starting %s : \n%s"%(cmd.get_bash(), \
+ cmd.popen.stderr))
+ # Print command list.
+ def get_cmd_list(self):
+ print(self.exec_list)
+ # Add new command to list.
+ def add_cmd(self, newcmd):
+ self.exec_list.append(newcmd)
+
+class VectorAlgebraLexer(object):
+ """!Lexical analyzer for the GRASS GIS vector algebra"""
+
+ # Buffer functions from v.buffer
+ vector_buff_functions = {
+ 'buff_p' : 'BUFF_POINT',
+ 'buff_l' : 'BUFF_LINE',
+ 'buff_a' : 'BUFF_AREA'
+ }
+
+ # This is the list of token names.
+ tokens = (
+ 'INT',
+ 'FLOAT',
+ 'LPAREN',
+ 'RPAREN',
+ 'COMMA',
+ 'EQUALS',
+ 'SYMBOL',
+ 'NAME',
+ 'AND', # v.overlay
+ 'NOT', # v.overlay
+ 'OR', # v.overlay
+ 'XOR', # v.overlay
+ 'DISOR', # v.patch
+ )
+
+ # Build the token list
+ tokens = tokens + tuple(vector_buff_functions.values())
+
+ # Regular expression rules for simple tokens
+ t_LPAREN = r'\('
+ t_RPAREN = r'\)'
+ t_COMMA = r','
+ t_EQUALS = r'='
+ t_AND = r'&'
+ t_NOT = r'\~'
+ t_OR = r'\|'
+ t_XOR = r'\^'
+ t_DISOR = r'\+'
+
+ # These are the things that should be ignored.
+ t_ignore = ' \t'
+
+ def __init__(self):
+ self.name_list = {}
+
+ # Read in a float. This rule has to be done before the int rule.
+ def t_FLOAT(self, t):
+ r'-?\d+\.\d*(e-?\d+)?'
+ t.value = float(t.value)
+ return t
+
+ # Read in an int.
+ def t_INT(self, t):
+ r'-?\d+'
+ t.value = int(t.value)
+ return t
+
+ # Ignore comments.
+ def t_comment(self, t):
+ r'[#][^\n]*'
+ pass
+
+ # Track line numbers.
+ def t_newline(self, t):
+ r'\n+'
+ t.lineno += len(t.value)
+
+ # Parse symbols
+ def t_SYMBOL(self, t):
+ r'[a-zA-Z_][a-zA-Z_0-9]*'
+ # Check for reserved words
+ if t.value in VectorAlgebraLexer.vector_buff_functions.keys():
+ t.type = VectorAlgebraLexer.vector_buff_functions.get(t.value)
+ else:
+ t.type = 'NAME'
+ self.name_list[t.value] = t.value
+ 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 = {}
+ self.lexer.input(data)
+ while True:
+ tok = self.lexer.token()
+ if not tok: break
+ print tok
+
+class VectorAlgebraParser(object):
+ """This is the vector algebra parser class"""
+
+ # Get the tokens from the lexer class
+ tokens = VectorAlgebraLexer.tokens
+
+ # Setting equal precedence level for boolean operations.
+ precedence = (
+ ('left', 'AND', 'OR', 'NOT', 'XOR', 'DISOR'), # 1
+ )
+
+ def __init__(self, pid=None, run=True, debug=False):
+ self.run = run
+ self.debug = debug
+ self.pid = pid
+ self.lexer = VectorAlgebraLexer()
+ self.lexer.build()
+ # Intermediate vector map names
+ self.names = {}
+ # Count map names
+ self.count = 0
+ self.parser = yacc.yacc(module=self)
+ # Create empty command list object
+ self.cmdlist = CmdMapList()
+
+ def parse(self, expression):
+ self.count = 0
+ self.parser.parse(expression)
+
+ def generate_vector_map_name(self):
+ """!Generate an unique intermediate vector map name
+ and register it in the objects map list for later removement.
+
+ The vector map names are unique between processes. Do not use the
+ same object for map name generation in multiple threads.
+ """
+ self.count += 1
+ if self.pid != None:
+ pid = self.pid
+ else:
+ pid = os.getpid()
+ name = "tmp_vect_name_%i_%i"%(pid, self.count)
+ self.names[name] = name
+ #print(name)
+ return name
+
+ def p_statement_assign(self,t):
+ """
+ statement : NAME EQUALS expression
+ | NAME EQUALS name
+ | NAME EQUALS paren_name
+ """
+ # We remove the invalid vector name from the list
+ if self.names.has_key(t[3]):
+ self.names.pop(t[3])
+
+ # We rename the resulting vector map
+ if self.debug:
+ print "g.rename vector=%s,%s"%(t[3],t[1])
+
+ if self.run:
+ m = mod.Module("g.rename", vect=(t[3],t[1]), overwrite=grass.overwrite,
+ run_ = False)
+ self.cmdlist.add_cmd(m)
+ self.remove_intermediate_vector_maps()
+
+ def remove_intermediate_vector_maps(self):
+ if self.debug:
+ for name in self.names:
+ print "g.remove vect=%s"%(name)
+ if self.run:
+ for name in self.names:
+ m = mod.Module("g.remove", vect=name, run_ = False)
+ self.cmdlist.add_cmd(m)
+
+ def p_bool_and_operation(self, t):
+ """
+ expression : name AND name
+ | expression AND name
+ | name AND expression
+ | expression AND expression
+ | name OR name
+ | expression OR name
+ | name OR expression
+ | expression OR expression
+ | name XOR name
+ | expression XOR name
+ | name XOR expression
+ | expression XOR expression
+ | name NOT name
+ | expression NOT name
+ | name NOT expression
+ | expression NOT expression
+ | name DISOR name
+ | expression DISOR name
+ | name DISOR expression
+ | expression DISOR expression
+ """
+
+ # Generate an intermediate name
+ name = self.generate_vector_map_name()
+
+ # Assign ids to expressions, names and operators.
+ firstid = 1
+ secondid = 3
+ operatorid = 2
+
+ # Define operation commands.
+ if t[operatorid] == "&":
+ if self.debug:
+ print "v.overlay operator=and ainput=%s binput=%s output=%s"\
+ %(t[firstid], t[secondid], name)
+
+ if self.run:
+ m = mod.Module("v.overlay", operator="and", ainput=t[firstid], \
+ binput=t[secondid], output=name, run_ = False)
+ self.cmdlist.add_cmd(m)
+ t[0] = name
+
+ elif t[operatorid] == "|":
+ if self.debug:
+ print "v.overlay operator=or ainput=%s binput=%s output=%s"\
+ %(t[firstid], t[secondid], name)
+
+ if self.run:
+ m = mod.Module("v.overlay", operator="or", ainput=t[firstid], \
+ binput=t[secondid], output=name, run_ = False)
+ self.cmdlist.add_cmd(m)
+ t[0] = name
+
+ elif t[operatorid] == "^":
+ if self.debug:
+ print "v.overlay operator=xor ainput=%s binput=%s output=%s"\
+ %(t[firstid], t[secondid], name)
+
+ if self.run:
+ m = mod.Module("v.overlay", operator="xor", ainput=t[firstid], \
+ binput=t[secondid], output=name, run_ = False)
+ self.cmdlist.add_cmd(m)
+ t[0] = name
+
+ elif t[operatorid] == "~":
+ if self.debug:
+ print "v.overlay operator=not ainput=%s binput=%s output=%s"\
+ %(t[firstid], t[secondid], name)
+
+ if self.run:
+ m = mod.Module("v.overlay", operator="not", ainput=t[firstid], \
+ binput=t[secondid], output=name, run_ = False)
+ self.cmdlist.add_cmd(m)
+ t[0] = name
+
+ elif t[operatorid] == "+":
+ patchinput = t[firstid] + ',' + t[secondid]
+ if self.debug:
+ print "v.patch input=%s output=%s"\
+ %(patchinput, name)
+
+ if self.run:
+ m = mod.Module("v.patch", input=patchinput, output=name, run_ = False)
+ self.cmdlist.add_cmd(m)
+ t[0] = name
+
+ def p_buffer_operation(self,t):
+ """
+ expression : buff_function LPAREN name COMMA number RPAREN
+ | buff_function LPAREN expression COMMA number RPAREN
+ """
+ # Generate an intermediate name
+ name = self.generate_vector_map_name()
+
+ # Assign ids to expressions, names and operators.
+ mapid = 3
+ operatorid = 5
+
+ if t[1] == "buff_p":
+ if self.debug:
+ print "v.buffer input=%s type=point distance=%g output=%s"\
+ %(t[mapid], t[operatorid], name)
+
+ if self.run:
+ m = mod.Module("v.buffer", type="point", input=t[mapid], \
+ distance=float(t[operatorid]), output=name, \
+ run_ = False)
+ self.cmdlist.add_cmd(m)
+ t[0] = name
+ elif t[1] == "buff_l":
+ if self.debug:
+ print "v.buffer input=%s type=line distance=%g output=%s"\
+ %(t[mapid], t[operatorid], name)
+
+ if self.run:
+ m = mod.Module("v.buffer", type="line", input=t[mapid], \
+ distance=float(t[operatorid]), output=name, \
+ run_ = False)
+ self.cmdlist.add_cmd(m)
+ t[0] = name
+ elif t[1] == "buff_a":
+ if self.debug:
+ print "v.buffer input=%s type=area distance=%g output=%s"\
+ %(t[mapid], t[operatorid], name)
+
+ if self.run:
+ m = mod.Module("v.buffer", type="area", input=t[mapid], \
+ distance=float(t[operatorid]), output=name, \
+ run_ = False)
+ self.cmdlist.add_cmd(m)
+ t[0] = name
+
+ def p_paren_expr(self, t):
+ """ expression : LPAREN expression RPAREN"""
+ t[0] = t[2]
+
+ def p_number_int(self, t):
+ """number : INT"""
+ t[0] = t[1]
+
+ def p_number_float(self, t):
+ """number : FLOAT"""
+ t[0] = t[1]
+
+ def p_name(self, t):
+ """name : NAME
+ | SYMBOL
+ """
+ t[0] = t[1]
+
+ def p_paren_name(self, t):
+ """paren_name : LPAREN NAME RPAREN
+ | LPAREN SYMBOL RPAREN
+ """
+ t[0] = t[2]
+
+ def p_buff_function(self, t):
+ """buff_function : BUFF_POINT
+ | BUFF_LINE
+ | BUFF_AREA
+ """
+ t[0] = t[1]
+
+ # Error rule for syntax errors.
+ def p_error(self,t):
+ raise SyntaxError("invalid syntax")
+
+def main():
+ expression = options['expression']
+
+ p = VectorAlgebraParser(run = True, debug=False)
+ p.parse(expression)
+ p.cmdlist.get_cmd_list()
+ p.cmdlist.exec_cmd_list()
+
+if __name__ == "__main__":
+ options, flags = grass.parser()
+ sys.exit(main())
+
More information about the grass-commit
mailing list