Index: trunk/src/flag_str.c =================================================================== --- trunk/src/flag_str.c (revision 12436) +++ trunk/src/flag_str.c (revision 12437) @@ -62,7 +62,7 @@ {FN(PCB_FLAG_CLEARPOLY), N("clearpoly"), PCB_TYPE_POLYGON, "For polygons, this flag means that pins and vias will normally clear these polygons (thus, thermals are required for electrical connection). When clear, polygons will solidly connect to pins and vias. " }, {FN(PCB_FLAG_HIDENAME), N("hidename"), PCB_TYPE_ELEMENT, "For elements, when set the name of the element is hidden." }, {FN(PCB_FLAG_DISPLAYNAME), N("showname"), PCB_TYPE_ELEMENT, "OBSOLETE: For elements, when set the names of pins are shown." }, - {FN(PCB_FLAG_CLEARLINE), N("clearline"), PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_TEXT, "For lines and arcs, the line/arc will clear polygons instead of connecting to them." }, + {FN(PCB_FLAG_CLEARLINE), N("clearline"), PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_TEXT | PCB_TYPE_PADSTACK, "For lines and arcs, the line/arc will clear polygons instead of connecting to them." }, {FN(PCB_FLAG_SELECTED), N("selected"), PCB_TYPEMASK_ALL, "Set when the object is selected."}, {FN(PCB_FLAG_ONSOLDER), N("onsolder"), PCB_TYPE_ELEMENT | PCB_TYPE_PAD | PCB_TYPE_TEXT, "For elements and pads, indicates that they are on the solder side."}, {FN(PCB_FLAG_AUTO), N("auto"), PCB_TYPEMASK_ALL, "For lines and vias, indicates that these were created by the autorouter."}, Index: trunk/src/polygon.c =================================================================== --- trunk/src/polygon.c (revision 12436) +++ trunk/src/polygon.c (revision 12437) @@ -54,6 +54,7 @@ #define UNSUBTRACT_BLOAT 10 #define SUBTRACT_PIN_VIA_BATCH_SIZE 100 +#define SUBTRACT_PADSTACK_BATCH_SIZE 50 #define SUBTRACT_LINE_BATCH_SIZE 20 #define sqr(x) ((x)*(x)) @@ -829,6 +830,22 @@ return Subtract(np, p, pcb_true); } +/* remove the padstack clearance from the polygon */ +static int SubtractPadstack(pcb_data_t *d, pcb_padstack_t *ps, pcb_layer_t *l, pcb_poly_t *p) +{ + pcb_polyarea_t *np; + pcb_layer_id_t i; + + if (!PCB_NONPOLY_HAS_CLEARANCE(ps)) + return 0; + i = pcb_layer_id(d, l); + np = pcb_thermal_area_padstack(pcb_data_get_top(d), ps, i); + if (np == 0) + return 0; + + return Subtract(np, p, pcb_true); +} + /* return the clearance polygon for a line */ static pcb_polyarea_t *line_clearance_poly(pcb_cardinal_t layernum, pcb_board_t *pcb, pcb_line_t *line) { @@ -947,6 +964,39 @@ return PCB_R_DIR_FOUND_CONTINUE; } +static pcb_r_dir_t padstack_sub_callback(const pcb_box_t *b, void *cl) +{ + pcb_padstack_t *ps = (pcb_padstack_t *)b; + struct cpInfo *info = (struct cpInfo *)cl; + pcb_poly_t *polygon; + pcb_polyarea_t *np; + pcb_polyarea_t *merged; + pcb_layer_id_t i; + + /* don't subtract the object that was put back! */ + if (b == info->other) + return PCB_R_DIR_NOT_FOUND; + polygon = info->polygon; + + if (!PCB_NONPOLY_HAS_CLEARANCE(ps)) + return PCB_R_DIR_NOT_FOUND; + i = pcb_layer_id(info->data, info->layer); + + np = pcb_thermal_area_padstack(pcb_data_get_top(info->data), ps, i); + if (np == 0) + return PCB_R_DIR_FOUND_CONTINUE; + + pcb_polyarea_boolean_free(info->accumulate, np, &merged, PCB_PBO_UNITE); + info->accumulate = merged; + + info->batch_size++; + + if (info->batch_size == SUBTRACT_PADSTACK_BATCH_SIZE) + subtract_accumulated(info, polygon); + + return PCB_R_DIR_FOUND_CONTINUE; +} + static pcb_r_dir_t arc_sub_callback(const pcb_box_t * b, void *cl) { pcb_arc_t *arc = (pcb_arc_t *) b; @@ -1237,6 +1287,8 @@ r += seen; pcb_r_search(Data->pin_tree, ®ion, NULL, pin_sub_callback, &info, &seen); r += seen; + pcb_r_search(Data->padstack_tree, ®ion, NULL, padstack_sub_callback, &info, &seen); + r += seen; subtract_accumulated(&info, polygon); } polygon->NoHolesValid = 0; @@ -1683,6 +1735,10 @@ SubtractPin(Data, (pcb_pin_t *) ptr2, Layer, Polygon); Polygon->NoHolesValid = 0; return PCB_R_DIR_FOUND_CONTINUE; + case PCB_TYPE_PADSTACK: + SubtractPadstack(Data, (pcb_padstack_t *) ptr2, Layer, Polygon); + Polygon->NoHolesValid = 0; + return PCB_R_DIR_FOUND_CONTINUE; case PCB_TYPE_LINE: SubtractLine((pcb_line_t *) ptr2, Polygon); Polygon->NoHolesValid = 0; Index: trunk/src/thermal.c =================================================================== --- trunk/src/thermal.c (revision 12436) +++ trunk/src/thermal.c (revision 12437) @@ -465,7 +465,32 @@ return NULL; } +pcb_polyarea_t *pcb_thermal_area_padstack(pcb_board_t *pcb, pcb_padstack_t *ps, pcb_layer_id_t lid) +{ + unsigned char shp; + /* if we have no clearance, there's no reason to do anything */ + if (!PCB_NONPOLY_HAS_CLEARANCE(ps)) /* no clearance -> solid connection */ + return NULL; + + /* retrieve shape; assume 0 (no shape) for layers not named */ + if (lid < ps->thermals.used) + shp = ps->thermals.shape[lid]; + else + shp = 0; + + switch(ps->thermals.shape[lid] & 3) { + case PCB_THERMAL_NOSHAPE: return NULL; + case PCB_THERMAL_SOLID: return NULL; + + case PCB_THERMAL_ROUND: + case PCB_THERMAL_SHARP: + return NULL; + } + + return NULL; +} + pcb_polyarea_t *pcb_thermal_area(pcb_board_t *pcb, pcb_any_obj_t *obj, pcb_layer_id_t lid) { switch(obj->type) { @@ -479,9 +504,10 @@ case PCB_OBJ_POLYGON: return pcb_thermal_area_poly(pcb, (pcb_poly_t *)obj, lid); + case PCB_OBJ_PADSTACK: + return pcb_thermal_area_padstack(pcb, (pcb_padstack_t *)obj, lid); + case PCB_OBJ_ARC: - - case PCB_OBJ_PADSTACK: break; default: break; Index: trunk/src/thermal.h =================================================================== --- trunk/src/thermal.h (revision 12436) +++ trunk/src/thermal.h (revision 12437) @@ -53,5 +53,6 @@ pcb_polyarea_t *pcb_thermal_area_pin(pcb_board_t *pcb, pcb_pin_t *pin, pcb_layer_id_t lid); pcb_polyarea_t *pcb_thermal_area_line(pcb_board_t *pcb, pcb_line_t *line, pcb_layer_id_t lid); pcb_polyarea_t *pcb_thermal_area_poly(pcb_board_t *pcb, pcb_poly_t *poly, pcb_layer_id_t lid); +pcb_polyarea_t *pcb_thermal_area_padstack(pcb_board_t *pcb, pcb_padstack_t *ps, pcb_layer_id_t lid); #endif