00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <stdio.h>
00011 #include <math.h>
00012
00013 #include "global.h"
00014 #include "data.h"
00015 #include "hid.h"
00016 #include "misc.h"
00017 #include "create.h"
00018 #include "rtree.h"
00019 #include "undo.h"
00020
00021 static PinTypePtr pin;
00022 static int layer;
00023 static int px, py;
00024 static LayerTypePtr silk;
00025
00026 static int new_arcs = 0;
00027
00028 static int
00029 check_line_callback (const BoxType * box, void *cl)
00030 {
00031 LayerTypePtr lay = & PCB->Data->Layer[layer];
00032 LineTypePtr l = (LineTypePtr) box;
00033 int x1, x2, y1, y2;
00034 double a, b, c, x, r, t;
00035 double dx, dy, len;
00036 double ax, ay, lx, ly, theta;
00037 double ldist, adist, radius;
00038 double vx, vy, vr, vl;
00039 int delta, aoffset, count;
00040 ArcTypePtr arc;
00041
00042 if (l->Point1.X == px && l->Point1.Y == py)
00043 {
00044 x1 = l->Point1.X;
00045 y1 = l->Point1.Y;
00046 x2 = l->Point2.X;
00047 y2 = l->Point2.Y;
00048 }
00049 else if (l->Point2.X == px && l->Point2.Y == py)
00050 {
00051 x1 = l->Point2.X;
00052 y1 = l->Point2.Y;
00053 x2 = l->Point1.X;
00054 y2 = l->Point1.Y;
00055 }
00056 else
00057 return 1;
00058
00059 r = pin->Thickness / 2.0;
00060 t = l->Thickness / 2.0;
00061
00062 if (t > r)
00063 return 1;
00064
00065 a = 1;
00066 b = 4 * t - 2 * r;
00067 c = 2 * t * t - r * r;
00068
00069 x = (-b + sqrt (b * b - 4 * a * c)) / (2 * a);
00070
00071 len = sqrt (((double)x2-x1)*(x2-x1) + ((double)y2-y1)*(y2-y1));
00072
00073 if (len > (x+t))
00074 {
00075 adist = ldist = x + t;
00076 radius = x + t;
00077 delta = 45;
00078
00079 if (radius < r || radius < t)
00080 return 1;
00081 }
00082 else if (len > r + t)
00083 {
00084
00085
00086 x = (len*len - r*r + t*t) / (2 * (r - t));
00087 ldist = len;
00088 adist = x + t;
00089 radius = x + t;
00090 delta = atan2 (len, x + t) * 180.0/M_PI;
00091 }
00092 else
00093 return 1;
00094
00095 dx = ((double)x2 - x1) / len;
00096 dy = ((double)y2 - y1) / len;
00097 theta = atan2 (y2 - y1, x1 - x2) * 180.0/M_PI;
00098
00099 lx = px + dx * ldist;
00100 ly = py + dy * ldist;
00101
00102
00103
00104 ax = lx - dy * adist;
00105 ay = ly + dx * adist;
00106 vl = sqrt (r*r - t*t);
00107 vx = px + dx * vl;
00108 vy = py + dy * vl;
00109 vx -= dy * t;
00110 vy += dx * t;
00111 vr = sqrt ((ax-vx) * (ax-vx) + (ay-vy) * (ay-vy));
00112
00113 aoffset = 0;
00114 count = 0;
00115 do {
00116 if (++count > 5)
00117 {
00118 printf("a %d,%d v %d,%d adist %g radius %g vr %g\n",
00119 (int)ax, (int)ay, (int)vx, (int)vy, adist, radius, vr);
00120 return 1;
00121 }
00122
00123 ax = lx - dy * adist;
00124 ay = ly + dx * adist;
00125
00126 arc = CreateNewArcOnLayer (lay, (int)ax, (int)ay, (int)radius, (int)radius,
00127 (int)theta+90+aoffset, delta-aoffset,
00128 l->Thickness, l->Clearance, l->Flags);
00129 if (arc)
00130 AddObjectToCreateUndoList (ARC_TYPE, lay, arc, arc);
00131
00132 ax = lx + dy * (x+t);
00133 ay = ly - dx * (x+t);
00134
00135 arc = CreateNewArcOnLayer (lay, (int)ax, (int)ay, (int)radius, (int)radius,
00136 (int)theta-90-aoffset, -delta+aoffset,
00137 l->Thickness, l->Clearance, l->Flags);
00138 if (arc)
00139 AddObjectToCreateUndoList (ARC_TYPE, lay, arc, arc);
00140
00141 radius += t*1.9;
00142 aoffset = acos ((double)adist / radius) * 180.0 / M_PI;
00143
00144 new_arcs ++;
00145 } while (vr > radius - t);
00146
00147 return 1;
00148 }
00149
00150 static void
00151 check_pin (PinTypePtr _pin)
00152 {
00153 BoxType spot;
00154
00155 pin = _pin;
00156
00157 px = pin->X;
00158 py = pin->Y;
00159
00160 spot.X1 = px - 1;
00161 spot.Y1 = py - 1;
00162 spot.X2 = px + 1;
00163 spot.Y2 = py + 1;
00164
00165 for (layer = 0; layer < max_layer; layer ++)
00166 {
00167 LayerTypePtr l = &(PCB->Data->Layer[layer]);
00168 r_search (l->line_tree, &spot, NULL, check_line_callback, l);
00169 }
00170 }
00171
00172 static int
00173 teardrops (int argc, char **argv, int x, int y)
00174 {
00175 silk = & PCB->Data->SILKLAYER;
00176
00177 new_arcs = 0;
00178
00179 VIA_LOOP (PCB->Data);
00180 {
00181 check_pin (via);
00182 }
00183 END_LOOP;
00184
00185 ALLPIN_LOOP (PCB->Data);
00186 {
00187 check_pin (pin);
00188 }
00189 ENDALL_LOOP;
00190
00191 gui->invalidate_all ();
00192
00193 if (new_arcs)
00194 IncrementUndoSerialNumber ();
00195
00196 return 0;
00197 }
00198
00199 static HID_Action teardrops_action_list[] = {
00200 {"Teardrops", NULL, teardrops,
00201 NULL, NULL}
00202 };
00203
00204 REGISTER_ACTIONS (teardrops_action_list)
00205
00206 void
00207 hid_teardrops_init()
00208 {
00209 register_teardrops_action_list();
00210 }