Latest LQ Deal: Linux Power User Bundle
 Home Forums HCL Reviews Tutorials Articles Register Search Today's Posts Mark Forums Read
 LinuxQuestions.org math help in awk to pivot xy coordinates
 Programming This forum is for all programming questions. The question does not have to be directly related to Linux and any language is fair game.

Notices

 01-23-2011, 05:29 AM #1 gary_in_springhill Member   Registered: Mar 2008 Posts: 136 Rep: math help in awk to pivot xy coordinates 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 the awk script Code: ```BEGIN { RS="[;\n\r]"; FS="[, \t]+"; } /[[:space:]]*(PU|PD)[-[:digit:]]+/ { cmd = substr(\$1,1,2); x = substr(\$1,3) + 0; y = \$2 + 0; diffx = maxx - minx; diffy = maxy - miny; newx = maxy - (diffy / 2); ### / 2); ###- (miny/2); ######+ (maxx-miny)/2; newy = maxx + (diffx / 2); ###- (maxx/2); ####+(maxy-minx)/2; printf("%s%d,%d;",cmd,newx,newy); next; } { if( \$1 != "" ) { printf("%s;\n", \$0); } }``` I guess I need a variation for 90, 180, and 270 in separate awk scripts. Thanks Attached Thumbnails
 01-23-2011, 06:20 AM #2 Nominal Animal Senior Member   Registered: Dec 2010 Location: Finland Distribution: Xubuntu, CentOS, LFS Posts: 1,723 Blog Entries: 3 Rep: If the script is fed minx, miny, maxx, maxy, and rotation (in degrees counterclockwise) as variables, put this in the BEGIN section Code: ```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``` and you can use the following for any rotation: Code: ```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.
 01-23-2011, 06:26 AM #3 grail LQ Guru   Registered: Sep 2009 Location: Perth Distribution: Manjaro Posts: 9,592 Rep: ummm ... huh? 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? btw. the following 2 are equivalent: Code: ```{ if( \$1 != "" ) { printf("%s;\n", \$0); } } \$1```
 01-23-2011, 07:01 AM #4 gary_in_springhill Member   Registered: Mar 2008 Posts: 136 Original Poster Rep: Unbelievable... I embarrassed to say 2 days, a headache, and many pots of coffee and you people solved it in 60 min! At least I tried it on my own Only thing is how do I pass the degree argument coming into bash from python on to awk? Code: ```#!/bin/sh if [ \$1 -eq 90 ]; then (gawk -f \$HOME/bin/minmax.awk \$HOME/hpgl-hot-folder/temp.plot > \$HOME/hpgl-hot-folder/temp-conv) cp \$HOME/hpgl-hot-folder/temp.plot \$HOME/hpgl-hot-folder/temp2.plot rm temp.plot (echo "BEGIN { "; gawk -f \$HOME/bin/minmax.awk \$HOME/hpgl-hot-folder/temp2.plot; echo "}"; cat \$HOME/bin/conv90.awk) > \$HOME/bin/temp-conv gawk -f \$HOME/bin/temp-conv \$HOME/hpgl-hot-folder/temp2.plot > \$HOME/hpgl-hot-folder/temp.plot fi```
 01-23-2011, 07:58 AM #5 grail LQ Guru   Registered: Sep 2009 Location: Perth Distribution: Manjaro Posts: 9,592 Rep: Well I am not sure I see any python in the snippet you have shown, but generally just assign it to a variable using -v and you should be good to go.
 01-23-2011, 08:20 AM #6 gary_in_springhill Member   Registered: Mar 2008 Posts: 136 Original Poster Rep: variable from bash 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?
01-23-2011, 08:36 AM   #7
Nominal Animal
Senior Member

Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep:
Quote:
 Originally Posted by gary_in_springhill At least I tried it on my own
Right on! That was also why I responded.

Quote:
 Originally Posted by gary_in_springhill 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
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.

 01-23-2011, 10:14 AM #8 gary_in_springhill Member   Registered: Mar 2008 Posts: 136 Original Poster Rep: file = ? 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. If file=\$2 the : No such file.
 01-23-2011, 10:38 AM #9 gary_in_springhill Member   Registered: Mar 2008 Posts: 136 Original Poster Rep: on the original multi file setup? I'm not sure but I think I have the variable passing in the wrong spot?? Code: ```(gawk -f \$HOME/bin/minmax.awk \$HOME/hpgl-hot-folder/temp.plot > \$HOME/hpgl-hot-folder/temp-conv) cp \$HOME/hpgl-hot-folder/temp.plot \$HOME/hpgl-hot-folder/temp2.plot rm \$HOME/hpgl-hot-folder/temp.plot (echo "BEGIN { "; gawk -v rotation=90 -f \$HOME/bin/minmax.awk \$HOME/hpgl-hot-folder/temp2.plot; echo "}"; cat \$HOME/bin/rotate.awk) > \$HOME/bin/temp-conv gawk -f \$HOME/bin/temp-conv \$HOME/hpgl-hot-folder/temp2.plot > \$HOME/hpgl-hot-folder/temp.plot``` -v rotation=90 looks like it should go here??
01-23-2011, 12:11 PM   #10
Nominal Animal
Senior Member

Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep:
Quote:
 Originally Posted by gary_in_springhill 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
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.

1 members found this post helpful.
 01-23-2011, 12:52 PM #11 gary_in_springhill Member   Registered: Mar 2008 Posts: 136 Original Poster Rep: thanks nominal 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 ..... As always thanks so much for your help

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is Off HTML code is Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post knockout_artist Programming 7 11-25-2011 02:13 PM LXer Syndicated Linux News 0 06-30-2008 01:20 AM Four General 5 04-19-2006 08:02 PM Joseph Schiller Programming 8 01-12-2006 05:00 AM Veteq Linux - General 0 01-29-2005 07:19 PM

LinuxQuestions.org

All times are GMT -5. The time now is 10:57 PM.

 Contact Us - Advertising Info - Rules - LQ Merchandise - Donations - Contributing Member - LQ Sitemap -