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 l
.Flags
= NoFlags ();
208 d
= pin
->Thickness
/ 2 - pcb
->ThermScale
* pin
->Clearance
;
209 out
= pin
->Thickness
/ 2 + pin
->Clearance
/ 4;
210 in
= pin
->Clearance
/ 2;
212 l
.Point1
.X
= pin
->X
- d
;
213 l
.Point2
.Y
= l
.Point1
.Y
= pin
->Y
+ out
;
214 l
.Point2
.X
= pin
->X
+ d
;
215 p
= LinePoly (&l
, in
);
217 l
.Point1
.X
= l
.Point2
.X
= pin
->X
+ out
;
218 l
.Point1
.Y
= pin
->Y
- d
;
219 l
.Point2
.Y
= pin
->Y
+ d
;
220 p2
= LinePoly (&l
, in
);
224 l
.Point1
.X
= pin
->X
- d
;
225 l
.Point2
.Y
= l
.Point1
.Y
= pin
->Y
- out
;
226 l
.Point2
.X
= pin
->X
+ d
;
227 p2
= LinePoly (&l
, in
);
231 l
.Point1
.X
= l
.Point2
.X
= pin
->X
- out
;
232 l
.Point1
.Y
= pin
->Y
- d
;
233 l
.Point2
.Y
= pin
->Y
+ d
;
234 p2
= LinePoly (&l
, in
);
241 default: /* style 2 and 5 */
242 d
= 0.5 * pcb
->ThermScale
* pin
->Clearance
;
245 out
= (pin
->Thickness
+ pin
->Clearance
) / 2;
246 in
= pin
->Thickness
/ 2;
250 if ((c
= poly_NewContour (v
)) == NULL
)
253 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
257 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
260 frac_circle (c
, v
[0] + pin
->Clearance
/ 4, v
[1], v
, 2);
262 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
263 /* pivot 1/4 circle to next point */
264 frac_circle (c
, pin
->X
+ in
, pin
->Y
+ in
, v
, 4);
266 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
269 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
271 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
274 frac_circle (c
, v
[0], v
[1] - pin
->Clearance
/ 4, v
, 2);
275 p
= ContourToPoly (c
);
279 if ((c
= poly_NewContour (v
)) == NULL
)
282 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
284 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
288 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
291 frac_circle (c
, v
[0], v
[1] - pin
->Clearance
/ 4, v
, 2);
293 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
294 /* pivot 1/4 circle to next point */
295 frac_circle (c
, pin
->X
+ in
, pin
->Y
- in
, v
, 4);
297 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
299 frac_circle (c
, v
[0] - pin
->Clearance
/ 4, v
[1], v
, 2);
300 p2
= ContourToPoly (c
);
306 if ((c
= poly_NewContour (v
)) == NULL
)
309 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
311 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
315 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
318 frac_circle (c
, v
[0] - pin
->Clearance
/ 4, v
[1], v
, 2);
320 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
321 /* pivot 1/4 circle to next point */
322 frac_circle (c
, pin
->X
- in
, pin
->Y
- in
, v
, 4);
324 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
326 frac_circle (c
, v
[0], v
[1] + pin
->Clearance
/ 4, v
, 2);
327 p2
= ContourToPoly (c
);
333 if ((c
= poly_NewContour (v
)) == NULL
)
336 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
337 /* pivot 1/4 circle to next point (x-out, y+in) */
338 frac_circle (c
, pin
->X
- in
, pin
->Y
+ in
, v
, 4);
340 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
344 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
347 frac_circle (c
, v
[0] + pin
->Clearance
/ 4, v
[1], v
, 2);
349 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
351 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
353 frac_circle (c
, v
[0], v
[1] + pin
->Clearance
/ 4, v
, 2);
354 p2
= ContourToPoly (c
);
364 oct_therm (PinTypePtr pin
, Cardinal style
)
366 POLYAREA
*p
, *p2
, *m
;
367 BDimension t
= 0.5 * pcb
->ThermScale
* pin
->Clearance
;
368 BDimension w
= pin
->Thickness
+ pin
->Clearance
;
370 p
= OctagonPoly (pin
->X
, pin
->Y
, w
);
371 p2
= OctagonPoly (pin
->X
, pin
->Y
, pin
->Thickness
);
372 /* make full clearance ring */
373 poly_Boolean_free (p
, p2
, &m
, PBO_SUB
);
378 p
= diag_line (pin
->X
, pin
->Y
, w
, t
, true);
379 poly_Boolean_free (m
, p
, &p2
, PBO_SUB
);
380 p
= diag_line (pin
->X
, pin
->Y
, w
, t
, false);
381 poly_Boolean_free (p2
, p
, &m
, PBO_SUB
);
384 p
= RectPoly (pin
->X
- t
, pin
->X
+ t
, pin
->Y
- w
, pin
->Y
+ w
);
385 poly_Boolean_free (m
, p
, &p2
, PBO_SUB
);
386 p
= RectPoly (pin
->X
- w
, pin
->X
+ w
, pin
->Y
- t
, pin
->Y
+ t
);
387 poly_Boolean_free (p2
, p
, &m
, PBO_SUB
);
389 /* fix me add thermal style 4 */
392 BDimension t
= pin
->Thickness
/ 2;
394 /* cheat by using the square therm's rounded parts */
395 p
= square_therm (pin
, style
);
396 q
= RectPoly (pin
->X
- t
, pin
->X
+ t
, pin
->Y
- t
, pin
->Y
+ t
);
397 poly_Boolean_free (p
, q
, &p2
, PBO_UNITE
);
398 poly_Boolean_free (m
, p2
, &p
, PBO_ISECT
);
404 /* ThermPoly returns a POLYAREA having all of the clearance that when
405 * subtracted from the plane create the desired thermal fingers.
406 * Usually this is 4 disjoint regions.
410 ThermPoly (PCBTypePtr p
, PinTypePtr pin
, Cardinal laynum
)
414 Cardinal style
= GET_THERM (laynum
, pin
);
417 return NULL
; /* solid connection no clearance */
419 if (TEST_FLAG (SQUAREFLAG
, pin
))
420 return square_therm (pin
, style
);
421 if (TEST_FLAG (OCTAGONFLAG
, pin
))
422 return oct_therm (pin
, style
);
423 /* must be circular */
430 BDimension t
= (pin
->Thickness
+ pin
->Clearance
) / 2;
431 BDimension w
= 0.5 * pcb
->ThermScale
* pin
->Clearance
;
432 pa
= CirclePoly (pin
->X
, pin
->Y
, t
);
433 arc
= CirclePoly (pin
->X
, pin
->Y
, pin
->Thickness
/ 2);
434 /* create a thin ring */
435 poly_Boolean_free (pa
, arc
, &m
, PBO_SUB
);
436 /* fix me needs error checking */
439 pa
= RectPoly (pin
->X
- t
, pin
->X
+ t
, pin
->Y
- w
, pin
->Y
+ w
);
440 poly_Boolean_free (m
, pa
, &arc
, PBO_SUB
);
441 pa
= RectPoly (pin
->X
- w
, pin
->X
+ w
, pin
->Y
- t
, pin
->Y
+ t
);
445 pa
= diag_line (pin
->X
, pin
->Y
, t
, w
, true);
446 poly_Boolean_free (m
, pa
, &arc
, PBO_SUB
);
447 pa
= diag_line (pin
->X
, pin
->Y
, t
, w
, false);
449 poly_Boolean_free (arc
, pa
, &m
, PBO_SUB
);
457 a
.Height
= a
.Width
= pin
->Thickness
/ 2 + pin
->Clearance
/ 4;
459 a
.Clearance
= pin
->Clearance
/ 2;
460 a
.Flags
= NoFlags ();
463 (a
.Clearance
* (1. + 2. * pcb
->ThermScale
) * 180) / (M_PI
* a
.Width
);
464 a
.StartAngle
= 90 - a
.Delta
/ 2 + (style
== 4 ? 0 : 45);
465 pa
= ArcPoly (&a
, a
.Clearance
);
469 arc
= ArcPoly (&a
, a
.Clearance
);
475 arc
= ArcPoly (&a
, a
.Clearance
);
481 arc
= ArcPoly (&a
, a
.Clearance
);