diff -upN pcb_orig/src/action.c pcb/src/action.c --- pcb_orig/src/action.c 2010-10-22 15:41:48.000000000 +0200 +++ pcb/src/action.c 2010-10-21 18:25:30.000000000 +0200 @@ -1176,7 +1176,7 @@ NotifyMode (void) { if (((type = - SearchScreen (Note.X, Note.Y, PIN_TYPES, &ptr1, &ptr2, + SearchScreen (Note.X, Note.Y, THERMAL_TYPES, &ptr1, &ptr2, &ptr3)) != NO_TYPE) && !TEST_FLAG (HOLEFLAG, (PinTypePtr) ptr3)) { diff -upN pcb_orig/src/change.c pcb/src/change.c --- pcb_orig/src/change.c 2010-10-22 15:41:48.000000000 +0200 +++ pcb/src/change.c 2010-10-22 15:38:48.000000000 +0200 @@ -114,6 +114,7 @@ static void *SetPadSquare (ElementTypePt static void *ClrPadSquare (ElementTypePtr, PadTypePtr); static void *ChangeViaThermal (PinTypePtr); static void *ChangePinThermal (ElementTypePtr, PinTypePtr); +static void *ChangePadThermal (ElementTypePtr, PadTypePtr); static void *ChangeLineJoin (LayerTypePtr, LineTypePtr); static void *SetLineJoin (LayerTypePtr, LineTypePtr); static void *ClrLineJoin (LayerTypePtr, LineTypePtr); @@ -167,7 +168,7 @@ static ObjectFunctionType ChangeThermalF NULL, NULL, ChangePinThermal, - NULL, + ChangePadThermal, NULL, NULL, NULL, @@ -387,6 +388,26 @@ ChangePinThermal (ElementTypePtr element } /* --------------------------------------------------------------------------- + * changes the thermal on a pad + * returns TRUE if changed + */ +static void * +ChangePadThermal (ElementTypePtr element, PadTypePtr Pad) +{ + AddObjectToClearPolyUndoList (PAD_TYPE, element, Pad, Pad, false); + RestoreToPolygon (PCB->Data, PAD_TYPE, CURRENT, Pad); + AddObjectToFlagUndoList (PAD_TYPE, element, Pad, Pad); + if (!Delta) /* remove the thermals */ + CLEAR_THERM (INDEXOFCURRENT, Pad); + else + ASSIGN_THERM (INDEXOFCURRENT, Delta, Pad); + AddObjectToClearPolyUndoList (PAD_TYPE, element, Pad, Pad, true); + ClearFromPolygon (PCB->Data, PAD_TYPE, CURRENT, Pad); + DrawPad (Pad, 0); + return Pad; +} + +/* --------------------------------------------------------------------------- * changes the size of a via * returns TRUE if changed */ Files pcb_orig/src/.change.c.swo and pcb/src/.change.c.swo differ diff -upN pcb_orig/src/const.h pcb/src/const.h --- pcb_orig/src/const.h 2010-10-22 15:41:48.000000000 +0200 +++ pcb/src/const.h 2010-10-21 18:23:06.000000000 +0200 @@ -312,6 +312,7 @@ When set, element names are not drawn. #define LOCKED_TYPE 0x10000 /* used to tell search to include locked items. */ #define PIN_TYPES (VIA_TYPE | PIN_TYPE) +#define THERMAL_TYPES (VIA_TYPE | PIN_TYPE | PAD_TYPE) #define LOCK_TYPES (VIA_TYPE | LINE_TYPE | ARC_TYPE | POLYGON_TYPE | ELEMENT_TYPE \ | TEXT_TYPE | ELEMENTNAME_TYPE | LOCKED_TYPE) diff -upN pcb_orig/src/polygon.c pcb/src/polygon.c --- pcb_orig/src/polygon.c 2010-10-22 15:41:48.000000000 +0200 +++ pcb/src/polygon.c 2010-10-21 20:42:38.000000000 +0200 @@ -832,23 +832,34 @@ SubtractText (TextType * text, PolygonTy } static int -SubtractPad (PadType * pad, PolygonType * p) +SubtractPad (DataType * d, PadType * pad, LayerType * l, PolygonType * p) { POLYAREA *np = NULL; + Cardinal i; if (pad->Clearance == 0) return 0; - if (TEST_FLAG (SQUAREFLAG, pad)) + i = GetLayerNumber (d, l); + if (TEST_THERM (i, pad)) { - if (! - (np = SquarePadPoly (pad, pad->Thickness + pad->Clearance))) - return -1; + np = ThermPolyPad ((PCBTypePtr) (d->pcb), pad, i); + if (!np) + return 0; } else { - if (! - (np = LinePoly ((LineType *) pad, pad->Thickness + pad->Clearance))) - return -1; + if (TEST_FLAG (SQUAREFLAG, pad)) + { + if (! + (np = SquarePadPoly (pad, pad->Thickness + pad->Clearance))) + return -1; + } + else + { + if (! + (np = LinePoly ((LineType *) pad, pad->Thickness + pad->Clearance))) + return -1; + } } return Subtract (np, p, true); } @@ -912,7 +923,7 @@ pad_sub_callback (const BoxType * b, voi polygon = info->polygon; if (XOR (TEST_FLAG (ONSOLDERFLAG, pad), !info->solder)) { - if (SubtractPad (pad, polygon) < 0) + if (SubtractPad (info->data, pad, info->layer, polygon) < 0) longjmp (info->env, 1); return 1; } @@ -1416,7 +1427,7 @@ subtract_plow (DataTypePtr Data, LayerTy Polygon->NoHolesValid = 0; return 1; case PAD_TYPE: - SubtractPad ((PadTypePtr) ptr2, Polygon); + SubtractPad (Data, (PadTypePtr) ptr2, Layer, Polygon); Polygon->NoHolesValid = 0; return 1; case TEXT_TYPE: diff -upN pcb_orig/src/thermal.c pcb/src/thermal.c --- pcb_orig/src/thermal.c 2010-10-22 15:41:48.000000000 +0200 +++ pcb/src/thermal.c 2010-10-22 15:33:03.000000000 +0200 @@ -79,6 +79,10 @@ RCSID ("$Id$"); static PCBTypePtr pcb; +static POLYAREA * +square_therm_pad (PadTypePtr pad, Cardinal style); + + struct cent { LocationType x, y; @@ -489,3 +497,374 @@ ThermPoly (PCBTypePtr p, PinTypePtr pin, return pa; } } + +/* ThermPolyPad returns a POLYAREA having all of the clearance that when + * subtracted from the plane create the desired thermal fingers. + * Usually this is 4 disjoint regions. + * + */ +POLYAREA * +ThermPolyPad (PCBTypePtr p, PadTypePtr pad, Cardinal laynum) +{ + ArcType a; + POLYAREA *pa, *arc; + Cardinal style = GET_THERM (laynum, pad); + + if (style == 3) + return NULL; /* solid connection no clearance */ + pcb = p; + if (TEST_FLAG (SQUAREFLAG, pad)) + return square_therm_pad (pad, style); + switch (style) + { + case 1: + case 2: + { + POLYAREA *m; + BDimension t = (pad->Thickness + pad->Clearance) / 2; + BDimension w = 0.5 * pcb->ThermScale * pad->Clearance; + + m = LinePoly ((LineType *) pad, pad->Thickness + pad->Clearance); + if (style == 2) + { + pa = RectPoly (pad->Point1.X - t, pad->Point2.X + t, (pad->Point1.Y+pad->Point2.Y)/2 - w, (pad->Point1.Y+pad->Point2.Y)/2 + w); + poly_Boolean_free (m, pa, &arc, PBO_SUB); + pa = RectPoly ((pad->Point1.X+pad->Point2.X)/2 - w, (pad->Point1.X+pad->Point2.X)/2 + w, pad->Point1.Y - t, pad->Point2.Y + t); + poly_Boolean_free (arc, pa, &m, PBO_SUB); + return m; + } + else + { + PLINE *c; + Vector v; + BDimension wx = w*sqrt(1+1); + BDimension wy = w; + v[0] = pad->Point1.X - t-wx; + v[1] = pad->Point1.Y - t-wy; + if ((c = poly_NewContour (v)) == NULL) + return NULL; + v[0] = pad->Point1.X - t+wx; + v[1] = pad->Point1.Y - t-wy; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[0] = pad->Point2.X + t+wx; + v[1] = pad->Point2.Y + t+wy; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[0] = pad->Point2.X + t-wx; + v[1] = pad->Point2.Y + t+wy; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + + pa = ContourToPoly (c); + poly_Boolean_free (m, pa, &arc, PBO_SUB); + v[0] = pad->Point1.X + t-wx; + v[1] = pad->Point1.Y - t-wy; + if ((c = poly_NewContour (v)) == NULL) + return NULL; + v[0] = pad->Point1.X + t+wx; + v[1] = pad->Point1.Y - t-wy; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[0] = pad->Point2.X - t+wx; + v[1] = pad->Point2.Y + t+wy; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[0] = pad->Point2.X - t-wx; + v[1] = pad->Point2.Y + t+wy; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + pa = ContourToPoly (c); + poly_Boolean_free (arc, pa, &m, PBO_SUB); + return m; + } + + } + default: + a.X = pad->Point2.X; + a.Y = pad->Point2.Y; + a.Height = a.Width = pad->Thickness / 2 + pad->Clearance / 4; + a.Thickness = 1; + a.Clearance = pad->Clearance / 2; + a.Flags = NoFlags (); + a.Delta = + 90 - + (a.Clearance * (1. + 2. * pcb->ThermScale) * 180) / (M_PI * a.Width); + a.StartAngle = 90 - a.Delta / 2 + (style == 4 ? 0 : 45); + pa = ArcPoly (&a, a.Clearance); + if (!pa) + return NULL; + if (style == 5) + { + a.X = pad->Point1.X; + a.Y = pad->Point1.Y; + } + else + { + a.X = (pad->Point1.X+pad->Point2.X)/2; + a.Y = (pad->Point1.Y+pad->Point2.Y)/2; + } + a.StartAngle += 90; + arc = ArcPoly (&a, a.Clearance); + if (!arc) + return NULL; + pa->f = arc; + arc->b = pa; + a.X = pad->Point1.X; + a.Y = pad->Point1.Y; + a.StartAngle += 90; + arc = ArcPoly (&a, a.Clearance); + if (!arc) + return NULL; + pa->f->f = arc; + arc->b = pa->f; + if (style == 5) + { + a.X = pad->Point2.X; + a.Y = pad->Point2.Y; + } + else + { + a.X = (pad->Point1.X+pad->Point2.X)/2; + a.Y = (pad->Point1.Y+pad->Point2.Y)/2; + } + a.StartAngle += 90; + arc = ArcPoly (&a, a.Clearance); + if (!arc) + return NULL; + pa->b = arc; + pa->f->f->f = arc; + arc->b = pa->f->f; + arc->f = pa; + pa->b = arc; + return pa; + } + return NULL; +} + +static POLYAREA * +square_therm_pad (PadTypePtr pad, Cardinal style) +{ + POLYAREA *p, *p2; + PLINE *c; + Vector v; + BDimension d, in, out; + switch (style) + { + case 1: + d = pcb->ThermScale * pad->Clearance * M_SQRT1_2; + out = (pad->Thickness + pad->Clearance) / 2; + in = pad->Thickness / 2; + /* top (actually bottom since +y is down) */ + v[0] = pad->Point1.X - in + d; + v[1] = pad->Point2.Y + in; + if ((c = poly_NewContour (v)) == NULL) + return NULL; + v[0] = pad->Point2.X + in - d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[0] = pad->Point2.X + out - d; + v[1] = pad->Point2.Y + out; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[0] = pad->Point1.X - out + d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + p = ContourToPoly (c); + /* right */ + v[0] = pad->Point2.X + in; + v[1] = pad->Point2.Y + in - d; + if ((c = poly_NewContour (v)) == NULL) + return NULL; + v[1] = pad->Point1.Y - in + d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[0] = pad->Point2.X + out; + v[1] = pad->Point1.Y - out + d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[1] = pad->Point2.Y + out - d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + p2 = ContourToPoly (c); + p->f = p2; + p2->b = p; + /* left */ + v[0] = pad->Point1.X - in; + v[1] = pad->Point1.Y - in + d; + if ((c = poly_NewContour (v)) == NULL) + return NULL; + v[1] = pad->Point2.Y + in - d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[0] = pad->Point1.X - out; + v[1] = pad->Point2.Y + out - d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[1] = pad->Point1.Y - out + d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + p2 = ContourToPoly (c); + p->f->f = p2; + p2->b = p->f; + /* bottom (actually top since +y is down) */ + v[0] = pad->Point2.X + in - d; + v[1] = pad->Point1.Y - in; + if ((c = poly_NewContour (v)) == NULL) + return NULL; + v[0] = pad->Point1.X - in + d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[0] = pad->Point1.X - out + d; + v[1] = pad->Point1.Y - out; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[0] = pad->Point2.X + out - d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + p2 = ContourToPoly (c); + p->f->f->f = p2; + p2->f = p; + p2->b = p->f->f; + p->b = p2; + return p; + case 4: + { + LineType l; + l.Flags = NoFlags (); + d = pad->Thickness / 2 - pcb->ThermScale * pad->Clearance; + out = pad->Thickness / 2 + pad->Clearance / 4; + in = pad->Clearance / 2; + /* top */ + l.Point1.X = pad->Point1.X - d; + l.Point2.Y = l.Point1.Y = pad->Point2.Y + out; + l.Point2.X = pad->Point2.X + d; + p = LinePoly (&l, in); + /* right */ + l.Point1.X = l.Point2.X = pad->Point2.X + out; + l.Point1.Y = pad->Point1.Y - d; + l.Point2.Y = pad->Point2.Y + d; + p2 = LinePoly (&l, in); + p->f = p2; + p2->b = p; + /* bottom */ + l.Point1.X = pad->Point1.X - d; + l.Point2.Y = l.Point1.Y = pad->Point1.Y - out; + l.Point2.X = pad->Point2.X + d; + p2 = LinePoly (&l, in); + p->f->f = p2; + p2->b = p->f; + /* left */ + l.Point1.X = l.Point2.X = pad->Point1.X - out; + l.Point1.Y = pad->Point1.Y - d; + l.Point2.Y = pad->Point2.Y + d; + p2 = LinePoly (&l, in); + p->f->f->f = p2; + p2->b = p->f->f; + p->b = p2; + p2->f = p; + return p; + } + default: /* style 2 and 5 */ + d = 0.5 * pcb->ThermScale * pad->Clearance; + if (style == 5) + d += d; + out = (pad->Thickness + pad->Clearance) / 2; + in = pad->Thickness / 2; + /* topright */ + v[0] = pad->Point2.X + in; + v[1] = pad->Point2.Y + in; + if ((c = poly_NewContour (v)) == NULL) + return NULL; + v[1] = pad->Point2.Y + d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + if (style == 2) + { + v[0] = pad->Point2.X + out; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + } + else + frac_circle (c, v[0] + pad->Clearance / 4, v[1], v, 2); + v[1] = pad->Point2.Y + in; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + /* pivot 1/4 circle to next point */ + frac_circle (c, pad->Point2.X + in, pad->Point2.Y + in, v, 4); + v[0] = pad->Point2.X + d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + if (style == 2) + { + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[1] = pad->Point2.Y + in; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + } + else + frac_circle (c, v[0], v[1] - pad->Clearance / 4, v, 2); + p = ContourToPoly (c); + /* bottom right */ + v[0] = pad->Point2.X + in; + v[1] = pad->Point1.Y - d; + if ((c = poly_NewContour (v)) == NULL) + return NULL; + v[1] = pad->Point1.Y - in; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[0] = pad->Point2.X + d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + if (style == 2) + { + v[1] = pad->Point1.Y - out; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + } + else + frac_circle (c, v[0], v[1] - pad->Clearance / 4, v, 2); + v[0] = pad->Point2.X + in; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + /* pivot 1/4 circle to next point */ + frac_circle (c, pad->Point2.X + in, pad->Point1.Y - in, v, 4); + v[1] = pad->Point1.Y - d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + if (style == 5) + frac_circle (c, v[0] - pad->Clearance / 4, v[1], v, 2); + p2 = ContourToPoly (c); + p->f = p2; + p2->b = p; + /* bottom left */ + v[0] = pad->Point1.X - d; + v[1] = pad->Point1.Y - in; + if ((c = poly_NewContour (v)) == NULL) + return NULL; + v[0] = pad->Point1.X - in; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[1] = pad->Point1.Y - d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + if (style == 2) + { + v[0] = pad->Point1.X - out; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + } + else + frac_circle (c, v[0] - pad->Clearance / 4, v[1], v, 2); + v[1] = pad->Point1.Y - in; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + /* pivot 1/4 circle to next point */ + frac_circle (c, pad->Point1.X - in, pad->Point1.Y - in, v, 4); + v[0] = pad->Point1.X - d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + if (style == 5) + frac_circle (c, v[0], v[1] + pad->Clearance / 4, v, 2); + p2 = ContourToPoly (c); + p->f->f = p2; + p2->b = p->f; + /* top left */ + v[0] = pad->Point1.X - d; + v[1] = pad->Point2.Y + out; + if ((c = poly_NewContour (v)) == NULL) + return NULL; + v[0] = pad->Point1.X - in; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + /* pivot 1/4 circle to next point (x-out, y+in) */ + frac_circle (c, pad->Point1.X - in, pad->Point2.Y + in, v, 4); + v[1] = pad->Point2.Y + d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + if (style == 2) + { + v[0] = pad->Point1.X - in; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + } + else + frac_circle (c, v[0] + pad->Clearance / 4, v[1], v, 2); + v[1] = pad->Point2.Y + in; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + v[0] = pad->Point1.X - d; + poly_InclVertex (c->head.prev, poly_CreateNode (v)); + if (style == 5) + frac_circle (c, v[0], v[1] + pad->Clearance / 4, v, 2); + p2 = ContourToPoly (c); + p->f->f->f = p2; + p2->f = p; + p2->b = p->f->f; + p->b = p2; + return p; + } +} diff -upN pcb_orig/src/thermal.h pcb/src/thermal.h --- pcb_orig/src/thermal.h 2010-10-22 15:41:48.000000000 +0200 +++ pcb/src/thermal.h 2010-10-21 19:03:37.000000000 +0200 @@ -42,5 +42,6 @@ #include "mymem.h" POLYAREA * ThermPoly (PCBTypePtr, PinTypePtr, Cardinal); +POLYAREA * ThermPolyPad (PCBTypePtr, PadTypePtr, Cardinal); #endif