#usage	"<b>drillplan-autodim-updated.ulp</b>"
	"<p>
	"Code has been updated to run on versions after 4.11<br><br>"
	"This ulp will generate a neat drill plan and place dimensions for the board."
	"all dimensions are in mm.<br><br>
	"It is important to note that in order for this file to work the user must create a folder named temp "
	"in their c drive.<br><br>
	"The other important point to note is that for the drill plan to develop correctly you must first go to "
	"Options-> Set-> Drill -> Set.<br><br>
	"<i>Updated by Jorge Garcia 04/07/2010 original code by L.Lile</i>"

/*
 
---04/07/2010 ULP updated to work in version 4.11 and beyond, changed ARC references to use the new syntax-----

Warning - tested in Eagle 4.09R2,  has problems in Eagle 4.11 because of ARC command


Section 1; Operation:

Use this script to automatically dimension your board and add a drill plan. 

1.  In the Board, go to Options Set Drill Set.  This extracts drill info from the board. There doesn't seem to be a way to do this by script. 

2.  Run the ulp "pretty.ulp"  

3. Your board will be dimensioned in mm, and you will have a drill plan with hole counts, SMT counts and other useful info. 



FEATURES ADDED: 
 	Now counts total number of thru-hole pads, number of SMT pads top and bottom. 
	Output is in mm units.  Auto-executes a script located in c:\temp\tempdrillplanmm.scr
	THIS DIRECTORY (C:\temp)  must exist!
	lile 5-sept-2002
	

	Added auto-dim capabilities
	Tested in Windows 2000 and Eagle 4.09r2
	output on layers Measures and Document
	lile 23 oct 2003
*/

//////*************************************************************************************
//                                                                                       //
//   AutoDimensionning of Board in inches, (Version 3.00) for EAGLE 4.X only!            *
//                                                                                       *
//   
//  HACKED TO WORK IN mm BY LILE
//
//
//SORCE Filename: adimv2_0.ulp                                                        *
//   ORIGONAL Written by: Michel Dagenais <jcmae@sympatico.ca>                           *
//   Date: September 12th 1998                                                           *
//                                                                                       *
//   Now places text on appropriate side (closer to object being dimensionned).          *
//                                                                                       *   
//   Filename: adimv3_0.ulp                                                              *
//   Edited by: Jeff Moore <engineer@nctimes.net>                                        *
//   Date: February 1st 2001                                                             *
//                                                                                       *
//   This ULP program will put all the necessary dimensions for holes (layer 45) and     *
//   board outline (arcs and wires on layer 20) for your board into a .scr file of your  *
//   choice and into the directory of your choice.                                       *
//   Run the resulting script on your board to place the dimentions into the board file. *
//                                                                                       *
//   Few requirements:                                                                   *
//                                                                                       *
//      1.   The shape of your board (board outline) is drawn on layer 20 (Dimension).   *
//      2.   You reserve layer 47 (Measures) to dimension your board.                    *
//                                                                                       *
//                                                                                       *
//                                                                                       *
//***************************************************************************************/
//
//   Filename: pretty.ulp                                                              
//   Edited by: Jeff Moore <engineer@nctimes.net>                                       
//   Date: February 5th 2001
//   Options - Set - Drill - Set
//
//   Edited by: Brad Goodman <brad@bradgoodman.com>
//   Date: January, 30, 2002
//   Added separate counts and reporting for plated drills.
//   Changed order of drawing, to smallest drills are first.
// 
//  Origonal Filename: drillplan.ulp
//  by: Frank Hoffman
//
//  Dieses ULP generiert ein Script, das eine Bohrlegende
//  im Layout plaziert.
//  Aktualisieren Sie anschließend die Symbole für die
//  Bohrdurchmesser mit 
//
//   Options - Set - Drill - Set
///


// auto-dim stuff

real datum_dot_diameter = 1.27050;      //   diameter of connecting dot on datum line

real datum_wire_width = 0.504;        //   width or datum line
real default_wire_width = 0.203;      //   default wire width for dimension extender and leader
real wire_width;

real extender_clearance = 1.27;       //   clearance from closest edge
real text_offset = 12.7;               // distance of dimension text from closest edge

real right_top_extender_length = text_offset * 0.9;
real left_bottom_extender_length = text_offset * 0.9;

real right_top_datum_location = extender_clearance + (right_top_extender_length * 0.75);
real left_bottom_datum_location = extender_clearance + (left_bottom_extender_length * 0.75);

int right_limit;
int top_limit;
int left_limit;
int bottom_limit;

int x_points[];
string x_points_loc[];   // top or bottom
int y_points[];
string y_points_loc[];   // right or left
string text_location;
string fileName;

int lower_right;
int higher_right;
int lower_top;
int higher_top;
int lower_left;
int higher_left;
int lower_bottom;
int higher_bottom;

int count_x_points;
int count_y_points;


//Drillplan stuff

// Used in Counting Pads
int ipads, i, j, k, h, l, s ;
ipads = j = k = h = l = 0;



// Used in making Drill Plan
int Drilling[];
int Counts[];
int Index[];
int Plating[];
int imax = 0;
int totalDrills = 0;
int totalPlates = 0;


void AddDrilling(int Size,int plated)
{
	for ( int i = imax; --i >= 0; )
	{
    	if (Drilling[i] == Size)
    	{
			Counts[i]++;
			totalDrills++;
			if (plated == 1)
			{
				Plating[i]++;
				totalPlates++;
			}
			return;
		}
	}
	Drilling[imax] = Size;
	if (plated == 1)
		{
		Plating[imax]=1;
		totalPlates++;
		}
	else
		Plating[imax]=0;
	Counts[imax++] = 1;
	totalDrills++;
}

//Auto-Dim stuff:

void check_x_points(int point_cxp, int y_point_cxp)
{
   for (i = 0; i <= count_x_points; ++i)
   {
      if (point_cxp == x_points[i])
         break;
   }
   if (i > count_x_points)
   {
      x_points[count_x_points] = point_cxp;
      int middle = bottom_limit + ((abs(bottom_limit) + abs(top_limit)) * 0.5);
      if (y_point_cxp < middle)
         text_location = "bottom";
      else
         text_location = "top";
      x_points_loc[count_x_points] = text_location;
      ++count_x_points;
   }
}

void check_y_points(int point_cxp, int x_point_cxp)
{
   for (i = 0; i <= count_y_points; ++i)
   {
      if (point_cxp == y_points[i])
         break;
   }
   if (i > count_y_points)
   {
      y_points[count_y_points] = point_cxp;
      int middle = left_limit + ((abs(left_limit) + abs(right_limit)) * 0.5);
      if (x_point_cxp < middle)
         text_location = "left";
      else
         text_location = "right";
      y_points_loc[count_y_points] = text_location;
      ++count_y_points;
   }
}



//************************************************
///Main Program:
//************************************************


board(B)
{
  real ylegend;
  real xlegend = u2mil(B.area.x2) + 200; // was u2mil(B.area.x2) + 40;
  real drill = 0;  



// Determine filename for script
// NOTE:  directory C:\temp must exist!!  
fileName = dlgFileSave("Save Dimensioning Script", filesetext("C:/temp/tempDrillPlanmm",".scr"), "*.scr");	
if (fileName == "") exit(0);


// Auto-Dim Section:

 output(fileName)
{
   printf(";\n");
   printf("Grid mm;\n");
   printf("Change Width 0.2032;\n");
   printf("Change Size 1.778;\n");
   printf("Change Ratio 8;\n");
   printf("Display 20 45 47;\n");
   printf("Layer 47;\n");
   
      B.wires(W)
      {
         if (W.layer == 20)
         {
            switch (W.y2 - W.y1)
            {
               case 0:
               {
                  if (W.y2 > top_limit)
                     top_limit = W.y2;
                  else
                  {
                     if (W.y2 < bottom_limit)
                        bottom_limit = W.y2;
                  }
               }
               default:
               {
                  if (W.y2 > W.y1)
                  {
                     if (W.y2 > top_limit)
                        top_limit = W.y2;
                     if (W.y1 < bottom_limit)
                        bottom_limit = W.y1;
                  }
                  else
                  {
                     if (W.y1 > top_limit)
                        top_limit = W.y1;
                     if (W.y2 < bottom_limit)
                        bottom_limit = W.y2;
                  }
               }
            }
            switch (W.x2 - W.x1)
            {
               case 0:
               {
                  if (W.x2 > right_limit)
                     right_limit = W.x2;
                  else
                  {
                     if (W.x2 < left_limit)
                        left_limit = W.x2;
                  }
               }
               default:
               {
                  if (W.x2 > W.x1)
                  {
                     if (W.x2 > right_limit)
                        right_limit = W.x2;
                     if (W.x1 < left_limit)
                        left_limit = W.x1;
                  }
                  else
                  {
                     if (W.x1 > right_limit)
                        right_limit = W.x1;
                     if (W.x2 < left_limit)
                        left_limit = W.x2;
                  }
               }
            }
         }
      }
      B.wires(W)
      {
         if (W.layer == 20)
        {
            check_y_points(W.y2, W.x2);
            check_y_points(W.y1, W.x1);
            check_x_points(W.x2, W.y2);
            check_x_points(W.x1, W.y1);
         if (W.arc)
         {
	  check_x_points(W.arc.xc, W.arc.yc);
	  check_y_points(W.arc.yc, W.arc.xc);
         }
        }	
      }
      B.holes(H)
      {
         check_x_points(H.x, H.y);
         check_y_points(H.y, H.x);
      }
      B.elements(E)
      {
         if (strsub(E.name, 1, 1) == "$")
         {
            check_x_points(E.x, E.y);
            check_y_points(E.y, E.x);
         }
      }
//
//   Adding X dimensions
//
      for (i = 0; i <= count_x_points; ++i)
      {
         if (x_points[i] == 0)
         {
            printf("Circle 0 (0 %.3f) (0 %.3f);\n", (u2mm(top_limit) + right_top_datum_location), (u2mm(top_limit) + right_top_datum_location + (datum_dot_diameter /2)));
            printf("Circle 0 (0 %.3f) (0 %.3f);\n", (u2mm(bottom_limit) - left_bottom_datum_location), (u2mm(bottom_limit) - left_bottom_datum_location - (datum_dot_diameter /2)));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", datum_wire_width, u2mm(x_points[i]), (u2mm(top_limit) + extender_clearance), u2mm(x_points[i]), (u2mm(top_limit) + right_top_extender_length));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", datum_wire_width, u2mm(x_points[i]), (u2mm(bottom_limit) - extender_clearance), u2mm(x_points[i]), (u2mm(bottom_limit) - left_bottom_extender_length));
            printf("Text '%.3f' R90 (%.3f %.3f);\n", abs(u2mm(x_points[i])), u2mm(x_points[i]), (u2mm(top_limit) + text_offset));
            printf("Text '%.3f' R90 (%.3f %.3f);\n", abs(u2mm(x_points[i])), u2mm(x_points[i]), (u2mm(bottom_limit) - text_offset - 0.3));

         }
         if (x_points_loc[i] == "top")
         {
            if (x_points[i] > higher_top)
               higher_top = x_points[i];
            if (x_points[i] < lower_top)
               lower_top = x_points[i];
            printf("Text '%.3f' R90 (%.3f %.3f);\n", abs(u2mm(x_points[i])), u2mm(x_points[i]), (u2mm(top_limit) + text_offset));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, u2mm(x_points[i]), (u2mm(top_limit) + extender_clearance), u2mm(x_points[i]), (u2mm(top_limit) + right_top_extender_length));
         }
         else
         {
            if (x_points[i] > higher_bottom)
               higher_bottom = x_points[i];
            if (x_points[i] < lower_bottom)
               lower_bottom = x_points[i];
            printf("Text '%.3f' R90 (%.3f %.3f);\n", abs(u2mm(x_points[i])), u2mm(x_points[i]), (u2mm(bottom_limit) - text_offset - 0.3));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, u2mm(x_points[i]), (u2mm(bottom_limit) - extender_clearance), u2mm(x_points[i]), (u2mm(bottom_limit) - left_bottom_extender_length));
         }
      }
//   Join all X dimensions
         if (lower_top != higher_top)
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, u2mm(lower_top), (u2mm(top_limit) + right_top_datum_location), u2mm(higher_top), (u2mm(top_limit) + right_top_datum_location));
         if (lower_bottom != higher_bottom)
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, u2mm(lower_bottom), (u2mm(bottom_limit) - left_bottom_datum_location), u2mm(higher_bottom), (u2mm(bottom_limit) - left_bottom_datum_location));

//
// Adding Y dimensions
//
      for (i = 0; i <= count_y_points; ++i)
      {
         if (y_points[i] == 0)
         {
            printf("Circle 0 (%.3f 0) (%.3f 0);\n", (u2mm(right_limit) + right_top_datum_location), (u2mm(right_limit) + right_top_datum_location + (datum_dot_diameter /2)));
            printf("Circle 0 (%.3f 0) (%.3f 0);\n", (u2mm(left_limit) - left_bottom_datum_location), (u2mm(left_limit) - left_bottom_datum_location - (datum_dot_diameter /2)));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", datum_wire_width, (u2mm(right_limit) + extender_clearance), u2mm(y_points[i]), (u2mm(right_limit) + right_top_extender_length), u2mm(y_points[i]));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", datum_wire_width, (u2mm(left_limit) - extender_clearance), u2mm(y_points[i]), (u2mm(left_limit) - left_bottom_extender_length), u2mm(y_points[i]));
            printf("Text '%.3f' R0 (%.3f %.3f);\n", abs(u2mm(y_points[i])), (u2mm(right_limit) + text_offset), u2mm(y_points[i]));
            printf("Text '%.3f' R0 (%.3f %.3f);\n", abs(u2mm(y_points[i])), (u2mm(left_limit) - text_offset - 0.3), u2mm(y_points[i]));
         }
         if (y_points_loc[i] == "right")
         {
            if (y_points[i] > higher_right)
               higher_right = y_points[i];
            if (y_points[i] < lower_right)
               lower_right = y_points[i];
            printf("Text '%.3f' R0 (%.3f %.3f);\n", abs(u2mm(y_points[i])), (u2mm(right_limit) + text_offset), u2mm(y_points[i]));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, (u2mm(right_limit) + extender_clearance), u2mm(y_points[i]), (u2mm(right_limit) + right_top_extender_length), u2mm(y_points[i]));
         }
         else
         {
            if (y_points[i] > higher_left)
               higher_left = y_points[i];
            if (y_points[i] < lower_left)
               lower_left = y_points[i];
            printf("Text '%.3f' R0 (%.3f %.3f);\n", abs(u2mm(y_points[i])), (u2mm(left_limit) - text_offset - 0.3), u2mm(y_points[i]));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, (u2mm(left_limit) - extender_clearance), u2mm(y_points[i]), (u2mm(left_limit) - left_bottom_extender_length), u2mm(y_points[i]));
         }
      }
//   Join all Y dimensions
         if (lower_right != higher_right)
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, (u2mm(right_limit) + right_top_datum_location), u2mm(lower_right), (u2mm(right_limit) + right_top_datum_location), u2mm(higher_right));
         if (lower_left != higher_left)
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, (u2mm(left_limit) - left_bottom_datum_location), u2mm(lower_left), (u2mm(left_limit) - left_bottom_datum_location), u2mm(higher_left));



//   }  // 

   printf("Grid Last;\n");
   printf("Window Fit;\n");

 // end auto-dim section


// Drillplan subroutines:

// Count section:
 B.holes(L) {
     h++;
     }

   B.elements(E) {
     E.package.holes(H) {
       h++;
       }
     E.package.contacts(C) {

       if (C.pad)
          ipads++ ;
       if (C.smd && (C.smd.layer == 1))
          j++ ;
       if (C.smd && (C.smd.layer == 16))
          l++;
       }
   }

  B.signals(S) {
     S.vias(V) {
          k++;
     }
  }



// DrillPlan Section:
  B.holes(H) AddDrilling(H.drill,0);
  B.signals(S) S.vias(V) AddDrilling(V.drill,1);
  B.elements(E)
  {
    E.package.contacts(C)
    {
      if (C.pad)
         AddDrilling(C.pad.drill,1);
    }
    E.package.holes(H) AddDrilling(H.drill,0);
  }

  sort(imax, Index, Drilling, Counts );

 




  ylegend = u2mil(B.area.y1) + (imax* 200);
 
    printf("GRID mil 50 ON;\n");
    printf("CHANGE SIZE 70;\n");
    printf("CHANGE LAYER 48;\n");	// now layer 48 document was 45 holes
    printf("WINDOW FIT;\n");
    for (int i = 0; i < imax; ++i)
    {
        printf("HOLE  %f (%f %f);\n", u2mm(Drilling[Index[i]]),
                xlegend + 200, ylegend - 100);
	    printf("WIRE 5  (%f %f) (%f %f);\n",
        	    xlegend, ylegend,
            	xlegend + 3100, ylegend );
        printf("TEXT '%5.2f mm' (%f %f);\n", 
				u2mm(Drilling[Index[i]]),
				xlegend + 440,
				ylegend - 135 );
	    printf("TEXT '+/-0.07 mm' (%f %f);\n",
    	        xlegend + 1250, ylegend - 135 );
	    printf("TEXT '%4d' (%f %f);\n",Counts[Index[i]],
    	        xlegend + 2200, ylegend - 135 );
	    if (Counts[Index[i]] == Plating[Index[i]])
		printf("TEXT 'Yes' (%f %f);\n",
    	        	xlegend + 2600, ylegend - 135 );
	    else
		printf("TEXT '%4d' (%f %f);\n",Plating[Index[i]],
    	        	xlegend + 2600, ylegend - 135 );

        ylegend -= 200;
    }

// Print counts:
 printf("TEXT ' Number of Pads:  %d' (%f %f);\n", ipads, xlegend + 40, ylegend - 400);  
 printf("TEXT ' Number of Vias:  %d' (%f %f);\n", k, xlegend + 40, ylegend - 600); 
 printf("TEXT ' Number of Smds:  %d' (%f %f);\n", j+l, xlegend + 40, ylegend - 800); 
 printf("TEXT ' Smds in Top:  %d' (%f %f);\n", j, xlegend + 240, ylegend - 1000); 
 printf("TEXT ' Smds in Bot:  %d' (%f %f);\n", l, xlegend + 240, ylegend - 1200); 

printf("WIRE 5  (%f %f) (%f %f);\n", xlegend, ylegend - 200, 
					xlegend + 1500, ylegend - 200);

 printf("WIRE 5  (%f %f) (%f %f);\n", xlegend, ylegend - 1400, 
					xlegend + 1500, ylegend - 1400);

printf("WIRE 5  (%f %f) (%f %f);\n", xlegend, ylegend- 200 , 
					xlegend, ylegend - 1400);
printf("WIRE 5  (%f %f) (%f %f);\n", xlegend + 1500, ylegend - 200 , 
					xlegend + 1500, ylegend - 1400);



    ylegend = u2mil(B.area.y1) + (imax* 200);

    printf("WIRE 5  (%f %f) (%f %f);\n",
            xlegend, u2mil(B.area.y1),
            xlegend + 3100, u2mil(B.area.y1));

    printf("WIRE 5  (%f %f) (%f %f);\n",
            xlegend, ylegend + 400,
            xlegend + 3100, ylegend + 400 );

    printf("WIRE 5  (%f %f) (%f %f);\n", 
            xlegend, u2mil(B.area.y1),
            xlegend, ylegend + 400 );

    printf("WIRE 5  (%f %f) (%f %f);\n", 
            xlegend + 3100, u2mil(B.area.y1),
            xlegend + 3100, ylegend + 400 );

    printf("WIRE 5  (%f %f) (%f %f);\n",
            xlegend, ylegend + 200,
            xlegend + 3100, ylegend + 200 );

    printf("WIRE 5  (%f %f) (%f %f);\n",
            xlegend, ylegend,
            xlegend + 3100, ylegend );

    printf("WIRE 5  (%f %f) (%f %f);\n", 
            xlegend + 370, u2mil(B.area.y1),
            xlegend + 370, ylegend + 200 );

    printf("WIRE 5  (%f %f) (%f %f);\n", 
            xlegend + 2100, u2mil(B.area.y1),
            xlegend + 2100, ylegend + 200 );

    printf("WIRE 5  (%f %f) (%f %f);\n", 
            xlegend + 2500, u2mil(B.area.y1),
            xlegend + 2500, ylegend + 200 );

    printf("CHANGE SIZE 150;\n");

    printf("TEXT 'DRILL PLAN ' (%f %f);\n",
            xlegend + 800, ylegend + 225);

    printf("CHANGE SIZE 100;\n");

    printf("TEXT 'SYM' (%f %f);\n",
            xlegend + 50, ylegend + 50);

    printf("TEXT 'SIZE' (%f %f);\n",
            xlegend + 460, ylegend + 50);

    printf("TEXT 'TOL.' (%f %f);\n",
            xlegend + 1250, ylegend + 50);

    printf("TEXT 'CNT' (%f %f);\n",
            xlegend + 2190, ylegend + 50);

    printf("TEXT 'PLATE' (%f %f);\n",
            xlegend + 2590, ylegend + 50);

    printf("CHANGE SIZE 70;\n");

    printf("TEXT 'TOTAL' (%f %f);\n",
            xlegend + 1600, u2mil(B.area.y1) - 150 );
    printf("TEXT '%4d' (%f %f);\n",totalDrills,
   	        xlegend + 2200, u2mil(B.area.y1) - 150 );
    printf("TEXT '%4d' (%f %f);\n",totalPlates,
   	        xlegend + 2600, u2mil(B.area.y1) - 150 );

    printf("TEXT '(Set the drill symbols with' (%f %f);\n",
            xlegend + 120, ylegend + 1000 );

    printf("TEXT 'Options - Set - Drill - Set)' (%f %f);\n",
            xlegend + 120, ylegend + 900);

    printf("TEXT 'Drill file will contain one extra of' (%f %f);\n",
            xlegend + 120, ylegend + 700 );

    printf("TEXT 'each drill, placed in above diagram.' (%f %f);\n",
            xlegend + 120, ylegend + 600);

    printf("WINDOW FIT;\n");
  }
}


exit("SCRIPT C:/temp/tempDrillPlanmm");



