ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I'm trying to get 3 awk scripts done to pivot a region (using the center of min-max values as pivot point) 90 180 270 degrees the contents of a xy file.
It works almost (it rotates but location is off) but my math calcs are off along with my math skills.
The minmax are supplied by another script and read as follows
minx=9356
maxx=11388
miny=5191
maxy=7682
if (x >= minx && maxx <= maxx && y >= miny && y <= maxy) {
dx = x - midx
dy = y - midy
x = midx + dx * cosr + dy * sinr
y = midy - dx * sinr + dy * cosr
}
Since the result has to have integral coordinates, use
Code:
printf("%s%.0f,%.0f;",cmd,x,y);
or (to get unsigned zeroes) convert the results to integers via
Code:
if (x > 0) x = int(x + 0.5)
if (x < 0) x = int(x - 0.5)
if (x == 0) x = 0
if (y > 0) y = int(y + 0.5)
if (y < 0) y = int(y - 0.5)
if (y == 0) y = 0
since in awk int(-0.7) == -0
The complete awk script:
Code:
BEGIN {
RS="[;\n\r]";
FS="[, \t]+";
rotation = rotation % 360.0
radians = rotation * 3.14159265358979323846 / 180.0
sinr = sin(radians)
cosr = cos(radians)
midx = (minx + maxx) / 2.0
midy = (miny + maxy) / 2.0
}
/[[:space:]]*(PU|PD)[-[:digit:]]+/ {
cmd = substr($1,1,2);
dx = substr($1,3) - midx;
dy = $2 - midy;
x = midx + dx * cosr + dy * sinr
y = midy - dx * sinr + dy * cosr
if (x > 0) x = int(x + 0.5)
if (x < 0) x = int(x - 0.5)
if (x == 0) x = 0
if (y > 0) y = int(y + 0.5)
if (y < 0) y = int(y - 0.5)
if (y == 0) y = 0
printf("%s%d,%d;", cmd, x, y)
next
}
/[^;[:space:]]/ { printf("%s;", $0) }
Does this help?
Nominal Animal
Last edited by Nominal Animal; 03-21-2011 at 05:58 AM.
I must be a bit off here as I cannot quite work out what it is you are asking to do?
You are printing the newx and newy but I am not seeing what this has to do with 90, 180, 270 degrees?
The variable is going to come from bash not python , python originally generates it and passes it to the bash script above. Also that awk script is already being passed two variables $1 $2 so I need "rotation passed along from bash as $3?? It must be a placement somewhere on the awk line that calls the awk script?
Only thing is how do I pass the degree argument coming into bash from python on to awk?
Add option -v rotation=somevalue to the gawk command.
_ _ _ _
You can simplify your script quite a bit, by embedding the two gawk scripts in a single Bash script file.
This will take the rotation angle as the first parameter, then the name or names of the files to be rotated:
Code:
#!/bin/bash
if [ $# -lt 1 ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
echo "Usage: $0 angle HPGL-file(s)..." >&2
exit 1
fi
# Take the rotation angle.
angle="$1"
shift 1
# Create a safe temporary directory; also remove it automagically.
temps="/tmp/rotation.`hostname -s`.$$"
trap 'rm -rf "$temps"' EXIT
mkdir -m 0700 "$temps" || exit $?
# File loop.
while [ $# -gt 0 ]; do
file="$1"
shift 1
if [ ! -f "$file" ]; then
echo "$file: No such file." >&2
continue
fi
# Determine box size: minx miny maxx maxy
box=(`gawk '
BEGIN {
minx = miny = +1e9999
maxx = maxy = -1e9999
}
{ /* Compare, e.g. */
if ($1 < minx) minx = $1
if ($1 > maxx) maxx = $1
if ($2 < miny) miny = $2
if ($2 > maxy) maxy = $2
}
END {
if (minx <= maxx && miny <= maxy)
print minx, miny, maxx, maxy
}
' "$file" 2>/dev/null`)
if [ ${#box[@]} -ne 4 ]; then
echo "$file: Cannot parse box." >&2
continue
fi
if ! gawk -v minx=${box[0]} -v miny=${box[1]} -v maxx=${box[1]} -v maxy=${box[2]} -v rotation=$angle '
BEGIN {
RS="[;\n\r]";
FS="[, \t]+";
rotation = rotation % 360.0
radians = rotation * 3.14159265358979323846 / 180.0
sinr = sin(radians)
cosr = cos(radians)
midx = (minx + maxx) / 2.0
midy = (miny + maxy) / 2.0
}
/[[:space:]]*(PU|PD)[-[:digit:]]+/ {
cmd = substr($1,1,2);
dx = substr($1,3) - midx;
dy = $2 - midy;
x = midx + dx * cosr + dy * sinr
y = midy - dx * sinr + dy * cosr
if (x > 0) x = int(x + 0.5)
if (x < 0) x = int(x - 0.5)
if (x == 0) x = 0
if (y > 0) y = int(y + 0.5)
if (y < 0) y = int(y - 0.5)
if (y == 0) y = 0
printf("%s%d,%d;", cmd, x, y)
next
}
/[^;[:space:]]/ { printf("%s;", $0) }
' "$file" > "$temps/output" ; then
rm -f "$temps/output"
echo "$file: Rotation failed miserably!" >&2
continue
fi
mv -f "$temps/output" "$file"
echo "$file: Rotated $angle degrees clockwise." >&2
done
The above script could use a nice cleanup. I didn't even test it, but it should be a good starting point.
For one, you'll need to parse the coordinates properly in the first gawk script, similar to the second script.
I find it easier to maintain if each script is in a single file.
Nominal Animal
Last edited by Nominal Animal; 03-21-2011 at 05:56 AM.
In the above file should file="$1" be $2??
I'm having trouble parsing the file location to your script keeps coming back with "usage error" relevant python string is
Code:
job = os.path.expanduser("~/hpgl-hot-folder/temp.plot")
job = str(job) ##just in case
subprocess.Popen([os.getenv("HOME")+"/bin/rotate2.sh", angle, 'job'], shell=True,stdout=subprocess.PIPE)
When manually runing your script with file=$1 it errors with /home/store/hpgl-hot-folder/temp.plot: Cannot parse box.
When manually runing your script with file=$1 it errors with /home/store/hpgl-hot-folder/temp.plot: Cannot parse box.
That's to be expected, since I didn't include the coordinate scanning part (your minmax.awk). I hoped you'd read the code and notice and fix it yourself. There were other issues, like only supporting PU and PD and only with one point, too.
$1 is correct, since shift 1 pops the first parameter ($1) off, and shifts the rest of the parameters one place down. $# is always the number of parameters left.
To save us time, here's a bit more complete version (still untested, though):
Code:
#!/bin/bash
if [ $# -lt 1 ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
echo "Usage: $0 angle HPGL-file(s)..." >&2
exit 1
fi
# Take the rotation angle.
angle="$1"
shift 1
# Create a safe temporary directory; also remove it automagically.
temps="/tmp/rotation.`hostname -s`.$$"
trap 'rm -rf "$temps"' EXIT
mkdir -m 0700 "$temps" || exit $?
# File loop.
while [ $# -gt 0 ]; do
file="$1"
shift 1
if [ ! -f "$file" ]; then
echo "$file: No such file." >&2
continue
fi
# Determine box size: minx miny maxx maxy
box=(`gawk '
BEGIN {
minx = miny = +1e9999
maxx = maxy = -1e9999
RS="[;\n\r]+";
FS="[, \t]+";
}
($1 ~ /^[Pp][UuDd]/) {
$1 = substr($1, 2);
for (i = 1; i < NF; i += 2) {
j = i + 1
x = int($i)
y = int($j)
if (x < minx) minx = x
if (x > maxx) maxx = x
if (y < miny) miny = y
if (y > maxy) maxy = y
}
}
END {
if (minx <= maxx && miny <= maxy)
print minx, miny, maxx, maxy
}' "$file" 2>/dev/null`)
if [ ${#box[@]} -ne 4 ]; then
echo "$file: Cannot parse box." >&2
continue
fi
if ! gawk -v minx=${box[0]} -v miny=${box[1]} -v maxx=${box[1]} -v maxy=${box[2]} -v rotation=$angle '
BEGIN {
RS="[;\n\r]+";
FS="[, \t]+";
rotation = rotation % 360.0
radians = rotation * 3.14159265358979323846 / 180.0
sinr = sin(radians)
cosr = cos(radians)
midx = (minx + maxx) / 2.0
midy = (miny + maxy) / 2.0
}
($1 ~ /^[Pp][UuDd]/) {
s = substr($1, 1, 2)
$1 = substr($1, 3)
for (i = 1; i < NF; i += 2) {
j = i+1
dx = $i - midx
dy = $j - midy
x = midx + dx * cosr + dy * sinr
y = midy - dx * sinr + dy * cosr
if (x > 0) x = int(x + 0.5)
if (x < 0) x = int(x - 0.5)
if (x == 0) x = 0
if (y > 0) y = int(y + 0.5)
if (y < 0) y = int(y - 0.5)
if (y == 0) y = 0
printf("%s%d,%d", s, x, y)
s = ","
}
printf(";")
next
}
/[^\t ]/ { printf("%s;", $0) }
' "$file" > "$temps/output" ; then
rm -f "$temps/output"
echo "$file: Rotation failed miserably!" >&2
continue
fi
mv -f "$temps/output" "$file"
echo "$file: Rotated $angle degrees clockwise." >&2
done
Nominal Animal
Last edited by Nominal Animal; 03-21-2011 at 07:39 AM.
I've got it going just now with the multi file script and the correct variable input but I'll work on the more efficient one on one of those sleepless nights I have .....
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.