program hilbert(output,cam);    { from April 1986 BYTE - modified }
type
     one_char = char;
var
    angle,xcoord,ycoord,stepsize : real;
    out_dev,order,lin_num,num_pts,num_ptr,i,PointCount : integer;
    cam : text;
    xmin,xmax,ymin,ymax : real;
    xlim,ylim,xscale,yscale,xoffset,yoffset : real;
    xbuf,ybuf : real;
    x,y : longint;
    plotCode,OutRun : boolean;

procedure move; {moves stepsize in present direction}
begin
    xcoord:=xcoord+stepsize*cos(angle);
    ycoord:=ycoord+stepsize*sin(angle);
    if not OutRun then begin
      if xcoord < xmin then xmin := xcoord;
      if xcoord > xmax then xmax := xcoord;
      if ycoord < ymin then ymin := ycoord;
      if ycoord > ymax then ymax := ycoord;
    end
    else begin
      Xbuf := Xcoord * xscale + xoffset;
      Ybuf := Ycoord * yscale + yoffset;
      if xbuf < xmin then xmin := xbuf;
      if xbuf > xmax then xmax := xbuf;
      if ybuf < ymin then ymin := ybuf;
      if ybuf > ymax then ymax := ybuf;
      if pointCount = 1 then begin
        x := round(xbuf);
        y := round(ybuf);
        if plotcode then
          writeln(cam,'X',x,'Y',y,'D02*')
        else begin
          writeln(cam,'N',lin_num,' X',x,' Y',y,' Z0100');
          lin_num := lin_num + 1;
          writeln(cam,'N',lin_num,' G01 Z-0500');
          lin_num := lin_num + 1;
        end;
      end;         { if PointCount }
      if pointCount > 1 then begin
        x := round(xbuf);
        y := round(ybuf);
        if plotcode then
          writeln(cam,'X',x,'Y',y,'D01*')
        else begin
          writeln(cam,'N',lin_num,' X',x,' Y',y);
          lin_num := lin_num +1;
        end;
      end;
      PointCount := PointCount + 1;
    end;
end;

procedure turn(delta : real);  { turn the turtle }
begin
    angle:=angle+delta/57.3;    {convert degrees to radians }
{    writeln(log,'TURN   ',angle*57.3:12:4);}
end;

procedure rec_dragon(sign : real;level : integer);  {the recursive part }
begin
    writeln(output,'HILBERT  ',level);
    if level<=0 then move
    else begin
        turn(sign*(-90.0));
        rec_dragon(1.0,level-1);
        rec_dragon(1.0,level-1);
        turn(sign*(90.0));
        rec_dragon(-1.0,level-1);
        rec_dragon(-1.0,level-1);
        turn(sign*(90.0));
        rec_dragon(-1.0,level-1);
        rec_dragon(-1.0,level-1);
    end;
end;

begin   { main program }
    OutRun := false;
    xmin :=  100000.0;
    xmax := -100000.0;
    ymin :=  100000.0;
    ymax := -100000.0;
    xcoord:=1.0;
    ycoord:=1.0;
    angle:=2160.0;
    writeln('Enter 1 for milling codes, 2 for photoplotter codes:');
    readln(i);
    if i > 1 then
      plotcode := true
    else
     plotcode := false;
    writeln('Enter order (2..16) integer');
    readln(order);
    stepsize := 0.0;
    move;
    stepsize := 1.0;
    rec_dragon(1.0,order);         { run it once to gauge limits }
    writeln(output,'initial limits :');
    writeln(output,'xmin,xmax ',xmin:9:4,xmax:9:4);
    writeln(output,'ymin,ymax ',ymin:9:4,ymax:9:4);
    writeln(output,'Enter dimensions of material, x,y (real)');
    readln(input,xlim,ylim);
    xscale := ((xlim * 10000) / (xmax - xmin)) * 0.9;
    yscale := ((ylim * 10000)/ (ymax - ymin)) * 0.9;
    if abs(xscale) < abs(yscale) then begin     { make 'tightest' dimension }
      yscale := xscale;                         { control the scale }
      ylim := xlim;
    end else begin
      xscale := yscale;
      xlim := ylim;
    end;
    xoffset := (xlim*10000)/2.0 -((xmax+xmin)/2.0) * xscale;
    yoffset := (ylim*10000)/2.0 -((ymax+ymin)/2.0) * yscale;
    writeln(output,' scale factor ',xscale:12:4);
    writeln(output,'Xoffset,Yoffset ',xoffset:12:4,yoffset:12:4);
    { now repeat whole process for output }
    OutRun := true;
    PointCount := 1;
    assign(cam,'hilbert.cam');
    rewrite(cam);
    xmin :=  100000.0;
    xmax := -100000.0;
    ymin :=  100000.0;
    ymax := -100000.0;
    xcoord:=1.0;
    ycoord:=1.0;
    angle:=2160.0;
    lin_num := 1;
    if PlotCode then begin
      writeln(cam,'*%FSLAX44Y44*');
      writeln(cam,'SFA1.0B1.0*%');
      writeln(cam,'G70*');
      writeln(cam,'G90*');
      writeln(cam,'G01*');
      writeln(cam,'D02*');
      writeln(cam,'D10*');
    end
    else
      writeln(cam,'N',lin_num,' G00 F50000');
    lin_num := lin_num + 1;
    xbuf := round(xcoord * xscale + Xoffset);
    ybuf := round(ycoord * yscale + Yoffset);
    stepsize := 0.0;
    move;
    stepsize := 1.0;
    rec_dragon(1.0,order);
        { finally, push out last point }
{    xcoord:=xcoord+stepsize*cos(angle);
    ycoord:=ycoord+stepsize*sin(angle);
    Xbuf := Xcoord * xscale + xoffset;
    Ybuf := Ycoord * yscale + yoffset;
    x := round(xbuf);
    y := round(ybuf);
    if plotcode then
      writeln(cam,'X',x,'Y',y,'D01*')
    else begin
      writeln(cam,'N',lin_num,' X',x,' Y',y);
      lin_num := lin_num +1;
    end; }
    if plotcode then
      writeln(cam,'D02M02*')
    else begin
      writeln(cam,'N',lin_num,' Z0100');
      lin_num := lin_num + 1;
      writeln(cam,'N',lin_num,' X',300,' Y',700);
      lin_num := lin_num + 1;
	writeln(cam,'N',lin_num,' M02'); 
   end;
    close(cam);
    writeln(output,' final drawing limits :');
    writeln(output,'Xmin ',xmin:8:2,'       Xmax ',xmax:8:2);
    writeln(output,'Ymin ',ymin:8:2,'       Ymax ',ymax:8:2);
end.

