#!/usr/bin/env python # -*- coding: utf-8 -*- ############################################################################ # # MODULE: v.to.lines (former v.polytoline) # AUTHOR(S): Luca Delucchi # point support added by Markus Neteler # # PURPOSE: Converts polygons and points to lines # COPYRIGHT: (C) 2013-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. # TODO # support centroids (treat as points)? ############################################################################# #%module #% description: Converts vector polygons or points to lines. #% keyword: vector #% keyword: geometry #% keyword: area #% keyword: line #% keyword: point #%end #%option G_OPT_V_INPUT #%end #%option G_OPT_V_OUTPUT #%end #%option #% key: method #% type: string #% description: Method used for point interpolation #% options: delaunay #% answer: delaunay #% guisection: Area #%end import grass.script as grass from grass.script.utils import decode from grass.exceptions import CalledModuleError import os def main(): # Get the options input = options["input"] input_name = input.split('@')[0] output = options["output"] method = options["method"] min_cat = None max_cat = None point = None overwrite = grass.overwrite() quiet = True if grass.verbosity() > 2: quiet = False in_info = grass.vector_info(input) # check for wild mixture of vector types if in_info['points'] > 0 and in_info['boundaries'] > 0: grass.fatal(_("The input vector map contains both polygons and points," " cannot handle mixed types")) pid = os.getpid() # process points via triangulation, then exit if in_info['points'] > 0: point = True layer = 1 # hardcoded for now out_temp = '{inp}_point_tmp_{pid}'.format(inp=input_name, pid=pid) if method == 'delaunay': grass.message(_("Processing point data (%d points found)...") % in_info['points']) grass.run_command('v.delaunay', input=input, layer=layer, output=out_temp, quiet=quiet) grass.run_command('v.db.addtable', map=out_temp, quiet=True) input = out_temp in_info = grass.vector_info(input) # process areas if in_info['areas'] == 0 and in_info['boundaries'] == 0: grass.fatal(_("The input vector map does not contain polygons")) out_type = '{inp}_type_{pid}'.format(inp=input_name, pid=pid) input_tmp = '{inp}_tmp_{pid}'.format(inp=input_name, pid=pid) remove_names = "%s,%s" % (out_type, input_tmp) grass.message(_("Processing area data (%d areas found)...") % in_info['areas']) try: grass.run_command('v.category', layer="2", type='boundary', option='add', input=input, out=input_tmp, quiet=quiet) except CalledModuleError: grass.run_command('g.remove', flags='f', type='vector', name=input_tmp, quiet=quiet) grass.fatal(_("Error creating layer 2")) try: grass.run_command('v.db.addtable', map=input_tmp, layer="2", columns="left integer,right integer", quiet=quiet) except CalledModuleError: grass.run_command('g.remove', flags='f', type='vector', name=input_tmp, quiet=quiet) grass.fatal(_("Error creating new table for layer 2")) try: grass.run_command('v.to.db', map=input_tmp, option="sides", columns="left,right", layer="2", quiet=quiet) except CalledModuleError: grass.run_command('g.remove', flags='f', type='vector', name=input_tmp, quiet=quiet) grass.fatal(_("Error populating new table for layer 2")) try: grass.run_command('v.type', input=input_tmp, output=out_type, from_type='boundary', to_type='line', quiet=quiet, layer="2") except CalledModuleError: grass.run_command('g.remove', flags='f', type='vector', name=remove_names, quiet=quiet) grass.fatal(_("Error converting polygon to line")) report = grass.read_command('v.category', flags='g', input=out_type, option='report', quiet=quiet) report = decode(report).split('\n') for r in report: if r.find('centroid') != -1: min_cat = report[0].split()[-2] max_cat = report[0].split()[-1] break if min_cat and max_cat: try: grass.run_command('v.edit', map=out_type, tool='delete', type='centroid', layer=2, quiet=quiet, cats='{mi}-{ma}'.format(mi=min_cat, ma=max_cat)) except CalledModuleError: grass.run_command('g.remove', flags='f', type='vector', name=remove_names, quiet=quiet) grass.fatal(_("Error removing centroids")) try: try: # TODO: fix magic numbers for layer here and there grass.run_command('v.db.droptable', map=out_type, layer=1, flags='f', quiet=True) except CalledModuleError: grass.run_command('g.remove', flags='f', type='vector', name=remove_names, quiet=quiet) grass.fatal(_("Error removing table from layer 1")) # TODO: when this except is happaning, it seems that never, so it seems wrong except: grass.warning(_("No table for layer %d" % 1)) try: grass.run_command('v.category', input=out_type, option='transfer', output=output, layer="2,1", quiet=quiet, overwrite=overwrite) except CalledModuleError: grass.run_command('g.remove', flags='f', type='vector', name=remove_names, quiet=quiet) grass.fatal(_("Error adding categories")) grass.run_command('g.remove', flags='f', type='vector', name=remove_names, quiet=quiet) if point: grass.run_command('g.remove', flags='f', type='vector', name=out_temp, quiet=quiet) if __name__ == "__main__": options, flags = grass.parser() main()