Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 596 lines (478 sloc) 14.8 KB
#!/bin/sh
############################################################################
#
# MODULE: d.frontline
# AUTHOR(S): Alexander Muriy
# (Institute of Environmental Geoscience, Moscow, Russia)
# e-mail: amuriy AT gmail DOT com
#
# PURPOSE: Displays frontlines on the graphic monitor using d.graph
# (optionally save graph file and ps.map file)
#
# COPYRIGHT: (C) 05-06/2011 Alexander Muriy / 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: Display different types of frontlines on the graphic monitor using d.graph (optionally save graph file and ps.map file)
#% keywords: display, graphics, vector, symbology
#%End
#%Option
#% key: map
#% type: string
#% required: yes
#% multiple: no
#% key_desc: name
#% description: Name of input vector map
#% gisprompt: old,vector,vector
#% guisection: Select
#%End
#%Option
#% key: where
#% type: string
#% description: The WHERE statement for data filtering
#% label: WHERE conditions of SQL query statement without 'where' keyword
#% required : no
#% guisection: Select
#%End
#%Option
#% key: hcolor
#% type: string
#% description: Standard color name or R:G:B
#% label: Highlight color for vector interactive selecting
#% required : no
#% answer: yellow
#% gisprompt: old_color,color,color
#% guisection: Select
#%End
#%Option
#% key: list
#% type: string
#% description: Example: 1,3,7-9,13
#% label: Category number(s)
#% required : no
#% guisection: Select
#%End
#%Option
#% key: layer
#% type: integer
#% label: Layer number. If -1, all layers are extracted.
#% description: A single vector map can be connected to multiple database tables. This number determines which table to use.
#% required : no
#% answer: 1
#% guisection: Select
#%End
#%Option
#% key: side
#% type: string
#% description: Side of the frontline
#% options: left,right,both
#% answer: left
#%End
#%Option
#% key: interval
#% type: double
#% required: yes
#% description: Interval between symbols (in mapset units)
#%End
#%Option
#% key: symbol
#% type: string
#% required: yes
#% multiple: no
#% description: Type of symbol (<front/...> symbols will be produced by script at first use: front/arrow_int, front/arrow_ext, front/box, front/circle, front/half_box, front/line, front/triangle). May be any symbol from $GISBASE/etc/symbol/ or $MAPSET/symbol/ directories.
#% guisection: Symbol
#%End
#%Option
#% key: size
#% type: integer
#% required: no
#% description: Symbol size
#% answer: 20
#% guisection: Symbol
#%End
#%Option
#% key: line_color
#% type: string
#% required: no
#% description: Color for line (standard color name or R:G:B)
#% answer: black
#% gisprompt: old_color,color,color
#% guisection: Symbol
#%End
#%Option
#% key: fill_color
#% type: string
#% required: no
#% description: Color for fill (standard color name or R:G:B)
#% answer: grey
#% gisprompt: old_color,color,color
#% guisection: Symbol
#%End
#%Option
#% key: width
#% type: integer
#% required: no
#% description: Width of symbol's line
#% answer: 0
#% guisection: Symbol
#%End
#%Option
#% key: graph
#% type: string
#% required: no
#% multiple: no
#% key_desc: name
#% description: Output file to save the d.graph commands
#% gisprompt: new_file,file,output
#%End
#%Option
#% key: psmap
#% type: string
#% required: no
#% multiple: no
#% key_desc: name
#% description: Output file to save the ps.map commands
#% gisprompt: new_file,file,output
#%End
#%Flag
#% key: m
#% description: Select vector features interactively (with a mouse)
#% guisection: Select
#%End
#%Flag
#% key: s
#% description: Save graphics commands in file(s) (for use with d.graph and/or ps.map)
#%End
if [ -z "$GISBASE" ] ; then
echo "You must be in GRASS GIS to run this program." 1>&2
exit 1
fi
if [ "$1" != "@ARGS_PARSED@" ] ; then
exec g.parser "$0" "$@"
fi
## set environment so that awk works properly in all languages ##
unset LC_ALL
export LC_NUMERIC=C
############################################################
cleanup()
{
g.mremove -f vect="TMP*" --quiet
\rm -f $TMP1* $TMP2* $TMP3* $TMP4* $TMP5*
}
############################################################
## 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
############################################################
## check for awk
if [ ! -x "$(which awk)" ] ; then
g.message -e "awk required, please install awk or gawk first"
exit 1
fi
## does map exist?
eval "$(g.gisenv)"
eval "$(g.findfile mapset="$MAPSET" element=vector file="$GIS_OPT_MAP")"
if [ ! "$file" ]; then
g.message -e "Vector map <"$GIS_OPT_MAP"> not found"
exit 1
fi
## check for lines and boundaries in input map
eval "$(v.info -t "$GIS_OPT_MAP")"
if [ "$lines" -eq 0 ] && [ "$boundaries" -eq 0 ]; then
g.message -e "Input vector map not contain lines or boundaries"
exit 1
fi
for vars in "$(v.info -t "$GIS_OPT_MAP" | cut -d"=" -f1)"; do
unset -v "$vars"
done
## check if monitor started
if [ "$(d.mon -p | cut -f1 -d' ')" != "Currently" ] ; then
g.message -e "No active monitors. Please start <d.mon ...> first"
exit 1
fi
## check for "-m" flag and "where" option
if [ "$GIS_FLAG_M" -eq 1 ] && [ -n "$GIS_OPT_WHERE" -o -n "$GIS_OPT_LIST" ]; then
g.message -e "Please choose only one of selection methods:
interactive (flag <"-m">) OR non-interactive -- (<"where"> statement or <"list"> of category values )"
exit 1
fi
## check for "list" and "where" options
if [ -n "$GIS_OPT_WHERE" ] && [ -n "$GIS_OPT_LIST" ]; then
g.message -e "Please choose only one of non-interactive selection methods: <"where"> statement or <"list"> of category values"
exit 1
fi
## is input vector displayed now ?
d.save -oc | grep -e "d.vect map=" | cut -d'"' -f2 | grep -e "$GIS_OPT_MAP" --quiet
if [ "$?" -eq 1 ]; then
g.message -e "Input vector map <""$GIS_OPT_MAP""> is not on the monitor. Please use <d.vect "$GIS_OPT_MAP" ..> to display it"
exit 1
fi
############################################################
## setup temporary files ##
# create temporary file for segments azimuth
TMP1="$(g.tempfile pid=$$)"
if [ "$?" -ne 0 ] || [ -z "$TMP1" ] ; then
g.message -e "ERROR: Unable to create temporary files."
exit 1
fi
# create temporary file for symbols' points coordinates
TMP2="$(g.tempfile pid=$$)"
if [ "$?" -ne 0 ] || [ -z "$TMP2" ] ; then
g.message -e "ERROR: Unable to create temporary files."
exit 1
fi
# create temporary file for points to lines query
TMP3="$(g.tempfile pid=$$)"
if [ "$?" -ne 0 ] || [ -z "$TMP3" ] ; then
g.message -e "ERROR: Unable to create temporary files."
exit 1
fi
# create temporary file for d.graph commands file
TMP4="$(g.tempfile pid=$$)"
if [ "$?" -ne 0 ] || [ -z "$TMP4" ] ; then
g.message -e "ERROR: Unable to create temporary files."
exit 1
fi
# create temporary file for d.graph commands file
TMP5="$(g.tempfile pid=$$)"
if [ "$?" -ne 0 ] || [ -z "$TMP4" ] ; then
g.message -e "ERROR: Unable to create temporary files."
exit 1
fi
# create temporary file for psmap file
TMP6="$(g.tempfile pid=$$)"
if [ "$?" -ne 0 ] || [ -z "$TMP5" ] ; then
g.message -e "ERROR: Unable to create temporary files."
exit 1
fi
############################################################
## vector selecting
if [ "$GIS_FLAG_M" -eq 1 ]; then
echo "Select vector(s) with mouse
- L: draw box with left mouse button to select
- M: draw box with middle mouse button to remove from display
- R: quit and save selected vectors to new map"
d.extract input="$GIS_OPT_MAP" output=TMP_select type=line,boundary hcolor="$GIS_OPT_HCOLOR" --quiet
elif [ "$GIS_FLAG_M" -eq 0 -a -z "$GIS_OPT_WHERE" -a -z "$GIS_OPT_LIST" ]; then
g.copy vect="$GIS_OPT_MAP",TMP_select --quiet
fi
if [ -n "$GIS_OPT_WHERE" ]; then
v.extract -t input="$GIS_OPT_MAP" output=TMP_select type=line,boundary where="$GIS_OPT_WHERE" layer="$GIS_OPT_LAYER" --quiet
elif [ -n "$GIS_OPT_LIST" ]; then
v.extract -t input="$GIS_OPT_MAP" output=TMP_select type=line,boundary list="$GIS_OPT_LIST" layer="$GIS_OPT_LAYER" --quiet
fi
## TODO: maybe use v.segment for more precise segments splitting ???
## In that case --> generate split-file with points for v.segment with v.to.db
## (line length) and AWK
## bounds to lines (if needed)
eval "$(v.info -t TMP_select)"
if [ "$boundaries" -ne 0 ]; then
v.type input=TMP_select output=TMP_select_lines type=boundary,line --quiet
else
g.rename vect=TMP_select,TMP_select_lines --quiet
fi
for vars in "$(v.info -t TMP_select_lines | cut -d"=" -f1)"; do
unset -v "$vars"
done
## split line into segments; delete old cats, add new cats
v.split input=TMP_select_lines output=TMP_select_lines_split vertices=2 --quiet > /dev/null
v.category input=TMP_select_lines_split output=TMP_select_lines_split_catdel option=del --quiet
v.category input=TMP_select_lines_split_catdel output=TMP_select_lines_split_catdel_cats option=add step=1 --quiet
SEGM=TMP_select_lines_split_catdel_cats
## find azimuth of each segment in a line or boundary
v.to.db -p map="$SEGM" option=azimuth --quiet >> "$TMP1"
## take points for future symbols
v.to.points -t -i input=TMP_select_lines type=line dmax="$GIS_OPT_INTERVAL" output=TMP_pts --quiet
## take coordinates of points
v.to.db -p map=TMP_pts layer=2 option=coor --quiet >> "$TMP2"
## points to segments' categories query
v.distance -p from=TMP_pts to="$SEGM" from_layer=2 to_type=line,boundary upload=cat column=dummy_nearest_cats --quiet >> "$TMP3"
awk 'NR>1 {print $0}' "$TMP3" | tr '|' ' ' > "$TMP3.clean"
##
awk -F"|" 'BEGIN { OFMT="%.6f" } {print $1,$2,$3}' "$TMP2" >> "$TMP2.pts.coor"
join -j 1 "$TMP2.pts.coor" "$TMP3.clean" > "$TMP2.pts.segm"
## find angles of symbols
left_front()
{
awk -F"|" 'BEGIN { OFMT="%.0f" } {print $1,450-$2}' "$TMP1" > "$TMP1.left.angle"
awk 'NR==FNR{a[$1]=$2;next}$4 in a{$4=a[$4]}1' "$TMP1.left.angle" "$TMP2.pts.segm" > "$TMP1.left.table"
awk '{print "'"rotation"'", $4, "'"symbol $GIS_OPT_SYMBOL"'", "'"$GIS_OPT_SIZE"'", $2, $3, "'"$GIS_OPT_LINE_COLOR"'", "'"$GIS_OPT_FILL_COLOR"'", "'"width"'", "'"$GIS_OPT_WIDTH"'"}' "$TMP1.left.table" >> "$TMP4"
if [ -n "$GIS_OPT_PSMAP" ]; then
awk '{print "'"point"'", $2, $3, "'"color $GIS_OPT_LINE_COLOR"'", "'"fcolor $GIS_OPT_FILL_COLOR"'", "'"symbol $GIS_OPT_SYMBOL"'", "'"size $GIS_OPT_SIZE"'", "'"rotate"'", $4, "'"end"'"}' "$TMP1.left.table" >> "$TMP6"
fi
}
right_front()
{
awk -F"|" 'BEGIN { OFMT="%.0f" } {print $1,270-$2}' "$TMP1" > "$TMP1.right.angle"
awk 'NR==FNR{a[$1]=$2;next}$4 in a{$4=a[$4]}1' "$TMP1.right.angle" "$TMP2.pts.segm" > "$TMP1.right.table"
awk '{print "'"rotation"'", $4, "'"symbol $GIS_OPT_SYMBOL"'", "'"$GIS_OPT_SIZE"'", $2, $3, "'"$GIS_OPT_LINE_COLOR"'", "'"$GIS_OPT_FILL_COLOR"'", "'"width"'", "'"$GIS_OPT_WIDTH"'"}' "$TMP1.right.table" >> "$TMP4"
if [ -n "$GIS_OPT_PSMAP" ]; then
awk '{print "'"point"'", $2, $3, "'"color $GIS_OPT_LINE_COLOR"'", "'"fcolor $GIS_OPT_FILL_COLOR"'", "'"symbol $GIS_OPT_SYMBOL"'", "'"size $GIS_OPT_SIZE"'", "'"rotate"'", $4, "'"end"'"}' "$TMP1.right.table" >> "$TMP6"
fi
}
case "$GIS_OPT_SIDE" in
left)
left_front
;;
right)
right_front
;;
both)
left_front
right_front
;;
*)
esac
## make custom front symbols in the user's mapset ($MAPSET/symbol/type/name) ???
echo "VERSION 1.0
BOX -0.5 -0.5 1.5 1.5
STRING
LINE
0 0
0 1.5
END
END
STRING
LINE
0.4 0.75
0 0
END
END
STRING
LINE
-0.4 0.75
0 0
END
END" > "$TMP5.arrow.int"
echo "VERSION 1.0
BOX -0.5 -0.5 1.5 1.5
STRING
LINE
0 0
0 1.5
END
END
STRING
LINE
0.4 0.75
0 1.5
END
END
STRING
LINE
-0.4 0.75
0 1.5
END
END" > "$TMP5.arrow.ext"
echo "VERSION 1.0
BOX -0.5 -0.5 0.5 0.5
POLYGON
RING
LINE
-0.2 0
-0.2 0.4
0.2 0.4
0.2 0
END
END
END" > "$TMP5.box"
echo "VERSION 1.0
BOX -0.5 -0.5 0.5 0.5
POLYGON
RING
ARC 0 0 0.333 0 180
END
END" > "$TMP5.circle"
echo "VERSION 1.0
BOX -0.5 -0.5 0.5 0.5
POLYGON
RING
LINE
-0.2 0
-0.2 0.2
0.2 0.2
0.2 0
END
END
END" > "$TMP5.half_box"
echo "VERSION 1.0
BOX -0.5 -0.5 0.5 0.5
STRING
LINE
0 0
0 0.5
END
END" > "$TMP5.line"
echo "VERSION 1.0
BOX -0.5 -0.5 0.5 0.5
POLYGON
RING
LINE
-0.25 0
0 0.5
0.25 0
END
END
END" > "$TMP5.triangle"
eval "$(g.gisenv)"
symbol_path="$GISDBASE"/"$LOCATION_NAME"/"$MAPSET"/symbol/front
if [ ! -d "$symbol_path" ]; then
mkdir -p "$symbol_path"
cp -f "$TMP5.arrow.int" "$symbol_path"/arrow_int
cp -f "$TMP5.arrow.ext" "$symbol_path"/arrow_ext
cp -f "$TMP5.box" "$symbol_path"/box
cp -f "$TMP5.circle" "$symbol_path"/circle
cp -f "$TMP5.half_box" "$symbol_path"/half_box
cp -f "$TMP5.line" "$symbol_path"/line
cp -f "$TMP5.triangle" "$symbol_path"/triangle
fi
## format d.graph input file and ps.map points file
awk '{print $1,$2,"'"\n"'",$10,$11,"'"\n"'",$3,$4,$5,$6,$7,$8,$9}' "$TMP4" >> "$TMP4.fmt"
awk '{print $1,$2,$3,"'"\n"'",$4,$5,"'"\n"'",$6,$7,"'"\n"'",$8,$9,"'"\n"'",$10,$11,"'"\n"'",$12,$13,"'"\n"'","'"end"'"}' "$TMP6" >> "$TMP6.fmt"
## draw frontlines and (optionally) save graph file and psmap file
if [ "$GIS_FLAG_S" -eq 0 ] && [ -n "$GIS_OPT_GRAPH" ]; then
g.message -e "Please use flag <"-s"> to save line graphics in file <"$GIS_OPT_GRAPH">"
cleanup
exit 1
fi
if [ "$GIS_FLAG_S" -eq 1 ]; then
if [ -n "$GIS_OPT_GRAPH" ]; then
cp -f "$TMP4.fmt" "$GIS_OPT_GRAPH"
d.graph -m input="$GIS_OPT_GRAPH" color=none
else
SYMBOL="$(echo $GIS_OPT_SYMBOL | tr '/' '_')"
GRAPH_FILE=""$GISDBASE"/"$LOCATION_NAME"/"$GIS_OPT_MAP"__"$SYMBOL"_"$GIS_OPT_INTERVAL"_"$GIS_OPT_SIDE"_"$GIS_OPT_LINE_COLOR"".graph
# cp -f "$TMP4.fmt" "$GRAPH_FILE"
cat "$TMP4.fmt" >> "$GRAPH_FILE"
d.graph -m input="$GRAPH_FILE" color=none
fi
else
d.graph -m input="$TMP4.fmt" color=none
fi
if [ "$GIS_FLAG_S" -eq 0 ] && [ -n "$GIS_OPT_PSMAP" ]; then
g.message -e "Please use flag <"-s"> to save line graphics in file <"$GIS_OPT_PSMAP"> for use with ps.map"
cleanup
exit 1
fi
if [ -n "$GIS_OPT_PSMAP" ]; then
# cp -f "$TMP6.fmt" "$GIS_OPT_PSMAP"
cat "$TMP6.fmt" >> "$GIS_OPT_PSMAP"
fi
cleanup
exit 0
Jump to Line
Something went wrong with that request. Please try again.