#usage "outline_drill_holes_cutoff \n"
"
"
"Usage: RUN outline_drill_holes_cutoff"
"
"
"Author: http://www.mi-ra-i.com/OPEN-JMM/"
"
"
"Author: miracute@hotmail.co.jp
"
//////////////////////////////////////////////////////
//////////////////// ユーザー設定 ////////////////////
//////////////////////////////////////////////////////
string DefaultSuffix = "_cut.tap"; // お使いのCNC似合わせた拡張子に変更してください
real dtool = 0.8; // エンドミルの直径を指定してください
real zstep = 0.4; // Z軸のステップ値を指定してください
real depth = -1.5; // 基板の厚さを指定してください
int fvalue = 200; // XY軸のF値を指定してください
int z_fvalue = 50; // Z軸のF値を指定してください
real cut_up = 1; // 空転移動時の高さを指定してください
int drill_cut = 1; // 取り付け穴のパスが必要ない場合は0にしてください
int drill_on = 1; // エンドミルによるドリルのオンオフ
int pecker_mode = 1; // キツツキドリルのオンオフ
///////////////////////////////////////////////////////
////////////////////// ここまで ///////////////////////
///////////////////////////////////////////////////////
real pai = 3.14159265358979;
real tool = dtool / 2.0;
real zpos = 0.0;
int layer =-1;
int into = 1;
real g_line_number = 10;
int g_fg_line_number = 1;
int g_fg_sort = 1;
int g_fg_sort_x_or_y = 1;
int g_x[], g_y[]; // coordinate of hole
int g_xy_array_size;
real g_round = 0.1;
real g_drill_size_list[];
int g_drill_size_list_array_size;
string gFileName;
//-------------------------------------------------------------------------------
//
void add_to_drill_list( int size )
{
real x;
int i;
x = ( u2mm( size ) / g_round ) * g_round;
// printf (">add_to_drill_list( size=%.3f ) \n" , x );
for (i=0; i < g_drill_size_list_array_size; i++ ) {
if ( g_drill_size_list[i] == x ) return;
}
g_drill_size_list[g_drill_size_list_array_size] = x;
g_drill_size_list_array_size++;
}
//-------------------------------------------------------------------------------
//
void sort_drill_size_list()
{
int i, j;
real a1,a2;
for(i=0; ii; j--){
if( g_drill_size_list[ j-1 ] > g_drill_size_list[ j ] ){
a1 = g_drill_size_list[ j - 1];
a2 = g_drill_size_list[ j ];
g_drill_size_list[ j - 1] = a2;
g_drill_size_list[ j ] = a1;
}
}
}
}
//-------------------------------------------------------------------------------
//
int create_drill_size_list()
{
// printf (">create_drill_size_list() \n");
g_drill_size_list_array_size = 0;
if ( board ) board( B ) {
B.holes(H) {
add_to_drill_list( H.drill );
}
B.elements(E) {
E.package.holes(H) {
add_to_drill_list( H.drill );
}
E.package.contacts(C) {
if (C.pad) {
add_to_drill_list( C.pad.drill );
}
}
}
B.signals(S) {
S.vias(V) {
add_to_drill_list( V.drill );
}
}
}
sort_drill_size_list();
return g_drill_size_list_array_size;
}
//-------------------------------------------------------------------------------
// ULP のSortにはバグがあり、エレメントのサイズが 0xffff より
// 大きいと駄目である、int は32bitなのだが、Sortできるのは16Bitの
// ようである。
// 単純にBubble Sortする。(エレメントが少ないからOKかな)
//
void bubble_sort( int begin, int num_of_record , int option )
{
int i, j;
int a1,a2;
if ( option ) {
// Yを基準にソートする
for(i=begin; ii; j--){
if( g_y[ j-1 ] > g_y[ j ] ){
a1 = g_y[ j - 1];
a2 = g_y[ j ];
g_y[ j - 1] = a2;
g_y[ j ] = a1;
a1 = g_x[ j - 1];
a2 = g_x[ j ];
g_x[ j - 1] = a2;
g_x[ j ] = a1;
}
}
}
} else {
// Xを基準にソートする
for(i=begin; ii; j--){
if( g_x[ j-1 ] > g_x[ j ] ){
a1 = g_x[ j - 1];
a2 = g_x[ j ];
g_x[ j - 1] = a2;
g_x[ j ] = a1;
a1 = g_y[ j - 1];
a2 = g_y[ j ];
g_y[ j - 1] = a2;
g_y[ j ] = a1;
}
}
}
}
}
//-------------------------------------------------------------------------------
//
// ある程度グループ化して、その中で二次元ソートを行う
//
void block_sort( int number_of_record )
{
int step_count = 0;
int block_step;
int block_number_of_record;
int j,i,n;
int begin;
// 始めに、1次元のソートを行う。
bubble_sort( 0, number_of_record , g_fg_sort_x_or_y );
// 次に、1次元ソートの結果をある程度グループ化して、その中で
// 2次元目のソートを行う。
begin = 0;
if ( g_fg_sort_x_or_y ) {
// Yを基準にXをソートする
// block のレコード数を数える
// とりあえず、5等分してブロック化する。
block_step = g_y[ number_of_record - 1 ] / 5;
for (j=1; j <= 10; j++ ) {
n = 0;
for (i = begin; i < number_of_record; i++ , n++) {
if ( g_y[i] > block_step ) {
//printf ("(block_step=%d)\n", block_step );
//printf ("(j=%d i=%d n=%d)\n", j,i,n );
bubble_sort( begin, n, 0 );
begin = i;
block_step += block_step;
break;
}
}
}
} else {
// Xを基準にソートする
// とりあえず、5等分してブロック化する。
block_step = g_x[ number_of_record - 1 ] / 5;
for (j=1; j <= 10; j++ ) {
n = 0;
for (i = begin; i < number_of_record; i++ , n++) {
if ( g_x[i] > block_step ) {
//printf ("(block_step=%d)\n", block_step );
//printf ("(j=%d i=%d n=%d)\n", j,i,n );
bubble_sort( begin, n, 1 );
begin = i;
block_step += block_step;
break;
}
}
}
}
}
//-------------------------------------------------------------------------------
//
void create_xy_data_by_drill_size( real d_size )
{
real d;
g_xy_array_size = 0;
if ( board ) board( B ) {
B.holes(H) {
d = ( u2mm( H.drill ) / g_round ) * g_round;
if ( d == d_size ) {
g_x[g_xy_array_size] = H.x;
g_y[g_xy_array_size] = H.y;
g_xy_array_size++;
}
}
B.elements(E) {
E.package.holes(H) {
d = ( u2mm( H.drill ) / g_round ) * g_round;
if ( d == d_size ) {
g_x[g_xy_array_size] = H.x;
g_y[g_xy_array_size] = H.y;
g_xy_array_size++;
}
}
E.package.contacts(C) {
if (C.pad) {
d = ( u2mm( C.pad.drill ) / g_round ) * g_round;
if ( d == d_size ) {
g_x[g_xy_array_size] = C.pad.x;
g_y[g_xy_array_size] = C.pad.y;
g_xy_array_size++;
}
}
}
}
B.signals(S) {
S.vias(V) {
d = ( u2mm( V.drill ) / g_round ) * g_round;
if ( d == d_size ) {
g_x[g_xy_array_size] = V.x;
g_y[g_xy_array_size] = V.y;
g_xy_array_size++;
}
}
}
}
}
//-------------------------------------------------------------------------------
//
void put_line_number()
{
if ( g_fg_line_number ) {
printf("N%05.0f ", g_line_number );
}
g_line_number += 1;
}
//-------------------------------------------------------------------------------
//
void put_nc_code( int x, int y )
{
if (drill_on == 1)
{
put_line_number();
printf("G00 X%.3f Y%.3f\n", u2mm(x), u2mm(-y));
if (1 == pecker_mode)
{
while ((depth + 0.000001) < (zpos -= zstep))
{
if ( 1 == into )
{
put_line_number();
printf("G00 Z%.3f\n",0.2);
zpos = -0.2;
put_line_number();
printf("G01 Z%.3f F%d\n",zpos, z_fvalue/2);
into = 0;
}else
{
put_line_number();
printf("G01 Z%.3f F%d\n",zpos, z_fvalue);
}
put_line_number();
printf("G00 Z%.3f\n", zpos + zstep);
put_line_number();
printf("G00 Z%.3f\n", zpos);
}
}else
{
put_line_number();
printf("G00 Z%.3f\n",0.2);
zpos = -0.2;
into = 0;
}
put_line_number();
printf("G1Z%.3f F%d\n" , depth , z_fvalue );
put_line_number();
printf("G00 Z%.3f\n" , cut_up );
zpos = 0;
into = 1;
}
}
//-------------------------------------------------------------------------------
//
//
void output_nc_header()
{
printf ("(This G-Code generated with CNC-DRILL-GCODE.ulp program)\n");
printf ("(running under Eagle CAD.)\n");
printf ("\n" );
put_line_number();
printf ("G00 Z2.00\n");
}
//-------------------------------------------------------------------------------
//
//
void output_nc_sepaleter( real d_size )
{
printf ("(----------------------------------------------------------)\n" );
printf ("( Drill size=%.3fmm )\n", d_size );
printf ("(----------------------------------------------------------)\n" );
}
//-------------------------------------------------------------------------------
//
//
void output_nc_footer()
{
printf ("\n" );
printf ("(----------------------------------------------------------)\n" );
put_line_number();
printf ("G00 Z2.00\n");
put_line_number();
printf ("G00 X0 Y0\n");
put_line_number();
printf ("M05 \n" );
}
void holes_cut(int x, int y, real h_d)
{
real h_x = u2mm(x);
real h_y = u2mm(y);
real raza=(h_d-dtool)/2;
if (h_d > dtool)
{
put_line_number();
printf("G00 X%.3f Y%.3f\n", h_x, (h_y + raza) * layer);
while ((depth + 0.000001) < (zpos -= zstep))
{
if ( 1 == into )
{
put_line_number();
printf("G00 Z%.3f\n",0.2);
zpos = -0.2;
into = 0;
}
put_line_number();
printf("G01 Z%.3f F%d\n",zpos, z_fvalue);
put_line_number();
printf("G02 X%.3f Y%.3f R%3f F%d\n", h_x - raza , h_y * layer , raza, fvalue);
put_line_number();
printf("G02 X%.3f Y%.3f R%3f F%d\n", h_x , (h_y - raza) * layer, raza, fvalue);
put_line_number();
printf("G02 X%.3f Y%.3f R%3f F%d\n", h_x + raza , h_y * layer , raza, fvalue);
put_line_number();
printf("G02 X%.3f Y%.3f R%3f F%d\n", h_x , (h_y + raza) * layer, raza, fvalue);
}
zpos = depth;
put_line_number();
printf("G01 Z%.3f F%d\n",zpos, z_fvalue);
put_line_number();
printf("G02 X%.3f Y%.3f R%3f F%d\n", h_x - raza , h_y * layer , raza, fvalue);
put_line_number();
printf("G02 X%.3f Y%.3f R%3f F%d\n", h_x , (h_y - raza) * layer, raza, fvalue);
put_line_number();
printf("G02 X%.3f Y%.3f R%3f F%d\n", h_x + raza , h_y * layer , raza, fvalue);
put_line_number();
printf("G02 X%.3f Y%.3f R%3f F%d\n", h_x , (h_y + raza) * layer, raza, fvalue);
put_line_number();
printf("G00 Z%.3f\n\n", cut_up);
zpos = 0;
into = 1;
}
}
real ver_x[];
real ver_y[];
int count = 0;
int state = 0;
void line_counter()
{
board(B)
{
B.wires(W)
{
if (W.layer == LAYER_DIMENSION)
{
if (state == 0)
{
ver_x[count] = u2mm(W.x1);
ver_y[count] = -u2mm(W.y1);
//printf("G00 X%f Y%f\n", ver_x[count] , ver_y[count] );
state = 1;
count ++;
}
ver_x[count] = u2mm(W.x2);
ver_y[count] = -u2mm(W.y2);
//printf("G01 X%f Y%f\n", ver_x[count] , ver_y[count] );
count ++;
}
}
count --;
printf("\n");
}
}
real ax, ay, bx, by, res_0, res_1;
real total_l = 0;
real total_r = 0;
int cou_l = 0;
int cou_r = 0;
int cc0, cc1, ioo, fc;
void checkturn_right_or_left()
{
for (fc = 0; fc <= count; fc ++)
{
if (fc == 0)
cc0 = count - 1;
else
cc0 = fc - 1;
if (fc == count)
cc1 = 1;
else
cc1 = fc + 1;
ax = ver_x[cc0] - ver_x[fc];
ay = ver_y[cc0] - ver_y[fc];
bx = ver_x[cc1] - ver_x[fc];
by = ver_y[cc1] - ver_y[fc];
res_0 = asin(( ax * by - ay * bx ) / ( sqrt(ax*ax + ay*ay) * sqrt(bx*bx + by*by)));
res_1 = acos(( ax * bx + ay * by ) / ( sqrt(ax*ax + ay*ay) * sqrt(bx*bx + by*by)));
if (res_0 < 0)
res_1 = 360 - res_1;
//printf("%f\n\n", res_1 * 180 / pai );
if (res_0 > 0)
cou_l ++;
else
cou_r ++;
total_l += res_0 * 180 / pai;
total_r += 360 + res_0 * 180 / pai;
}
if (cou_l > cou_r)
{
//printf("turn right!\n");
ioo = 0;
}else
{
//printf("turn left!\n");
ioo = 1;
}
}
int fc2;
real ang_0, ang_1, xd, yd, xr, yr, xroot, yroot, at;
real x_arg[], y_arg[], ret[], fir[] , bacv[];
real arct;
void write_outline()
{
for (fc = 0; fc < count; fc ++)
{
fc2 = fc + 1;
x_arg[0] = ver_x[fc];
x_arg[1] = ver_x[fc2];
y_arg[0] = ver_y[fc];
y_arg[1] = ver_y[fc2];
xroot = x_arg[1] - x_arg[0];
yroot = y_arg[1] - y_arg[0];
if (xroot == 0.0 || yroot == 0.0)
{
if (xroot == 0 && y_arg[0] < y_arg[1])
ang_0 = 0;
if (xroot == 0 && y_arg[0] > y_arg[1])
ang_0 = 0;
if (yroot == 0 && x_arg[0] < x_arg[1])
ang_0 = 90;
if (yroot == 0 && x_arg[0] > x_arg[1])
ang_0 = 90;
}else
{
at = atan( yroot / xroot );
ang_0 = at * 180 / pai;
//printf("%f\n", ang_0 );
ang_0 = 90 - sqrt(ang_0*ang_0);
}
ret[0] = cos( ang_0 / 180 * pai ) * tool;
ret[1] = sin( ang_0 / 180 * pai ) * tool;
if (xroot > 0 && yroot > 0)
{
ret[0] = -ret[0];
ret[1] = ret[1];
}
if (xroot < 0 && yroot > 0)
{
ret[0] = ret[0];
ret[1] = ret[1];
}
if (xroot < 0 && yroot < 0)
{
ret[0] = -ret[0];
ret[1] = ret[1];
}
if (xroot > 0 && yroot < 0)
{
ret[0] = ret[0];
ret[1] = ret[1];
}
ax = xroot;
ay = yroot;
bx = ret[0];
by = ret[1];
arct = ( ax * by - ay * bx ) / ( sqrt(ax*ax + ay*ay) * sqrt(bx*bx + by*by));
if ( arct < -1 )
arct = -1;
if ( arct > 1 )
arct = 1;
//printf("%f\n", arct );
res_0 = asin( arct );
//printf("%f\n", xroot );
//printf("%f\n", yroot );
//printf("%f\n", ret[0] );
//printf("%f\n\n", ret[1] );
//printf("%f\n", res_0 );
if (ioo == 0)
{
if (res_0 < 0)
{
if (fc != 0)
printf("G02 X%f Y%f I%f J%f\n\n", x_arg[0] - ret[0], y_arg[0] - ret[1], bacv[2], bacv[3] );
else
{
printf("G00 X%f Y%f\n", x_arg[0] - ret[0] , y_arg[0] - ret[1]);
printf("G01 Z%f F%d\n", zpos , z_fvalue);
fir[0] = x_arg[0] - ret[0];
fir[1] = y_arg[0] - ret[1];
}
printf("G01 X%f Y%f F%d\n", x_arg[1] - ret[0] , y_arg[1] - ret[1] , fvalue);
bacv[2] = ret[0];
bacv[3] = ret[1];
}else
{
if (fc != 0)
printf("G02 X%f Y%f I%f J%f\n\n", x_arg[0] + ret[0], y_arg[0] + ret[1], bacv[2], bacv[3] );
else
{
printf("G00 X%f Y%f\n", x_arg[0] + ret[0] , y_arg[0] + ret[1]);
printf("G01 Z%f F%d\n", zpos , z_fvalue);
fir[0] = x_arg[0] + ret[0];
fir[1] = y_arg[0] + ret[1];
}
printf("G01 X%f Y%f F%d\n", x_arg[1] + ret[0] , y_arg[1] + ret[1] , fvalue);
bacv[2] = -ret[0];
bacv[3] = -ret[1];
}
}else
{
if (res_0 > 0)
{
if (fc != 0)
printf("G03 X%f Y%f I%f J%f\n\n", x_arg[0] - ret[0], y_arg[0] - ret[1], bacv[2], bacv[3] );
else
{
printf("G00 X%f Y%f\n", x_arg[0] - ret[0] , y_arg[0] - ret[1]);
printf("G01 Z%f F%d\n", zpos , z_fvalue);
fir[0] = x_arg[0] - ret[0];
fir[1] = y_arg[0] - ret[1];
}
printf("G01 X%f Y%f F%d\n", x_arg[1] - ret[0] , y_arg[1] - ret[1] , fvalue);
bacv[2] = ret[0];
bacv[3] = ret[1];
}else
{
if (fc != 0)
printf("G03 X%f Y%f I%f J%f\n\n", x_arg[0] + ret[0], y_arg[0] + ret[1], bacv[2], bacv[3] );
else
{
printf("G00 X%f Y%f\n", x_arg[0] + ret[0] , y_arg[0] + ret[1]);
printf("G01 Z%f F%d\n", zpos , z_fvalue);
fir[0] = x_arg[0] + ret[0];
fir[1] = y_arg[0] + ret[1];
}
printf("G01 X%f Y%f F%d\n", x_arg[1] + ret[0] , y_arg[1] + ret[1] , fvalue);
bacv[2] = -ret[0];
bacv[3] = -ret[1];
}
}
}
if (ioo == 0)
printf("G02 X%f Y%f I%f J%f\n\n", fir[0], fir[1], bacv[2], bacv[3] );
else
printf("G03 X%f Y%f I%f J%f\n\n", fir[0], fir[1], bacv[2], bacv[3] );
}
//-------------------------------------------------------------------------------
// output g-code
//
void output_g_code(real size)
{
int j;
for (j=0; j < g_xy_array_size; j++ )
{
if (size == dtool)put_nc_code(g_x[j], g_y[j] );
if (size > dtool)holes_cut(g_x[j], g_y[j], size);
}
}
/////////////main/////////////
board(B)
{
int j;
int n;
output(filesetext(B.name, DefaultSuffix))
{
line_counter();
checkturn_right_or_left();
printf("T2 M06 S0 M03\n");
if (drill_cut == 1)
{
g_drill_size_list_array_size = create_drill_size_list();
output_nc_header();
for (j=0; j < g_drill_size_list_array_size; j++ )
{
create_xy_data_by_drill_size( g_drill_size_list[ j ] );
block_sort( g_xy_array_size );
output_nc_sepaleter( g_drill_size_list[ j ] );
output_g_code(g_drill_size_list[ j ]);
}
}
printf("G00 Z%f\n", 2.0 );
if ( depth < zstep)
while ((depth + 0.000001) < (zpos -= zstep))
write_outline();
zpos = depth;
write_outline();
printf("G00 Z%f\n", 2.0 );
}
}