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
48 #include <sys/param.h>
50 #include <sys/types.h>
72 #ifdef HAVE_LIBDMALLOC
87 diag_line (Coord X
, Coord Y
, Coord l
, Coord w
, bool rt
)
95 x1
= (l
- w
) * M_SQRT1_2
;
96 x2
= (l
+ w
) * M_SQRT1_2
;
102 x2
= -(l
- w
) * M_SQRT1_2
;
103 x1
= -(l
+ w
) * M_SQRT1_2
;
110 if ((c
= poly_NewContour (v
)) == NULL
)
114 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
117 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
120 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
121 return ContourToPoly (c
);
125 square_therm (PinType
*pin
, Cardinal style
)
135 d
= pcb
->ThermScale
* pin
->Clearance
* M_SQRT1_2
;
136 out
= (pin
->Thickness
+ pin
->Clearance
) / 2;
137 in
= pin
->Thickness
/ 2;
138 /* top (actually bottom since +y is down) */
139 v
[0] = pin
->X
- in
+ d
;
141 if ((c
= poly_NewContour (v
)) == NULL
)
143 v
[0] = pin
->X
+ in
- d
;
144 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
145 v
[0] = pin
->X
+ out
- d
;
147 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
148 v
[0] = pin
->X
- out
+ d
;
149 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
150 p
= ContourToPoly (c
);
153 v
[1] = pin
->Y
+ in
- d
;
154 if ((c
= poly_NewContour (v
)) == NULL
)
156 v
[1] = pin
->Y
- in
+ d
;
157 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
159 v
[1] = pin
->Y
- out
+ d
;
160 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
161 v
[1] = pin
->Y
+ out
- d
;
162 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
163 p2
= ContourToPoly (c
);
168 v
[1] = pin
->Y
- in
+ d
;
169 if ((c
= poly_NewContour (v
)) == NULL
)
171 v
[1] = pin
->Y
+ in
- d
;
172 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
174 v
[1] = pin
->Y
+ out
- d
;
175 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
176 v
[1] = pin
->Y
- out
+ d
;
177 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
178 p2
= ContourToPoly (c
);
181 /* bottom (actually top since +y is down) */
182 v
[0] = pin
->X
+ in
- d
;
184 if ((c
= poly_NewContour (v
)) == NULL
)
186 v
[0] = pin
->X
- in
+ d
;
187 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
188 v
[0] = pin
->X
- out
+ d
;
190 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
191 v
[0] = pin
->X
+ out
- d
;
192 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
193 p2
= ContourToPoly (c
);
202 l
.Flags
= NoFlags ();
203 d
= pin
->Thickness
/ 2 - pcb
->ThermScale
* pin
->Clearance
;
204 out
= pin
->Thickness
/ 2 + pin
->Clearance
/ 4;
205 in
= pin
->Clearance
/ 2;
207 l
.Point1
.X
= pin
->X
- d
;
208 l
.Point2
.Y
= l
.Point1
.Y
= pin
->Y
+ out
;
209 l
.Point2
.X
= pin
->X
+ d
;
210 p
= LinePoly (&l
, in
);
212 l
.Point1
.X
= l
.Point2
.X
= pin
->X
+ out
;
213 l
.Point1
.Y
= pin
->Y
- d
;
214 l
.Point2
.Y
= pin
->Y
+ d
;
215 p2
= LinePoly (&l
, in
);
219 l
.Point1
.X
= pin
->X
- d
;
220 l
.Point2
.Y
= l
.Point1
.Y
= pin
->Y
- out
;
221 l
.Point2
.X
= pin
->X
+ d
;
222 p2
= LinePoly (&l
, in
);
226 l
.Point1
.X
= l
.Point2
.X
= pin
->X
- out
;
227 l
.Point1
.Y
= pin
->Y
- d
;
228 l
.Point2
.Y
= pin
->Y
+ d
;
229 p2
= LinePoly (&l
, in
);
236 default: /* style 2 and 5 */
237 d
= 0.5 * pcb
->ThermScale
* pin
->Clearance
;
240 out
= (pin
->Thickness
+ pin
->Clearance
) / 2;
241 in
= pin
->Thickness
/ 2;
245 if ((c
= poly_NewContour (v
)) == NULL
)
248 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
252 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
255 frac_circle (c
, v
[0] + pin
->Clearance
/ 4, v
[1], v
, 2);
257 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
258 /* pivot 1/4 circle to next point */
259 frac_circle (c
, pin
->X
+ in
, pin
->Y
+ in
, v
, 4);
261 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
264 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
266 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
269 frac_circle (c
, v
[0], v
[1] - pin
->Clearance
/ 4, v
, 2);
270 p
= ContourToPoly (c
);
274 if ((c
= poly_NewContour (v
)) == NULL
)
277 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
279 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
283 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
286 frac_circle (c
, v
[0], v
[1] - pin
->Clearance
/ 4, v
, 2);
288 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
289 /* pivot 1/4 circle to next point */
290 frac_circle (c
, pin
->X
+ in
, pin
->Y
- in
, v
, 4);
292 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
294 frac_circle (c
, v
[0] - pin
->Clearance
/ 4, v
[1], v
, 2);
295 p2
= ContourToPoly (c
);
301 if ((c
= poly_NewContour (v
)) == NULL
)
304 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
306 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
310 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
313 frac_circle (c
, v
[0] - pin
->Clearance
/ 4, v
[1], v
, 2);
315 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
316 /* pivot 1/4 circle to next point */
317 frac_circle (c
, pin
->X
- in
, pin
->Y
- in
, v
, 4);
319 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
321 frac_circle (c
, v
[0], v
[1] + pin
->Clearance
/ 4, v
, 2);
322 p2
= ContourToPoly (c
);
328 if ((c
= poly_NewContour (v
)) == NULL
)
331 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
332 /* pivot 1/4 circle to next point (x-out, y+in) */
333 frac_circle (c
, pin
->X
- in
, pin
->Y
+ in
, v
, 4);
335 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
339 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
342 frac_circle (c
, v
[0] + pin
->Clearance
/ 4, v
[1], v
, 2);
344 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
346 poly_InclVertex (c
->head
.prev
, poly_CreateNode (v
));
348 frac_circle (c
, v
[0], v
[1] + pin
->Clearance
/ 4, v
, 2);
349 p2
= ContourToPoly (c
);
359 oct_therm (PinType
*pin
, Cardinal style
)
361 POLYAREA
*p
, *p2
, *m
;
362 Coord t
= 0.5 * pcb
->ThermScale
* pin
->Clearance
;
363 Coord w
= pin
->Thickness
+ pin
->Clearance
;
365 p
= OctagonPoly (pin
->X
, pin
->Y
, w
);
366 p2
= OctagonPoly (pin
->X
, pin
->Y
, pin
->Thickness
);
367 /* make full clearance ring */
368 poly_Boolean_free (p
, p2
, &m
, PBO_SUB
);
373 p
= diag_line (pin
->X
, pin
->Y
, w
, t
, true);
374 poly_Boolean_free (m
, p
, &p2
, PBO_SUB
);
375 p
= diag_line (pin
->X
, pin
->Y
, w
, t
, false);
376 poly_Boolean_free (p2
, p
, &m
, PBO_SUB
);
379 p
= RectPoly (pin
->X
- t
, pin
->X
+ t
, pin
->Y
- w
, pin
->Y
+ w
);
380 poly_Boolean_free (m
, p
, &p2
, PBO_SUB
);
381 p
= RectPoly (pin
->X
- w
, pin
->X
+ w
, pin
->Y
- t
, pin
->Y
+ t
);
382 poly_Boolean_free (p2
, p
, &m
, PBO_SUB
);
384 /* fix me add thermal style 4 */
387 Coord t
= pin
->Thickness
/ 2;
389 /* cheat by using the square therm's rounded parts */
390 p
= square_therm (pin
, style
);
391 q
= RectPoly (pin
->X
- t
, pin
->X
+ t
, pin
->Y
- t
, pin
->Y
+ t
);
392 poly_Boolean_free (p
, q
, &p2
, PBO_UNITE
);
393 poly_Boolean_free (m
, p2
, &p
, PBO_ISECT
);
399 /* ThermPoly returns a POLYAREA having all of the clearance that when
400 * subtracted from the plane create the desired thermal fingers.
401 * Usually this is 4 disjoint regions.
405 ThermPoly (PCBType
*p
, PinType
*pin
, Cardinal laynum
)
409 Cardinal style
= GET_THERM (laynum
, pin
);
412 return NULL
; /* solid connection no clearance */
414 if (TEST_FLAG (SQUAREFLAG
, pin
))
415 return square_therm (pin
, style
);
416 if (TEST_FLAG (OCTAGONFLAG
, pin
))
417 return oct_therm (pin
, style
);
418 /* must be circular */
425 Coord t
= (pin
->Thickness
+ pin
->Clearance
) / 2;
426 Coord w
= 0.5 * pcb
->ThermScale
* pin
->Clearance
;
427 pa
= CirclePoly (pin
->X
, pin
->Y
, t
);
428 arc
= CirclePoly (pin
->X
, pin
->Y
, pin
->Thickness
/ 2);
429 /* create a thin ring */
430 poly_Boolean_free (pa
, arc
, &m
, PBO_SUB
);
431 /* fix me needs error checking */
434 /* t is the theoretically required length, but we use twice that
435 * to avoid descritisation errors in our circle approximation.
437 pa
= RectPoly (pin
->X
- t
* 2, pin
->X
+ t
* 2, pin
->Y
- w
, pin
->Y
+ w
);
438 poly_Boolean_free (m
, pa
, &arc
, PBO_SUB
);
439 pa
= RectPoly (pin
->X
- w
, pin
->X
+ w
, pin
->Y
- t
* 2, pin
->Y
+ t
* 2);
443 /* t is the theoretically required length, but we use twice that
444 * to avoid descritisation errors in our circle approximation.
446 pa
= diag_line (pin
->X
, pin
->Y
, t
* 2, w
, true);
447 poly_Boolean_free (m
, pa
, &arc
, PBO_SUB
);
448 pa
= diag_line (pin
->X
, pin
->Y
, t
* 2, w
, false);
450 poly_Boolean_free (arc
, pa
, &m
, PBO_SUB
);
458 a
.Height
= a
.Width
= pin
->Thickness
/ 2 + pin
->Clearance
/ 4;
460 a
.Clearance
= pin
->Clearance
/ 2;
461 a
.Flags
= NoFlags ();
464 (a
.Clearance
* (1. + 2. * pcb
->ThermScale
) * 180) / (M_PI
* a
.Width
);
465 a
.StartAngle
= 90 - a
.Delta
/ 2 + (style
== 4 ? 0 : 45);
466 pa
= ArcPoly (&a
, a
.Clearance
);
470 arc
= ArcPoly (&a
, a
.Clearance
);
476 arc
= ArcPoly (&a
, a
.Clearance
);
482 arc
= ArcPoly (&a
, a
.Clearance
);