2 * \file src/teardrops.c
4 * \brief Functions for handling the teardrop property of pins and vias.
8 * <h1><b>Copyright.</b></h1>\n
10 * PCB, interactive printed circuit board design
12 * Copyright (C) 2006 DJ Delorie <dj@delorie.com>
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
41 #define MIN_LINE_LENGTH 700
42 #define MAX_DISTANCE 700
47 static LayerType
* silk
;
49 static int new_arcs
= 0;
52 distance_between_points(int x1
,int y1
, int x2
, int y2
)
59 distance
= hypot (a
, b
);
64 check_line_callback (const BoxType
* box
, void *cl
)
66 LayerType
* lay
= & PCB
->Data
->Layer
[layer
];
67 LineType
* l
= (LineType
*) box
;
69 double a
, b
, c
, x
, r
, t
;
71 double ax
, ay
, lx
, ly
, theta
;
72 double ldist
, adist
, radius
;
73 double vx
, vy
, vr
, vl
;
74 int delta
, aoffset
, count
;
77 /* if our line is to short ignore it */
78 if (distance_between_points(l
->Point1
.X
,l
->Point1
.Y
,l
->Point2
.X
,l
->Point2
.Y
) < MIN_LINE_LENGTH
)
83 if (distance_between_points(l
->Point1
.X
,l
->Point1
.Y
,px
,py
) < MAX_DISTANCE
)
90 else if (distance_between_points(l
->Point2
.X
,l
->Point2
.Y
,px
,py
) < MAX_DISTANCE
)
100 r
= pin
->Thickness
/ 2.0;
101 t
= l
->Thickness
/ 2.0;
108 c
= 2 * t
* t
- r
* r
;
110 x
= (-b
+ sqrt (b
* b
- 4 * a
* c
)) / (2 * a
);
112 len
= sqrt (((double)x2
-x1
)*(x2
-x1
) + ((double)y2
-y1
)*(y2
-y1
));
116 adist
= ldist
= x
+ t
;
120 if (radius
< r
|| radius
< t
)
123 else if (len
> r
+ t
)
125 /* special "short teardrop" code */
127 x
= (len
*len
- r
*r
+ t
*t
) / (2 * (r
- t
));
131 delta
= atan2 (len
, x
+ t
) * 180.0/M_PI
;
136 dx
= ((double)x2
- x1
) / len
;
137 dy
= ((double)y2
- y1
) / len
;
138 theta
= atan2 (y2
- y1
, x1
- x2
) * 180.0/M_PI
;
140 lx
= px
+ dx
* ldist
;
141 ly
= py
+ dy
* ldist
;
143 /* We need one up front to determine how many segments it will take
145 ax
= lx
- dy
* adist
;
146 ay
= ly
+ dx
* adist
;
147 vl
= sqrt (r
*r
- t
*t
);
152 vr
= sqrt ((ax
-vx
) * (ax
-vx
) + (ay
-vy
) * (ay
-vy
));
159 printf("a %d,%d v %d,%d adist %g radius %g vr %g\n",
160 (int)ax
, (int)ay
, (int)vx
, (int)vy
, adist
, radius
, vr
);
164 ax
= lx
- dy
* adist
;
165 ay
= ly
+ dx
* adist
;
167 arc
= CreateNewArcOnLayer (lay
, (int)ax
, (int)ay
, (int)radius
, (int)radius
,
168 (int)theta
+90+aoffset
, delta
-aoffset
,
169 l
->Thickness
, l
->Clearance
, l
->Flags
);
171 AddObjectToCreateUndoList (ARC_TYPE
, lay
, arc
, arc
);
173 ax
= lx
+ dy
* (x
+t
);
174 ay
= ly
- dx
* (x
+t
);
176 arc
= CreateNewArcOnLayer (lay
, (int)ax
, (int)ay
, (int)radius
, (int)radius
,
177 (int)theta
-90-aoffset
, -delta
+aoffset
,
178 l
->Thickness
, l
->Clearance
, l
->Flags
);
180 AddObjectToCreateUndoList (ARC_TYPE
, lay
, arc
, arc
);
183 aoffset
= acos ((double)adist
/ radius
) * 180.0 / M_PI
;
186 } while (vr
> radius
- t
);
192 check_pin (PinType
* _pin
)
206 for (layer
= 0; layer
< max_copper_layer
; layer
++)
208 LayerType
* l
= &(PCB
->Data
->Layer
[layer
]);
209 r_search (l
->line_tree
, &spot
, NULL
, check_line_callback
, l
);
213 /* %start-doc actions Teardrops
215 The @code{Teardrops()} action adds teardrops to the intersections
216 between traces and pins/vias.
218 This is a simplistic test, so there are cases where you'd think it would
219 add them but doesn't.
221 If the trace doesn't end at @emph{exactly} the same point as the pin/via, it
224 This often happens with metric parts on an Imperial grid or visa-versa.
226 If a trace passes through a pin/via but doesn't end there, there won't
229 Use @code{:djopt(none)} to split those lines into two segments, each of which
234 This action takes no parameters.
236 To invoke it, use the command window, usually by typing ":".
242 @center @image{td_ex1,,,Example of how Teardrops works,png}
244 With the lesstif HID you can add this action to your menu or a hotkey by
245 editing $HOME/.pcb/pcb-menu.res (grab a copy from the pcb source if you
246 haven't one there yet).
250 Square pins are teardropped too.
252 Refdes silk is no longer visible.
256 teardrops (int argc
, char **argv
, Coord x
, Coord y
)
258 silk
= & PCB
->Data
->SILKLAYER
;
262 VIA_LOOP (PCB
->Data
);
268 ALLPIN_LOOP (PCB
->Data
);
274 gui
->invalidate_all ();
277 IncrementUndoSerialNumber ();
282 static HID_Action teardrops_action_list
[] = {
283 {"Teardrops", NULL
, teardrops
,
287 REGISTER_ACTIONS (teardrops_action_list
)
292 register_teardrops_action_list();