[GRASS-SVN] r72616 - grass-addons/grass7/vector/v.clean.ogr

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Apr 10 13:10:08 PDT 2018


Author: mmetz
Date: 2018-04-10 13:10:08 -0700 (Tue, 10 Apr 2018)
New Revision: 72616

Added:
   grass-addons/grass7/vector/v.clean.ogr/Makefile
   grass-addons/grass7/vector/v.clean.ogr/v.clean.ogr.html
   grass-addons/grass7/vector/v.clean.ogr/v.clean.ogr.py
Log:
new addon v.clean.ogr to pipe non-topological polygons through GRASS

Added: grass-addons/grass7/vector/v.clean.ogr/Makefile
===================================================================
--- grass-addons/grass7/vector/v.clean.ogr/Makefile	                        (rev 0)
+++ grass-addons/grass7/vector/v.clean.ogr/Makefile	2018-04-10 20:10:08 UTC (rev 72616)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../..
+
+PGM = v.clean.ogr
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script


Property changes on: grass-addons/grass7/vector/v.clean.ogr/Makefile
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/x-makefile
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: grass-addons/grass7/vector/v.clean.ogr/v.clean.ogr.html
===================================================================
--- grass-addons/grass7/vector/v.clean.ogr/v.clean.ogr.html	                        (rev 0)
+++ grass-addons/grass7/vector/v.clean.ogr/v.clean.ogr.html	2018-04-10 20:10:08 UTC (rev 72616)
@@ -0,0 +1,80 @@
+<h2>DESCRIPTION</h2>
+
+<em>v.clean.ogr</em> cleans non-topological polygons in an OGR 
+datasource by importing, cleaning, and exporting these polgons. This 
+module should not be used with polygons that are correctly overlapping, 
+e.g. buffers.
+<p>
+<em>v.clean.ogr</em> imports vector data from files and database 
+connections supported by the <a href="http://gdal.org/">OGR</a> library 
+into a temporary location. Only one input layer is imported.
+<p>
+Polygons in the input layer are automatically cleaned during impport. 
+More thorough cleaning can be achieved by using the <b>snap</b> and 
+<b>min_area</b> options. 
+<p>
+The cleaned result is exported to the selected <b>output</b> datasource 
+with "_clean" appended to the input layer name. Any overlaps 
+are exported with "_overlaps" appended to the input layer name.
+
+<h3>Supported Vector Formats</h3>
+
+<em>v.clean.ogr</em> uses the OGR library which supports various vector data
+formats including <a href="http://gdal.org/drv_geopackage.html">GeoPackage</a>, 
+<a href="http://www.gdal.org/drv_shapefile.html">ESRI Shapefile</a>, 
+<a href="http://www.gdal.org/drv_mitab.html">Mapinfo File</a>, UK .NTF, 
+SDTS, TIGER, IHO S-57 (ENC), DGN, GML, GPX, AVCBin, REC, Memory, OGDI, 
+and PostgreSQL, depending on the local OGR installation. For details see 
+the <a href="http://www.gdal.org/ogr_formats.html">OGR web site</a>. The 
+OGR (Simple Features Library) is part of the <a 
+href="http://www.gdal.org">GDAL</a> library, hence GDAL needs to be 
+installed to use <em>v.clean.ogr</em>.
+
+<p>
+The list of actually supported formats can be printed by <b>-f</b> flag.
+
+<h2>NOTES</h2>
+
+<h3>Topology cleaning</h3>
+
+When importing polygons, non-topological polygons are converted to 
+topological areas. If the input polygons contain errors (unexpected 
+overlapping areas, small gaps between polygons, or warnings about being 
+unable to calculate centroids), the import might need to be repeated 
+using a <em>snap</em> value as suggested in the output messages.
+
+<p>
+The <em>snap</em> threshold defines the maximal distance from one to another
+vertex in map units (for latitude-longitude locations in degree). If there
+is no other vertex within <em>snap</em> distance, no snapping will be done.
+Note that a too large value can severely damage area topology, beyond repair.
+<p>
+Further cleaning can be achieved by removing small areas using the 
+<b>min_area</b> option. Note that units are always squaremeters. Values 
+for <b>min_area</b> should generally be small, a value of 0.5 can already 
+clean up lots of artefacts.
+
+<h2>EXAMPLE</h2>
+
+Cleaning polygons in a Shapefile in the current directory <em>research_area</em>
+<div class="code"><pre>
+v.clean.ogr input=research_area layer=research_area output=research_area \
+            snap=1e-4 min_area=1 -u --overwrite
+</pre></div>
+Two new Shapefile layers "research_area_clean" and 
+"research_area_overlaps" may be created in the same directory.
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="v.in.ogr.html">v.in.ogr</a>,
+<a href="v.clean.html">v.clean</a>,
+<a href="v.out.ogr.html">v.out.ogr</a>
+</em>
+
+<h2>AUTHORS</h2>
+
+Markus Metz<br>
+
+<p>
+<i>Last changed: $Date$</i>


Property changes on: grass-addons/grass7/vector/v.clean.ogr/v.clean.ogr.html
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/html
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: grass-addons/grass7/vector/v.clean.ogr/v.clean.ogr.py
===================================================================
--- grass-addons/grass7/vector/v.clean.ogr/v.clean.ogr.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.clean.ogr/v.clean.ogr.py	2018-04-10 20:10:08 UTC (rev 72616)
@@ -0,0 +1,310 @@
+#!/usr/bin/env python
+############################################################################
+#
+# MODULE:       v.clean.ogr
+# AUTHOR(S):    Markus Metz
+# PURPOSE:      Import, clean, and export an OGR layer
+# COPYRIGHT:    (C) 2018 by the GRASS Development Team
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+############################################################################
+
+#%module
+#% description: Imports vector data into a GRASS vector map, cleans the data, and exports them again using OGR library.
+#% keyword: vector
+#% keyword: cleaning
+#% keyword: OGR
+#% keyword: topology
+#% keyword: geometry
+#% keyword: snapping
+#%end
+
+# input options
+
+#%option
+#% key: input
+#% type: string
+#% required: yes
+#% multiple: no
+#% label: Name of OGR datasource to be imported
+#% description: Example: directory containing shapefiles
+#% gisprompt: old,datasource,datasource
+#% guisection: Input
+#%end
+#%option
+#% key: layer
+#% type: string
+#% required: yes
+#% multiple: no
+#% label: OGR layer name.
+#% description: Examples: shapefile name without .shp
+#% gisprompt: old,datasource_layer,datasource_layer
+#% guisection: Input
+#%end
+#%option
+#% key: where
+#% type: string
+#% required: no
+#% multiple: no
+#% key_desc: sql_query
+#% label: WHERE conditions of SQL statement without 'where' keyword
+#% description: Example: income < 1000 and population >= 10000
+#% gisprompt: old,sql_query,sql_query
+#% guisection: Selection
+#%end
+#%option
+#% key: encoding
+#% type: string
+#% required: no
+#% multiple: no
+#% label: Encoding value for attribute data
+#% description: Overrides encoding interpretation, useful when importing ESRI Shapefile
+#% guisection: Attributes
+#%end
+#%option
+#% key: key
+#% type: string
+#% required: no
+#% multiple: no
+#% label: Name of column used for categories
+#% description: If not given, categories are generated as unique values and stored in 'cat' column
+#% guisection: Attributes
+#%end
+#%option
+#% key: geometry
+#% type: string
+#% required: no
+#% multiple: no
+#% key_desc: name
+#% label: Name of geometry column
+#% description: If not given, all geometry columns from the input are used
+#% gisprompt: old,dbcolumn,dbcolumn
+#% guisection: Selection
+#%end
+#%flag
+#% key: l
+#% suppress_required: yes
+#% description: List available OGR layers in data source and exit
+#% guisection: Input
+#%end
+
+# cleaning options
+
+#%option
+#% key: snap
+#% type: double
+#% required: no
+#% multiple: no
+#% label: Snapping threshold for boundaries (map units)
+#% description: '-1' for no snap
+#% answer: -1
+#% guisection: Cleaning
+#%end
+#%option
+#% key: min_area
+#% type: double
+#% required: no
+#% multiple: no
+#% label: Minimum size of areas to be retained in output (square meters)
+#% description: Disabled with values <= 0
+#% answer: 0
+#% guisection: Cleaning
+#%end
+
+# output options
+
+#%option
+#% key: output
+#% type: string
+#% required: yes
+#% multiple: no
+#% key_desc: name
+#% label: Name of output OGR datasource
+#% description: Examples: filename for a GeoPackage, directory for shapefiles
+#% gisprompt: new,file,file
+#% guisection: Output
+#%end
+#%option
+#% key: format
+#% type: string
+#% required: yes
+#% multiple: no
+#% description: Data format to write
+#% answer: GPKG
+#% guisection: Output
+#%end
+#%flag
+#% key: u
+#% description: Open an existing output OGR datasource for update
+#% guisection: Output
+#%end
+#%flag
+#% key: f
+#% suppress_required: yes
+#% description: List supported output formats and exit
+#% guisection: Output
+#%end
+
+import sys
+import os
+import atexit
+
+import grass.script as grass
+from grass.exceptions import CalledModuleError
+
+# initialize global vars
+TMPLOC = None
+SRCGISRC = None
+GISDBASE = None
+
+def cleanup():
+    # remove temp location
+    if TMPLOC:
+        grass.try_rmdir(os.path.join(GISDBASE, TMPLOC))
+    if SRCGISRC:
+        grass.try_remove(SRCGISRC)
+
+def main():
+    indsn = options['input']
+    inlayer = options['layer']
+    inwhere = options['where']
+    inenc = options['encoding']
+    inkey = options['key']
+    ingeom = options['geometry']
+    listlayers = flags['l']
+    
+    min_area = options['min_area']
+
+    outdsn = options['output']
+    outformat = options['format']
+    outclean = "%s_clean" % inlayer
+    outoverlaps = "%s_overlaps" % inlayer
+
+    overwrite = grass.overwrite()
+
+    # list input layers
+    if flags['l']:
+	try:
+	    grass.run_command('v.in.ogr', input=indsn, flags = 'l')
+	except CalledModuleError:
+	    grass.fatal(_("Unable to list layers in OGR datasource <%s>") % indsn)
+	return 0
+
+    # list output formats
+    if flags['f']:
+	grass.run_command('v.out.ogr', flags = 'l')
+	return 0
+
+    # import options
+    vopts = {}
+    if options['encoding']:
+        vopts['encoding'] = options['encoding']
+    if options['where']:
+        vopts['where'] = options['where']
+    if options['geometry']:
+        vopts['geometry'] = options['geometry']
+    if options['key']:
+        vopts['key'] = options['key']
+    if options['snap']:
+        vopts['snap'] = options['snap']
+    
+    # create temp location from input without import
+    grassenv = grass.gisenv()
+    tgtloc = grassenv['LOCATION_NAME']
+    tgtmapset = grassenv['MAPSET']
+    GISDBASE = grassenv['GISDBASE']
+    tgtgisrc = os.environ['GISRC']
+    SRCGISRC = grass.tempfile()
+
+    TMPLOC = 'temp_import_location_' + str(os.getpid())
+
+    f = open(SRCGISRC, 'w')
+    f.write('MAPSET: PERMANENT\n')
+    f.write('GISDBASE: %s\n' % GISDBASE)
+    f.write('LOCATION_NAME: %s\n' % TMPLOC)
+    f.write('GUI: text\n')
+    f.close()
+
+    grass.verbose(_("Creating temporary location for <%s>...") % indsn)
+    try:
+        grass.run_command('v.in.ogr', input=indsn,
+                          location=TMPLOC, flags='i', quiet=True, overwrite=overwrite, **vopts)
+    except CalledModuleError:
+        grass.fatal(_("Unable to create location from OGR datasource <%s>") % indsn)
+
+    # switch to temp location
+    os.environ['GISRC'] = str(SRCGISRC)
+
+    outvect = 'vector_clean'
+    outvect_tmp = 'vector_clean'
+    if float(min_area) > 0:
+	outvect_tmp = 'vector_clean_import'
+
+    # import into temp location
+    grass.message(_("Importing <%s>, layer <%s> ...") % (indsn, inlayer))
+    try:
+        grass.run_command('v.in.ogr', input=indsn, layer=inlayer,
+                          output=outvect_tmp, overwrite=overwrite, **vopts)
+    except CalledModuleError:
+        grass.fatal(_("Unable to import OGR datasource <%s>") % indsn)
+    
+    # remove small areas
+    if float(min_area) > 0:
+	grass.message(_("Removing small areas in data source <%s>, layer <%s> ...") % (indsn, inlayer))
+	try:
+	    grass.run_command('v.clean', input=outvect_tmp, output=outvect,
+			      type='area', tool='rmarea', threshold=min_area, overwrite=overwrite)
+	except CalledModuleError:
+	    grass.fatal(_("Removing small areas in data source <%s>, layer <%s> failed") % (indsn, inlayer))
+    
+    # export
+    oflags = 'sm'
+    if flags['u']:
+	oflags = 'smu'
+	overwrite = True
+
+    outlayer = '%s_clean' % inlayer
+    grass.message=(_("Exporting cleaned layer as <%s>") % outlayer)
+    try:
+	grass.run_command('v.out.ogr', input=outvect, layer='1', output=outdsn, 
+	                  output_layer=outlayer, format=outformat, flags=oflags,
+			  overwrite=overwrite)
+    except CalledModuleError:
+        grass.fatal(_("Unable to export to OGR datasource <%s>") % outdsn)
+
+    # export any overlaps
+    outlayers = grass.read_command('v.category', input=outvect, option='layers')
+
+    nlayers = len(outlayers.splitlines())
+    #for layer in outlayers.splitlines():
+    #    nlayers += 1
+
+    if nlayers == 2:
+	outlayer = '%s_overlaps' % inlayer
+	oflags = 'smu'
+	grass.message=(_("Exporting overlaps as <%s>") % outlayer)
+	try:
+	    grass.run_command('v.out.ogr', input=outvect, layer='2', output=outdsn, 
+			      output_layer=outlayer, format=outformat, flags=oflags,
+			      overwrite=True)
+	except CalledModuleError:
+	    grass.fatal(_("Unable to export to OGR datasource <%s>") % outdsn)
+    
+    # switch to target location
+    os.environ['GISRC'] = str(tgtgisrc)
+
+    return 0
+
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    atexit.register(cleanup)
+    sys.exit(main())


Property changes on: grass-addons/grass7/vector/v.clean.ogr/v.clean.ogr.py
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/x-python
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property


More information about the grass-commit mailing list