Index: trunk/src/funchash_core_list.h =================================================================== --- trunk/src/funchash_core_list.h (revision 10169) +++ trunk/src/funchash_core_list.h (revision 10170) @@ -18,6 +18,7 @@ action_entry(ClearAndRedraw) action_entry(ClearList) action_entry(Close) +action_entry(CloseHole) action_entry(Connection) action_entry(Convert) action_entry(ConvertSubc) Index: trunk/src/polygon.c =================================================================== --- trunk/src/polygon.c (revision 10169) +++ trunk/src/polygon.c (revision 10170) @@ -1390,6 +1390,69 @@ pcb_undo_inc_serial(); } +/* --------------------------------------------------------------------------- + * close polygon hole if possible + */ +void pcb_polygon_close_hole(void) +{ + pcb_cardinal_t n = pcb_crosshair.AttachedPolygon.PointN; + + /* check number of points */ + if (n >= 3) { + /* if 45 degree lines are what we want do a quick check + * if closing the polygon makes sense + */ + if (!conf_core.editor.all_direction_lines) { + pcb_coord_t dx, dy; + + dx = coord_abs(pcb_crosshair.AttachedPolygon.Points[n - 1].X - pcb_crosshair.AttachedPolygon.Points[0].X); + dy = coord_abs(pcb_crosshair.AttachedPolygon.Points[n - 1].Y - pcb_crosshair.AttachedPolygon.Points[0].Y); + if (!(dx == 0 || dy == 0 || dx == dy)) { + pcb_message(PCB_MSG_ERROR, _("Cannot close polygon hole because 45 degree lines are requested.\n")); + return; + } + } + pcb_polygon_hole_create_from_attached(); + pcb_draw(); + } + else + pcb_message(PCB_MSG_ERROR, _("A polygon hole has to have at least 3 points\n")); +} + +/* --------------------------------------------------------------------------- + * creates a hole of attached polygon shape in the underneath polygon + */ +void pcb_polygon_hole_create_from_attached(void) +{ + pcb_polyarea_t *original, *new_hole, *result; + pcb_flag_t Flags; + + /* Create pcb_polyarea_ts from the original polygon + * and the new hole polygon */ + original = pcb_poly_from_poly((pcb_polygon_t *) pcb_crosshair.AttachedObject.Ptr2); + new_hole = pcb_poly_from_poly(&pcb_crosshair.AttachedPolygon); + + /* Subtract the hole from the original polygon shape */ + pcb_polyarea_boolean_free(original, new_hole, &result, PCB_PBO_SUB); + + /* Convert the resulting polygon(s) into a new set of nodes + * and place them on the page. Delete the original polygon. + */ + pcb_undo_save_serial(); + Flags = ((pcb_polygon_t *) pcb_crosshair.AttachedObject.Ptr2)->Flags; + pcb_poly_to_polygons_on_layer(PCB->Data, (pcb_layer_t *) pcb_crosshair.AttachedObject.Ptr1, result, Flags); + pcb_remove_object(PCB_TYPE_POLYGON, + pcb_crosshair.AttachedObject.Ptr1, pcb_crosshair.AttachedObject.Ptr2, pcb_crosshair.AttachedObject.Ptr3); + pcb_undo_restore_serial(); + pcb_undo_inc_serial(); + + /* reset state of attached line */ + memset(&pcb_crosshair.AttachedPolygon, 0, sizeof(pcb_polygon_t)); + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST; + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_FIRST; + pcb_added_lines = 0; +} + /* find polygon holes in range, then call the callback function for * each hole. If the callback returns non-zero, stop * the search. Index: trunk/src/polygon.h =================================================================== --- trunk/src/polygon.h (revision 10169) +++ trunk/src/polygon.h (revision 10170) @@ -61,6 +61,8 @@ void pcb_polygon_go_to_prev_point(void); void pcb_polygon_close_poly(void); void pcb_polygon_copy_attached_to_layer(void); +void pcb_polygon_close_hole(void); +void pcb_polygon_hole_create_from_attached(void); int pcb_poly_holes(pcb_polygon_t * ptr, const pcb_box_t * range, int (*callback) (pcb_pline_t *, void *user_data), void *user_data); int pcb_poly_plows(pcb_data_t *, int, void *, void *, pcb_r_dir_t (*callback) (pcb_data_t *, pcb_layer_t *, pcb_polygon_t *, int, void *, void *)); Index: trunk/src/polygon_act.c =================================================================== --- trunk/src/polygon_act.c (revision 10169) +++ trunk/src/polygon_act.c (revision 10170) @@ -93,7 +93,7 @@ /* --------------------------------------------------------------------------- */ -static const char pcb_polygon_syntax[] = "Polygon(Close|PreviousPoint)"; +static const char pcb_polygon_syntax[] = "Polygon(Close|CloseHole|PreviousPoint)"; static const char pcb_acth_Polygon[] = "Some polygon related stuff."; @@ -107,6 +107,10 @@ Creates the final segment of the polygon. This may fail if clipping to 45 degree lines is switched on, in which case a warning is issued. +@item CloseHole +Creates the final segment of the polygon hole. This may fail if clipping +to 45 degree lines is switched on, in which case a warning is issued. + @item PreviousPoint Resets the newly entered corner to the previous one. The Undo action will call Polygon(PreviousPoint) when appropriate to do so. @@ -118,7 +122,7 @@ static int pcb_act_Polygon(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) { const char *function = PCB_ACTION_ARG(0); - if (function && conf_core.editor.mode == PCB_MODE_POLYGON) { + if (function && ((conf_core.editor.mode == PCB_MODE_POLYGON) || (conf_core.editor.mode == PCB_MODE_POLYGON_HOLE))) { pcb_notify_crosshair_change(pcb_false); switch (pcb_funchash_get(function, NULL)) { /* close open polygon if possible */ @@ -125,7 +129,12 @@ case F_Close: pcb_polygon_close_poly(); break; - + + /* close open polygon hole if possible */ + case F_CloseHole: + pcb_polygon_close_hole(); + break; + /* go back to the previous point */ case F_PreviousPoint: pcb_polygon_go_to_prev_point();