00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <math.h>
00020
00021 #include "global.h"
00022 #include "data.h"
00023 #include "macro.h"
00024 #include "create.h"
00025 #include "remove.h"
00026 #include "hid.h"
00027 #include "error.h"
00028 #include "rtree.h"
00029 #include "polygon.h"
00030 #include "polyarea.h"
00031 #include "assert.h"
00032 #include "strflags.h"
00033 #include "find.h"
00034 #include "misc.h"
00035 #include "draw.h"
00036 #include "undo.h"
00037
00038 static POLYAREA *
00039 original_poly (PolygonType * p, bool *forward)
00040 {
00041 PLINE *contour = NULL;
00042 POLYAREA *np = NULL;
00043 Cardinal n;
00044 Vector v;
00045 int hole = 0;
00046
00047 *forward = true;
00048
00049 if ((np = poly_Create ()) == NULL)
00050 return NULL;
00051
00052
00053 for (n = 0; n < p->PointN; n++)
00054 {
00055
00056
00057
00058 v[0] = p->Points[n].X;
00059 v[1] = p->Points[n].Y;
00060 if (contour == NULL)
00061 {
00062 if ((contour = poly_NewContour (v)) == NULL)
00063 return NULL;
00064 }
00065 else
00066 {
00067 poly_InclVertex (contour->head.prev, poly_CreateNode (v));
00068 }
00069
00070
00071 if (n == p->PointN - 1 ||
00072 (hole < p->HoleIndexN && n == p->HoleIndex[hole] - 1))
00073 {
00074 poly_PreContour (contour, TRUE);
00075
00076
00077 if (hole == 0)
00078 *forward = (contour->Flags.orient == PLF_DIR);
00079
00080
00081 if (contour->Flags.orient != (hole ? PLF_INV : PLF_DIR))
00082 poly_InvContour (contour);
00083 assert (contour->Flags.orient == (hole ? PLF_INV : PLF_DIR));
00084
00085 poly_InclContour (np, contour);
00086 contour = NULL;
00087 assert (poly_Valid (np));
00088
00089 hole++;
00090 }
00091 }
00092 return np;
00093 }
00094
00095 typedef struct poly_tree poly_tree;
00096
00097 struct poly_tree {
00098 PolygonType *polygon;
00099 bool forward;
00100 POLYAREA *polyarea;
00101 poly_tree *parent;
00102 poly_tree *child;
00103 poly_tree *prev;
00104 poly_tree *next;
00105 };
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 static bool
00132 PolygonContainsPolygon (POLYAREA *outer, POLYAREA *inner)
00133 {
00134
00135
00136
00137
00138
00139
00140 return poly_ContourInContour (outer->contours, inner->contours);
00141 }
00142
00143
00144 static poly_tree *
00145 insert_node_recursive (poly_tree *start_point, poly_tree *to_insert)
00146 {
00147 poly_tree *cur_node, *next = NULL;
00148
00149 bool to_insert_contains_cur_node;
00150 bool cur_node_contains_to_insert;
00151 bool placed_to_insert = false;
00152
00153 poly_tree *return_root = start_point;
00154
00155 if (start_point == NULL)
00156 {
00157
00158
00159 return to_insert;
00160 }
00161
00162
00163 for (cur_node = start_point; cur_node != NULL; cur_node = next)
00164 {
00165 next = cur_node->next;
00166
00167
00168 to_insert_contains_cur_node = PolygonContainsPolygon (to_insert->polyarea, cur_node->polyarea);
00169
00170 #if 0
00171 printf ("Inspecting polygon %ld %s, curnode is %ld %s: to_insert_isects_cur_node = %d, to_insert_contains_cur_node = %i\n",
00172 to_insert->polygon->ID,
00173 to_insert->forward ? "FWD" : "BWD",
00174 cur_node->polygon->ID,
00175 cur_node->forward ? "FWD" : "BWD",
00176 to_insert_isects_cur_node,
00177 to_insert_contains_cur_node);
00178
00179 if (to_insert_isects_cur_node)
00180 {
00181 }
00182 #endif
00183
00184 if (to_insert_contains_cur_node)
00185 {
00186
00187 if (cur_node->prev)
00188 cur_node->prev->next = cur_node->next;
00189 if (cur_node->next)
00190 cur_node->next->prev = cur_node->prev;
00191
00192
00193 if (!placed_to_insert)
00194 {
00195 to_insert->parent = cur_node->parent;
00196 to_insert->next = cur_node->next;
00197 to_insert->prev = cur_node->prev;
00198 if (to_insert->prev)
00199 to_insert->prev->next = to_insert;
00200 if (to_insert->next)
00201 to_insert->next->prev = to_insert;
00202 placed_to_insert = true;
00203
00204 if (cur_node == start_point)
00205 return_root = to_insert;
00206 }
00207
00208
00209 cur_node->parent = to_insert;
00210
00211 cur_node->prev = NULL;
00212 cur_node->next = to_insert->child;
00213 if (to_insert->child)
00214 to_insert->child->prev = cur_node;
00215 to_insert->child = cur_node;
00216
00217 }
00218 }
00219
00220 if (placed_to_insert)
00221 {
00222
00223 return return_root;
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233 for (cur_node = start_point; cur_node != NULL; cur_node = next)
00234 {
00235 next = cur_node->next;
00236
00237 cur_node_contains_to_insert = PolygonContainsPolygon (cur_node->polyarea, to_insert->polyarea);
00238
00239 #if 0
00240 printf ("Inspecting polygon %ld, curnode is %ld: cur_node_contains_to_insert = %d\n",
00241 to_insert->polygon->ID, cur_node->polygon->ID,
00242 cur_node_contains_to_insert);
00243 #endif
00244
00245
00246 if (cur_node_contains_to_insert)
00247 {
00248
00249 to_insert->parent = cur_node;
00250 cur_node->child = insert_node_recursive (cur_node->child, to_insert);
00251 return start_point;
00252
00253 }
00254 }
00255
00256
00257
00258
00259 to_insert->parent = start_point->parent;
00260 to_insert->prev = NULL;
00261 to_insert->next = start_point;
00262 to_insert->next->prev = to_insert;
00263
00264 return to_insert;
00265 }
00266
00267 static POLYAREA *
00268 compute_polygon_recursive (poly_tree *root, POLYAREA *accumulate)
00269 {
00270 POLYAREA *res;
00271 poly_tree *cur_node;
00272 for (cur_node = root; cur_node != NULL; cur_node = cur_node->next)
00273 {
00274
00275
00276 poly_Boolean_free (accumulate, cur_node->polyarea, &res, cur_node->forward ? PBO_UNITE : PBO_SUB);
00277 accumulate = res;
00278
00279
00280 if (cur_node->child)
00281 {
00282
00283 accumulate = compute_polygon_recursive (cur_node->child, accumulate);
00284 }
00285 }
00286 return accumulate;
00287 }
00288
00289 static int
00290 polycombine (int argc, char **argv, int x, int y)
00291 {
00292 POLYAREA *res;
00293 bool forward;
00294
00295 POLYAREA *np;
00296
00297
00298
00299
00300 LayerType *Layer = NULL;
00301 poly_tree *root = NULL;
00302 poly_tree *this_node;
00303
00304
00305 VISIBLEPOLYGON_LOOP (PCB->Data);
00306 {
00307 if (!TEST_FLAG (SELECTEDFLAG, polygon))
00308 continue;
00309
00310
00311 if (Layer == NULL)
00312 Layer = layer;
00313
00314
00315 if (Layer != layer)
00316 continue;
00317
00318 np = original_poly (polygon, &forward);
00319
00320
00321 this_node = calloc (1, sizeof (poly_tree));
00322 this_node->polygon = polygon;
00323 this_node->forward = forward;
00324 this_node->polyarea = np;
00325
00326
00327 root = insert_node_recursive (root, this_node);
00328
00329
00330 }
00331 ENDALL_LOOP;
00332
00333
00334 res = compute_polygon_recursive (root, NULL);
00335
00336 SaveUndoSerialNumber ();
00337
00338
00339 VISIBLEPOLYGON_LOOP (PCB->Data);
00340 {
00341 if (!TEST_FLAG (SELECTEDFLAG, polygon))
00342 continue;
00343
00344
00345 if (Layer != layer)
00346 continue;
00347
00348 RemovePolygon (layer, polygon);
00349 }
00350 ENDALL_LOOP;
00351
00352
00353 PolyToPolygonsOnLayer (PCB->Data, Layer, res,
00354 string_to_pcbflags ("clearpoly", NULL));
00355 RestoreUndoSerialNumber ();
00356 IncrementUndoSerialNumber ();
00357 Draw ();
00358
00359 return 0;
00360 }
00361
00362 static HID_Action polycombine_action_list[] = {
00363 {"PolyCombine", "???", polycombine,
00364 NULL, NULL}
00365 };
00366
00367 REGISTER_ACTIONS (polycombine_action_list)
00368
00369 void
00370 pcb_plugin_init()
00371 {
00372 register_polycombine_action_list();
00373 }