4 * PCB, interactive printed circuit board design
5 * Copyright (C) 1994,1995,1996,2004,2006 Thomas Nau
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Contact addresses for paper mail and Email:
22 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
23 * Thomas.Nau@rz.uni-ulm.de
27 /* this file, thermal.c was written by and is
28 * (C) Copyright 2006, harry eaton
31 /* negative thermal finger polygons
47 #include <sys/param.h>
49 #include <sys/types.h>
71 #ifdef HAVE_LIBDMALLOC
86 diag_line (Coord X
, Coord Y
, Coord l
, Coord w
, bool rt
)
94 x1
= (l
- w
) * M_SQRT1_2
;
95 x2
= (l
+ w
) * M_SQRT1_2
;
101 x2
= -(l
- w
) * M_SQRT1_2
;
102 x1
= -(l
+ w
) * M_SQRT1_2
;
109 if ((c
= poly_NewContour (v
)) == NULL
)
113 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
116 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
119 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
120 return ContourToPoly (c
);
124 square_therm (PinType
*pin
, Cardinal style
)
134 d
= pcb
->ThermScale
* pin
->Clearance
* M_SQRT1_2
;
135 out
= (pin
->Thickness
+ pin
->Clearance
) / 2;
136 in
= pin
->Thickness
/ 2;
137 /* top (actually bottom since +y is down) */
138 v
[0] = pin
->X
- in
+ d
;
140 if ((c
= poly_NewContour (v
)) == NULL
)
142 v
[0] = pin
->X
+ in
- d
;
143 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
144 v
[0] = pin
->X
+ out
- d
;
146 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
147 v
[0] = pin
->X
- out
+ d
;
148 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
149 p
= ContourToPoly (c
);
152 v
[1] = pin
->Y
+ in
- d
;
153 if ((c
= poly_NewContour (v
)) == NULL
)
155 v
[1] = pin
->Y
- in
+ d
;
156 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
158 v
[1] = pin
->Y
- out
+ d
;
159 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
160 v
[1] = pin
->Y
+ out
- d
;
161 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
162 p2
= ContourToPoly (c
);
167 v
[1] = pin
->Y
- in
+ d
;
168 if ((c
= poly_NewContour (v
)) == NULL
)
170 v
[1] = pin
->Y
+ in
- d
;
171 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
173 v
[1] = pin
->Y
+ out
- d
;
174 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
175 v
[1] = pin
->Y
- out
+ d
;
176 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
177 p2
= ContourToPoly (c
);
180 /* bottom (actually top since +y is down) */
181 v
[0] = pin
->X
+ in
- d
;
183 if ((c
= poly_NewContour (v
)) == NULL
)
185 v
[0] = pin
->X
- in
+ d
;
186 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
187 v
[0] = pin
->X
- out
+ d
;
189 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
190 v
[0] = pin
->X
+ out
- d
;
191 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
192 p2
= ContourToPoly (c
);
201 l
.Flags
= NoFlags ();
202 d
= pin
->Thickness
/ 2 - pcb
->ThermScale
* pin
->Clearance
;
203 out
= pin
->Thickness
/ 2 + pin
->Clearance
/ 4;
204 in
= pin
->Clearance
/ 2;
206 l
.Point1
.X
= pin
->X
- d
;
207 l
.Point2
.Y
= l
.Point1
.Y
= pin
->Y
+ out
;
208 l
.Point2
.X
= pin
->X
+ d
;
209 p
= LinePoly (&l
, in
);
211 l
.Point1
.X
= l
.Point2
.X
= pin
->X
+ out
;
212 l
.Point1
.Y
= pin
->Y
- d
;
213 l
.Point2
.Y
= pin
->Y
+ d
;
214 p2
= LinePoly (&l
, in
);
218 l
.Point1
.X
= pin
->X
- d
;
219 l
.Point2
.Y
= l
.Point1
.Y
= pin
->Y
- out
;
220 l
.Point2
.X
= pin
->X
+ d
;
221 p2
= LinePoly (&l
, in
);
225 l
.Point1
.X
= l
.Point2
.X
= pin
->X
- out
;
226 l
.Point1
.Y
= pin
->Y
- d
;
227 l
.Point2
.Y
= pin
->Y
+ d
;
228 p2
= LinePoly (&l
, in
);
235 default: /* style 2 and 5 */
236 d
= 0.5 * pcb
->ThermScale
* pin
->Clearance
;
239 out
= (pin
->Thickness
+ pin
->Clearance
) / 2;
240 in
= pin
->Thickness
/ 2;
244 if ((c
= poly_NewContour (v
)) == NULL
)
247 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
251 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
254 frac_circle (c
, v
[0] + pin
->Clearance
/ 4, v
[1], v
, 2);
256 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
257 /* pivot 1/4 circle to next point */
258 frac_circle (c
, pin
->X
+ in
, pin
->Y
+ in
, v
, 4);
260 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
263 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
265 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
268 frac_circle (c
, v
[0], v
[1] - pin
->Clearance
/ 4, v
, 2);
269 p
= ContourToPoly (c
);
273 if ((c
= poly_NewContour (v
)) == NULL
)
276 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
278 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
282 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
285 frac_circle (c
, v
[0], v
[1] - pin
->Clearance
/ 4, v
, 2);
287 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
288 /* pivot 1/4 circle to next point */
289 frac_circle (c
, pin
->X
+ in
, pin
->Y
- in
, v
, 4);
291 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
293 frac_circle (c
, v
[0] - pin
->Clearance
/ 4, v
[1], v
, 2);
294 p2
= ContourToPoly (c
);
300 if ((c
= poly_NewContour (v
)) == NULL
)
303 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
305 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
309 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
312 frac_circle (c
, v
[0] - pin
->Clearance
/ 4, v
[1], v
, 2);
314 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
315 /* pivot 1/4 circle to next point */
316 frac_circle (c
, pin
->X
- in
, pin
->Y
- in
, v
, 4);
318 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
320 frac_circle (c
, v
[0], v
[1] + pin
->Clearance
/ 4, v
, 2);
321 p2
= ContourToPoly (c
);
327 if ((c
= poly_NewContour (v
)) == NULL
)
330 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
331 /* pivot 1/4 circle to next point (x-out, y+in) */
332 frac_circle (c
, pin
->X
- in
, pin
->Y
+ in
, v
, 4);
334 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
338 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
341 frac_circle (c
, v
[0] + pin
->Clearance
/ 4, v
[1], v
, 2);
343 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
345 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
347 frac_circle (c
, v
[0], v
[1] + pin
->Clearance
/ 4, v
, 2);
348 p2
= ContourToPoly (c
);
358 oct_therm (PinType
*pin
, Cardinal style
)
360 POLYAREA
*p
, *p2
, *m
;
361 Coord t
= 0.5 * pcb
->ThermScale
* pin
->Clearance
;
362 Coord w
= pin
->Thickness
+ pin
->Clearance
;
364 p
= OctagonPoly (pin
->X
, pin
->Y
, w
);
365 p2
= OctagonPoly (pin
->X
, pin
->Y
, pin
->Thickness
);
366 /* make full clearance ring */
367 poly_Boolean_free (p
, p2
, &m
, PBO_SUB
);
372 p
= diag_line (pin
->X
, pin
->Y
, w
, t
, true);
373 poly_Boolean_free (m
, p
, &p2
, PBO_SUB
);
374 p
= diag_line (pin
->X
, pin
->Y
, w
, t
, false);
375 poly_Boolean_free (p2
, p
, &m
, PBO_SUB
);
378 p
= RectPoly (pin
->X
- t
, pin
->X
+ t
, pin
->Y
- w
, pin
->Y
+ w
);
379 poly_Boolean_free (m
, p
, &p2
, PBO_SUB
);
380 p
= RectPoly (pin
->X
- w
, pin
->X
+ w
, pin
->Y
- t
, pin
->Y
+ t
);
381 poly_Boolean_free (p2
, p
, &m
, PBO_SUB
);
383 /* fix me add thermal style 4 */
386 Coord t
= pin
->Thickness
/ 2;
388 /* cheat by using the square therm's rounded parts */
389 p
= square_therm (pin
, style
);
390 q
= RectPoly (pin
->X
- t
, pin
->X
+ t
, pin
->Y
- t
, pin
->Y
+ t
);
391 poly_Boolean_free (p
, q
, &p2
, PBO_UNITE
);
392 poly_Boolean_free (m
, p2
, &p
, PBO_ISECT
);
398 /* ThermPoly returns a POLYAREA having all of the clearance that when
399 * subtracted from the plane create the desired thermal fingers.
400 * Usually this is 4 disjoint regions.
404 ThermPoly (PCBType
*p
, PinType
*pin
, Cardinal laynum
)
408 Cardinal style
= GET_THERM (laynum
, pin
);
411 return NULL
; /* solid connection no clearance */
413 if (TEST_FLAG (SQUAREFLAG
, pin
))
414 return square_therm (pin
, style
);
415 if (TEST_FLAG (OCTAGONFLAG
, pin
))
416 return oct_therm (pin
, style
);
417 /* must be circular */
424 Coord t
= (pin
->Thickness
+ pin
->Clearance
) / 2;
425 Coord w
= 0.5 * pcb
->ThermScale
* pin
->Clearance
;
426 pa
= CirclePoly (pin
->X
, pin
->Y
, t
);
427 arc
= CirclePoly (pin
->X
, pin
->Y
, pin
->Thickness
/ 2);
428 /* create a thin ring */
429 poly_Boolean_free (pa
, arc
, &m
, PBO_SUB
);
430 /* fix me needs error checking */
433 /* t is the theoretically required length, but we use twice that
434 * to avoid descritisation errors in our circle approximation.
436 pa
= RectPoly (pin
->X
- t
* 2, pin
->X
+ t
* 2, pin
->Y
- w
, pin
->Y
+ w
);
437 poly_Boolean_free (m
, pa
, &arc
, PBO_SUB
);
438 pa
= RectPoly (pin
->X
- w
, pin
->X
+ w
, pin
->Y
- t
* 2, pin
->Y
+ t
* 2);
442 /* t is the theoretically required length, but we use twice that
443 * to avoid descritisation errors in our circle approximation.
445 pa
= diag_line (pin
->X
, pin
->Y
, t
* 2, w
, true);
446 poly_Boolean_free (m
, pa
, &arc
, PBO_SUB
);
447 pa
= diag_line (pin
->X
, pin
->Y
, t
* 2, 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
);