/****************************************************************************************
*                                                                                       *
*   AutoDimensionning of Board (Version 2.00)                                           *
*                                                                                       *
*   Filename: adimv2_00.ulp                                                             *
*   Written by: Michel Dagenais <jcmae@sympatico.ca>                                    *
*   Date: September 12th 1998                                                           *
*                                                                                       *
*   Now places text on appropriate side (closer to object beeing dimensionned).         *
*                                                                                       *
*   This ULP program will put all the necessary dimensions for holes (layer 45) and     *
*   board outline (arcs and wires on layer 20) on your board.                           *
*                                                                                       *
*   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.                    *
*                                                                                       *
*   After this ULP has finished, run script adimv2_00.scr in your working directory     *
*                                                                                       *
****************************************************************************************/

real datum_dot_diameter = 0.050;      //   diameter of connecting dot on datum line

real datum_wire_width = 0.020;        //   width or datum line
real default_wire_width = 0.008;      //   default wire width for dimension extender and leader
real wire_width;

real extender_clearance = 0.05;       //   clearance from closest edge
real text_offset = 0.5;               // 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;

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;

int i;
int j;

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;
   }
}

output("adimv2_00.scr")
{
   printf(";\n");
   printf("Grid Inch;\n");
   printf("Change Width 0.008;\n");
   printf("Change Size 0.070;\n");
   printf("Change Ratio 8;\n");
   printf("Display 20 45 47;\n");
   printf("Layer 47;\n");
   board(B)
   {
      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.arcs(A)
      {
         if (A.layer == 20)
         {
            check_x_points(A.xc, A.yc);
            check_y_points(A.yc, A.xc);
          }
      }
      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);
         }
      }
      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", (u2inch(top_limit) + right_top_datum_location), (u2inch(top_limit) + right_top_datum_location + (datum_dot_diameter /2)));
            printf("Circle 0 (0 %.3f) (0 %.3f);\n", (u2inch(bottom_limit) - left_bottom_datum_location), (u2inch(bottom_limit) - left_bottom_datum_location - (datum_dot_diameter /2)));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", datum_wire_width, u2inch(x_points[i]), (u2inch(top_limit) + extender_clearance), u2inch(x_points[i]), (u2inch(top_limit) + right_top_extender_length));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", datum_wire_width, u2inch(x_points[i]), (u2inch(bottom_limit) - extender_clearance), u2inch(x_points[i]), (u2inch(bottom_limit) - left_bottom_extender_length));
            printf("Text '%.3f' R90 (%.3f %.3f);\n", abs(u2inch(x_points[i])), u2inch(x_points[i]), (u2inch(top_limit) + text_offset));
            printf("Text '%.3f' R90 (%.3f %.3f);\n", abs(u2inch(x_points[i])), u2inch(x_points[i]), (u2inch(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(u2inch(x_points[i])), u2inch(x_points[i]), (u2inch(top_limit) + text_offset));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, u2inch(x_points[i]), (u2inch(top_limit) + extender_clearance), u2inch(x_points[i]), (u2inch(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(u2inch(x_points[i])), u2inch(x_points[i]), (u2inch(bottom_limit) - text_offset - 0.3));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, u2inch(x_points[i]), (u2inch(bottom_limit) - extender_clearance), u2inch(x_points[i]), (u2inch(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, u2inch(lower_top), (u2inch(top_limit) + right_top_datum_location), u2inch(higher_top), (u2inch(top_limit) + right_top_datum_location));
         if (lower_bottom != higher_bottom)
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, u2inch(lower_bottom), (u2inch(bottom_limit) - left_bottom_datum_location), u2inch(higher_bottom), (u2inch(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", (u2inch(right_limit) + right_top_datum_location), (u2inch(right_limit) + right_top_datum_location + (datum_dot_diameter /2)));
            printf("Circle 0 (%.3f 0) (%.3f 0);\n", (u2inch(left_limit) - left_bottom_datum_location), (u2inch(left_limit) - left_bottom_datum_location - (datum_dot_diameter /2)));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", datum_wire_width, (u2inch(right_limit) + extender_clearance), u2inch(y_points[i]), (u2inch(right_limit) + right_top_extender_length), u2inch(y_points[i]));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", datum_wire_width, (u2inch(left_limit) - extender_clearance), u2inch(y_points[i]), (u2inch(left_limit) - left_bottom_extender_length), u2inch(y_points[i]));
            printf("Text '%.3f' R0 (%.3f %.3f);\n", abs(u2inch(y_points[i])), (u2inch(right_limit) + text_offset), u2inch(y_points[i]));
            printf("Text '%.3f' R0 (%.3f %.3f);\n", abs(u2inch(y_points[i])), (u2inch(left_limit) - text_offset - 0.3), u2inch(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(u2inch(y_points[i])), (u2inch(right_limit) + text_offset), u2inch(y_points[i]));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, (u2inch(right_limit) + extender_clearance), u2inch(y_points[i]), (u2inch(right_limit) + right_top_extender_length), u2inch(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(u2inch(y_points[i])), (u2inch(left_limit) - text_offset - 0.3), u2inch(y_points[i]));
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, (u2inch(left_limit) - extender_clearance), u2inch(y_points[i]), (u2inch(left_limit) - left_bottom_extender_length), u2inch(y_points[i]));
         }
      }
//   Join all Y dimensions
         if (lower_right != higher_right)
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, (u2inch(right_limit) + right_top_datum_location), u2inch(lower_right), (u2inch(right_limit) + right_top_datum_location), u2inch(higher_right));
         if (lower_left != higher_left)
            printf("Wire %.3f (%.3f %.3f) (%.3f %.3f);\n", default_wire_width, (u2inch(left_limit) - left_bottom_datum_location), u2inch(lower_left), (u2inch(left_limit) - left_bottom_datum_location), u2inch(higher_left));
   }
   printf("Grid Last;\n");
   printf("Window Fit;\n");
}
