#!/usr/sbin/perl
# Program to convert HPGL files to
# AutoCAD vers 12+ script files
# See hpgl2dxf.perl if you want speed on input to AutoCAD
#  (with a loss of "correctness")

# See HPGL2SCR.ZIP (available on the "net") 
# if you want background on this program 
# (some of the scaling algorithms are described therein in hpgl2scr.doc)
# Many thanks for this work by William D. Palmer (wdp@ee.egr.duke.edu)

# See the AutoCAD manual for further information on scripts

# Albert Putnam (putnam@msc.cornell.edu) Nov 18, 1992.
# Materials Science Center, Cornell University
# Work part of Cornell-IBM Joint Study on Computing for Scientific Research
# This software is provided as is and without warantee.

# Bugs:
# Entity capabilties are not complete.
# Heaven help you if you have a ; in your label strings.

# usage: hpgl2scr a.plt > a.scr


open(FILE1,@ARGV[0]);            # open the file

$p1x  = 250;    $p1y = 279;              # initial scaling sizes
$p2x  = 10250;  $p2y = 7479;
$u1x  = $p1x;   $u1y = $p1y;             # more scaling
$u2x  = $p2x;   $u2y = $p2y;
$xfact = ($p2x - $p1x) / ($u2x - $u1x);  # scaling factors (loop use)
$yfact = ($p2y - $p1y) / ($u2y - $u1y);
$true = 1;                               # useful variables
$false = 0;


$/ = ";" ;            # separator character is ";" for hpgl
$draw = $false;       # assume the pen is up to start with

while (<FILE1>) {
 s/\n//;                  # get rid of newlines in the file
 chop;                    # get rid of the ; separator
 $a = substr($_,0,2);     # get the first two characters (the command)
 $b = substr($_,2);       # the rest of the record is command data

 # now act on the various commands
 # note the order is probably important in what follows
 # once the right elsif is found the rest need not be checked

 # The absolute pen positioning command
 if ($a =~ "PA") { 
   # it needs the last coordinate xl,yl to know where to start
   if ( $draw ) { printf("_LINE\n%.4f,%.4f\n",$xl,$yl); }
   while (length($b)!=0) {
     # divide up the line into the appropriate chunks
     ($x,$y,$b) = split(/,/,$b,3);
     # rescale coordinates
     $x = (($x - $u1x) * $xfact + $p1x) / 1000;
     $y = (($y - $u1y) * $yfact + $p1y) / 1000;
     if ( $draw ) {
       printf("%.4f,%.4f\n",$x,$y);
     }
     $xl = $x;
     $yl = $y;
   }
   if ( $draw ) {print "\n";}
 }

 elsif ($a =~ "PU") {$draw = $false;}    #pen up

 elsif ($a =~ "PD") {$draw = $true;}     #pen down

 # The relative pen positioning command 
 # Only difference from PA is  @ in the main loop
 elsif ($a =~ "PR") { 
   # it needs the last coordinate xl,yl to know where to start
   if ( $draw ) { printf("_LINE\n%.4f,%.4f\n",$xl,$yl); }
   while (length($b)!=0) {
     # divide up the line into the appropriate chunks
     ($x,$y,$b) = split(/,/,$b,3);
     $x = (($x - $u1x) * $xfact + $p1x) / 1000;
     $y = (($y - $u1y) * $yfact + $p1y) / 1000;
     if ( $draw ) {
       printf("@%.4f,%.4f\n",$x,$y);
     }
     $xl = $x;
     $yl = $y;
   }
   if ( $draw ) {print "\n";}
 }

 # circle command (really an ellipse - chords not supported)
 # Note the HPGL manual says circles are always drawn (PD automatic)
 # Automatic return to initial state at end (PD/PU).
 elsif ($a =~ "CI") {
   ($radius) = split(/,/,$b,1);
   $xaxis = (($radius - $u1x) * $xfact + $p1x) / 1000;
   $yaxis = (($radius - $u1y) * $yfact + $p1y) / 1000;
   printf("_ELLIPSE\nC\n%.4f,%.4f\n",$xl,$yl);
   printf("@%.4f,0\n@0,%.4f\n",$xaxis,$yaxis);
 }

 # label command
 # manual is unclear whether labels are always drawn (PU/PD?)
 elsif ($a =~ "LB" && $draw) {
   chop($b);
   printf("_TEXT\n%.4f,%.4f\n\n\n%s\n",$xl,$yl,$b);
 }

 # scaling
 elsif ($a =~ "IP") {
   ($p1x,$p1y,$ip2x,$ip2y) = split(/,/,$b,4);
   if (length($p1x)==0) {   # reset to defaults
     $p1x  = 250;    $p1y = 279;              # initial scaling sizes
     $p2x  = 10250;  $p2y = 7479;
   }
   if (length($ip2x)!=0) { $p2x = $ip2x; $p2y = $ip2y; }
   $xfact = ($p2x - $p1x) / ($u2x - $u1x);
   $yfact = ($p2y - $p1y) / ($u2y - $u1y);
 }

 # scaling
 elsif ($a =~ "SC") {
   ($u1x,$u1y,$u2x,$u2y) = split(/,/,$b,4);
   if (length($u1x)==0) {   # reset to defaults
     $u1x  = $p1x;   $u1y = $p1y;
     $u2x  = $p2x;   $u2y = $p2y;
   }
   $xfact = ($p2x - $p1x) / ($u2x - $u1x);
   $yfact = ($p2y - $p1y) / ($u2y - $u1y);
 }

 # relative character size
 elsif ($a =~ "SR") {
   ($width,$height) = split(/,/,$b,2);
   if (length($width)==0) { $width = 0.75; $height = 1.5; }
   $aspect = $width / $height * ($p2x - $p1x) / ($p2y - $p1y);
   $height = $height * ($p2y - $p1y) / 100000;
   printf("_STYLE\n\n%s\n%s\n\n\n\n\n",$height,$width);
 }

 # absolute character size
 elsif ($a =~ "SI") {
   ($width,$height) = split(/,/,$b,2);
   if (length($width)==0) { $width = 0.19; $height = 0.27; }
   $aspect = $width / $height;
   $height = $height * 2.54;
   printf("_STYLE\n\n%s\n%s\n\n\n\n\n",$height,$width);
 }

 # pen selection
 elsif ($a =~ "SP") {
   $layer = $b-1;
   printf("_LAYER\nMAKE\n%d\n\n",$b);
 }

 elsif ($a =~ "O[AC]") 
    {print STDERR "$a output position request: Pen at $xl,$yl\n";} 
 elsif ($a =~ "O[PW]") 
    {print STDERR "$a output window request: $p1x,$p1y,$p2x,$p2y\n";} 
 elsif ($a =~ "V[A-Z]") 
    {print STDERR "Velocity statement $a$b not needed\n";} 
 elsif ($a =~ "A[A-Z]") 
    {print STDERR "Statement $a$b not supported\n";} 
 elsif ($a =~ "C[A-Z]") 
    {print STDERR "Character set statement $a$b not supported\n";} 
 elsif ($a =~ "D[CPR]") 
    {print STDERR "Digitizer statement $a$b not supported\n";} 
 elsif ($a =~ "DF") 
    {print STDERR "Default reset statement $a$b not supported\n";} 
 elsif ($a =~ "IN") 
    {print STDERR "Initialize statement $a$b not supported\n";} 
 elsif ($a =~ "[D-S][A-Z]") 
    {print STDERR "Statement $a$b not supported\n";} 
 elsif ($a =~ "[TXY][A-Z]") 
    {print STDERR "Tick statement $a$b not supported\n";} 
 elsif ($a =~ "U[A-Z]") 
    {print STDERR "User defined char statement $a$b not supported\n";} 
 elsif ($a =~ "[A-Z][A-Z]") 
    {print STDERR "Statement $a$b unknown, check HPGL docn\n";} 

}

