6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996,2004,2006 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
29 /* this file, thermal.c was written by and is
30 * (C) Copyright 2006, harry eaton
33 /* negative thermal finger polygons
50 #include <sys/param.h>
52 #include <sys/types.h>
74 #ifdef HAVE_LIBDMALLOC
80 static PCBTypePtr pcb
;
91 diag_line (LocationType X
, LocationType Y
, BDimension l
, BDimension w
,
96 BDimension x1
, x2
, y1
, y2
;
100 x1
= (l
- w
) * M_SQRT1_2
;
101 x2
= (l
+ w
) * M_SQRT1_2
;
107 x2
= -(l
- w
) * M_SQRT1_2
;
108 x1
= -(l
+ w
) * M_SQRT1_2
;
115 if ((c
= poly_NewContour (v
)) == NULL
)
119 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
122 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
125 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
126 return ContourToPoly (c
);
130 square_therm (PinTypePtr pin
, Cardinal style
)
135 BDimension d
, in
, out
;
140 d
= pcb
->ThermScale
* pin
->Clearance
* M_SQRT1_2
;
141 out
= (pin
->Thickness
+ pin
->Clearance
) / 2;
142 in
= pin
->Thickness
/ 2;
143 /* top (actually bottom since +y is down) */
144 v
[0] = pin
->X
- in
+ d
;
146 if ((c
= poly_NewContour (v
)) == NULL
)
148 v
[0] = pin
->X
+ in
- d
;
149 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
150 v
[0] = pin
->X
+ out
- d
;
152 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
153 v
[0] = pin
->X
- out
+ d
;
154 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
155 p
= ContourToPoly (c
);
158 v
[1] = pin
->Y
+ in
- d
;
159 if ((c
= poly_NewContour (v
)) == NULL
)
161 v
[1] = pin
->Y
- in
+ d
;
162 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
164 v
[1] = pin
->Y
- out
+ d
;
165 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
166 v
[1] = pin
->Y
+ out
- d
;
167 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
168 p2
= ContourToPoly (c
);
173 v
[1] = pin
->Y
- in
+ d
;
174 if ((c
= poly_NewContour (v
)) == NULL
)
176 v
[1] = pin
->Y
+ in
- d
;
177 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
179 v
[1] = pin
->Y
+ out
- d
;
180 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
181 v
[1] = pin
->Y
- out
+ d
;
182 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
183 p2
= ContourToPoly (c
);
186 /* bottom (actually top since +y is down) */
187 v
[0] = pin
->X
+ in
- d
;
189 if ((c
= poly_NewContour (v
)) == NULL
)
191 v
[0] = pin
->X
- in
+ d
;
192 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
193 v
[0] = pin
->X
- out
+ d
;
195 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
196 v
[0] = pin
->X
+ out
- d
;
197 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
198 p2
= ContourToPoly (c
);
207 d
= pin
->Thickness
/ 2 - pcb
->ThermScale
* pin
->Clearance
;
208 out
= pin
->Thickness
/ 2 + pin
->Clearance
/ 4;
209 in
= pin
->Clearance
/ 2;
211 l
.Point1
.X
= pin
->X
- d
;
212 l
.Point2
.Y
= l
.Point1
.Y
= pin
->Y
+ out
;
213 l
.Point2
.X
= pin
->X
+ d
;
214 p
= LinePoly (&l
, in
);
216 l
.Point1
.X
= l
.Point2
.X
= pin
->X
+ out
;
217 l
.Point1
.Y
= pin
->Y
- d
;
218 l
.Point2
.Y
= pin
->Y
+ d
;
219 p2
= LinePoly (&l
, in
);
223 l
.Point1
.X
= pin
->X
- d
;
224 l
.Point2
.Y
= l
.Point1
.Y
= pin
->Y
- out
;
225 l
.Point2
.X
= pin
->X
+ d
;
226 p2
= LinePoly (&l
, in
);
230 l
.Point1
.X
= l
.Point2
.X
= pin
->X
- out
;
231 l
.Point1
.Y
= pin
->Y
- d
;
232 l
.Point2
.Y
= pin
->Y
+ d
;
233 p2
= LinePoly (&l
, in
);
240 default: /* style 2 and 5 */
241 d
= 0.5 * pcb
->ThermScale
* pin
->Clearance
;
244 out
= (pin
->Thickness
+ pin
->Clearance
) / 2;
245 in
= pin
->Thickness
/ 2;
249 if ((c
= poly_NewContour (v
)) == NULL
)
252 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
256 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
259 frac_circle (c
, v
[0] + pin
->Clearance
/ 4, v
[1], v
, 2);
261 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
262 /* pivot 1/4 circle to next point */
263 frac_circle (c
, pin
->X
+ in
, pin
->Y
+ in
, v
, 4);
265 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
268 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
270 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
273 frac_circle (c
, v
[0], v
[1] - pin
->Clearance
/ 4, v
, 2);
274 p
= ContourToPoly (c
);
278 if ((c
= poly_NewContour (v
)) == NULL
)
281 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
283 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
287 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
290 frac_circle (c
, v
[0], v
[1] - pin
->Clearance
/ 4, v
, 2);
292 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
293 /* pivot 1/4 circle to next point */
294 frac_circle (c
, pin
->X
+ in
, pin
->Y
- in
, v
, 4);
296 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
298 frac_circle (c
, v
[0] - pin
->Clearance
/ 4, v
[1], v
, 2);
299 p2
= ContourToPoly (c
);
305 if ((c
= poly_NewContour (v
)) == NULL
)
308 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
310 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
314 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
317 frac_circle (c
, v
[0] - pin
->Clearance
/ 4, v
[1], v
, 2);
319 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
320 /* pivot 1/4 circle to next point */
321 frac_circle (c
, pin
->X
- in
, pin
->Y
- in
, v
, 4);
323 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
325 frac_circle (c
, v
[0], v
[1] + pin
->Clearance
/ 4, v
, 2);
326 p2
= ContourToPoly (c
);
332 if ((c
= poly_NewContour (v
)) == NULL
)
335 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
336 /* pivot 1/4 circle to next point (x-out, y+in) */
337 frac_circle (c
, pin
->X
- in
, pin
->Y
+ in
, v
, 4);
339 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
343 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
346 frac_circle (c
, v
[0] + pin
->Clearance
/ 4, v
[1], v
, 2);
348 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
350 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
352 frac_circle (c
, v
[0], v
[1] + pin
->Clearance
/ 4, v
, 2);
353 p2
= ContourToPoly (c
);
363 oct_therm (PinTypePtr pin
, Cardinal style
)
365 POLYAREA
*p
, *p2
, *m
;
366 BDimension t
= 0.5 * pcb
->ThermScale
* pin
->Clearance
;
367 BDimension w
= pin
->Thickness
+ pin
->Clearance
;
369 p
= OctagonPoly (pin
->X
, pin
->Y
, w
);
370 p2
= OctagonPoly (pin
->X
, pin
->Y
, pin
->Thickness
);
371 /* make full clearance ring */
372 poly_Boolean_free (p
, p2
, &m
, PBO_SUB
);
377 p
= diag_line (pin
->X
, pin
->Y
, w
, t
, true);
378 poly_Boolean_free (m
, p
, &p2
, PBO_SUB
);
379 p
= diag_line (pin
->X
, pin
->Y
, w
, t
, false);
380 poly_Boolean_free (p2
, p
, &m
, PBO_SUB
);
383 p
= RectPoly (pin
->X
- t
, pin
->X
+ t
, pin
->Y
- w
, pin
->Y
+ w
);
384 poly_Boolean_free (m
, p
, &p2
, PBO_SUB
);
385 p
= RectPoly (pin
->X
- w
, pin
->X
+ w
, pin
->Y
- t
, pin
->Y
+ t
);
386 poly_Boolean_free (p2
, p
, &m
, PBO_SUB
);
388 /* fix me add thermal style 4 */
391 BDimension t
= pin
->Thickness
/ 2;
393 /* cheat by using the square therm's rounded parts */
394 p
= square_therm (pin
, style
);
395 q
= RectPoly (pin
->X
- t
, pin
->X
+ t
, pin
->Y
- t
, pin
->Y
+ t
);
396 poly_Boolean_free (p
, q
, &p2
, PBO_UNITE
);
397 poly_Boolean_free (m
, p2
, &p
, PBO_ISECT
);
403 /* ThermPoly returns a POLYAREA having all of the clearance that when
404 * subtracted from the plane create the desired thermal fingers.
405 * Usually this is 4 disjoint regions.
409 ThermPoly (PCBTypePtr p
, PinTypePtr pin
, Cardinal laynum
)
413 Cardinal style
= GET_THERM (laynum
, pin
);
416 return NULL
; /* solid connection no clearance */
418 if (TEST_FLAG (SQUAREFLAG
, pin
))
419 return square_therm (pin
, style
);
420 if (TEST_FLAG (OCTAGONFLAG
, pin
))
421 return oct_therm (pin
, style
);
422 /* must be circular */
429 BDimension t
= (pin
->Thickness
+ pin
->Clearance
) / 2;
430 BDimension w
= 0.5 * pcb
->ThermScale
* pin
->Clearance
;
431 pa
= CirclePoly (pin
->X
, pin
->Y
, t
);
432 arc
= CirclePoly (pin
->X
, pin
->Y
, pin
->Thickness
/ 2);
433 /* create a thin ring */
434 poly_Boolean_free (pa
, arc
, &m
, PBO_SUB
);
435 /* fix me needs error checking */
438 pa
= RectPoly (pin
->X
- t
, pin
->X
+ t
, pin
->Y
- w
, pin
->Y
+ w
);
439 poly_Boolean_free (m
, pa
, &arc
, PBO_SUB
);
440 pa
= RectPoly (pin
->X
- w
, pin
->X
+ w
, pin
->Y
- t
, pin
->Y
+ t
);
444 pa
= diag_line (pin
->X
, pin
->Y
, t
, w
, true);
445 poly_Boolean_free (m
, pa
, &arc
, PBO_SUB
);
446 pa
= diag_line (pin
->X
, pin
->Y
, t
, w
, false);
448 poly_Boolean_free (arc
, pa
, &m
, PBO_SUB
);
456 a
.Height
= a
.Width
= pin
->Thickness
/ 2 + pin
->Clearance
/ 4;
458 a
.Clearance
= pin
->Clearance
/ 2;
459 a
.Flags
= NoFlags ();
462 (a
.Clearance
* (1. + 2. * pcb
->ThermScale
) * 180) / (M_PI
* a
.Width
);
463 a
.StartAngle
= 90 - a
.Delta
/ 2 + (style
== 4 ? 0 : 45);
464 pa
= ArcPoly (&a
, a
.Clearance
);
468 arc
= ArcPoly (&a
, a
.Clearance
);
474 arc
= ArcPoly (&a
, a
.Clearance
);
480 arc
= ArcPoly (&a
, a
.Clearance
);