#!/usr/local/bin/perl # This PERL script takes a file that was saved by xfig 3.1 and creates # ASCII output that lists the polygons in a way that is easy to parse. # AUTHOR: Steven M. LaValle # Computer Science Department # Stanford University # DATE: 18 January 1997 # DESCRIPTION: This tool was developed to help students generate motion # planning examples easily in CS326A, Motion Planning. The objects that # are drawn must be color coded. Each color identifies a type, such as # "OBSTACLE" or "ROBOT1". These names and colors can be easily modified # below. Some objects can be translated to make their centroid be the # origin (which is useful for a robot). These translatable objects # are listed below in the variable @movables. # # Perform these steps to use this script: # # 1. Use xfig to generate a figure using polygon and rectangle functions. # 2. Click on "Edit" to change each polygon "Fill color" to one listed # below. You can optionally change the "Fill style" to "Filled" to # prevent confusion amongst different types of polygons. # 3. Save the resulting file in the .fig format. # 4. Run this script from UNIX as: xfig2mp .fig > output # If UNIX says "Permission denied", first enter: chmod 755 xfig2mp # # You can alternatively change the fill style and color while drawing # the polygons or rectangles, but be warned that this could cause xfig # to crash on some SGI systems (because xfig doesn't realize that it can # use 24-bit color). # Change the correspondences here to make new types with corresponding # colors. The keys in %types are color indices that appear in the xfig # file. # Here are some color codes: 0 = Black, 1 = Blue, 2 = Green, 4 = Red, # 6 = Yellow, 7 = White # # 5 = Magenta # 3 = Cyan # 8 = Blue4 # # You can find other codes by changing object colors and doing a "diff" # on the two files. %types = (0,"OBSTACLES", 1,"ROBOT1", 2,"ROBOT2", 4,"ROBOT3", 7,"BORDER", 6,"GOAL", 5,"PATH1", 3,"PATH2", 8,"PATH3"); # Place any object name below that you would like to have translated to # have its centroid be the origin. @movables = ("ROBOT1", "ROBOT2", "ROBOT3"); %polys = (); # Read each line of the file, grabbing rectangles and polygons @text = <>; $index = 5; while ($index <= $#text) { if (@text[$index] =~ /^2 2|^2 3|^2 1/) # If the line represents a polygon or rectangle { @text[$index] =~ /^2 \d \S+ \S+ \S+ (\d+)/; # $1 will now contain the color index $index++; # Grab all of the points while ( !(@text[$index] =~ /^\d \d/) && ($index <= $#text)) { # Concatenate the points based on color $polys{ $1 } .= @text[$index]; $index++; } } else { $index++; } } foreach $key (keys %types) { if ($polys{$key}) { print $types{$key},"\n"; # Print the polygon type @pts = &STRINGTONUMBERS($polys{$key}); # Convert string to array if (grep($types{$key} eq $_, @movables)) { # Check to translate it @pts = &CENTER_POLYGONS(@pts); } $index = 0; while ($index < $#pts) { $firstx = @pts[$index]; $firsty = @pts[$index + 1]; @polygon = ($firstx,$firsty); $index += 2; while ((($firstx != @pts[$index]) || ($firsty != @pts[$index + 1])) && ($index <= $#pts)) { push(@polygon,@pts[$index]); push(@polygon,@pts[$index + 1]); $index += 2; } print(($#polygon + 1)/2,"\n"); # Print number of points in polygon for ($i = 0; $i < $#polygon; $i = $i+2) { # Print each point print @polygon[$i]/100," ",@polygon[$i+1]/100,"\n"; } $index += 2; } print "\n\n"; } } # This routine converts the concatenated strings containing integers into an # array of integers. sub STRINGTONUMBERS { local($string)=@_; local(@nums)=(); $numbers_left = ($string =~ /(\d+\b)/); while ($numbers_left) { push(@nums,$1); $string = substr($string,index($string,$1)+length($1)); $numbers_left = ($string =~ / (\d+)/); } @nums; } # This routine translates the polygon so that its centroid is the origin. # Note this is the centroid of the vertices, not the area centroid. sub CENTER_POLYGONS { local($pts)=@_; local(@newpts)=(); local($xmean)=0.0; local($ymean)=0.0; for ($i = 0; $i < $#pts; $i = $i+2) { $xmean += @pts[$i]; $ymean += @pts[$i + 1]; } $xmean = $xmean * 2 / ($#pts+1); $ymean = $ymean * 2 / ($#pts+1); for ($i = 0; $i < $#pts; $i = $i+2) { push(@newpts,@pts[$i] - $xmean); push(@newpts,@pts[$i + 1] - $ymean); } @newpts; }