#!/bin/bash # ############################################################################ # # MODULE: v.flip # # AUTHOR(S): Maciej Sieczka, sieczka@biol.uni.wroc.pl # Intitute of Plant Biology, Wroclaw University, Poland # # PURPOSE: Flip direction of selected vector lines. # # VERSION: 1.7, developed over Grass 6.1 CVS 2006.05.19 # # COPYRIGHT: (c) 2006 Maciej Sieczka # # NOTES: Developed within the course and for the purpose of the CAVES # project http://caves.cfpm.org, funded under the EU 6FP NEST # programme. # # This program is free software under the GNU General Public # License (>=v2). Read the file COPYING that comes with GRASS # for details. # ############################################################################# # CHANGELOG: # 1.6, 2006.05.19: # - first public release # 1.7, 2007.01.30: # - cosmetics #%Module #% description: Flip direction of selected vector lines. #%END #%option #% key: input #% type: string #% gisprompt: old,vector,vector #% description: Input vector name #% required : yes #%END #%option #% key: layer #% type: string #% description: Input's layer containing lines to be flipped #% required : yes #%END #%option #% key: cat #% type: string #% description: Category ranges of lines to be flipped (e.g. 1,3-8,13) #% required : yes #%END #%option #% key: output #% type: string #% gisprompt: new,dig,vector #% description: Output vector name #% required : yes #%END # called from Grass? if test "$GISBASE" = ""; then echo "ERROR: You must be in GRASS GIS to run this program." >&2 exit 1 fi if [ "$1" != "@ARGS_PARSED@" ] ; then exec g.parser "$0" "$@" fi PROG=`basename $0` # check if we have awk if [ ! -x "`which awk`" ] ; then echo "ERROR: awk required, please install awk or gawk first." 2>&1 exit 1 fi # set environment so that awk works properly in all languages unset LC_ALL export LC_NUMERIC=C # set up temporary files TMP="`g.tempfile pid=$$`" if [ $? -ne 0 ] || [ -z "$TMP" ] ; then echo "ERROR: Unable to create temporary files." 1>&2 exit 1 fi cleanup() { \rm -f $TMP $TMP.${PROG} $TMP.${PROG}.flip $TMP.${PROG}.meta $TMP.${PROG}.data $TMP.${PROG}.head $TMP.${PROG}.cat_toflip $TMP.${PROG}.cat_all $TMP.${PROG}.cat_asis $TMP.${PROG}.cat_asis_short $TMP.${PROG}.start_stop } # what to do in case of user break: exitprocedure() { echo "User break!" cleanup exit 1 } # shell check for user break (signal list: trap -l) trap "exitprocedure" 2 3 15 INPUT="$GIS_OPT_INPUT" OUTPUT="$GIS_OPT_OUTPUT" CAT="$GIS_OPT_CAT" LAYER="$GIS_OPT_LAYER" for i in toflip leaveasis flipped patched; do g.findfile elem=vector file=${OUTPUT}_$i > /dev/null if [ $? -eq 0 ] ; then echo "ERROR: Intermediate vector <${OUTPUT}_$i> already exists." 1>&2 exit 1 fi done ### DO IT ### # is a table connected to the given layer? v.db.connect -p layer=$LAYER map=$INPUT >/dev/null 2>&1 CNCTSTAT=$? if [ "$CNCTSTAT" -eq "0" ]; then # extract the database connection settings of the input vector cnct=`v.db.connect -g layer=$LAYER map=$INPUT` tbl=`echo $cnct | cut -d " " -f2` key=`echo $cnct | cut -d " " -f3` dbs=`echo $cnct | cut -d " " -f4` drv=`echo $cnct | cut -d " " -f5` fi # extract lines to be reverted into separate vector v.extract -t layer=$LAYER input=$INPUT list=$CAT output="${OUTPUT}_toflip" > /dev/null #transform it to ascii for reverting lines v.out.ascii input="${OUTPUT}_toflip" format=standard > $TMP.${PROG}.flip # get categories of lines NOT to be reverted v.category layer=$LAYER input="${OUTPUT}_toflip" option=print > $TMP.${PROG}.cat_toflip v.category layer=$LAYER input=$INPUT option=print > $TMP.${PROG}.cat_all cat $TMP.${PROG}.cat_toflip $TMP.${PROG}.cat_all | sort -n | uniq -u > $TMP.${PROG}.cat_asis # translate long category list like "1,2,3,...,100" to "1-100" # (to avoid hitting the 4096 chars Bash variable limit) awk ' {if (NR==1) {prev=$1; print} else {if ($1==prev+1) {foll="-"$1} else {print foll; print ","$1; foll=""} prev=$1} } END {print foll} ' $TMP.${PROG}.cat_asis | grep . > $TMP.${PROG}.cat_asis_short asis=`cat $TMP.${PROG}.cat_asis_short` asis=`echo $asis | sed 's/ //g'` # extract lines NOT to be reverted into a separate vector v.extract -t layer=$LAYER input=$INPUT list=$asis output="${OUTPUT}_leaveasis" > /dev/null # extract header from to-be-reverted vector (for later patching) awk '(NR<11)' $TMP.${PROG}.flip > $TMP.${PROG}.head # extract vector type, number of lines and categories (for later patching) awk ' {if ((NR>10) && ($1=="L") || ($1=='$LAYER')) {print} else if (NR>10) {print""}} ' $TMP.${PROG}.flip > $TMP.${PROG}.meta # get starting and ending lines of each line feature awk ' ($1 == "L") {print FNR+1","$2+FNR} ' $TMP.${PROG}.flip > $TMP.${PROG}.start_stop # pipe vertices into a file... for a in `cat $TMP.${PROG}.start_stop`; do echo >> $TMP.${PROG}.data # ...reverting lines at the same time (tac) cat $TMP.${PROG}.flip | sed -n "$a p" | tac >> $TMP.${PROG}.data # empty echoes are to make empty lines where needed echo >> $TMP.${PROG}.data done # merge header, data and meta into final, reverted ascii vector paste -d '' $TMP.${PROG}.data $TMP.${PROG}.meta >> $TMP.${PROG}.head echo v.in.ascii input=$TMP.${PROG}.head output="${OUTPUT}_flipped" format=standard > /dev/null # patch reverted and left-as-is, clean to snap nodes v.patch input="${OUTPUT}_leaveasis","${OUTPUT}_flipped" output="${OUTPUT}_patched" > /dev/null echo v.clean input="${OUTPUT}_patched" output=$OUTPUT type=line tool=snap thresh=0.0001 > /dev/null echo ### ALL DONE ### cleanup g.remove vect="${OUTPUT}_toflip","${OUTPUT}_leaveasis","${OUTPUT}_flipped","${OUTPUT}_patched" > /dev/null if [ "$CNCTSTAT" -eq "0" ]; then # copy the original table using the OUTPUT vector name, and connect to the OUTPUT db.copy from_driver=$drv from_database=$dbs from_table=$tbl to_driver=$drv to_database=$dbs to_table=$OUTPUT > /dev/null v.db.connect map=$OUTPUT layer=$LAYER driver=$drv database=$dbs table=$OUTPUT key=$key > /dev/null fi echo