Kaynağa Gözat

v.clip: added to trunk

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@71634 15284696-431f-4ddb-bdfa-cd5b030d7da7
Markus Neteler 7 yıl önce
ebeveyn
işleme
50bf9649c3

+ 1 - 0
scripts/Makefile

@@ -51,6 +51,7 @@ SUBDIRS = \
 	r3.in.xyz \
 	v.build.all \
 	v.centroids \
+	v.clip \
 	v.db.addcolumn \
 	v.db.addtable \
 	v.db.join \

+ 7 - 0
scripts/v.clip/Makefile

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

+ 87 - 0
scripts/v.clip/testsuite/test_v_clip.py

@@ -0,0 +1,87 @@
+"""
+Name:       v.clip test
+Purpose:    Tests v.clip input parsing.
+            Uses NC Basic data set.
+
+Author:     Luca Delucchi
+Copyright:  (C) 2017 by Luca Delucchi and the GRASS Development Team
+Licence:    This program is free software under the GNU General Public
+            License (>=v2). Read the file COPYING that comes with GRASS
+            for details.
+"""
+
+import os
+
+from grass.gunittest.case import TestCase
+from grass.gunittest.main import test
+
+class TestClipling(TestCase):
+    inpclip = 'zipcodes'
+    inpoint = 'hospitals'
+    inlines = 'roadsmajor'
+    inpoly = 'geology'
+    outreg = 'hospreg'
+    outclip = 'hospzip'
+    outline = 'roadsgarner'
+    outpoly = 'geogarner'
+    outdiss = 'geodiss'
+    garner = 'garner'
+
+    @classmethod
+    def setUpClass(cls):
+        """Ensures expected computational region and generated data"""
+        cls.use_temp_region()
+        cls.runModule('g.region', vector=cls.inpclip)
+        cls.runModule('v.extract', input=cls.inpclip, output=cls.garner, 
+                      where="ZIPNAME = '{na}'".format(na=cls.garner.upper()))
+
+    @classmethod
+    def tearDownClass(cls):
+        """Remove the temporary region and generated data"""
+        cls.runModule('g.remove', flags='f', type='vector',
+                      name=(cls.outclip, cls.outreg, cls.garner, cls.outline,
+                            cls.outpoly, cls.outdiss))
+        cls.del_temp_region()
+
+    def test_points(self):
+        """Test clipping points"""
+        self.assertModule('v.clip', input=self.inpoint, clip=self.inpclip,
+                          output=self.outclip)
+        self.assertVectorExists(self.outclip)
+        topology = dict(points=8)
+        self.assertVectorFitsTopoInfo(self.outclip, topology)
+
+    def test_region(self):
+        """Test clipping point by region"""
+        self.assertModule('v.clip', input=self.inpoint, clip=self.inpclip,
+                          output=self.outreg, flags='r')
+        self.assertVectorExists(self.outreg)
+        topology = dict(points=13)
+        self.assertVectorFitsTopoInfo(self.outreg, topology)
+
+    def test_lines(self):
+        """Test clipping lines"""
+        self.assertModule('v.clip', input=self.inlines, clip=self.garner,
+                          output=self.outline)
+        self.assertVectorExists(self.outline)
+        topology = dict(lines=13, nodes=16)
+        self.assertVectorFitsTopoInfo(self.outline, topology)
+
+    def test_poly(self):
+        """Test clipping polygon without dissolve"""
+        self.assertModule('v.clip', input=self.inpoly, clip=self.inpclip,
+                          output=self.outpoly)
+        self.assertVectorExists(self.outpoly)
+        topology = dict(areas=275)
+        self.assertVectorFitsTopoInfo(self.outpoly, topology)
+
+    def test_poly_diss(self):
+        """Test clipping polygon without dissolve"""
+        self.assertModule('v.clip', input=self.inpoly, clip=self.inpclip,
+                          output=self.outdiss, flags='d')
+        self.assertVectorExists(self.outdiss)
+        topology = dict(areas=276)
+        self.assertVectorFitsTopoInfo(self.outdiss, topology)
+
+if __name__ == '__main__':
+    test()

+ 85 - 0
scripts/v.clip/v.clip.html

@@ -0,0 +1,85 @@
+<h2>DESCRIPTION</h2>
+
+<em>v.clip</em> module enables extracting those features of input
+vector map, which overlay features of clip map, as well as their
+storing in a new vector map.
+ 
+<p>In default, boundaries of clip map are dissolved before
+clipping. Alternatively, flag <b>-d</b> can be ticked to retain the
+boundaries of clip map. Flag <b>-b</b> facilitates clipping by current
+computational region.
+
+<p>It is possible to clip vector maps consisting of points, lines,
+areas or combinations of these. However, the current version does not
+fully support clipping of mixed geometry containing points. In such a
+case, the output map will only store clipped lines and/or areas.
+
+<h2>NOTES</h2>
+
+<em>v.clip</em> is a front-end
+to <em><a href="v.overlay.html">v.overlay</a></em>, as well
+as <em><a href="v.select.html">v.select</a></em>. Clipping of areas
+and/or lines can be achieved
+using <em><a href="v.overlay.html">v.overlay</a></em>. Clipping of
+points can be performed
+with <em><a href="v.select.html">v.select<a></em>.
+
+<h2>EXAMPLES</h2>
+
+<h3>Basic use</h3>
+
+Clip railroads by counties Wake and Johnston in North Carolina (North
+Carolina data set).
+
+<div class="code"><pre>
+v.extract input=boundary_county where="NAME='WAKE' OR NAME='JOHNSTON'" output=county_WAKE_JOHNSTON
+v.clip input=railroads clip=county_WAKE_JOHNSTON output=railroads_WAKE_JOHNSTON
+</pre></div>
+
+<center>
+ <img src="v_clip_poly.png" alt="v.clip example" height="255" width="600" ><br>
+ <em>Figure: v.clip example - basic use</em>
+</center>
+
+
+<h3>Retain boundaries of clip map</h3>
+
+<div class="code"><pre>
+v.clip -d input=railroads clip=county_WAKE_JOHNSTON output=railroads_WAKE_JOHNSTON
+</pre></div>
+
+<h3>Clip by current computational region</h3>
+
+Clip hospitals by computational region adjusted to counties Wake and
+Johnston in North Carolina (North Carolina data set).
+
+It is not obligatory to enter name of clip map. In case it is stated,
+the clip map will be omitted.
+
+<div class="code"><pre>
+v.extract input=boundary_county where="NAME='WAKE' OR NAME='JOHNSTON'" output=county_WAKE_JOHNSTON
+v.clip -r input=hospitals output=hospitals_clip
+</pre></div>
+
+<center>
+ <img src="v_clip_region.png" alt="v.clip example" height="259" width="600"><br>
+ <em>Figure: v.clip example - clip by computational region</em>
+</center>
+
+<h2>SEE ALSO</h2>
+
+<em>
+  <a href="v.overlay.html">v.overlay</a>,
+  <a href="v.select.html">v.select</a>, 
+  <a href="v.dissolve.html">v.dissolve</a>,
+  <a href="v.in.region.html">v.in.region</a>
+</em>
+
+<h2>AUTHOR</h2>
+
+Zofie
+Cimburova, <a href="http://geomatics.fsv.cvut.cz/research/geoforall/">GeoForAll
+Lab</a>, Czech Technical University in Prague, Czech Republic
+
+<p>
+<i>Last changed: $Date: 2016-06-28 19:30:00 +0001 (Tue, 28 Jun 2016)$</i>

+ 199 - 0
scripts/v.clip/v.clip.py

@@ -0,0 +1,199 @@
+#!/usr/bin/env python
+
+############################################################################
+#
+# MODULE:       v.clip
+# AUTHOR:       Zofie Cimburova, CTU Prague, Czech Republic
+# PURPOSE:      Clips vector features
+# COPYRIGHT:    (C) 2016 Zofie Cimburova
+#               This program is free software under the GNU General
+#               Public License (>=v2). Read the file COPYING that
+#               comes with GRASS for details.
+#
+#############################################################################
+
+#%module
+#% description: Extracts features of input map which overlay features of clip map.
+#% keyword: vector
+#% keyword: clip
+#% keyword: area
+#%end
+
+#%option G_OPT_V_INPUT
+#% label: Name of vector map to be clipped
+#% key: input
+#%end
+
+#%option G_OPT_V_INPUT
+#% key: clip
+#% label: Name of clip vector map
+#%end
+
+#%option G_OPT_V_OUTPUT
+#% key: output
+#%end
+
+#%flag
+#% key: d
+#% description: Do not dissolve clip map
+#%end
+
+#%flag
+#% key: r
+#% description: Clip by region
+#% suppress_required: yes
+#% guisection: Region
+#%end
+
+# flags -d and -r are mutualy exclusive
+# with flag -r, suppress_required: yes, but input and output must be defined
+#%rules
+#% exclusive: -d, -r
+#% requires_all: -r, input, output
+#%end
+
+import os
+import sys
+import atexit
+
+from grass.script import run_command, message, parser
+import grass.script as grass
+from grass.exceptions import CalledModuleError
+
+TMP = []
+
+
+def cleanup():
+    for name in TMP:
+        try:
+            grass.run_command('g.remove', flags='f',
+                              type='vector', name=name, quiet=True)
+
+        except CalledModuleError as e:
+            grass.fatal(_("Deleting of temporary layer failed. "
+                          "Check above error messages and "
+                          "see following details:\n%s") % e)
+
+
+def section_message(msg):
+    grass.message('{delim}\n{msg}\n{delim}'.format(msg=msg, delim='-' * 80))
+
+
+def main():
+    input_map = opt['input']
+    clip_map = opt['clip']
+    output_map = opt['output']
+
+    flag_dissolve = flg['d']
+    flag_region = flg['r']
+
+    # ======================================== #
+    # ========== INPUT MAP TOPOLOGY ========== #
+    # ======================================== #
+    vinfo = grass.vector_info_topo(input_map)
+
+    # ==== only points ==== #
+    if (vinfo['points'] > 0 and vinfo['lines'] == 0 and vinfo['areas'] == 0):
+
+        # ==================================== #
+        # ========== CLIP BY REGION ========== #
+        # ==================================== #
+        if (flag_region):
+            clip_by_region(input_map, output_map, clip_select)
+
+        # ================================== #
+        # ========== DEFAULT CLIP ========== #
+        # ================================== #
+        else:
+            section_message("Clipping.")
+            # perform clipping
+            clip_select(input_map, clip_map, output_map)
+
+    # ==== lines, areas, lines + areas ==== #
+    # ==== points + areas, points + lines, points + areas + lines ==== #
+    else:
+        if (vinfo['points'] > 0):
+            grass.warning("Input map contains multiple geometry, "
+                          "only lines and areas will be clipped.")
+
+        # ==================================== #
+        # ========== CLIP BY REGION ========== #
+        # ==================================== #
+        if (flag_region):
+            clip_by_region(input_map, output_map, clip_overlay)
+
+        # ===================================================== #
+        # ========== CLIP WITHOUT DISSOLVED CLIP MAP ========== #
+        # ===================================================== #
+        elif (flag_dissolve):
+            section_message("Clipping without dissolved clip map.")
+            clip_overlay(input_map, clip_map, output_map)
+
+        # ========================================================== #
+        # ========== DEFAULT CLIP WITH DISSOLVED CLIP MAP ========== #
+        # ========================================================== #
+        else:
+            section_message("Default clipping with dissolved clip map.")
+
+            # setup temporary map
+            temp_clip_map = '%s_%s' % ("temp", str(os.getpid()))
+            TMP.append(temp_clip_map)
+
+            # dissolve clip_map
+            grass.run_command('v.dissolve', input=clip_map,
+                              output=temp_clip_map)
+
+            # perform clipping
+            clip_overlay(input_map, temp_clip_map, output_map)
+
+    # ======================================== #
+    # ========== OUTPUT MAP TOPOLOGY========== #
+    # ======================================== #
+    vinfo = grass.vector_info_topo(output_map)
+    if vinfo['primitives'] == 0:
+        grass.warning("Output map is empty.")
+
+    return 0
+
+
+# clip input map by computational region
+# clip_select for points, clip_overlay for areas and lines
+def clip_by_region(input_map, output_map, clip_fn):
+    section_message("Clipping by region.")
+
+    # setup temporary map
+    temp_region_map = '%s_%s' % ("temp", str(os.getpid()))
+    TMP.append(temp_region_map)
+
+    # create a map covering current computational region
+    grass.run_command('v.in.region', output=temp_region_map)
+
+    # perform clipping
+    clip_fn(input_map, temp_region_map, output_map)
+
+
+def clip_overlay(input_data, clip_data, out_data):
+    try:
+        grass.run_command('v.overlay', ainput=input_data, binput=clip_data,
+                          operator='and', output=out_data, olayer='0,1,0')
+    except CalledModuleError as e:
+        grass.fatal(_("Clipping steps failed."
+                      " Check above error messages and"
+                      " see following details:\n%s") % e)
+
+
+def clip_select(input_data, clip_data, out_data):
+    try:
+        grass.run_command('v.select', ainput=input_data, binput=clip_data,
+                          output=out_data, operator='overlap')
+
+    except CalledModuleError as e:
+        grass.fatal(_("Clipping steps failed."
+                      " Check above error messages and"
+                      " see following details:\n%s") % e)
+
+
+if __name__ == "__main__":
+    atexit.register(cleanup)
+    opt, flg = parser()
+    sys.exit(main())

BIN
scripts/v.clip/v_clip_poly.png


BIN
scripts/v.clip/v_clip_region.png


+ 1 - 0
vector/v.overlay/v.overlay.html

@@ -264,6 +264,7 @@ v.overlay ainput=roadsmajor atype=line binput=raleigh out=roadsmajor_raleigh ope
 <h2>SEE ALSO</h2>
 
 <em>
+<a href="v.clip.html">v.clip</a>,
 <a href="v.db.connect.html">v.db.connect</a>,
 <a href="v.select.html">v.select</a>,
 <a href="g.copy.html">g.copy</a>

+ 1 - 0
vector/v.select/v.select.html

@@ -302,6 +302,7 @@ speed-up is desired.
 
 <em>
 <a href="v.category.html">v.category</a>,
+<a href="v.clip.html">v.clip</a>,
 <a href="v.overlay.html">v.overlay</a>,
 <a href="v.extract.html">v.extract</a>
 </em>