pcb 4.1.1
An interactive printed circuit board layout editor.

toporouter.c

Go to the documentation of this file.
00001 
00065 #include "toporouter.h"
00066 #include "pcb-printf.h"
00067 
00068 #define BOARD_EDGE_RESOLUTION MIL_TO_COORD (100.)
00069 #define VIA_COST_AS_DISTANCE  MIL_TO_COORD (100.)
00070 #define ROAR_DETOUR_THRESHOLD MIL_TO_COORD (10.)
00071 
00072 
00076 static void 
00077 toporouter_edge_init (toporouter_edge_t *edge)
00078 {
00079   edge->routing = NULL;
00080   edge->flags = 0;
00081 }
00082 
00083 toporouter_edge_class_t * 
00084 toporouter_edge_class(void)
00085 {
00086   static toporouter_edge_class_t *klass = NULL;
00087 
00088   if (klass == NULL) {
00089     GtsObjectClassInfo constraint_info = {
00090       "toporouter_edge_t",
00091       sizeof (toporouter_edge_t),
00092       sizeof (toporouter_edge_class_t),
00093       (GtsObjectClassInitFunc) NULL,
00094       (GtsObjectInitFunc) toporouter_edge_init,
00095       (GtsArgSetFunc) NULL,
00096       (GtsArgGetFunc) NULL
00097     };
00098     klass = (toporouter_edge_class_t *)gts_object_class_new (GTS_OBJECT_CLASS (gts_edge_class ()), &constraint_info);
00099   }
00100 
00101   return klass;
00102 }
00103 
00107 static void 
00108 toporouter_bbox_init (toporouter_bbox_t *box)
00109 {
00110   box->data = NULL;
00111   box->type = OTHER;
00112   box->constraints = NULL;
00113   box->cluster = NULL;
00114 }
00115 
00116 toporouter_bbox_class_t * 
00117 toporouter_bbox_class(void)
00118 {
00119   static toporouter_bbox_class_t *klass = NULL;
00120 
00121   if (klass == NULL) {
00122     GtsObjectClassInfo constraint_info = {
00123       "toporouter_bbox_t",
00124       sizeof (toporouter_bbox_t),
00125       sizeof (toporouter_bbox_class_t),
00126       (GtsObjectClassInitFunc) NULL,
00127       (GtsObjectInitFunc) toporouter_bbox_init,
00128       (GtsArgSetFunc) NULL,
00129       (GtsArgGetFunc) NULL
00130     };
00131     klass = (toporouter_bbox_class_t *)gts_object_class_new (GTS_OBJECT_CLASS (gts_bbox_class ()), &constraint_info);
00132   }
00133 
00134   return klass;
00135 }
00136 
00140 static void 
00141 toporouter_vertex_class_init (toporouter_vertex_class_t *klass)
00142 {
00143 
00144 }
00145 
00149 static void 
00150 toporouter_vertex_init (toporouter_vertex_t *vertex)
00151 {
00152   vertex->bbox = NULL;
00153   vertex->parent = NULL;
00154   vertex->child = NULL;
00155   vertex->flags = 0;
00156   vertex->routingedge = NULL;
00157   vertex->arc = NULL;
00158   vertex->oproute = NULL;
00159   vertex->route = NULL;
00160 
00161   vertex->gcost = 0.;
00162   vertex->hcost = 0.;
00163   vertex->gn = 0;
00164 }
00165 
00166 toporouter_vertex_class_t * 
00167 toporouter_vertex_class(void)
00168 {
00169   static toporouter_vertex_class_t *klass = NULL;
00170 
00171   if (klass == NULL) {
00172     GtsObjectClassInfo constraint_info = {
00173       "toporouter_vertex_t",
00174       sizeof (toporouter_vertex_t),
00175       sizeof (toporouter_vertex_class_t),
00176       (GtsObjectClassInitFunc) toporouter_vertex_class_init,
00177       (GtsObjectInitFunc) toporouter_vertex_init,
00178       (GtsArgSetFunc) NULL,
00179       (GtsArgGetFunc) NULL
00180     };
00181     klass = (toporouter_vertex_class_t *)gts_object_class_new (GTS_OBJECT_CLASS (gts_vertex_class ()), &constraint_info);
00182   }
00183 
00184   return klass;
00185 }
00186 
00190 static void 
00191 toporouter_constraint_class_init (toporouter_constraint_class_t *klass)
00192 {
00193 
00194 }
00195 
00199 static void 
00200 toporouter_constraint_init (toporouter_constraint_t *constraint)
00201 {
00202   constraint->box = NULL;
00203   constraint->routing = NULL;
00204 }
00205 
00206 toporouter_constraint_class_t * 
00207 toporouter_constraint_class(void)
00208 {
00209   static toporouter_constraint_class_t *klass = NULL;
00210 
00211   if (klass == NULL) {
00212     GtsObjectClassInfo constraint_info = {
00213       "toporouter_constraint_t",
00214       sizeof (toporouter_constraint_t),
00215       sizeof (toporouter_constraint_class_t),
00216       (GtsObjectClassInitFunc) toporouter_constraint_class_init,
00217       (GtsObjectInitFunc) toporouter_constraint_init,
00218       (GtsArgSetFunc) NULL,
00219       (GtsArgGetFunc) NULL
00220     };
00221     klass = (toporouter_constraint_class_t *)gts_object_class_new (GTS_OBJECT_CLASS (gts_constraint_class ()), &constraint_info);
00222   }
00223 
00224   return klass;
00225 }
00226 
00230 static void 
00231 toporouter_arc_init (toporouter_arc_t *arc)
00232 {
00233   arc->x0 = -1.;
00234   arc->y0 = -1.;
00235   arc->x1 = -1.;
00236   arc->y1 = -1.;
00237   arc->centre = NULL;
00238   arc->v = NULL;
00239   arc->v1 = NULL;
00240   arc->v2 = NULL;
00241   arc->r = -1.;
00242   arc->dir = 31337;
00243   arc->clearance = NULL;
00244   arc->oproute = NULL;
00245 }
00246 
00247 toporouter_arc_class_t * 
00248 toporouter_arc_class(void)
00249 {
00250   static toporouter_arc_class_t *klass = NULL;
00251 
00252   if (klass == NULL) {
00253     GtsObjectClassInfo constraint_info = {
00254       "toporouter_arc_t",
00255       sizeof (toporouter_arc_t),
00256       sizeof (toporouter_arc_class_t),
00257       (GtsObjectClassInitFunc) NULL,
00258       (GtsObjectInitFunc) toporouter_arc_init,
00259       (GtsArgSetFunc) NULL,
00260       (GtsArgGetFunc) NULL
00261     };
00262     klass = (toporouter_arc_class_t *)gts_object_class_new (GTS_OBJECT_CLASS (gts_constraint_class ()), &constraint_info);
00263   }
00264 
00265   return klass;
00266 }
00267 
00268 #define MARGIN 10.0f
00269 
00273 drawing_context_t *
00274 toporouter_output_init(int w, int h, char *filename) 
00275 {
00276   drawing_context_t *dc;
00277 
00278   dc = (drawing_context_t *)malloc(sizeof(drawing_context_t));
00279 
00280   dc->iw = w;
00281   dc->ih = h;
00282   dc->filename = filename;
00283   
00284   /* Calculate scaling to maintain aspect ratio */
00285   if(PCB->MaxWidth > PCB->MaxHeight) {
00286     /* Scale board width to match image width minus 2xMARGIN */
00287     dc->s = ((double)dc->iw - (2 * MARGIN)) / (double)PCB->MaxWidth; 
00288     dc->ih = (double)PCB->MaxHeight * dc->s + (2 * MARGIN);
00289   }else{
00290     /* Scale board height to match image height minus 2xMARGIN */
00291     dc->s = ((double)dc->ih - (2 * MARGIN)) / (double)PCB->MaxHeight;
00292     dc->iw = (double)PCB->MaxWidth * dc->s + (2 * MARGIN);
00293   }
00294 
00295 #if TOPO_OUTPUT_ENABLED
00296   dc->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dc->iw, dc->ih);
00297   dc->cr = cairo_create (dc->surface);
00298   
00299   cairo_rectangle (dc->cr, 0, 0, dc->iw, dc->ih);
00300   cairo_set_source_rgb (dc->cr, 0, 0, 0);
00301   cairo_fill (dc->cr);
00302 
00303 #endif
00304 
00305   return dc;
00306 }
00307 
00311 void
00312 toporouter_output_close(drawing_context_t *dc) 
00313 {
00314 #if TOPO_OUTPUT_ENABLED
00315   cairo_surface_write_to_png (dc->surface, dc->filename);
00316   cairo_destroy (dc->cr);
00317   cairo_surface_destroy (dc->surface);
00318 #endif
00319 }
00320 
00324 gdouble
00325 lookup_keepaway(char *name) 
00326 {
00327   if(name)
00328   STYLE_LOOP(PCB);
00329   {
00330 //    if(!strcmp(style->Name, name)) return style->Keepaway + 1.;
00331     if(!strcmp(style->Name, name)) return style->Keepaway;
00332   }
00333   END_LOOP;
00334 //  return Settings.Keepaway + 1.;
00335   return Settings.Keepaway ;
00336 }
00337 
00341 gdouble
00342 lookup_thickness(char *name) 
00343 {
00344   if(name)
00345   STYLE_LOOP(PCB);
00346   {
00347     if(!strcmp(style->Name, name)) return style->Thick;
00348   }
00349   END_LOOP;
00350   return Settings.LineThickness;
00351 }
00352 
00353 static inline gdouble
00354 cluster_keepaway(toporouter_cluster_t *cluster) 
00355 {
00356   if(cluster) return lookup_keepaway(cluster->netlist->style);
00357   return lookup_keepaway(NULL);
00358 }
00359 
00360 static inline gdouble
00361 cluster_thickness(toporouter_cluster_t *cluster) 
00362 {
00363   if(cluster) return lookup_thickness(cluster->netlist->style);
00364   return lookup_thickness(NULL);
00365 }
00366 
00370 gint
00371 toporouter_draw_vertex(gpointer item, gpointer data)
00372 {
00373 #if TOPO_OUTPUT_ENABLED
00374   drawing_context_t *dc = (drawing_context_t *) data;
00375   toporouter_vertex_t *tv;
00376   PinType *pin;
00377   PadType *pad;
00378   gdouble blue;  
00379   
00380   if(TOPOROUTER_IS_VERTEX((GtsObject*)item)) {
00381     tv = TOPOROUTER_VERTEX((GtsObject*)item);
00382     
00383     if(tv->flags & VERTEX_FLAG_RED) {
00384       cairo_set_source_rgba(dc->cr, 1., 0., 0., 0.8f);
00385       cairo_arc(dc->cr, 
00386           tv->v.p.x * dc->s + MARGIN, 
00387           tv->v.p.y * dc->s + MARGIN, 
00388           MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
00389       cairo_fill(dc->cr);
00390 
00391     }else if(tv->flags & VERTEX_FLAG_GREEN) {
00392       cairo_set_source_rgba(dc->cr, 0., 1., 0., 0.8f);
00393       cairo_arc(dc->cr, 
00394           tv->v.p.x * dc->s + MARGIN, 
00395           tv->v.p.y * dc->s + MARGIN, 
00396           MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
00397       cairo_fill(dc->cr);
00398     
00399     }else if(tv->flags & VERTEX_FLAG_BLUE) {
00400       cairo_set_source_rgba(dc->cr, 0., 0., 1., 0.8f);
00401       cairo_arc(dc->cr, 
00402           tv->v.p.x * dc->s + MARGIN, 
00403           tv->v.p.y * dc->s + MARGIN, 
00404           MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
00405       cairo_fill(dc->cr);
00406 
00407 
00408     }
00409     //printf("tv->type = %d\n", tv->type);
00410     if(!dc->mode) {
00411       if(tv->bbox) {
00412         pin = (PinType*) tv->bbox->data;
00413         pad = (PadType*) tv->bbox->data;
00414 
00415         blue = 0.0f;
00416         switch(tv->bbox->type) {
00417           case PIN:
00418             cairo_set_source_rgba(dc->cr, 1.0f, 0., 0.0f, 0.2f);
00419             cairo_arc(dc->cr, 
00420                 tv->v.p.x * dc->s + MARGIN, 
00421                 tv->v.p.y * dc->s + MARGIN, 
00422                 (((gdouble)pin->Thickness / 2.0f) + (gdouble)lookup_keepaway(pin->Name) ) * dc->s, 0, 2 * M_PI);
00423             cairo_fill(dc->cr);
00424 
00425             cairo_set_source_rgba(dc->cr, 1.0f, 0., 0., 0.4f);
00426             cairo_arc(dc->cr, 
00427                 tv->v.p.x * dc->s + MARGIN, 
00428                 tv->v.p.y * dc->s + MARGIN, 
00429                 (gdouble)(pin->Thickness) / 2.0f * dc->s,
00430                 0, 2 * M_PI);
00431             cairo_fill(dc->cr);
00432 
00433             break;
00434           case VIA:
00435             cairo_set_source_rgba(dc->cr, 0.0f, 0., 1., 0.2f);
00436             cairo_arc(dc->cr, 
00437                 tv->v.p.x * dc->s + MARGIN, 
00438                 tv->v.p.y * dc->s + MARGIN, 
00439                 (((gdouble)pin->Thickness / 2.0f) + (gdouble)lookup_keepaway(pin->Name) ) * dc->s, 0, 2 * M_PI);
00440             cairo_fill(dc->cr);
00441 
00442             cairo_set_source_rgba(dc->cr, 0.0f, 0., 1., 0.4f);
00443             cairo_arc(dc->cr, 
00444                 tv->v.p.x * dc->s + MARGIN, 
00445                 tv->v.p.y * dc->s + MARGIN, 
00446                 (gdouble)(pin->Thickness) / 2.0f * dc->s,
00447                 0, 2 * M_PI);
00448             cairo_fill(dc->cr);
00449 
00450             break;
00451           case PAD:
00452             cairo_set_source_rgba(dc->cr, 0.0f, 1., 0., 0.5f);
00453             cairo_arc(dc->cr, 
00454                 tv->v.p.x * dc->s + MARGIN, 
00455                 tv->v.p.y * dc->s + MARGIN, 
00456                 MIL_TO_COORD (4.) * dc->s, 0, 2 * M_PI);
00457             cairo_fill(dc->cr);
00458 
00459             break;
00460           default:
00461             break;
00462         }
00463       }
00464     }else{
00465       if(tv->flags & VERTEX_FLAG_BLUE) {
00466         cairo_set_source_rgba(dc->cr, 0., 0., 1., 0.8f);
00467         cairo_arc(dc->cr, 
00468             tv->v.p.x * dc->s + MARGIN, 
00469             tv->v.p.y * dc->s + MARGIN, 
00470             MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
00471         cairo_fill(dc->cr);
00472       }else if(tv->flags & VERTEX_FLAG_RED) {
00473         cairo_set_source_rgba(dc->cr, 1., 0., 0., 0.8f);
00474         cairo_arc(dc->cr, 
00475             tv->v.p.x * dc->s + MARGIN, 
00476             tv->v.p.y * dc->s + MARGIN, 
00477             MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
00478         cairo_fill(dc->cr);
00479 
00480       }else if(tv->flags & VERTEX_FLAG_GREEN) {
00481         cairo_set_source_rgba(dc->cr, 0., 1., 0., 0.8f);
00482         cairo_arc(dc->cr, 
00483             tv->v.p.x * dc->s + MARGIN, 
00484             tv->v.p.y * dc->s + MARGIN, 
00485             MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
00486         cairo_fill(dc->cr);
00487       }
00488 
00489     }
00490   }else{
00491     fprintf(stderr, "Unknown data passed to toporouter_draw_vertex, aborting foreach\n");
00492     return -1;
00493   }
00494   return 0;
00495 #else 
00496   return -1;
00497 #endif
00498 }
00499 
00503 gint
00504 toporouter_draw_edge(gpointer item, gpointer data)
00505 {
00506 #if TOPO_OUTPUT_ENABLED
00507   drawing_context_t *dc = (drawing_context_t *) data;
00508   toporouter_edge_t *te;
00509   toporouter_constraint_t *tc;
00510   
00511   if(TOPOROUTER_IS_EDGE((GtsObject*)item)) {
00512     te = TOPOROUTER_EDGE((GtsObject*)item);
00513     cairo_set_source_rgba(dc->cr, 1.0f, 1.0f, 1.0f, 0.5f);
00514     cairo_move_to(dc->cr, 
00515         te->e.segment.v1->p.x * dc->s + MARGIN, 
00516         te->e.segment.v1->p.y * dc->s + MARGIN);
00517     cairo_line_to(dc->cr, 
00518         te->e.segment.v2->p.x * dc->s + MARGIN, 
00519         te->e.segment.v2->p.y * dc->s + MARGIN);
00520     cairo_stroke(dc->cr);
00521   }else if(TOPOROUTER_IS_CONSTRAINT((GtsObject*)item)) {
00522     tc = TOPOROUTER_CONSTRAINT((GtsObject*)item);
00523     if(tc->box) {
00524       switch(tc->box->type) {
00525         case BOARD:
00526           cairo_set_source_rgba(dc->cr, 1.0f, 0.0f, 1.0f, 0.9f);
00527           cairo_move_to(dc->cr, 
00528               tc->c.edge.segment.v1->p.x * dc->s + MARGIN, 
00529               tc->c.edge.segment.v1->p.y * dc->s + MARGIN);
00530           cairo_line_to(dc->cr, 
00531               tc->c.edge.segment.v2->p.x * dc->s + MARGIN, 
00532               tc->c.edge.segment.v2->p.y * dc->s + MARGIN);
00533           cairo_stroke(dc->cr);
00534           break;
00535         case PIN:
00536         case PAD:
00537           cairo_set_source_rgba(dc->cr, 1.0f, 0.0f, 0.0f, 0.9f);
00538           cairo_move_to(dc->cr, 
00539               tc->c.edge.segment.v1->p.x * dc->s + MARGIN, 
00540               tc->c.edge.segment.v1->p.y * dc->s + MARGIN);
00541           cairo_line_to(dc->cr, 
00542               tc->c.edge.segment.v2->p.x * dc->s + MARGIN, 
00543               tc->c.edge.segment.v2->p.y * dc->s + MARGIN);
00544           cairo_stroke(dc->cr);
00545           break;
00546         case LINE:
00547           cairo_set_source_rgba(dc->cr, 0.0f, 1.0f, 0.0f, 0.9f);
00548           cairo_move_to(dc->cr, 
00549               tc->c.edge.segment.v1->p.x * dc->s + MARGIN, 
00550               tc->c.edge.segment.v1->p.y * dc->s + MARGIN);
00551           cairo_line_to(dc->cr, 
00552               tc->c.edge.segment.v2->p.x * dc->s + MARGIN, 
00553               tc->c.edge.segment.v2->p.y * dc->s + MARGIN);
00554           cairo_stroke(dc->cr);
00555           break;
00556 
00557         default:
00558           cairo_set_source_rgba(dc->cr, 1.0f, 1.0f, 0.0f, 0.9f);
00559           cairo_move_to(dc->cr, 
00560               tc->c.edge.segment.v1->p.x * dc->s + MARGIN, 
00561               tc->c.edge.segment.v1->p.y * dc->s + MARGIN);
00562           cairo_line_to(dc->cr, 
00563               tc->c.edge.segment.v2->p.x * dc->s + MARGIN, 
00564               tc->c.edge.segment.v2->p.y * dc->s + MARGIN);
00565           cairo_stroke(dc->cr);
00566           break;
00567       }
00568     }else{
00569       printf("CONSTRAINT without box\n");
00570 
00571     }
00572   }else{
00573     fprintf(stderr, "Unknown data passed to toporouter_draw_edge, aborting foreach\n");
00574     return -1;
00575   }
00576 
00577   return 0;
00578 #else 
00579   return -1;
00580 #endif
00581 }
00582 
00583 //#define vertex_bbox(v) (v->bbox)
00585 toporouter_bbox_t *
00586 vertex_bbox(toporouter_vertex_t *v) 
00587 {
00588   return v ? v->bbox : NULL;
00589 }
00590 //*/
00591 char *
00592 vertex_netlist(toporouter_vertex_t *v)
00593 {
00594   toporouter_bbox_t *box = vertex_bbox(v);
00595 
00596   if(box && box->cluster) return box->cluster->netlist->netlist;
00597 
00598   return NULL;
00599 }
00600   
00601 char *
00602 constraint_netlist(toporouter_constraint_t *c)
00603 {
00604   toporouter_bbox_t *box = c->box;
00605 
00606   if(box && box->cluster) return box->cluster->netlist->netlist;
00607 
00608   return NULL;
00609 }
00610 
00611 static inline guint
00612 epsilon_equals(gdouble a, gdouble b) 
00613 {
00614   if(a > b - EPSILON && a < b + EPSILON) return 1;
00615   return 0;
00616 }
00617 
00621 void
00622 print_bbox(toporouter_bbox_t *box) 
00623 {
00624   printf("[BBOX ");
00625   switch(box->type) {
00626     case PAD:
00627       printf("PAD "); break;
00628     case PIN:
00629       printf("PIN "); break;
00630     case VIA:
00631       printf("VIA "); break;
00632     case LINE:
00633       printf("LINE "); break;
00634     case BOARD:
00635       printf("BOARD "); break;
00636     case POLYGON:
00637       printf("POLYGON "); break;
00638     default:
00639       printf("UNKNOWN "); break;
00640   }
00641 
00642   if(box->point) 
00643     printf("P: %f,%f,%f ", vx(box->point), vy(box->point), vz(box->point));
00644   else
00645     printf("P: NONE ");
00646 
00647   printf("LAYER: %d ", box->layer);
00648   printf("CLUSTER: %d]\n", box->cluster ? box->cluster->c : -1);
00649   
00650 }
00651 
00655 void
00656 print_vertex(toporouter_vertex_t *v)
00657 {
00658   if(v)
00659     printf("[V %f,%f,%f ", vx(v), vy(v), vz(v));
00660   else
00661     printf("[V (null) ");
00662   
00663   printf("%s ", vertex_netlist(v));
00664   if(v->route && v->route->netlist)
00665     printf("%s ", v->route->netlist->netlist);
00666 
00667   if(v->routingedge) {
00668     guint n = g_list_length(edge_routing(v->routingedge));
00669     guint pos = g_list_index(edge_routing(v->routingedge), v);
00670 
00671     if(TOPOROUTER_IS_CONSTRAINT(v->routingedge))
00672       printf("[CONST ");
00673     else
00674       printf("[EDGE ");
00675   
00676     printf("%d/%d] ", pos, n);
00677   
00678   }
00679 
00680 
00681   if(v->flags & VERTEX_FLAG_TEMP) printf("TEMP ");
00682   if(v->flags & VERTEX_FLAG_ROUTE) printf("ROUTE ");
00683   if(v->flags & VERTEX_FLAG_SPECCUT) printf("SPECCUT ");
00684   if(v->flags & VERTEX_FLAG_FAKE) printf("FAKE ");
00685 
00686   printf("]\n");
00687 
00688 }
00689 
00690 gdouble
00691 vertex_net_thickness(toporouter_vertex_t *v) 
00692 {
00693   toporouter_bbox_t *box = vertex_bbox(v);
00694   
00695   if(!box) {
00696     
00697     while(v && (v->flags & VERTEX_FLAG_TEMP || v->flags & VERTEX_FLAG_ROUTE)) {
00698       v = v->parent;
00699     }
00700 
00701     box = vertex_bbox(v);
00702 
00703   }else{
00704     if(box->type == PIN || box->type == VIA) {
00705       PinType *pin = (PinType *)box->data;
00706       if(TEST_FLAG(SQUAREFLAG, pin) || TEST_FLAG(OCTAGONFLAG, pin)) {
00707         return 0.;
00708       }
00709 //      return ((PinType *)box->data)->Thickness + 1.;
00710       return ((PinType *)box->data)->Thickness;
00711     }else if(box->type == PAD) {
00712       PadType *pad = (PadType *)box->data;
00713       if(pad->Point1.X == pad->Point2.X && pad->Point1.Y == pad->Point2.Y && !TEST_FLAG(SQUAREFLAG, pad)) {
00714         return pad->Thickness;
00715       }
00716       return 0.;
00717     }else if(box->type == BOARD) {
00718       return 0.;
00719     }else if(box->type == LINE) {
00720       LineType *line = (LineType *) box->data;
00721       return line->Thickness;
00722     }else if(box->type == POLYGON) {
00723       return 0.;
00724     }
00725 
00726     printf("Unrecognized type in thickness lookup..\n");
00727   }
00728 
00729 //  if(!box || !box->cluster) return Settings.LineThickness + 1.;
00730   if(!box || !box->cluster) return Settings.LineThickness;
00731   
00732   return cluster_thickness(box->cluster);
00733 }
00734 
00735 gdouble
00736 vertex_net_keepaway(toporouter_vertex_t *v) 
00737 {
00738   toporouter_bbox_t *box = vertex_bbox(v);
00739   if(!box) {
00740   
00741     while(v && (v->flags & VERTEX_FLAG_TEMP || v->flags & VERTEX_FLAG_ROUTE)) {
00742       v = v->parent;
00743     }
00744     box = vertex_bbox(v);
00745   } 
00746   else{
00747   //  if(box->type == PIN || box->type == VIA) 
00748   //    return ((PinType *)box->data)->Clearance;
00749   //  else if(box->type == PAD)
00750   //    return ((PadType *)box->data)->Clearance;
00751 
00752   }
00753   
00754 //  if(!box || !box->cluster) return Settings.Keepaway + 1.;
00755   if(!box || !box->cluster) return Settings.Keepaway;
00756   return cluster_keepaway(box->cluster);
00757 }
00758 
00763 static void
00764 point_from_point_to_point (toporouter_vertex_t *a,
00765                            toporouter_vertex_t *b,
00766                            double d,
00767                            double *x, double *y)
00768 {
00769   double theta = atan2 (vy(b) - vy(a), vx(b) - vx(a));
00770 
00771   *x = vx(a) + d * cos (theta);
00772   *y = vy(a) + d * sin (theta);
00773 }
00774 
00775 static inline gint
00776 coord_wind(gdouble ax, gdouble ay, gdouble bx, gdouble by, gdouble cx, gdouble cy) 
00777 {
00778   gdouble rval, dx1, dx2, dy1, dy2;
00779   dx1 = bx - ax; dy1 = by - ay;
00780   dx2 = cx - bx; dy2 = cy - by;
00781   rval = (dx1*dy2)-(dy1*dx2);
00782   return (rval > EPSILON) ? 1 : ((rval < -EPSILON) ? -1 : 0);
00783 }
00784 
00793 int 
00794 point_wind(GtsPoint *a, GtsPoint *b, GtsPoint *c) 
00795 {
00796   gdouble rval, dx1, dx2, dy1, dy2;
00797   dx1 = b->x - a->x; dy1 = b->y - a->y;
00798   dx2 = c->x - b->x; dy2 = c->y - b->y;
00799   rval = (dx1*dy2)-(dy1*dx2);
00800   return (rval > EPSILON) ? 1 : ((rval < -EPSILON) ? -1 : 0);
00801 }
00802 
00803 static inline int
00804 vertex_wind(GtsVertex *a, GtsVertex *b, GtsVertex *c) 
00805 {
00806   return point_wind(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c));
00807 }
00808 
00809 static inline int
00810 tvertex_wind(toporouter_vertex_t  *a, toporouter_vertex_t  *b, toporouter_vertex_t  *c) 
00811 {
00812   return point_wind(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c));
00813 }
00814 
00818 static void
00819 coord_move_towards_coord_values (double ax, double ay,
00820                                  double px, double py,
00821                                  double d,
00822                                  double *x, double *y)
00823 {
00824   double theta = atan2 (py - ay, px - ax);
00825 
00826   *x = ax + d * cos (theta);
00827   *y = ay + d * sin (theta);
00828 }
00829 
00833 static void
00834 vertex_move_towards_vertex_values (GtsVertex *v,
00835                                    GtsVertex *p,
00836                                    double d,
00837                                    double *x, double *y)
00838 {
00839   double theta = atan2 (GTS_POINT(p)->y - GTS_POINT(v)->y,
00840                         GTS_POINT(p)->x - GTS_POINT(v)->x);
00841 
00842   *x = GTS_POINT(v)->x + d * cos (theta);
00843   *y = GTS_POINT(v)->y + d * sin (theta);
00844 }
00845 
00846 #define tv_on_layer(v,l) (l == TOPOROUTER_BBOX(TOPOROUTER_VERTEX(v)->boxes->data)->layer)
00847 
00848 static inline gdouble
00849 min_spacing(toporouter_vertex_t *v1, toporouter_vertex_t *v2)
00850 {
00851 
00852   gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms;
00853 //  toporouter_edge_t *e = v1->routingedge;
00854   
00855   v1halfthick = vertex_net_thickness(TOPOROUTER_VERTEX(v1)) / 2.;
00856   v2halfthick = vertex_net_thickness(TOPOROUTER_VERTEX(v2)) / 2.;
00857 
00858   v1keepaway = vertex_net_keepaway(TOPOROUTER_VERTEX(v1));
00859   v2keepaway = vertex_net_keepaway(TOPOROUTER_VERTEX(v2));
00860 
00861   ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway);
00862 
00863 #ifdef SPACING_DEBUG
00864   printf("v1halfthick = %f v2halfthick = %f v1keepaway = %f v2keepaway = %f ms = %f\n",
00865       v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms);
00866 #endif 
00867   
00868   return ms;
00869 }
00870 
00871 // v1 is a vertex in the CDT, and v2 is a net... other way around?
00872 static inline gdouble
00873 min_vertex_net_spacing(toporouter_vertex_t *v1, toporouter_vertex_t *v2)
00874 {
00875 
00876   gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms;
00877   
00878   v1halfthick = vertex_net_thickness(TOPOROUTER_VERTEX(v1)) / 2.;
00879   v2halfthick = cluster_thickness(vertex_bbox(v2)->cluster) / 2.;
00880 
00881   v1keepaway = vertex_net_keepaway(TOPOROUTER_VERTEX(v1));
00882   v2keepaway = cluster_keepaway(vertex_bbox(v2)->cluster);
00883 
00884   ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway);
00885 
00886   return ms;
00887 }
00888 
00889 static inline gdouble
00890 min_oproute_vertex_spacing(toporouter_oproute_t *oproute, toporouter_vertex_t *v2)
00891 {
00892 
00893   gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms;
00894   
00895   v1halfthick = lookup_thickness(oproute->style) / 2.;
00896   v2halfthick = vertex_net_thickness(v2) / 2.;
00897 
00898   v1keepaway = lookup_keepaway(oproute->style);
00899   v2keepaway = vertex_net_keepaway(v2);
00900 
00901   ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway);
00902 
00903   return ms;
00904 }
00905 
00906 gdouble
00907 min_oproute_net_spacing(toporouter_oproute_t *oproute, toporouter_vertex_t *v2)
00908 {
00909 
00910   gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms;
00911   
00912   v1halfthick = lookup_thickness(oproute->style) / 2.;
00913   v2halfthick = cluster_thickness(v2->route->src) / 2.;
00914 
00915   v1keepaway = lookup_keepaway(oproute->style);
00916   v2keepaway = cluster_keepaway(v2->route->src);
00917 
00918   ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway);
00919 
00920   return ms;
00921 }
00922 
00923 gdouble
00924 min_net_net_spacing(toporouter_vertex_t *v1, toporouter_vertex_t *v2)
00925 {
00926 
00927   gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms;
00928   
00929   v1halfthick = cluster_thickness(v1->route->src) / 2.;
00930   v2halfthick = cluster_thickness(v2->route->src) / 2.;
00931 
00932   v1keepaway = cluster_keepaway(v1->route->src);
00933   v2keepaway = cluster_keepaway(v2->route->src);
00934 
00935   ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway);
00936 
00937   return ms;
00938 }
00939 
00940 void
00941 toporouter_draw_cluster(toporouter_t *r, drawing_context_t *dc, toporouter_cluster_t *cluster, gdouble red, gdouble green, gdouble blue, guint layer)
00942 {
00943 #if TOPO_OUTPUT_ENABLED
00944 //GList *i = cluster->i;
00945 
00946 //while(i) {
00947 //  toporouter_bbox_t *box = TOPOROUTER_BBOX(i->data);
00948 
00949 //  if(box->point && vz(box->point) == layer) {
00950 //    cairo_set_source_rgba(dc->cr, red, green, blue, 0.8f);
00951 //    cairo_arc(dc->cr, vx(box->point) * dc->s + MARGIN, vy(box->point) * dc->s + MARGIN, MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
00952 //    cairo_fill(dc->cr);
00953 //  }
00954 
00955 //  i = i->next;
00956 //}
00957 #endif
00958 }
00959 
00960 void
00961 toporouter_draw_surface(toporouter_t *r, GtsSurface *s, char *filename, int w, int h, int mode, GList *datas, int layer, GList *candidatepoints) 
00962 {
00963 #if TOPO_OUTPUT_ENABLED
00964   drawing_context_t *dc;
00965   GList *i; 
00966   toporouter_vertex_t *tv, *tv2 = NULL;
00967 
00968   dc = toporouter_output_init(w, h, filename);
00969   dc->mode = mode;
00970   dc->data = NULL;
00971 
00972   gts_surface_foreach_edge(s, toporouter_draw_edge, dc);
00973   gts_surface_foreach_vertex(s, toporouter_draw_vertex, dc);
00974 
00975   i = r->routednets;
00976   while(i) {
00977     GList *j = TOPOROUTER_ROUTE(i->data)->path;
00978     tv2 = NULL;
00979     while(j) {
00980       tv = TOPOROUTER_VERTEX(j->data);
00981       if(GTS_POINT(tv)->z == layer) {
00982         if(tv && tv2) {
00983           cairo_set_source_rgba(dc->cr, 0.0f, 1.0f, 0.0f, 0.8f);
00984           cairo_move_to(dc->cr, 
00985               GTS_POINT(tv)->x * dc->s + MARGIN, 
00986               GTS_POINT(tv)->y * dc->s + MARGIN);
00987           cairo_line_to(dc->cr, 
00988               GTS_POINT(tv2)->x * dc->s + MARGIN, 
00989               GTS_POINT(tv2)->y * dc->s + MARGIN);
00990           cairo_stroke(dc->cr);
00991         }
00992 
00993         if(tv->flags & VERTEX_FLAG_RED) {
00994           cairo_set_source_rgba(dc->cr, 1., 0., 0., 0.8f);
00995           cairo_arc(dc->cr, 
00996               tv->v.p.x * dc->s + MARGIN, 
00997               tv->v.p.y * dc->s + MARGIN, 
00998               MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
00999           cairo_fill(dc->cr);
01000 
01001         }else if(tv->flags & VERTEX_FLAG_GREEN) {
01002           cairo_set_source_rgba(dc->cr, 0., 1., 0., 0.8f);
01003           cairo_arc(dc->cr, 
01004               tv->v.p.x * dc->s + MARGIN, 
01005               tv->v.p.y * dc->s + MARGIN, 
01006               MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
01007           cairo_fill(dc->cr);
01008 
01009         }else if(tv->flags & VERTEX_FLAG_BLUE) {
01010           cairo_set_source_rgba(dc->cr, 0., 0., 1., 0.8f);
01011           cairo_arc(dc->cr, 
01012               tv->v.p.x * dc->s + MARGIN, 
01013               tv->v.p.y * dc->s + MARGIN, 
01014               MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
01015           cairo_fill(dc->cr);
01016 
01017         } 
01018         else {
01019 
01020           cairo_set_source_rgba(dc->cr, 1., 1., 1., 0.8f);
01021           cairo_arc(dc->cr, 
01022               tv->v.p.x * dc->s + MARGIN, 
01023               tv->v.p.y * dc->s + MARGIN, 
01024               MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
01025           cairo_fill(dc->cr);
01026 
01027 
01028         }
01029 
01030         if(tv->routingedge && !TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) {
01031           gdouble tempx, tempy, nms, pms;
01032           GList *i = g_list_find(edge_routing(tv->routingedge), tv);
01033           toporouter_vertex_t *nextv, *prevv;
01034 
01035           nextv = edge_routing_next(tv->routingedge,i);
01036           prevv = edge_routing_prev(tv->routingedge,i);
01037 
01038           nms = min_spacing(tv,nextv);
01039           pms = min_spacing(tv,prevv);
01040 
01041           g_assert(isfinite(nms)); g_assert(isfinite(pms));
01042 
01043           point_from_point_to_point(tv, nextv, nms, &tempx, &tempy);
01044 
01045           cairo_set_source_rgba(dc->cr, 0.0f, 1.0f, 1.0f, 0.8f);
01046           cairo_move_to(dc->cr, vx(tv) * dc->s + MARGIN, vy(tv) * dc->s + MARGIN);
01047           cairo_line_to(dc->cr, tempx * dc->s + MARGIN, tempy * dc->s + MARGIN);
01048           cairo_stroke(dc->cr);
01049 
01050           point_from_point_to_point(tv, prevv, pms, &tempx, &tempy);
01051 
01052           cairo_move_to(dc->cr, vx(tv) * dc->s + MARGIN, vy(tv) * dc->s + MARGIN);
01053           cairo_line_to(dc->cr, tempx * dc->s + MARGIN, tempy * dc->s + MARGIN);
01054           cairo_stroke(dc->cr);
01055 
01056 
01057 
01058 
01059         }
01060 
01061 
01062       }
01063       tv2 = tv;
01064       j = j->next;
01065     }
01066     i = i->next;
01067   }
01068  
01069   while(datas) {
01070     toporouter_route_t *routedata = (toporouter_route_t *) datas->data;
01071 
01072     GList *i;//, *k;
01073 
01074     toporouter_draw_cluster(r, dc, routedata->src, 1., 0., 0., layer);
01075     toporouter_draw_cluster(r, dc, routedata->dest, 0., 0., 1., layer);
01076 
01077     tv2 = NULL;
01078     i = routedata->path;
01079     while(i) {
01080       tv = TOPOROUTER_VERTEX(i->data);
01081       if(GTS_POINT(tv)->z == layer) {
01082         if(tv && tv2) {
01083           cairo_set_source_rgba(dc->cr, 0.0f, 1.0f, 0.0f, 0.8f);
01084           cairo_move_to(dc->cr, 
01085               GTS_POINT(tv)->x * dc->s + MARGIN, 
01086               GTS_POINT(tv)->y * dc->s + MARGIN);
01087           cairo_line_to(dc->cr, 
01088               GTS_POINT(tv2)->x * dc->s + MARGIN, 
01089               GTS_POINT(tv2)->y * dc->s + MARGIN);
01090           cairo_stroke(dc->cr);
01091         }
01092       }
01093       tv2 = tv;
01094       i = i->next;
01095     }
01096 
01097 
01098     if(routedata->alltemppoints) {
01099       GList *i, *j;
01100       i = j = g_hash_table_get_keys (routedata->alltemppoints);
01101       while(i) {
01102         toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
01103 
01104         if(GTS_POINT(tv)->z != layer) {
01105           i = i->next;
01106           continue;
01107         }
01108         if(tv->flags & VERTEX_FLAG_BLUE) {
01109           cairo_set_source_rgba(dc->cr, 0., 0., 1., 0.8f);
01110           cairo_arc(dc->cr, 
01111               tv->v.p.x * dc->s + MARGIN, 
01112               tv->v.p.y * dc->s + MARGIN, 
01113               MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
01114           cairo_fill(dc->cr);
01115         }else if(tv->flags & VERTEX_FLAG_RED) {
01116           cairo_set_source_rgba(dc->cr, 1., 0., 0., 0.8f);
01117           cairo_arc(dc->cr, 
01118               tv->v.p.x * dc->s + MARGIN, 
01119               tv->v.p.y * dc->s + MARGIN, 
01120               MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
01121           cairo_fill(dc->cr);
01122 
01123         }else if(tv->flags & VERTEX_FLAG_GREEN) {
01124           cairo_set_source_rgba(dc->cr, 0., 1., 0., 0.8f);
01125           cairo_arc(dc->cr, 
01126               tv->v.p.x * dc->s + MARGIN, 
01127               tv->v.p.y * dc->s + MARGIN, 
01128               MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
01129           cairo_fill(dc->cr);
01130         }else{
01131           cairo_set_source_rgba(dc->cr, 1., 1., 1., 0.8f);
01132           cairo_arc(dc->cr, 
01133               tv->v.p.x * dc->s + MARGIN, 
01134               tv->v.p.y * dc->s + MARGIN, 
01135               MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI);
01136           cairo_fill(dc->cr);
01137         }
01138         i = i->next;
01139       }
01140       g_list_free(j);
01141     }
01142     datas = datas->next;
01143   }
01144   toporouter_output_close(dc);
01145 #endif
01146 }
01147 
01148 
01152 void
01153 toporouter_layer_free(toporouter_layer_t *l) 
01154 {
01155   g_list_free(l->vertices);
01156   g_list_free(l->constraints);
01157 
01158 }
01159 
01160 guint
01161 groupcount(void)
01162 {
01163   int group;
01164   guint count = 0;
01165 
01166   for (group = 0; group < max_group; group++) {
01167     if(PCB->LayerGroups.Number[group] > 0) count++;
01168   }
01169   
01170   return count;
01171 }
01172 
01173 void
01174 toporouter_free(toporouter_t *r)
01175 {
01176   struct timeval endtime;
01177   double time_delta;
01178 
01179   int i;
01180   for(i=0;i<groupcount();i++) {
01181     toporouter_layer_free(&r->layers[i]);
01182   }
01183 
01184   gettimeofday (&endtime, NULL);
01185   time_delta = endtime.tv_sec - r->starttime.tv_sec +
01186                (endtime.tv_usec - r->starttime.tv_usec) / 1000000.;
01187 
01188   Message(_("Elapsed time: %.2f seconds\n"), time_delta);
01189   free(r->layers);  
01190   free(r);
01191 
01192 }
01193 
01202 int 
01203 wind(toporouter_spoint_t *p1, toporouter_spoint_t *p2, toporouter_spoint_t *p3) 
01204 {
01205   double rval, dx1, dx2, dy1, dy2;
01206   dx1 = p2->x - p1->x; dy1 = p2->y - p1->y;
01207   dx2 = p3->x - p2->x; dy2 = p3->y - p2->y;
01208   rval = (dx1*dy2)-(dy1*dx2);
01209   return (rval > 0.0001) ? 1 : ((rval < -0.0001) ? -1 : 0); /* XXX: Depends on PCB coordinate scaling */
01210 }
01211 
01212 static inline void
01213 print_toporouter_constraint(toporouter_constraint_t *tc) 
01214 {
01215   printf("%f,%f -> %f,%f ", 
01216       tc->c.edge.segment.v1->p.x,
01217       tc->c.edge.segment.v1->p.y,
01218       tc->c.edge.segment.v2->p.x,
01219       tc->c.edge.segment.v2->p.y);
01220 }
01221 
01222 static inline void
01223 print_toporouter_vertex(toporouter_vertex_t *tv) 
01224 {
01225   printf("%f,%f ", tv->v.p.x, tv->v.p.y); 
01226 }
01227 
01228 
01237 static void
01238 vertices_on_line (toporouter_spoint_t *a,
01239                   double m,
01240                   double r,
01241                   toporouter_spoint_t *b0,
01242                   toporouter_spoint_t *b1)
01243 {
01244 
01245   double c, dx;
01246 
01247   if (m == INFINITY || m == -INFINITY) {
01248 
01249     b0->x = a->x;
01250     b0->y = a->y + r;
01251 
01252     b1->x = a->x;
01253     b1->y = a->y - r;
01254 
01255     return;
01256   }
01257 
01258   c = a->y - m * a->x;
01259   dx = r / hypot (1, m);
01260 
01261   b0->x = a->x + dx;
01262   b0->y = m * b0->x + c;
01263 
01264   b1->x = a->x - dx;
01265   b1->y = m * b1->x + c;
01266 }
01267 
01276 static void
01277 coords_on_line (double ax, gdouble ay,
01278                 double m,
01279                 double r,
01280                 double *b0x, double *b0y,
01281                 double *b1x, double *b1y)
01282 {
01283   double c, dx;
01284 
01285   if (m == INFINITY || m == -INFINITY) {
01286 
01287     *b0x = ax;
01288     *b0y = ay + r;
01289 
01290     *b1x = ax;
01291     *b1y = ay - r;
01292 
01293     return;
01294   }
01295 
01296   c = ay - m * ax;
01297   dx = r / hypot (1, m);
01298 
01299   *b0x = ax + dx;
01300   *b0y = m * *b0x + c;
01301 
01302   *b1x = ax - dx;
01303   *b1y = m * *b1x + c;
01304 }
01305 
01309 gdouble
01310 vertex_gradient(toporouter_spoint_t *a, toporouter_spoint_t *b) 
01311 {
01312   if(a->x == b->x) return INFINITY;
01313 
01314   return ((b->y - a->y) / (b->x - a->x));
01315 }
01316 
01320 static inline gdouble
01321 cartesian_gradient(gdouble x0, gdouble y0, gdouble x1, gdouble y1) 
01322 {
01323   if(epsilon_equals(x0,x1)) return INFINITY;
01324 
01325   return ((y1 - y0) / (x1 - x0));
01326 }
01327 
01331 static inline gdouble
01332 point_gradient(GtsPoint *a, GtsPoint *b) 
01333 {
01334   return cartesian_gradient(a->x, a->y, b->x, b->y);
01335 }
01336 
01337 gdouble
01338 segment_gradient(GtsSegment *s)
01339 {
01340   return cartesian_gradient(
01341       GTS_POINT(s->v1)->x, 
01342       GTS_POINT(s->v1)->y, 
01343       GTS_POINT(s->v2)->x, 
01344       GTS_POINT(s->v2)->y); 
01345 }
01346 
01350 gdouble
01351 perpendicular_gradient(gdouble m) 
01352 {
01353   if(isinf(m)) return 0.0f;
01354   if(m < EPSILON && m > -EPSILON) return INFINITY;
01355   return -1.0f/m;
01356 }
01357 
01361 gdouble
01362 vertices_plane_distance(toporouter_spoint_t *a, toporouter_spoint_t *b) {
01363   return hypot(a->x - b->x, a->y - b->y);
01364 }
01365 
01370 static inline void
01371 vertex_outside_segment(toporouter_spoint_t *a, toporouter_spoint_t *b, gdouble r, toporouter_spoint_t *p) 
01372 {
01373   toporouter_spoint_t temp[2];
01374 
01375   vertices_on_line(a, vertex_gradient(a,b), r, &temp[0], &temp[1]);
01376 
01377   if(vertices_plane_distance(&temp[0], b) > vertices_plane_distance(&temp[1], b)) {
01378     p->x = temp[0].x;
01379     p->y = temp[0].y;
01380   }else{
01381     p->x = temp[1].x;
01382     p->y = temp[1].y;
01383   }
01384 
01385 }
01386 
01395 static bool
01396 coord_intersect_prop (double ax, double ay,
01397                       double bx, double by,
01398                       double cx, double cy,
01399                       double dx, double dy)
01400 {
01401   int wind_abc = coord_wind (ax, ay, bx, by, cx, cy);
01402   int wind_abd = coord_wind (ax, ay, bx, by, dx, dy);
01403   int wind_cda = coord_wind (cx, cy, dx, dy, ax, ay);
01404   int wind_cdb = coord_wind (cx, cy, dx, dy, bx, by);
01405 
01406   /* If any of the line end-points are colinear with the other line, return false */
01407   if (wind_abc == 0 || wind_abd == 0 || wind_cda == 0 || wind_cdb == 0)
01408     return false;
01409 
01410   return (wind_abc != wind_abd) && (wind_cda != wind_cdb);
01411 }
01412 
01421 static bool
01422 point_intersect_prop (GtsPoint *a, GtsPoint *b, GtsPoint *c, GtsPoint *d)
01423 {
01424   int wind_abc = point_wind (a, b, c);
01425   int wind_abd = point_wind (a, b, d);
01426   int wind_cda = point_wind (c, d, a);
01427   int wind_cdb = point_wind (c, d, b);
01428 
01429   /* If any of the line end-points are colinear with the other line, return false */
01430   if (wind_abc == 0 || wind_abd == 0 || wind_cda == 0 || wind_cdb == 0)
01431     return false;
01432 
01433   return (wind_abc != wind_abd) && (wind_cda != wind_cdb);
01434 }
01435 
01439 static inline int
01440 vertex_intersect_prop(GtsVertex *a, GtsVertex *b, GtsVertex *c, GtsVertex *d) 
01441 {
01442   return point_intersect_prop(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c), GTS_POINT(d));
01443 }
01444 
01453 GtsVertex *
01454 vertex_intersect(GtsVertex *a, GtsVertex *b, GtsVertex *c, GtsVertex *d) 
01455 {
01456   GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
01457   GtsVertex *rval;
01458   gdouble ua_top, ua_bot, ua, rx, ry;
01459 
01460   /* TODO: this could be done more efficiently without duplicating computation */
01461   if(!vertex_intersect_prop(a, b, c, d)) return NULL;
01462 
01463   ua_top = ((d->p.x - c->p.x) * (a->p.y - c->p.y)) - 
01464     ((d->p.y - c->p.y) * (a->p.x - c->p.x));
01465   ua_bot = ((d->p.y - c->p.y) * (b->p.x - a->p.x)) - 
01466     ((d->p.x - c->p.x) * (b->p.y - a->p.y));
01467   ua = ua_top / ua_bot;
01468   rx = a->p.x + (ua * (b->p.x - a->p.x));
01469   ry = a->p.y + (ua * (b->p.y - a->p.y));
01470 
01471   rval = gts_vertex_new (vertex_class, rx, ry, 0.0f);
01472 
01473   return rval;
01474 }
01475 
01484 void
01485 coord_intersect(gdouble ax, gdouble ay, gdouble bx, gdouble by, gdouble cx, gdouble cy, gdouble dx, gdouble dy, gdouble *rx, gdouble *ry) 
01486 {
01487   gdouble ua_top, ua_bot, ua;
01488 
01489   ua_top = ((dx - cx) * (ay - cy)) - ((dy - cy) * (ax - cx));
01490   ua_bot = ((dy - cy) * (bx - ax)) - ((dx - cx) * (by - ay));
01491   ua = ua_top / ua_bot;
01492   *rx = ax + (ua * (bx - ax));
01493   *ry = ay + (ua * (by - ay));
01494 
01495 }
01496 
01497 
01503 int
01504 point_between(GtsPoint *a, GtsPoint *b, GtsPoint *c) 
01505 {
01506   if( point_wind(a, b, c) != 0 ) return 0;
01507 
01508   if( a->x != b->x ) {
01509     return ((a->x <= c->x) &&
01510         (c->x <= b->x)) ||
01511       ((a->x >= c->x) &&
01512        (c->x >= b->x));
01513   }
01514   return ((a->y <= c->y) &&
01515       (c->y <= b->y)) ||
01516     ((a->y >= c->y) &&
01517      (c->y >= b->y));
01518 }
01519 
01520 static inline int
01521 vertex_between(GtsVertex *a, GtsVertex *b, GtsVertex *c) 
01522 {
01523   return point_between(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c));
01524 }
01525 
01526 void
01527 delaunay_create_from_vertices(GList *vertices, GtsSurface **surface, GtsTriangle **t) 
01528 {
01529   GList *i = vertices;
01530   GtsVertex *v1, *v2, *v3;
01531   GSList *vertices_slist = NULL;
01532 
01533   while (i) {
01534     vertices_slist = g_slist_prepend(vertices_slist, i->data);
01535     i = i->next;
01536   }
01537 
01538   // TODO: just work this out from the board outline
01539   *t = gts_triangle_enclosing (gts_triangle_class (), vertices_slist, 100000.0f);
01540   gts_triangle_vertices (*t, &v1, &v2, &v3);
01541  
01542   *surface = gts_surface_new (gts_surface_class (), gts_face_class (),
01543       GTS_EDGE_CLASS(toporouter_edge_class ()), GTS_VERTEX_CLASS(toporouter_vertex_class ()) );
01544 
01545   gts_surface_add_face (*surface, gts_face_new (gts_face_class (), (*t)->e1, (*t)->e2, (*t)->e3));
01546  
01547   i = vertices;
01548   while (i) {
01549     toporouter_vertex_t *v = TOPOROUTER_VERTEX(gts_delaunay_add_vertex (*surface, (GtsVertex *)i->data, NULL));
01550     
01551     if(v) {
01552       printf("ERROR: vertex could not be added to CDT ");
01553       print_vertex(v);
01554     }
01555 
01556     i = i->next;
01557   }
01558  
01559   gts_allow_floating_vertices = TRUE;
01560   gts_object_destroy (GTS_OBJECT (v1));
01561   gts_object_destroy (GTS_OBJECT (v2));
01562   gts_object_destroy (GTS_OBJECT (v3));
01563   gts_allow_floating_vertices = FALSE;
01564 
01565   g_slist_free(vertices_slist);
01566 //  return surface;
01567 }
01568 
01569 GSList *
01570 list_to_slist(GList *i) 
01571 {
01572   GSList *rval = NULL;
01573   while(i) {
01574     rval = g_slist_prepend(rval, i->data);
01575     i = i->next;
01576   }
01577   return rval;
01578 }
01579 
01580 toporouter_bbox_t *
01581 toporouter_bbox_create_from_points(int layer, GList *vertices, toporouter_term_t type, gpointer data)
01582 {
01583   toporouter_bbox_t *bbox;
01584   GSList *vertices_slist = list_to_slist(vertices);
01585 
01586 //  delaunay_create_from_vertices(vertices, &s, &t);
01587   bbox = TOPOROUTER_BBOX( gts_bbox_points(GTS_BBOX_CLASS(toporouter_bbox_class()), vertices_slist) );
01588   bbox->type = type;
01589   bbox->data = data;
01590 
01591   bbox->surface = NULL;
01592   bbox->enclosing = NULL;
01593 
01594   bbox->layer = layer;
01595 
01596   bbox->point = NULL;
01597   bbox->realpoint = NULL;
01598 
01599   g_slist_free(vertices_slist);
01600   return bbox;
01601 }
01602 
01603 toporouter_bbox_t *
01604 toporouter_bbox_create(int layer, GList *vertices, toporouter_term_t type, gpointer data)
01605 {
01606   toporouter_bbox_t *bbox;
01607   GtsSurface *s;
01608   GtsTriangle *t;
01609 
01610   delaunay_create_from_vertices(vertices, &s, &t);
01611   bbox = TOPOROUTER_BBOX( gts_bbox_surface(GTS_BBOX_CLASS(toporouter_bbox_class()), s) );
01612   bbox->type = type;
01613   bbox->data = data;
01614 
01615   bbox->surface = s;
01616   bbox->enclosing = t;
01617 
01618   bbox->layer = layer;
01619 
01620   return bbox;
01621 }
01622 
01623 GtsVertex *
01624 insert_vertex(toporouter_t *r, toporouter_layer_t *l, gdouble x, gdouble y, toporouter_bbox_t *box) 
01625 {
01626   GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
01627   GtsVertex *v;
01628   GList *i;
01629 
01630   i = l->vertices;
01631   while (i) {
01632     v = (GtsVertex *)i->data;
01633     if(v->p.x == x && v->p.y == y) {
01634       TOPOROUTER_VERTEX(v)->bbox = box;
01635       return v;
01636     }
01637     i = i->next;
01638   }
01639 
01640   v = gts_vertex_new (vertex_class , x, y, l - r->layers);
01641   TOPOROUTER_VERTEX(v)->bbox = box;
01642   l->vertices = g_list_prepend(l->vertices, v);
01643 
01644   return v;
01645 }
01646 
01647 GList *
01648 insert_constraint_edge(toporouter_t *r, toporouter_layer_t *l, gdouble x1, gdouble y1, guint flags1, 
01649     gdouble x2, gdouble y2, guint flags2, toporouter_bbox_t *box)
01650 {
01651   GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
01652   GtsEdgeClass *edge_class = GTS_EDGE_CLASS (toporouter_constraint_class ());
01653   GtsVertex *p[2];
01654   GtsVertex *v;
01655   GList *i;
01656   GtsEdge *e;
01657 
01658   p[0] = p[1] = NULL;
01659 
01660   /* insert or find points */
01661 
01662   i = l->vertices;
01663   while (i) {
01664     v = (GtsVertex *)i->data;
01665     if(v->p.x == x1 && v->p.y == y1) 
01666       p[0] = v;
01667     if(v->p.x == x2 && v->p.y == y2) 
01668       p[1] = v;
01669     i = i->next;
01670   }
01671   
01672   if(p[0] == NULL) {
01673     p[0] = gts_vertex_new (vertex_class, x1, y1, l - r->layers);
01674     TOPOROUTER_VERTEX(p[0])->bbox = box;
01675     l->vertices = g_list_prepend(l->vertices, p[0]);
01676   }
01677   if(p[1] == NULL) {
01678     p[1] = gts_vertex_new (vertex_class, x2, y2, l - r->layers);
01679     TOPOROUTER_VERTEX(p[1])->bbox = box;
01680     l->vertices = g_list_prepend(l->vertices, p[1]);
01681   }
01682 
01683   TOPOROUTER_VERTEX(p[0])->flags = flags1;
01684   TOPOROUTER_VERTEX(p[1])->flags = flags2;
01685   
01686   e = gts_edge_new (edge_class, p[0], p[1]);
01687   TOPOROUTER_CONSTRAINT(e)->box = box;
01688   l->constraints = g_list_prepend (l->constraints, e);
01689 //  return insert_constraint_edge_rec(r, l, p, box);
01690   return g_list_prepend(NULL, e);
01691 
01692 }
01693 
01694 void
01695 insert_constraints_from_list(toporouter_t *r, toporouter_layer_t *l, GList *vlist, toporouter_bbox_t *box) 
01696 {
01697   GList *i = vlist;
01698   toporouter_vertex_t *pv = NULL, *v;
01699 
01700   while(i) {
01701     v = TOPOROUTER_VERTEX(i->data);
01702 
01703     if(pv) {
01704       box->constraints = 
01705         g_list_concat(box->constraints, insert_constraint_edge(r, l, vx(v), vy(v), v->flags, vx(pv), vy(pv), pv->flags, box));
01706     }
01707 
01708     pv = v;
01709     i = i->next;
01710   }
01711   
01712   v = TOPOROUTER_VERTEX(vlist->data);
01713   box->constraints = 
01714     g_list_concat(box->constraints, insert_constraint_edge(r, l, vx(v), vy(v), v->flags, vx(pv), vy(pv), pv->flags, box));
01715 
01716 }
01717 
01718 void
01719 insert_centre_point(toporouter_t *r, toporouter_layer_t *l, gdouble x, gdouble y)
01720 {
01721   GList *i;
01722   GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
01723 
01724   i = l->vertices;
01725   while (i) {
01726     GtsPoint *p = GTS_POINT(i->data);
01727     if(p->x == x && p->y == y) 
01728       return;
01729     i = i->next;
01730   }
01731   
01732   l->vertices = g_list_prepend(l->vertices, gts_vertex_new(vertex_class, x, y, 0.0f));
01733 }
01734 
01735 GtsPoint *
01736 midpoint(GtsPoint *a, GtsPoint *b) 
01737 {
01738   return gts_point_new(gts_point_class(), (a->x + b->x) / 2., (a->y + b->y) / 2., 0.);
01739 }
01740 
01741 static inline gdouble
01742 pad_rad(PadType *pad)
01743 {
01744   return (lookup_thickness(pad->Name) / 2.) + lookup_keepaway(pad->Name);
01745 }
01746 
01747 static inline gdouble
01748 pin_rad(PinType *pin)
01749 {
01750   return (lookup_thickness(pin->Name) / 2.) + lookup_keepaway(pin->Name);
01751 }
01752 
01753 GList *
01754 rect_with_attachments(gdouble rad,
01755     gdouble x0, gdouble y0,
01756     gdouble x1, gdouble y1,
01757     gdouble x2, gdouble y2,
01758     gdouble x3, gdouble y3,
01759     gdouble z)
01760 {
01761   GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
01762   GList *r = NULL, *rr = NULL, *i;
01763   toporouter_vertex_t *curpoint, *temppoint;
01764 
01765 
01766   curpoint = TOPOROUTER_VERTEX(gts_vertex_new (vertex_class, x0, y0, z));
01767 
01768   r = g_list_prepend(NULL, curpoint);
01769   r = g_list_prepend(r, gts_vertex_new (vertex_class, x1, y1, z));
01770   r = g_list_prepend(r, gts_vertex_new (vertex_class, x2, y2, z));
01771   r = g_list_prepend(r, gts_vertex_new (vertex_class, x3, y3, z));
01772   
01773   i = r;
01774   while(i) {
01775     temppoint = TOPOROUTER_VERTEX(i->data);
01776     rr = g_list_prepend(rr, curpoint);
01777     
01778     curpoint = temppoint;
01779     i = i->next;
01780   }
01781 
01782   g_list_free(r);
01783 
01784   return rr;
01785 }
01786 
01787 #define VERTEX_CENTRE(x) TOPOROUTER_VERTEX( vertex_bbox(x)->point )
01788 
01794 int
01795 read_pads(toporouter_t *r, toporouter_layer_t *l, guint layer) 
01796 {
01797   toporouter_spoint_t p[2], rv[5];
01798   gdouble x[2], y[2], t, m;
01799 
01800   GList *vlist = NULL;
01801   toporouter_bbox_t *bbox = NULL;
01802 
01803   guint front = GetLayerGroupNumberBySide (TOP_SIDE);
01804   guint back = GetLayerGroupNumberBySide (BOTTOM_SIDE);
01805 
01806 //  printf("read_pads: front = %d back = %d layer = %d\n", 
01807 //     front, back, layer);
01808 
01809   /* If its not the top or bottom layer, there are no pads to read */
01810   if(l - r->layers != front && l - r->layers != back) return 0;
01811 
01812   ELEMENT_LOOP(PCB->Data);
01813   {
01814     PAD_LOOP(element);
01815     {
01816       if( (l - r->layers == back && TEST_FLAG(ONSOLDERFLAG, pad)) || 
01817           (l - r->layers == front && !TEST_FLAG(ONSOLDERFLAG, pad)) ) {
01818 
01819         t = (gdouble)pad->Thickness / 2.0f;
01820         x[0] = pad->Point1.X;
01821         x[1] = pad->Point2.X;
01822         y[0] = pad->Point1.Y;
01823         y[1] = pad->Point2.Y;
01824 
01825        
01826         if(TEST_FLAG(SQUAREFLAG, pad)) {
01827           /* Square or oblong pad. Four points and four constraint edges are
01828            * used */
01829           
01830           if(x[0] == x[1] && y[0] == y[1]) {
01831             /* Pad is square */
01832 
01833 //            vlist = g_list_prepend(NULL, gts_vertex_new (vertex_class, x[0]-t, y[0]-t, 0.));
01834 //            vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, x[0]-t, y[0]+t, 0.));
01835 //            vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, x[0]+t, y[0]+t, 0.));
01836 //            vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, x[0]+t, y[0]-t, 0.));
01837             vlist = rect_with_attachments(pad_rad(pad), 
01838                 x[0]-t, y[0]-t, 
01839                 x[0]-t, y[0]+t,
01840                 x[0]+t, y[0]+t,
01841                 x[0]+t, y[0]-t,
01842                 l - r->layers);
01843             bbox = toporouter_bbox_create(l - r->layers, vlist, PAD, pad);
01844             r->bboxes = g_slist_prepend(r->bboxes, bbox);
01845             insert_constraints_from_list(r, l, vlist, bbox);
01846             g_list_free(vlist);
01847             
01848             //bbox->point = GTS_POINT( gts_vertex_new(vertex_class, x[0], y[0], 0.) );
01849             bbox->point = GTS_POINT( insert_vertex(r, l, x[0], y[0], bbox) );
01850             g_assert(TOPOROUTER_VERTEX(bbox->point)->bbox == bbox);
01851           }else {
01852             /* Pad is diagonal oblong or othogonal oblong */ 
01853             
01854             m = cartesian_gradient(x[0], y[0], x[1], y[1]);
01855             
01856             p[0].x = x[0]; p[0].y = y[0]; 
01857             p[1].x = x[1]; p[1].y = y[1]; 
01858 
01859             vertex_outside_segment(&p[0], &p[1], t, &rv[0]); 
01860             vertices_on_line(&rv[0], perpendicular_gradient(m), t, &rv[1], &rv[2]);
01861 
01862             vertex_outside_segment(&p[1], &p[0], t, &rv[0]);
01863             vertices_on_line(&rv[0], perpendicular_gradient(m), t, &rv[3], &rv[4]);
01864 
01865             if(wind(&rv[1], &rv[2], &rv[3]) != wind(&rv[2], &rv[3], &rv[4])) {
01866               rv[0].x = rv[3].x; rv[0].y = rv[3].y;               
01867               rv[3].x = rv[4].x; rv[3].y = rv[4].y;               
01868               rv[4].x = rv[0].x; rv[4].y = rv[0].y;               
01869             }
01870             
01871 //            vlist = g_list_prepend(NULL,  gts_vertex_new (vertex_class, rv[1].x, rv[1].y, 0.));
01872 //            vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, rv[2].x, rv[2].y, 0.));
01873 //            vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, rv[3].x, rv[3].y, 0.));
01874 //            vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, rv[4].x, rv[4].y, 0.));
01875             vlist = rect_with_attachments(pad_rad(pad), 
01876                 rv[1].x, rv[1].y, 
01877                 rv[2].x, rv[2].y,
01878                 rv[3].x, rv[3].y,
01879                 rv[4].x, rv[4].y,
01880                 l - r->layers);
01881             bbox = toporouter_bbox_create(l - r->layers, vlist, PAD, pad);
01882             r->bboxes = g_slist_prepend(r->bboxes, bbox);
01883             insert_constraints_from_list(r, l, vlist, bbox);
01884             g_list_free(vlist);
01885             
01886             //bbox->point = GTS_POINT( gts_vertex_new(vertex_class, (x[0] + x[1]) / 2., (y[0] + y[1]) / 2., 0.) );
01887             bbox->point = GTS_POINT( insert_vertex(r, l, (x[0] + x[1]) / 2., (y[0] + y[1]) / 2., bbox) );
01888             g_assert(TOPOROUTER_VERTEX(bbox->point)->bbox == bbox);
01889 
01890           }
01891 
01892         }else {
01893           /* Either round pad or pad with curved edges */ 
01894           
01895           if(x[0] == x[1] && y[0] == y[1]) {
01896             /* One point */
01897 
01898             /* bounding box same as square pad */ 
01899             vlist = rect_with_attachments(pad_rad(pad), 
01900                 x[0]-t, y[0]-t, 
01901                 x[0]-t, y[0]+t,
01902                 x[0]+t, y[0]+t,
01903                 x[0]+t, y[0]-t,
01904                 l - r->layers);
01905             bbox = toporouter_bbox_create(l - r->layers, vlist, PAD, pad);
01906             r->bboxes = g_slist_prepend(r->bboxes, bbox);
01907             g_list_free(vlist);
01908             
01909             //bbox->point = GTS_POINT( insert_vertex(r, l, x[0], y[0], bbox) );
01910             bbox->point = GTS_POINT( insert_vertex(r, l, x[0], y[0], bbox) );
01911 
01912           }else{
01913             /* Two points and one constraint edge */
01914             
01915             /* the rest is just for bounding box */ 
01916             m = cartesian_gradient(x[0], y[0], x[1], y[1]);
01917             
01918             p[0].x = x[0]; p[0].y = y[0]; 
01919             p[1].x = x[1]; p[1].y = y[1]; 
01920 
01921             vertex_outside_segment(&p[0], &p[1], t, &rv[0]); 
01922             vertices_on_line(&rv[0], perpendicular_gradient(m), t, &rv[1], &rv[2]);
01923 
01924             vertex_outside_segment(&p[1], &p[0], t, &rv[0]);
01925             vertices_on_line(&rv[0], perpendicular_gradient(m), t, &rv[3], &rv[4]);
01926 
01927             if(wind(&rv[1], &rv[2], &rv[3]) != wind(&rv[2], &rv[3], &rv[4])) {
01928               rv[0].x = rv[3].x; rv[0].y = rv[3].y;               
01929               rv[3].x = rv[4].x; rv[3].y = rv[4].y;               
01930               rv[4].x = rv[0].x; rv[4].y = rv[0].y;               
01931             }
01932             
01933             vlist = rect_with_attachments(pad_rad(pad), 
01934                 rv[1].x, rv[1].y, 
01935                 rv[2].x, rv[2].y,
01936                 rv[3].x, rv[3].y,
01937                 rv[4].x, rv[4].y,
01938                 l - r->layers);
01939             bbox = toporouter_bbox_create(l - r->layers, vlist, PAD, pad);
01940             r->bboxes = g_slist_prepend(r->bboxes, bbox);
01941             insert_constraints_from_list(r, l, vlist, bbox);
01942             g_list_free(vlist);
01943             
01944             //bbox->point = GTS_POINT( gts_vertex_new(vertex_class, (x[0] + x[1]) / 2., (y[0] + y[1]) / 2., 0.) );
01945             bbox->point = GTS_POINT( insert_vertex(r, l, (x[0] + x[1]) / 2., (y[0] + y[1]) / 2., bbox) );
01946             
01947             //bbox->constraints = g_list_concat(bbox->constraints, insert_constraint_edge(r, l, x[0], y[0], x[1], y[1], bbox));
01948 
01949           }
01950 
01951 
01952         }
01953 
01954       }
01955     }
01956     END_LOOP;
01957   }
01958   END_LOOP;
01959 
01960   return 0;
01961 }
01962 
01968 int
01969 read_points(toporouter_t *r, toporouter_layer_t *l, int layer)
01970 {
01971   gdouble x, y, t;
01972   
01973   GList *vlist = NULL;
01974   toporouter_bbox_t *bbox = NULL;
01975   
01976   ELEMENT_LOOP(PCB->Data);
01977   {
01978     PIN_LOOP(element);
01979     {
01980       
01981       t = (gdouble)pin->Thickness / 2.0f;
01982       x = pin->X;
01983       y = pin->Y;
01984 
01985       if(TEST_FLAG (SQUAREFLAG, pin)) {
01986             
01987         vlist = rect_with_attachments(pin_rad(pin), 
01988             x-t, y-t, 
01989             x-t, y+t,
01990             x+t, y+t,
01991             x+t, y-t,
01992             l - r->layers);
01993         bbox = toporouter_bbox_create(l - r->layers, vlist, PIN, pin);
01994         r->bboxes = g_slist_prepend(r->bboxes, bbox);
01995         insert_constraints_from_list(r, l, vlist, bbox);
01996         g_list_free(vlist);
01997         bbox->point = GTS_POINT( insert_vertex(r, l, x, y, bbox) );
01998         
01999       }else if(TEST_FLAG(OCTAGONFLAG, pin)){
02000         /* TODO: Handle octagon pins */
02001         fprintf(stderr, "No support for octagon pins yet\n");
02002       }else{
02003         vlist = rect_with_attachments(pin_rad(pin), 
02004             x-t, y-t, 
02005             x-t, y+t,
02006             x+t, y+t,
02007             x+t, y-t,
02008             l - r->layers);
02009         bbox = toporouter_bbox_create(l - r->layers, vlist, PIN, pin);
02010         r->bboxes = g_slist_prepend(r->bboxes, bbox);
02011         g_list_free(vlist);
02012         bbox->point = GTS_POINT( insert_vertex(r, l, x, y, bbox) );
02013       }
02014     }
02015     END_LOOP;
02016   }
02017   END_LOOP;
02018  
02019   VIA_LOOP(PCB->Data);
02020   {
02021 
02022     t = (gdouble)via->Thickness / 2.0f;
02023     x = via->X;
02024     y = via->Y;
02025     
02026     if(TEST_FLAG (SQUAREFLAG, via)) {
02027         
02028       vlist = rect_with_attachments(pin_rad((PinType*)via), 
02029           x-t, y-t, 
02030           x-t, y+t,
02031           x+t, y+t,
02032           x+t, y-t,
02033           l - r->layers);
02034       bbox = toporouter_bbox_create(l - r->layers, vlist, VIA, via);
02035       r->bboxes = g_slist_prepend(r->bboxes, bbox);
02036       insert_constraints_from_list(r, l, vlist, bbox);
02037       g_list_free(vlist);
02038       bbox->point = GTS_POINT( insert_vertex(r, l, x, y, bbox) );
02039         
02040     }else if(TEST_FLAG(OCTAGONFLAG, via)){
02041       /* TODO: Handle octagon vias */
02042       fprintf(stderr, "No support for octagon vias yet\n");
02043     }else{
02044       
02045       vlist = rect_with_attachments(pin_rad((PinType*)via), 
02046           x-t, y-t, 
02047           x-t, y+t,
02048           x+t, y+t,
02049           x+t, y-t,
02050           l - r->layers);
02051       bbox = toporouter_bbox_create(l - r->layers, vlist, VIA, via);
02052       r->bboxes = g_slist_prepend(r->bboxes, bbox);
02053       g_list_free(vlist);
02054         
02055       bbox->point = GTS_POINT( insert_vertex(r, l, x, y, bbox) );
02056 
02057     }
02058   }
02059   END_LOOP;
02060   return 0;
02061 }
02062 
02068 int
02069 read_lines(toporouter_t *r, toporouter_layer_t *l, LayerType *layer, int ln) 
02070 {
02071   gdouble xs[2], ys[2];
02072   
02073   GList *vlist = NULL;
02074   toporouter_bbox_t *bbox = NULL;
02075 
02076   GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
02077   
02078   LINE_LOOP(layer);
02079   {
02080     xs[0] = line->Point1.X;
02081     xs[1] = line->Point2.X;
02082     ys[0] = line->Point1.Y;
02083     ys[1] = line->Point2.Y;
02084     if(!(xs[0] == xs[1] && ys[0] == ys[1])) {
02085       vlist = g_list_prepend(NULL, gts_vertex_new (vertex_class, xs[0], ys[0], l - r->layers));
02086       vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, xs[1], ys[1], l - r->layers));
02087       // TODO: replace this with surface version
02088       bbox = toporouter_bbox_create_from_points(GetLayerGroupNumberByNumber(ln), vlist, LINE, line);
02089       r->bboxes = g_slist_prepend(r->bboxes, bbox);
02090       //new;;
02091       //insert_constraints_from_list(r, l, vlist, bbox);
02092       g_list_free(vlist);
02093 //      bbox->point = GTS_POINT( insert_vertex(r, l, (xs[0]+xs[1])/2., (ys[0]+ys[1])/2., bbox) );
02094       
02095       bbox->constraints = g_list_concat(bbox->constraints, insert_constraint_edge(r, l, xs[0], ys[0], 0, xs[1], ys[1], 0, bbox));
02096     }
02097   }
02098   END_LOOP;
02099   
02100   return 0;
02101 }
02102 
02103 static void
02104 create_board_edge (double x0, double y0,
02105                    double x1, double y1,
02106                    int layer,
02107                    GList **vlist)
02108 {
02109   GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
02110   double edge_length = hypot (x0 - x1, y0 - y1);
02111   unsigned int vertices_per_edge = MIN (1, edge_length / BOARD_EDGE_RESOLUTION);
02112   unsigned int count;
02113   double inc = edge_length / vertices_per_edge;
02114   double x = x0, y = y0;
02115 
02116   *vlist = g_list_prepend (*vlist, gts_vertex_new (vertex_class, x, y, layer));
02117 
02118   for (count = 1; count < vertices_per_edge; count ++) {
02119     coord_move_towards_coord_values (x, y, x1, y1, inc, &x, &y);
02120     *vlist = g_list_prepend (*vlist, gts_vertex_new (vertex_class, x, y, layer));
02121   }
02122 }
02123 
02124 
02125 static void
02126 read_board_constraints (toporouter_t *r, toporouter_layer_t *l, int layer)
02127 {
02128   GList *vlist = NULL;
02129   toporouter_bbox_t *bbox;
02130 
02131   /* Create points for the board edges and constrain those edges */
02132   create_board_edge (0.,            0.,             PCB->MaxWidth, 0.,             layer, &vlist);
02133   create_board_edge (PCB->MaxWidth, 0.,             PCB->MaxWidth, PCB->MaxHeight, layer, &vlist);
02134   create_board_edge (PCB->MaxWidth, PCB->MaxHeight, 0.,            PCB->MaxHeight, layer, &vlist);
02135   create_board_edge (0.,            PCB->MaxHeight, 0.,            0.,             layer, &vlist);
02136 
02137   bbox = toporouter_bbox_create (layer, vlist, BOARD, NULL);
02138   r->bboxes = g_slist_prepend (r->bboxes, bbox);
02139   insert_constraints_from_list (r, l, vlist, bbox);
02140   g_list_free (vlist);
02141 }
02142 
02143 gdouble 
02144 triangle_cost(GtsTriangle *t, gpointer *data){
02145 
02146   gdouble *min_quality = (gdouble *)data[0];
02147   gdouble *max_area = (gdouble *)data[1];
02148   gdouble quality = gts_triangle_quality(t);
02149   gdouble area = gts_triangle_area(t);
02150   
02151   if (quality < *min_quality || area > *max_area)
02152     return quality;
02153   return 0.0;
02154 }
02155 
02156 
02157 void
02158 print_constraint(toporouter_constraint_t *e)
02159 {
02160   printf("CONSTRAINT:\n");
02161   print_vertex(tedge_v1(e));
02162   print_vertex(tedge_v2(e));
02163 }
02164 
02165 void
02166 print_edge(toporouter_edge_t *e)
02167 {
02168   GList *i = edge_routing(e);
02169 
02170   printf("EDGE:\n");
02171  
02172   print_vertex(tedge_v1(e));
02173   
02174   while(i) {
02175     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
02176     print_vertex(v);
02177     i = i->next;
02178   }
02179   
02180   print_vertex(tedge_v2(e));
02181 }
02182 static void pick_first_face (GtsFace * f, GtsFace ** first)
02183 {
02184   if (*first == NULL)
02185     *first = f;
02186 }
02187 
02188 void
02189 unconstrain(toporouter_layer_t *l, toporouter_constraint_t *c) 
02190 {
02191   toporouter_edge_t *e;
02192 
02193   gts_allow_floating_vertices = TRUE;
02194   e = TOPOROUTER_EDGE(gts_edge_new (GTS_EDGE_CLASS (toporouter_edge_class ()), GTS_SEGMENT(c)->v1, GTS_SEGMENT(c)->v2));
02195   gts_edge_replace(GTS_EDGE(c), GTS_EDGE(e));
02196   l->constraints = g_list_remove(l->constraints, c);
02197   c->box->constraints = g_list_remove(c->box->constraints, c);
02198   c->box = NULL;
02199   gts_object_destroy (GTS_OBJECT (c));
02200   gts_allow_floating_vertices = FALSE;
02201 }
02202 
02203 void
02204 build_cdt(toporouter_t *r, toporouter_layer_t *l) 
02205 {
02206   /* TODO: generalize into surface *cdt_create(vertices, constraints) */
02207   GList *i;
02208   //GtsEdge *temp;
02209   //GtsVertex *v;
02210   GtsTriangle *t;
02211   GtsVertex *v1, *v2, *v3;
02212   GSList *vertices_slist;
02213 
02214   vertices_slist = list_to_slist(l->vertices);
02215 
02216   if(l->surface) {
02217     GtsFace * first = NULL;
02218     gts_surface_foreach_face (l->surface, (GtsFunc) pick_first_face, &first);
02219     gts_surface_traverse_destroy(gts_surface_traverse_new (l->surface, first));
02220   }
02221   
02222   t = gts_triangle_enclosing (gts_triangle_class (), vertices_slist, 1000.0f);
02223   gts_triangle_vertices (t, &v1, &v2, &v3);
02224 
02225   g_slist_free(vertices_slist);
02226   
02227   l->surface = gts_surface_new (gts_surface_class (), gts_face_class (),
02228       GTS_EDGE_CLASS(toporouter_edge_class ()), GTS_VERTEX_CLASS(toporouter_vertex_class ()) );
02229 
02230   gts_surface_add_face (l->surface, gts_face_new (gts_face_class (), t->e1, t->e2, t->e3));
02231 
02232 
02233 //  fprintf(stderr, "ADDED VERTICES\n");
02234 /*
02235   GtsFace *debugface;
02236 
02237   if((debugface = gts_delaunay_check(l->surface))) {
02238     fprintf(stderr, "WARNING: Delaunay check failed\n");
02239     fprintf(stderr, "\tViolating triangle:\n");
02240     fprintf(stderr, "\t%f,%f %f,%f\n",
02241         debugface->triangle.e1->segment.v1->p.x,
02242         debugface->triangle.e1->segment.v1->p.y,
02243         debugface->triangle.e1->segment.v2->p.x,
02244         debugface->triangle.e1->segment.v2->p.y
02245         );
02246     fprintf(stderr, "\t%f,%f %f,%f\n",
02247         debugface->triangle.e2->segment.v1->p.x,
02248         debugface->triangle.e2->segment.v1->p.y,
02249         debugface->triangle.e2->segment.v2->p.x,
02250         debugface->triangle.e2->segment.v2->p.y
02251         );
02252     fprintf(stderr, "\t%f,%f %f,%f\n",
02253         debugface->triangle.e3->segment.v1->p.x,
02254         debugface->triangle.e3->segment.v1->p.y,
02255         debugface->triangle.e3->segment.v2->p.x,
02256         debugface->triangle.e3->segment.v2->p.y
02257         );
02258 //    toporouter_draw_surface(r, l->surface, "debug.png", 4096, 4096);
02259   {
02260     int i;
02261     for(i=0;i<groupcount();i++) {
02262       char buffer[256];
02263       sprintf(buffer, "debug-%d.png", i);
02264       toporouter_draw_surface(r, r->layers[i].surface, buffer, 2048, 2048, 2, NULL, i, NULL);
02265     }
02266   }
02267     
02268   }
02269 */
02270 check_cons_continuation:  
02271   i = l->constraints;
02272   while (i) {  
02273     toporouter_constraint_t *c1 = TOPOROUTER_CONSTRAINT(i->data);
02274     GList *j = i->next;
02275    // printf("adding cons: "); print_constraint(c1);
02276     
02277     while(j) {
02278       toporouter_constraint_t *c2 = TOPOROUTER_CONSTRAINT(j->data);
02279       guint rem = 0;
02280       GList *temp;
02281       
02282     //  printf("\tconflict: "); print_constraint(c2);
02283       toporouter_bbox_t *c1box = c1->box, *c2box = c2->box;
02284       toporouter_vertex_t *c1v1 = tedge_v1(c1);
02285       toporouter_vertex_t *c1v2 = tedge_v2(c1);
02286       toporouter_vertex_t *c2v1 = tedge_v1(c2);
02287       toporouter_vertex_t *c2v2 = tedge_v2(c2);
02288 
02289       if(gts_segments_are_intersecting(GTS_SEGMENT(c1), GTS_SEGMENT(c2)) == GTS_IN) {
02290         toporouter_vertex_t *v;
02291         unconstrain(l, c1); unconstrain(l, c2); 
02292         rem = 1;
02293         // proper intersection
02294         v = TOPOROUTER_VERTEX(vertex_intersect(
02295               GTS_VERTEX(c1v1),
02296               GTS_VERTEX(c1v2),
02297               GTS_VERTEX(c2v1),
02298               GTS_VERTEX(c2v2)));
02299 
02300         // remove both constraints
02301         // replace with 4x constraints
02302         // insert new intersection vertex
02303         GTS_POINT(v)->z = vz(c1v1);
02304 
02305         l->vertices = g_list_prepend(l->vertices, v);
02306 //        gts_delaunay_add_vertex (l->surface, GTS_VERTEX(v), NULL);
02307 
02308         v->bbox = c1box;
02309 
02310         temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(v), vy(v), 0, c1box);
02311         c1box->constraints = g_list_concat(c1box->constraints, temp);
02312 
02313         temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(v), vy(v), 0, c1box);
02314         c1box->constraints = g_list_concat(c1box->constraints, temp);
02315 
02316         temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(v), vy(v), 0, c2box);
02317         c2box->constraints = g_list_concat(c2box->constraints, temp);
02318 
02319         temp = insert_constraint_edge(r, l, vx(c2v2), vy(c2v2), 0, vx(v), vy(v), 0, c2box);
02320         c2box->constraints = g_list_concat(c2box->constraints, temp);
02321 
02322       }else if(gts_segments_are_intersecting(GTS_SEGMENT(c1), GTS_SEGMENT(c2)) == GTS_ON ||
02323           gts_segments_are_intersecting(GTS_SEGMENT(c2), GTS_SEGMENT(c1)) == GTS_ON) {
02324 
02325         if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v1(c1)) && vertex_between(edge_v1(c2), edge_v2(c2), edge_v2(c1))) {
02326           unconstrain(l, c1); unconstrain(l, c2); 
02327           rem = 1;
02328           // remove c1
02329           temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c2v2), vy(c2v2), 0, c2box);
02330           c2box->constraints = g_list_concat(c2box->constraints, temp);
02331 
02332         }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
02333           unconstrain(l, c1); unconstrain(l, c2); 
02334           rem = 1;
02335           // remove c2
02336           temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box);
02337           c1box->constraints = g_list_concat(c1box->constraints, temp);
02338 
02339         //}else if(!vertex_wind(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && !vertex_wind(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
02340    /*     }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2)) || vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
02341           unconstrain(l, c1); unconstrain(l, c2); 
02342           rem = 1;
02343           printf("all colinear\n");
02344           //   exit(1);
02345           temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box);
02346           c1box->constraints = g_list_concat(c1box->constraints, temp);
02347 
02348           if(vertex_between(GTS_VERTEX(c1v1), GTS_VERTEX(c1v2), GTS_VERTEX(c2v2))) {
02349             // v2 of c2 is inner
02350             if(vertex_between(GTS_VERTEX(c2v1), GTS_VERTEX(c2v2), GTS_VERTEX(c1v2))) {
02351               // v2 of c1 is inner
02352               // c2 = c1.v2 -> c2.v1
02353               temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v1), vy(c2v1), 0, c2box);
02354               c2box->constraints = g_list_concat(c2box->constraints, temp);
02355             }else{
02356               // v1 of c1 is inner
02357               // c2 = c1.v1 -> c2.v1
02358               temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v1), vy(c2v1), 0, c2box);
02359               c2box->constraints = g_list_concat(c2box->constraints, temp);
02360             }
02361           }else{
02362             // v1 of c2 is inner
02363             if(vertex_between(GTS_VERTEX(c2v1), GTS_VERTEX(c2v2), GTS_VERTEX(c1v2))) {
02364               // v2 of c1 is inner
02365               // c2 = c1.v2 -> c2.v2
02366               temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v2), vy(c2v2), 0, c2box);
02367               c2box->constraints = g_list_concat(c2box->constraints, temp);
02368             }else{
02369               // v1 of c1 is inner
02370               // c2 = c1.v1 -> c2.v2
02371               temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v2), vy(c2v2), 0, c2box);
02372               c2box->constraints = g_list_concat(c2box->constraints, temp);
02373             }
02374           }*/
02375         }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v1(c1)) && c1v1 != c2v1 && c1v1 != c2v2) {
02376           unconstrain(l, c1); unconstrain(l, c2); 
02377           rem = 1;
02378           //v1 of c1 is on c2
02379           printf("v1 of c1 on c2\n"); 
02380 
02381           // replace with 2x constraints
02382           temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c1v1), vy(c1v1), 0, c2box);
02383           c2box->constraints = g_list_concat(c2box->constraints, temp);
02384           temp = insert_constraint_edge(r, l, vx(c2v2), vy(c2v2), 0, vx(c1v1), vy(c1v1), 0, c2box);
02385           c2box->constraints = g_list_concat(c2box->constraints, temp);
02386 
02387           temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box);
02388           c1box->constraints = g_list_concat(c1box->constraints, temp);
02389 
02390           // restore c1
02391           //temp = insert_constraint_edge(r, l, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, c1->box);
02392           //c2->box->constraints = g_list_concat(c2->box->constraints, temp);
02393 
02394         }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v2(c1)) && c1v2 != c2v1 && c1v2 != c2v2) {
02395           unconstrain(l, c1); unconstrain(l, c2); 
02396           rem = 1;
02397           //v2 of c1 is on c2
02398           printf("v2 of c1 on c2\n"); 
02399 
02400           // replace with 2x constraints
02401           temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c1v2), vy(c1v2), 0, c2box);
02402           c2box->constraints = g_list_concat(c2box->constraints, temp);
02403           temp = insert_constraint_edge(r, l, vx(c2v2), vy(c2v2), 0, vx(c1v2), vy(c1v2), 0, c2box);
02404           c2box->constraints = g_list_concat(c2box->constraints, temp);
02405 
02406           temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box);
02407           c1box->constraints = g_list_concat(c1box->constraints, temp);
02408 
02409         }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && c2v1 != c1v1 && c2v1 != c1v2) {
02410           unconstrain(l, c1); unconstrain(l, c2); 
02411           rem = 1;
02412           //v1 of c2 is on c1
02413           printf("v1 of c2 on c1\n"); 
02414 
02415           // replace with 2x constraints
02416           temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v1), vy(c2v1), 0, c1box);
02417           c1box->constraints = g_list_concat(c1box->constraints, temp);
02418           temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v1), vy(c2v1), 0, c1box);
02419           c1box->constraints = g_list_concat(c1box->constraints, temp);
02420 
02421           temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c2v2), vy(c2v2), 0, c2box);
02422           c2box->constraints = g_list_concat(c2box->constraints, temp);
02423         }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2)) && c2v2 != c1v1 && c2v2 != c1v2) {
02424           unconstrain(l, c1); unconstrain(l, c2);
02425           rem = 1;
02426           //v2 of c2 is on c1
02427           printf("v2 of c2 on c1\n"); 
02428 
02429           // replace with 2x constraints
02430           temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v2), vy(c2v2), 0, c1box);
02431           c1box->constraints = g_list_concat(c1box->constraints, temp);
02432           temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v2), vy(c2v2), 0, c1box);
02433           c1box->constraints = g_list_concat(c1box->constraints, temp);
02434 
02435           temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c2v2), vy(c2v2), 0, c2box);
02436           c2box->constraints = g_list_concat(c2box->constraints, temp);
02437         }
02438       }
02439       if(rem) goto check_cons_continuation; 
02440 
02441       j = j->next;
02442     }
02443 
02444     i = i->next; 
02445   }  
02446 
02447   i = l->vertices;
02448   while (i) {
02449     //v = i->data;
02450     //if(r->flags & TOPOROUTER_FLAG_DEBUG_CDTS) 
02451   //  fprintf(stderr, "\tadding vertex %f,%f\n", v->p.x, v->p.y);
02452     toporouter_vertex_t *v = TOPOROUTER_VERTEX(gts_delaunay_add_vertex (l->surface, (GtsVertex *)i->data, NULL));
02453     if(v) {
02454       printf("conflict: "); print_vertex(v);
02455     }
02456 
02457     i = i->next;
02458   }
02459   i = l->constraints;
02460   while (i) {
02461 
02462     // toporouter_constraint_t *c1 = TOPOROUTER_CONSTRAINT(i->data);
02463     // printf("adding cons: "); print_constraint(c1);
02464 
02465     GSList *conflicts = gts_delaunay_add_constraint (l->surface, (GtsConstraint *)i->data);
02466     GSList *j = conflicts;
02467     while(j) {
02468       if(TOPOROUTER_IS_CONSTRAINT(j->data)) {
02469         toporouter_constraint_t *c2 = TOPOROUTER_CONSTRAINT(j->data);
02470 
02471         printf("\tconflict: "); print_constraint(c2);
02472       
02473       }
02474       j = j->next;
02475     }
02476     g_slist_free(conflicts);
02477 
02478     i = i->next;
02479   }
02480 
02481 //  if(rerun) 
02482 //        goto build_cdt_continuation;
02483 //  fprintf(stderr, "ADDED CONSTRAINTS\n");
02484   gts_allow_floating_vertices = TRUE;
02485   gts_object_destroy (GTS_OBJECT (v1));
02486   gts_object_destroy (GTS_OBJECT (v2));
02487   gts_object_destroy (GTS_OBJECT (v3));
02488   gts_allow_floating_vertices = FALSE;
02489   
02490 /*
02491   {
02492     gpointer data[2];
02493     gdouble quality = 0.50, area = G_MAXDOUBLE;
02494     guint num = gts_delaunay_conform(l->surface, -1, (GtsEncroachFunc) gts_vertex_encroaches_edge, NULL);
02495 
02496     if (num == 0){
02497       data[0] = &quality;
02498       data[1] = &area;
02499       num = gts_delaunay_refine(l->surface, -1, (GtsEncroachFunc) gts_vertex_encroaches_edge, NULL, (GtsKeyFunc) triangle_cost, data);
02500     }
02501   }
02502 */
02503 #ifdef DEBUG_IMPORT  
02504   gts_surface_print_stats(l->surface, stderr);
02505 #endif  
02506   
02507 #if 0
02508   {
02509     char buffer[64];
02510     FILE *fout2;
02511     sprintf(buffer, "surface%d.gts", l - r->layers);
02512     fout2 = fopen(buffer, "w");
02513     gts_surface_write(l->surface, fout2);
02514   }
02515 #endif
02516 
02517 }
02518 
02519 gint
02520 visited_cmp(gconstpointer a, gconstpointer b)
02521 {
02522   if(a<b) return -1;
02523   if(a>b) return 1;
02524   return 0;
02525 }
02526 
02527 static double
02528 coord_angle (double ax, double ay, double bx, double by)
02529 {
02530   return atan2 (by - ay, bx - ax);
02531 }
02532 
02533 GList *
02534 cluster_vertices(toporouter_t *r, toporouter_cluster_t *c)
02535 {
02536   GList *rval = NULL;
02537   
02538   if(!c) return NULL;
02539 
02540   FOREACH_CLUSTER(c->netlist->clusters) {
02541     if((r->flags & TOPOROUTER_FLAG_AFTERRUBIX && cluster->c == c->c) || (!(r->flags & TOPOROUTER_FLAG_AFTERRUBIX) && cluster == c)) {
02542       FOREACH_BBOX(cluster->boxes) {
02543         if(box->type == LINE) {
02544           g_assert(box->constraints->data);
02545           rval = g_list_prepend(rval, tedge_v1(box->constraints->data));
02546           rval = g_list_prepend(rval, tedge_v2(box->constraints->data));
02547         }else if(box->point) {
02548           rval = g_list_prepend(rval, TOPOROUTER_VERTEX(box->point));
02549           //g_assert(vertex_bbox(TOPOROUTER_VERTEX(box->point)) == box);
02550         }else {
02551           printf("WARNING: cluster_vertices: unhandled bbox type\n");
02552         }
02553 
02554       } FOREACH_END;
02555 
02556 
02557     }
02558       
02559   } FOREACH_END;
02560 
02561   return rval;
02562 }
02563 
02564 void
02565 print_cluster(toporouter_cluster_t *c)
02566 {
02567 
02568   if(!c) {
02569     printf("[CLUSTER (NULL)]\n");
02570     return;
02571   }
02572 
02573   printf("CLUSTER %d: NETLIST = %s STYLE = %s\n", c->c, c->netlist->netlist, c->netlist->style);
02574 
02575   FOREACH_BBOX(c->boxes) {
02576     print_bbox(box);
02577   } FOREACH_END;
02578 }
02579 
02580 
02581 toporouter_cluster_t *
02582 cluster_create(toporouter_t *r, toporouter_netlist_t *netlist)
02583 {
02584   toporouter_cluster_t *c = (toporouter_cluster_t *)malloc(sizeof(toporouter_cluster_t));
02585 
02586   c->c = c->pc = netlist->clusters->len;
02587   g_ptr_array_add(netlist->clusters, c);
02588   c->netlist = netlist;
02589   c->boxes = g_ptr_array_new();
02590 
02591   return c;
02592 }
02593 
02594 toporouter_bbox_t *
02595 toporouter_bbox_locate(toporouter_t *r, toporouter_term_t type, void *data, gdouble x, gdouble y, guint layergroup)
02596 {
02597   GtsPoint *p = gts_point_new(gts_point_class(), x, y, layergroup);
02598   GSList *boxes = gts_bb_tree_stabbed(r->bboxtree, p), *i = boxes;
02599   
02600   gts_object_destroy(GTS_OBJECT(p));
02601   
02602   while(i) {
02603     toporouter_bbox_t *box = TOPOROUTER_BBOX(i->data);
02604 
02605     if(box->type == type && box->data == data) {
02606       g_slist_free(boxes);
02607       return box;       
02608     }
02609     
02610     i = i->next;
02611   }
02612 
02613   g_slist_free(boxes);
02614   return NULL;
02615 }
02616 
02617 void
02618 cluster_join_bbox(toporouter_cluster_t *cluster, toporouter_bbox_t *box)
02619 {
02620   if(box) {
02621     g_ptr_array_add(cluster->boxes, box);
02622     box->cluster = cluster;
02623   }
02624 }
02625 
02626 toporouter_netlist_t *
02627 netlist_create(toporouter_t *r, char *netlist, char *style)
02628 {
02629   toporouter_netlist_t *nl = (toporouter_netlist_t *)malloc(sizeof(toporouter_netlist_t));
02630   nl->netlist = netlist; 
02631   nl->style = style;
02632   nl->clusters = g_ptr_array_new();
02633   nl->routes = g_ptr_array_new();
02634   nl->routed = NULL;
02635   nl->pair = NULL;
02636   g_ptr_array_add(r->netlists, nl);
02637   return nl;
02638 }
02639 
02640 void
02641 import_clusters(toporouter_t *r)
02642 {
02643   NetListListType nets;
02644   nets = CollectSubnets(false);
02645   NETLIST_LOOP(&nets);
02646   {
02647     if(netlist->NetN > 0) {
02648       toporouter_netlist_t *nl = netlist_create(r, netlist->Net->Connection->menu->Name, netlist->Net->Connection->menu->Style);
02649       
02650       NET_LOOP(netlist);
02651       {
02652 
02653         toporouter_cluster_t *cluster = cluster_create(r, nl);
02654 #ifdef DEBUG_MERGING  
02655         printf("NET:\n");
02656 #endif        
02657         CONNECTION_LOOP (net);
02658         {
02659 
02660           if(connection->type == LINE_TYPE) {
02661             LineType *line = (LineType *) connection->ptr2;
02662             toporouter_bbox_t *box = toporouter_bbox_locate(r, LINE, line, connection->X, connection->Y, connection->group);
02663             cluster_join_bbox(cluster, box);
02664 
02665 #ifdef DEBUG_MERGING  
02666             pcb_printf("\tLINE %#mD\n", connection->X, connection->Y);
02667 #endif        
02668           }else if(connection->type == PAD_TYPE) {
02669             PadType *pad = (PadType *) connection->ptr2;
02670             toporouter_bbox_t *box = toporouter_bbox_locate(r, PAD, pad, connection->X, connection->Y, connection->group);
02671             cluster_join_bbox(cluster, box);
02672 
02673 #ifdef DEBUG_MERGING  
02674             pcb_printf("\tPAD %#mD\n", connection->X, connection->Y);
02675 #endif        
02676           }else if(connection->type == PIN_TYPE) {
02677 
02678             for(guint m=0;m<groupcount();m++) {
02679               PinType *pin = (PinType *) connection->ptr2;
02680               toporouter_bbox_t *box = toporouter_bbox_locate(r, PIN, pin, connection->X, connection->Y, m);
02681               cluster_join_bbox(cluster, box);
02682             }
02683 
02684 #ifdef DEBUG_MERGING  
02685             pcb_printf("\tPIN %#mD\n", connection->X, connection->Y);
02686 #endif        
02687           }else if(connection->type == VIA_TYPE) {
02688 
02689             for(guint m=0;m<groupcount();m++) {
02690               PinType *pin = (PinType *) connection->ptr2;
02691               toporouter_bbox_t *box = toporouter_bbox_locate(r, VIA, pin, connection->X, connection->Y, m);
02692               cluster_join_bbox(cluster, box);
02693             }
02694 
02695 #ifdef DEBUG_MERGING  
02696             pcb_printf("\tVIA %#mD\n", connection->X, connection->Y);
02697 #endif        
02698           }else if(connection->type == POLYGON_TYPE) {
02699             PolygonType *polygon = (PolygonType *) connection->ptr2;
02700             toporouter_bbox_t *box = toporouter_bbox_locate(r, POLYGON, polygon, connection->X, connection->Y, connection->group);
02701             cluster_join_bbox(cluster, box);
02702 
02703 #ifdef DEBUG_MERGING  
02704             pcb_printf("\tPOLYGON %#mD\n", connection->X, connection->Y);
02705 #endif        
02706 
02707           }
02708         }
02709         END_LOOP;
02710 #ifdef DEBUG_MERGING  
02711         printf("\n");
02712 #endif        
02713       }
02714       END_LOOP;
02715 
02716     }
02717   }
02718   END_LOOP;
02719   FreeNetListListMemory(&nets);
02720 }
02721 
02722 void
02723 import_geometry(toporouter_t *r) 
02724 {
02725   toporouter_layer_t *cur_layer;
02726   
02727   int group;
02728 
02729 #ifdef DEBUG_IMPORT    
02730   for (group = 0; group < max_group; group++) {
02731     printf("Group %d: Number %d:\n", group, PCB->LayerGroups.Number[group]);
02732 
02733     for (int entry = 0; entry < PCB->LayerGroups.Number[group]; entry++) {
02734         printf("\tEntry %d\n", PCB->LayerGroups.Entries[group][entry]);
02735     }
02736   }
02737 #endif
02738   /* Allocate space for per layer struct */
02739   cur_layer = r->layers = (toporouter_layer_t *)malloc(groupcount() * sizeof(toporouter_layer_t));
02740 
02741   /* Foreach layer, read in pad vertices and constraints, and build CDT */
02742   for (group = 0; group < max_group; group++) {
02743 #ifdef DEBUG_IMPORT    
02744     printf("*** LAYER GROUP %d ***\n", group);
02745 #endif
02746     if(PCB->LayerGroups.Number[group] > 0){ 
02747       cur_layer->vertices    = NULL;
02748       cur_layer->constraints = NULL;
02749 
02750 #ifdef DEBUG_IMPORT    
02751       printf("reading board constraints from layer %d into group %d\n", PCB->LayerGroups.Entries[group][0], group);
02752 #endif
02753       read_board_constraints(r, cur_layer, PCB->LayerGroups.Entries[group][0]);
02754 #ifdef DEBUG_IMPORT    
02755       printf("reading points from layer %d into group %d \n",PCB->LayerGroups.Entries[group][0], group);
02756 #endif
02757       read_points(r, cur_layer, PCB->LayerGroups.Entries[group][0]);
02758 
02759 //#ifdef DEBUG_IMPORT    
02760 //      printf("reading pads from layer %d into group %d\n", number, group);
02761 //#endif
02762       read_pads(r, cur_layer, group);
02763 
02764       GROUP_LOOP(PCB->Data, group)
02765       {
02766 
02767 #ifdef DEBUG_IMPORT    
02768         printf("reading lines from layer %d into group %d\n", number, group);
02769 #endif
02770         read_lines(r, cur_layer, layer, number);
02771 
02772       }
02773       END_LOOP;
02774 
02775 
02776 
02777 #ifdef DEBUG_IMPORT    
02778       printf("building CDT\n");
02779 #endif
02780       build_cdt(r, cur_layer);
02781   printf("finished\n");
02782 /*      {
02783     int i;
02784     for(i=0;i<groupcount();i++) {
02785       char buffer[256];
02786       sprintf(buffer, "build%d.png", i);
02787       toporouter_draw_surface(r, r->layers[i].surface, buffer, 2048, 2048, 2, NULL, i, NULL);
02788     }
02789   }*/
02790 #ifdef DEBUG_IMPORT    
02791       printf("finished building CDT\n");
02792 #endif
02793       cur_layer++;
02794     }
02795   }
02796   
02797   r->bboxtree = gts_bb_tree_new(r->bboxes);
02798  
02799   import_clusters(r);
02800 
02801 #ifdef DEBUG_IMPORT
02802   printf("finished import!\n");
02803 #endif  
02804 }
02805 
02806 
02807 gint
02808 compare_points(gconstpointer a, gconstpointer b)
02809 {
02810   GtsPoint *i = GTS_POINT(a);
02811   GtsPoint *j = GTS_POINT(b);
02812 
02813   if(i->x == j->x) {
02814     if(i->y == j->y) return 0;
02815     if(i->y < j->y) return -1;
02816     return 1;
02817   }
02818   if(i->x < j->x) return -1;
02819   return 1;
02820 }
02821 
02822 gint
02823 compare_segments(gconstpointer a, gconstpointer b)
02824 {
02825   if(a == b) return 0;
02826   if(a < b) return -1;
02827   return 1;
02828 }
02829 #define DEBUG_CLUSTER_FIND 1
02830 toporouter_cluster_t *
02831 cluster_find(toporouter_t *r, gdouble x, gdouble y, gdouble z)
02832 {
02833   GtsPoint *p = gts_point_new(gts_point_class(), x, y, z);
02834   GSList *hits = gts_bb_tree_stabbed(r->bboxtree, p);
02835   toporouter_cluster_t *rval = NULL;
02836 
02837 #ifdef DEBUG_CLUSTER_FIND
02838   printf("FINDING %f,%f,%f\n\n", x, y, z);
02839 #endif
02840 
02841   while(hits) {
02842     toporouter_bbox_t *box = TOPOROUTER_BBOX(hits->data);
02843     
02844 #ifdef DEBUG_CLUSTER_FIND
02845     printf("HIT BOX: "); print_bbox(box);
02846 #endif
02847 
02848     if(box->layer == (int)z) { 
02849       if(box->type != BOARD) {
02850         if(box->type == LINE) {
02851           LineType *line = (LineType *)box->data;
02852           gint linewind = coord_wind(line->Point1.X, line->Point1.Y, x, y, line->Point2.X, line->Point2.Y);
02853 
02854           if(line->Point1.X > x - EPSILON && line->Point1.X < x + EPSILON &&
02855               line->Point1.Y > y - EPSILON && line->Point1.Y < y + EPSILON) {
02856             rval = box->cluster;
02857           //  break;
02858           }
02859           if(line->Point2.X > x - EPSILON && line->Point2.X < x + EPSILON &&
02860               line->Point2.Y > y - EPSILON && line->Point2.Y < y + EPSILON) {
02861             rval = box->cluster;
02862           //  break;
02863           }
02864           if(!linewind) {
02865             rval = box->cluster;
02866           //  break;
02867           }
02868 
02869         }else if(box->surface) {
02870 
02871           if(gts_point_locate(p, box->surface, NULL)) {
02872             rval = box->cluster;
02873             break;
02874           }
02875 
02876         }
02877       }
02878     }
02879     hits = hits->next;
02880   }
02881   
02882   gts_object_destroy(GTS_OBJECT(p));
02883  
02884 
02885 #ifdef DEBUG_CLUSTER_FIND
02886   printf("cluster_find: %f,%f,%f: ", x, y, z);
02887   print_cluster(rval);
02888 #endif
02889 
02890   return rval;
02891 }
02892 
02893 gdouble
02894 simple_h_cost(toporouter_t *r, toporouter_vertex_t *curpoint, toporouter_vertex_t *destpoint)
02895 {
02896   gdouble layerpenalty = (vz(curpoint) == vz(destpoint)) ? 0. : r->viacost;
02897 
02898   return gts_point_distance(GTS_POINT(curpoint), GTS_POINT(destpoint)) + layerpenalty;
02899 }
02900 
02901 #define FCOST(x) (x->gcost + x->hcost)
02902 gdouble     
02903 route_heap_cmp(gpointer item, gpointer data)
02904 {
02905   return FCOST(TOPOROUTER_VERTEX(item));  
02906 }
02907 
02908 #define closelist_insert(p) closelist = g_list_prepend(closelist, p)
02909 
02910 typedef struct {
02911   toporouter_vertex_t *key;
02912   toporouter_vertex_t *result;
02913 }toporouter_heap_search_data_t;
02914 
02915 void 
02916 toporouter_heap_search(gpointer data, gpointer user_data)
02917 {
02918   toporouter_vertex_t *v = TOPOROUTER_VERTEX(data);
02919   toporouter_heap_search_data_t *heap_search_data = (toporouter_heap_search_data_t *)user_data;
02920   if(v == heap_search_data->key) heap_search_data->result = v;
02921 }
02922 /*
02923 void 
02924 toporouter_heap_color(gpointer data, gpointer user_data)
02925 {
02926   toporouter_vertex_t *v = TOPOROUTER_VERTEX(data);
02927   v->flags |= (guint) user_data;
02928 }
02929 */
02930 static inline gdouble
02931 angle_span(gdouble a1, gdouble a2)
02932 {
02933   if(a1 > a2) 
02934     return ((2*M_PI)-a1 + a2);  
02935   return a2-a1;
02936 }
02937 
02938 gdouble
02939 edge_capacity(toporouter_edge_t *e)
02940 {
02941   return gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e)));
02942 }
02943 
02944 gdouble
02945 edge_flow(toporouter_edge_t *e, toporouter_vertex_t *v1, toporouter_vertex_t *v2, toporouter_vertex_t *dest)
02946 {
02947   GList *i = edge_routing(e);
02948   toporouter_vertex_t *pv = tedge_v1(e), *v = NULL;
02949   gdouble flow = 0.;
02950   guint waiting = 1;
02951 
02952   if((pv == v1 || pv == v2) && waiting) {
02953     flow += min_vertex_net_spacing(pv, dest);
02954     pv = dest;
02955     waiting = 0;
02956   }
02957 
02958   g_assert(v1 != v2);
02959 
02960   while(i) {
02961     v = TOPOROUTER_VERTEX(i->data);
02962    
02963 
02964     if(pv == dest)
02965       flow += min_vertex_net_spacing(v, pv);
02966     else
02967       flow += min_spacing(v, pv);
02968     
02969     if((v == v1 || v == v2) && waiting) {
02970       flow += min_vertex_net_spacing(v, dest);
02971       pv = dest;
02972       waiting = 0;
02973     }else{
02974       pv = v;
02975     }
02976     i = i->next;
02977   }
02978   
02979   if(pv == dest)
02980     flow += min_vertex_net_spacing(tedge_v2(e), pv);
02981   else
02982     flow += min_spacing(tedge_v2(e), pv);
02983 
02984   return flow;
02985 }
02986    
02987 void
02988 print_path(GList *path)
02989 {
02990   GList *i = path;
02991 
02992   printf("PATH:\n");
02993   while(i) {
02994     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
02995 //    printf("[V %f,%f,%f]\n", vx(v), vy(v), vz(v));
02996     print_vertex(v);
02997 
02998     if(v->child && !g_list_find(path, v->child)) 
02999       printf("\t CHILD NOT IN LIST\n");
03000     if(v->parent && !g_list_find(path, v->parent)) 
03001       printf("\t parent NOT IN LIST\n");
03002     i = i->next;
03003   }
03004 
03005 
03006 }
03007 
03008 GList *
03009 split_path(GList *path) 
03010 {
03011   toporouter_vertex_t *pv = NULL;
03012   GList *curpath = NULL, *i, *paths = NULL;
03013 #ifdef DEBUG_ROUTE
03014   printf("PATH:\n");
03015 #endif
03016   i = path;
03017   while(i) {
03018     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
03019 
03020 #ifdef DEBUG_ROUTE
03021     printf("v = %f,%f ", vx(v), vy(v));
03022     if(v->parent) printf("parent = %f,%f ", vx(v->parent), vy(v->parent));
03023     if(v->child) printf("child = %f,%f ", vx(v->child), vy(v->child));
03024     printf("\n");
03025 #endif
03026 //    printf("***\n");
03027 //    if(v) printf("v = %f,%f\n", GTS_POINT(v)->x, GTS_POINT(v)->y);
03028 //    if(pv) printf("pv = %f,%f\n", GTS_POINT(pv)->x, GTS_POINT(pv)->y);
03029     
03030     
03031     if(pv)
03032     if(GTS_POINT(v)->x == GTS_POINT(pv)->x && GTS_POINT(v)->y == GTS_POINT(pv)->y) {
03033       if(g_list_length(curpath) > 1) paths = g_list_prepend(paths, curpath);
03034       curpath = NULL;
03035 
03036       pv->child = NULL;
03037       v->parent = NULL;
03038     }
03039     
03040     curpath = g_list_append(curpath, v);
03041 
03042     pv = v;
03043     i = i->next;
03044   }
03045   
03046   if(g_list_length(curpath) > 1)
03047     paths = g_list_prepend(paths, curpath);
03048   
03049   return paths;
03050 }
03051 
03052 
03053 
03054 #define edge_gradient(e) (cartesian_gradient(GTS_POINT(GTS_SEGMENT(e)->v1)->x, GTS_POINT(GTS_SEGMENT(e)->v1)->y, \
03055     GTS_POINT(GTS_SEGMENT(e)->v2)->x, GTS_POINT(GTS_SEGMENT(e)->v2)->y))
03056 
03057 
03061 gint
03062 routing_edge_insert(gconstpointer a, gconstpointer b, gpointer user_data)
03063 {
03064   GtsPoint *v1 = GTS_POINT(edge_v1(user_data));
03065 
03066   if(gts_point_distance2(v1, GTS_POINT(a)) < gts_point_distance2(v1, GTS_POINT(b)) - EPSILON)
03067     return -1;
03068   if(gts_point_distance2(v1, GTS_POINT(a)) > gts_point_distance2(v1, GTS_POINT(b)) + EPSILON)
03069     return 1;
03070 /*
03071   printf("a = %x b = %x\n", (int) a, (int) b);
03072 
03073   printf("WARNING: routing_edge_insert() with same points..\n \
03074       v1 @ %f,%f\n\
03075       a  @ %f,%f\n\
03076       b  @ %f,%f\n", 
03077       v1->x, v1->y,
03078       vx(a), vy(a),
03079       vx(a), vy(b));
03080   printf("A: "); print_vertex(TOPOROUTER_VERTEX(a));
03081   printf("B: "); print_vertex(TOPOROUTER_VERTEX(b));
03082 
03083   TOPOROUTER_VERTEX(a)->flags |= VERTEX_FLAG_RED;
03084   TOPOROUTER_VERTEX(b)->flags |= VERTEX_FLAG_RED;
03085 */
03086   return 0;
03087 }
03088 
03089 
03090 toporouter_vertex_t *
03091 new_temp_toporoutervertex(gdouble x, gdouble y, toporouter_edge_t *e) 
03092 {
03093   GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
03094   GList *i = edge_routing(e);
03095   toporouter_vertex_t *r;
03097   while(i) {
03098     r = TOPOROUTER_VERTEX(i->data);
03099     if(epsilon_equals(vx(r),x) && epsilon_equals(vy(r),y)) {
03100       if(r->flags & VERTEX_FLAG_TEMP) return r;
03101     }
03102     i = i->next;
03103   }
03104 //*/
03105   r = TOPOROUTER_VERTEX( gts_vertex_new (vertex_class, x, y, vz(edge_v1(e))) );
03106   r->flags |= VERTEX_FLAG_TEMP;
03107   r->routingedge = e;
03108 
03109   if(TOPOROUTER_IS_CONSTRAINT(e))
03110     TOPOROUTER_CONSTRAINT(e)->routing = g_list_insert_sorted_with_data(edge_routing(e), r, routing_edge_insert, e);
03111   else
03112     e->routing = g_list_insert_sorted_with_data(edge_routing(e), r, routing_edge_insert, e);
03113   
03114   return r;
03115 }
03116 
03117 
03121 toporouter_vertex_t *
03122 new_temp_toporoutervertex_in_segment(toporouter_edge_t *e, toporouter_vertex_t *v, gdouble r, toporouter_vertex_t *ref) 
03123 {
03124   gdouble m = edge_gradient(e); 
03125   toporouter_spoint_t p, np1, np2;
03126 //  toporouter_vertex_t *b = TOPOROUTER_VERTEX((GTS_VERTEX(v) == edge_v1(e)) ? edge_v2(e) : edge_v1(e));
03127   toporouter_vertex_t *rval = NULL; 
03128   p.x = vx(v); p.y = vy(v);
03129 
03130   vertices_on_line(&p, m, r, &np1, &np2);
03131   
03132   if( (pow(np1.x - vx(ref), 2) + pow(np1.y - vy(ref), 2)) < (pow(np2.x - vx(ref), 2) + pow(np2.y - vy(ref), 2)) )
03133     rval = new_temp_toporoutervertex(np1.x, np1.y, e);
03134   else 
03135     rval = new_temp_toporoutervertex(np2.x, np2.y, e);
03136 
03137   return rval;
03138 }
03139 
03140 gint
03141 vertex_keepout_test(toporouter_t *r, toporouter_vertex_t *v) 
03142 {
03143   GList *i = r->keepoutlayers;
03144   while(i) {
03145     gdouble keepout = *((double *) i->data);
03146     if(vz(v) == keepout) return 1; 
03147     i = i->next;
03148   }
03149   return 0;
03150 }
03151 
03152 void
03153 closest_cluster_pair(toporouter_t *r, GList *src_vertices, GList *dest_vertices, toporouter_vertex_t **a, toporouter_vertex_t **b)
03154 {
03155   GList *i = src_vertices, *j = dest_vertices;
03156 
03157   gdouble min = 0.;
03158   *a = NULL; *b = NULL;
03159 
03160   i = src_vertices;
03161   while(i) {
03162     toporouter_vertex_t *v1 = TOPOROUTER_VERTEX(i->data);
03163 
03164     if(vertex_keepout_test(r, v1)) { i = i->next; continue; }
03165 
03166     j = dest_vertices;
03167     while(j) {
03168       toporouter_vertex_t *v2 = TOPOROUTER_VERTEX(j->data);
03169       if(vertex_keepout_test(r, v2) || vz(v2) != vz(v1)) { j = j->next; continue; }
03170 
03171       if(!*a) {
03172         *a = v1; *b = v2; min = simple_h_cost(r, *a, *b);
03173       }else{
03174         gdouble tempd = simple_h_cost(r, v1, v2);
03175         if(r->flags & TOPOROUTER_FLAG_GOFAR && tempd > min) {
03176           *a = v1; *b = v2; min = tempd;
03177         }else 
03178         if(tempd < min) {
03179           *a = v1; *b = v2; min = tempd;
03180         }
03181       }
03182 
03183       j = j->next;
03184     }
03185 
03186     i = i->next;
03187   }
03188 
03189 //  g_list_free(src_vertices);
03190 //  g_list_free(dest_vertices);
03191 }
03192 
03193 
03194 toporouter_vertex_t *
03195 closest_dest_vertex(toporouter_t *r, toporouter_vertex_t *v, toporouter_route_t *routedata)
03196 {
03197   GList //*vertices = cluster_vertices(r, routedata->dest), 
03198         *i = routedata->destvertices;
03199   toporouter_vertex_t *closest = NULL;
03200   gdouble closest_distance = 0.;
03201 
03202 //  if(routedata->flags & TOPOROUTER_FLAG_FLEX) i = r->destboxes;
03203 
03204   while(i) {
03205     toporouter_vertex_t *cv = TOPOROUTER_VERTEX(i->data);
03206 
03207     if(vz(cv) != vz(v)) { i = i->next; continue; }
03208 
03209     if(!closest) {
03210       closest = cv; closest_distance = simple_h_cost(r, v, closest);
03211     }else{
03212       gdouble tempd = simple_h_cost(r, v, cv);
03213       if(r->flags & TOPOROUTER_FLAG_GOFAR && tempd > closest_distance) {
03214         closest = cv; closest_distance = tempd;
03215       }else 
03216       if(tempd < closest_distance) {
03217         closest = cv; closest_distance = tempd;
03218       }
03219     }
03220     i = i->next;
03221   }
03222 
03223 //  g_list_free(vertices);
03224 
03225 #ifdef DEBUG_ROUTE
03226   printf("CLOSEST = %f,%f,%f\n", vx(closest), vy(closest), vz(closest));
03227 #endif
03228   return closest;
03229 }
03230 
03231 #define toporouter_edge_gradient(e) (cartesian_gradient(vx(edge_v1(e)), vy(edge_v1(e)), vx(edge_v2(e)), vy(edge_v2(e))))
03232 
03233 
03237 gdouble
03238 triangle_interior_capacity(GtsTriangle *t, toporouter_vertex_t *v)
03239 {
03240   toporouter_edge_t *e = TOPOROUTER_EDGE(gts_triangle_edge_opposite(t, GTS_VERTEX(v)));
03241   gdouble x, y, m1, m2, c2, c1;
03242 #ifdef DEBUG_ROUTE
03243   gdouble len;
03244 #endif
03245 
03246   g_assert(e);
03247 
03248   m1 = toporouter_edge_gradient(e);
03249   m2 = perpendicular_gradient(m1);
03250   c2 = (isinf(m2)) ? vx(v) : vy(v) - (m2 * vx(v));
03251   c1 = (isinf(m1)) ? vx(edge_v1(e)) : vy(edge_v1(e)) - (m1 * vx(edge_v1(e)));
03252 
03253   if(isinf(m2))
03254     x = vx(v);
03255   else if(isinf(m1))
03256     x = vx(edge_v1(e));
03257   else
03258     x = (c2 - c1) / (m1 - m2);
03259 
03260   y = (isinf(m2)) ? vy(edge_v1(e)) : (m2 * x) + c2;
03261 
03262 #ifdef DEBUG_ROUTE
03263   len = gts_point_distance2(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e)));
03264   printf("%f,%f len = %f v = %f,%f\n", x, y, len, vx(v), vy(v));
03265 #endif
03266 
03267   if(epsilon_equals(x,vx(edge_v1(e))) && epsilon_equals(y,vy(edge_v1(e)))) return INFINITY;
03268   if(epsilon_equals(x,vx(edge_v2(e))) && epsilon_equals(y,vy(edge_v2(e)))) return INFINITY;
03269 
03270   if(x >= MIN(vx(edge_v1(e)),vx(edge_v2(e))) && 
03271      x <= MAX(vx(edge_v1(e)),vx(edge_v2(e))) && 
03272      y >= MIN(vy(edge_v1(e)),vy(edge_v2(e))) && 
03273      y <= MAX(vy(edge_v1(e)),vy(edge_v2(e))))  
03274 
03275 //  if( (pow(vx(edge_v1(e)) - x, 2) + pow(vy(edge_v1(e)) - y, 2)) < len && (pow(vx(edge_v2(e)) - x, 2) + pow(vy(edge_v2(e)) - y, 2)) < len )
03276     return hypot(vx(v) - x, vy(v) - y);
03277 
03278   return INFINITY;
03279 }
03280 
03281 static inline toporouter_vertex_t *
03282 segment_common_vertex(GtsSegment *s1, GtsSegment *s2) 
03283 {
03284   if(!s1 || !s2) return NULL;
03285   if(s1->v1 == s2->v1) return TOPOROUTER_VERTEX(s1->v1);
03286   if(s1->v2 == s2->v1) return TOPOROUTER_VERTEX(s1->v2);
03287   if(s1->v1 == s2->v2) return TOPOROUTER_VERTEX(s1->v1);
03288   if(s1->v2 == s2->v2) return TOPOROUTER_VERTEX(s1->v2);
03289   return NULL;
03290 }
03291 
03292 static inline toporouter_vertex_t *
03293 route_vertices_common_vertex(toporouter_vertex_t *v1, toporouter_vertex_t *v2)
03294 {
03295   return segment_common_vertex(GTS_SEGMENT(v1->routingedge), GTS_SEGMENT(v2->routingedge));
03296 }
03297 
03298 
03299 static inline guint
03300 edges_third_edge(GtsSegment *s1, GtsSegment *s2, toporouter_vertex_t **v1, toporouter_vertex_t **v2) 
03301 {
03302   if(!s1 || !s2) return 0;
03303   if(s1->v1 == s2->v1) {
03304     *v1 = TOPOROUTER_VERTEX(s1->v2);
03305     *v2 = TOPOROUTER_VERTEX(s2->v2);
03306     return 1;
03307   }
03308   if(s1->v2 == s2->v1) {
03309     *v1 = TOPOROUTER_VERTEX(s1->v1);
03310     *v2 = TOPOROUTER_VERTEX(s2->v2);
03311     return 1;
03312   }
03313   if(s1->v1 == s2->v2) { 
03314     *v1 = TOPOROUTER_VERTEX(s1->v2);
03315     *v2 = TOPOROUTER_VERTEX(s2->v1);
03316     return 1;
03317   }
03318   if(s1->v2 == s2->v2) { 
03319     *v1 = TOPOROUTER_VERTEX(s1->v1);
03320     *v2 = TOPOROUTER_VERTEX(s2->v1);
03321     return 1;
03322   }
03323   return 0;
03324 }
03325 
03330 gdouble
03331 flow_from_edge_to_edge(GtsTriangle *t, toporouter_edge_t *e1, toporouter_edge_t *e2, 
03332     toporouter_vertex_t *common_v, toporouter_vertex_t *curpoint)
03333 {
03334   gdouble r = 0.;
03335   toporouter_vertex_t *pv = common_v, *v;
03336   toporouter_edge_t *op_edge;
03337   
03338   GList *i = edge_routing(e1);
03339   while(i) {
03340     v = TOPOROUTER_VERTEX(i->data);
03341 
03342     if(v == curpoint) {
03343       r += min_spacing(v, pv);
03344       pv = v;
03345       i = i->next; continue;
03346     }
03347 //    if(!(v->flags & VERTEX_FLAG_TEMP)) {
03348     if((v->flags & VERTEX_FLAG_ROUTE)) {
03349       if(v->parent)
03350         if(v->parent->routingedge == e2) {
03351           r += min_spacing(v, pv);
03352           pv = v;
03353           i = i->next; continue;
03354         }
03355 
03356       if(v->child)
03357         if(v->child->routingedge == e2) {
03358           r += min_spacing(v, pv);
03359           pv = v;
03360           i = i->next; continue;
03361         }
03362     }
03363     i = i->next;
03364   }
03365 
03366   op_edge = TOPOROUTER_EDGE(gts_triangle_edge_opposite(t, GTS_VERTEX(common_v)));
03367   
03368   g_assert(op_edge);
03369   g_assert(e1);
03370   g_assert(e2);
03371 
03372   v = segment_common_vertex(GTS_SEGMENT(e2), GTS_SEGMENT(op_edge)); 
03373   g_assert(v);
03374 
03375   //v = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(t, GTS_EDGE(e1)));
03376   if(v->flags & VERTEX_FLAG_ROUTE && v->parent && v->parent->routingedge) {
03377     if(v->parent->routingedge == e1) 
03378       r += min_spacing(v, pv);
03379   }
03380 
03381   v = segment_common_vertex(GTS_SEGMENT(e1), GTS_SEGMENT(op_edge)); 
03382   g_assert(v);
03383 
03384   //v = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(t, GTS_EDGE(e2)));
03385   if(v->flags & VERTEX_FLAG_ROUTE && v->parent && v->parent->routingedge) {
03386     if(v->parent->routingedge == e1) 
03387       r += min_spacing(v, pv);
03388   }
03389 
03390   if(TOPOROUTER_IS_CONSTRAINT(op_edge)) {
03391     toporouter_bbox_t *box = vertex_bbox(TOPOROUTER_VERTEX(edge_v1(op_edge)));
03392     r += vertex_net_thickness(v) / 2.;
03393     if(box) {
03394       r += MAX(vertex_net_keepaway(v), cluster_keepaway(box->cluster));
03395       r += cluster_thickness(box->cluster) / 2.;
03396     }else{
03397       r += vertex_net_keepaway(v);
03398 
03399     }
03400   }
03401 
03402   return r;
03403 }
03404 
03405 
03406 
03407 guint
03408 check_triangle_interior_capacity(GtsTriangle *t, toporouter_vertex_t *v, toporouter_vertex_t *curpoint, 
03409     toporouter_edge_t *op_edge, toporouter_edge_t *adj_edge1, toporouter_edge_t *adj_edge2)
03410 {
03411   gdouble ic = triangle_interior_capacity(t, v);
03412   gdouble flow = flow_from_edge_to_edge(t, adj_edge1, adj_edge2, v, curpoint);
03413 
03414   if(TOPOROUTER_IS_CONSTRAINT(adj_edge1) || TOPOROUTER_IS_CONSTRAINT(adj_edge2)) return 1;
03415 
03416 
03417   if(flow > ic) {
03418 #ifdef DEBUG_ROUTE    
03419     printf("fail interior capacity flow = %f ic = %f\n", flow, ic);
03420 #endif    
03421     return 0;
03422   }
03423 
03424   return 1;
03425 }
03426 
03427 toporouter_vertex_t *
03428 edge_routing_next_not_temp(toporouter_edge_t *e, GList *list) 
03429 {
03430   if(!TOPOROUTER_IS_CONSTRAINT(e)) {
03431     while(list) {
03432       toporouter_vertex_t *v = TOPOROUTER_VERTEX(list->data);
03433       if(!(v->flags & VERTEX_FLAG_TEMP))
03434         return v;
03435 
03436       list = list->next;
03437     }
03438   }
03439   return tedge_v2(e);
03440 }
03441 
03442 toporouter_vertex_t *
03443 edge_routing_prev_not_temp(toporouter_edge_t *e, GList *list) 
03444 {
03445   if(!TOPOROUTER_IS_CONSTRAINT(e)) {
03446     while(list) {
03447       toporouter_vertex_t *v = TOPOROUTER_VERTEX(list->data);
03448       if(!(v->flags & VERTEX_FLAG_TEMP))
03449         return v;
03450 
03451       list = list->prev;
03452     }
03453   }
03454   return tedge_v1(e);
03455 }
03456 
03457 void
03458 edge_adjacent_vertices(toporouter_edge_t *e, toporouter_vertex_t *v, toporouter_vertex_t **v1, toporouter_vertex_t **v2)
03459 {
03460   GList *r = g_list_find(edge_routing(e), v);
03461 
03462   if(v == tedge_v1(e)) {
03463     *v1 = NULL;
03464     *v2 = edge_routing_next_not_temp(e, edge_routing(e));
03465   }else if(v == tedge_v2(e)) {
03466     *v1 = edge_routing_prev_not_temp(e, g_list_last(edge_routing(e)));
03467     *v2 = NULL;
03468   }else{
03469 //    r = g_list_find(r, v);
03470     *v1 = edge_routing_prev_not_temp(e, r);
03471     *v2 = edge_routing_next_not_temp(e, r);
03472 
03473   }
03474 
03475 }
03476 
03477 
03478 GList *
03479 candidate_vertices(toporouter_vertex_t *v1, toporouter_vertex_t *v2, toporouter_vertex_t *dest, toporouter_edge_t *e) 
03480 {
03481   gdouble totald, v1ms, v2ms, flow, capacity, ms;
03482   GList *vs = NULL;
03483 
03484   g_assert(v1);
03485   g_assert(v2);
03486   g_assert(dest);
03487 
03488   g_assert(!(v1->flags & VERTEX_FLAG_TEMP));
03489   g_assert(!(v2->flags & VERTEX_FLAG_TEMP));
03490 #ifdef DEBUG_ROUTE
03491   printf("starting candidate vertices\n");
03492   printf("v1 = %f,%f v2 = %f,%f dest = %f,%f\n", vx(v1), vy(v1), vx(v2), vy(v2), vx(dest), vy(dest));
03493 #endif
03494   totald = gts_point_distance(GTS_POINT(v1), GTS_POINT(v2));
03495   v1ms = min_spacing(v1, dest);
03496   v2ms = min_spacing(v2, dest); 
03497   ms = min_spacing(dest, dest);
03498   flow = TOPOROUTER_IS_CONSTRAINT(e) ? 0. : edge_flow(e, v1, v2, dest);
03499   capacity = edge_capacity(e);
03500  
03501 #ifdef DEBUG_ROUTE
03502   g_assert(totald > 0);
03503  
03504   printf("v1ms = %f v2ms = %f totald = %f ms = %f capacity = %f flow = %f\n", v1ms, v2ms, totald, ms, capacity, flow);
03505 #endif
03506 
03507   if(flow >= capacity) return NULL;
03508 
03509 
03510   if(v1ms + v2ms + ms >= totald) {
03511     vs = g_list_prepend(vs, new_temp_toporoutervertex((vx(v1)+vx(v2)) / 2., (vy(v1)+vy(v2)) / 2., e));
03512   }else{
03513     gdouble x0, y0, x1, y1, d;
03514 
03515     vertex_move_towards_vertex_values(GTS_VERTEX(v1), GTS_VERTEX(v2), v1ms, &x0, &y0);
03516     
03517     vs = g_list_prepend(vs, new_temp_toporoutervertex(x0, y0, e));
03518     
03519     vertex_move_towards_vertex_values(GTS_VERTEX(v2), GTS_VERTEX(v1), v2ms, &x1, &y1);
03520     
03521     vs = g_list_prepend(vs, new_temp_toporoutervertex(x1, y1, e));
03522     
03523     d = hypot(x0-x1,y0-y1);
03524 
03525     if(ms < d) {
03526 //      guint nint = d / ms;
03527 //      gdouble dif = d / (nint + 1);
03528       gdouble dif = d / 2;
03529 
03530 //      for(guint j=0;j<nint;j++) {
03531         gdouble x, y;
03532 
03533 //        coord_move_towards_coord_values(x0, y0, x1, y1, dif * j, &x, &y);
03534         coord_move_towards_coord_values(x0, y0, x1, y1, dif, &x, &y);
03535 
03536         vs = g_list_prepend(vs, new_temp_toporoutervertex(x, y, e));
03537 
03538 //      }
03539 
03540     }
03541 
03542   }
03543 #ifdef DEBUG_ROUTE
03544   printf("candidate vertices returning %d\n", g_list_length(vs));
03545 #endif
03546   return vs;
03547 }
03548 
03549 GList *
03550 edge_routing_first_not_temp(toporouter_edge_t *e)
03551 {
03552   GList *i = edge_routing(e);
03553   toporouter_vertex_t *v;
03554 
03555   while(i) {
03556     v = TOPOROUTER_VERTEX(i->data);
03557     if(!(v->flags & VERTEX_FLAG_TEMP)) return i;
03558 
03559     i = i->next;
03560   }
03561  
03562   return NULL;
03563 }
03564 
03565 GList *
03566 edge_routing_last_not_temp(toporouter_edge_t *e)
03567 {
03568   GList *i = edge_routing(e), *last = NULL;
03569   toporouter_vertex_t *v;
03570 
03571   while(i) {
03572     v = TOPOROUTER_VERTEX(i->data);
03573     if(!(v->flags & VERTEX_FLAG_TEMP)) last = i;
03574     
03575     i = i->next;
03576   }
03577  
03578   return last;
03579 }
03580 
03581 void
03582 delete_vertex(toporouter_vertex_t *v)
03583 {
03584   
03585   if(v->flags & VERTEX_FLAG_TEMP) {
03586     if(v->routingedge) {
03587       if(TOPOROUTER_IS_CONSTRAINT(v->routingedge)) 
03588         TOPOROUTER_CONSTRAINT(v->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(v->routingedge)->routing, v);
03589       else
03590         v->routingedge->routing = g_list_remove(v->routingedge->routing, v);
03591     }
03592 
03593     gts_object_destroy ( GTS_OBJECT(v) );
03594   }
03595 }
03596 
03597 #define edge_is_blocked(e) (TOPOROUTER_IS_EDGE(e) ? (e->flags & EDGE_FLAG_DIRECTCONNECTION) : 0)
03598 
03599 GList *
03600 triangle_candidate_points_from_vertex(GtsTriangle *t, toporouter_vertex_t *v, toporouter_vertex_t *dest, toporouter_route_t *routedata)
03601 {
03602   toporouter_edge_t *op_e = TOPOROUTER_EDGE(gts_triangle_edge_opposite(t, GTS_VERTEX(v)));
03603   toporouter_vertex_t *vv1, *vv2, *constraintv = NULL;
03604   toporouter_edge_t *e1, *e2;
03605   GList *i;
03606   GList *rval = NULL;
03607 
03608 #ifdef DEBUG_ROUTE  
03609   printf("\tTRIANGLE CAND POINT FROM VERTEX\n");
03610 
03611   g_assert(op_e);
03612 #endif
03613 
03614   e1 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(v), edge_v1(op_e)));
03615   e2 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(v), edge_v2(op_e)));
03616     
03617 
03618   if(TOPOROUTER_IS_CONSTRAINT(op_e)) {
03619     if(TOPOROUTER_CONSTRAINT(op_e)->box->type == BOARD) {
03620 #ifdef DEBUG_ROUTE
03621       printf("BOARD constraint\n");
03622 #endif      
03623       return NULL;
03624     }
03625     if(constraint_netlist(TOPOROUTER_CONSTRAINT(op_e)) != vertex_netlist(dest)) { // || TOPOROUTER_CONSTRAINT(op_e)->routing) {
03626 #ifdef DEBUG_ROUTE
03627       printf("op_e routing:\n");
03628       print_edge(op_e);
03629 #endif      
03630       return NULL;
03631     }
03632 #ifdef DEBUG_ROUTE
03633     printf("RETURNING CONSTRAINT POING\n");
03634 #endif
03635     constraintv = new_temp_toporoutervertex_in_segment(op_e, TOPOROUTER_VERTEX(edge_v1(op_e)), 
03636         gts_point_distance(GTS_POINT(edge_v1(op_e)), GTS_POINT(edge_v2(op_e))) / 2., TOPOROUTER_VERTEX(edge_v2(op_e)));
03637 //    return g_list_prepend(NULL, vv1);
03638 
03639 
03640   }
03641 
03642   if(edge_is_blocked(op_e)) {
03643     goto triangle_candidate_points_from_vertex_exit;
03644   }
03645 //  v1 = tedge_v1(op_e); 
03646 //  v2 = tedge_v2(op_e);
03647  
03648   if(v == tedge_v1(e1)) {
03649     i = edge_routing_first_not_temp(e1);
03650   }else{
03651     i = edge_routing_last_not_temp(e1);
03652   }
03653 
03654   if(i) {
03655     toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data);
03656 
03657     if(temp->parent == tedge_v2(op_e) || temp->child == tedge_v2(op_e)) {
03658  #ifdef DEBUG_ROUTE
03659      printf("temp -> op_e->v2\n");
03660 #endif
03661       goto triangle_candidate_points_from_vertex_exit;
03662     }
03663     if(temp->parent->routingedge == op_e) {
03664       vv1 = temp->parent;  
03665 #ifdef DEBUG_ROUTE
03666       printf("vv1->parent\n");
03667 #endif
03668 
03669     }else if(temp->child->routingedge == op_e) {
03670       vv1 = temp->child;
03671 #ifdef DEBUG_ROUTE
03672       printf("vv1->child\n");
03673 #endif
03674 
03675     }else{
03676       // must be to e2
03677 #ifdef DEBUG_ROUTE
03678       printf("temp -> e2?\n");
03679       printf("op_e = %f,%f\t\t%f,%f\n", vx(edge_v1(op_e)), vy(edge_v1(op_e)), vx(edge_v2(op_e)), vy(edge_v2(op_e)) );
03680       if(temp->parent->routingedge)
03681         printf("temp->parent->routingedge = %f,%f \t\t %f,%f\n", 
03682             vx(edge_v1(temp->parent->routingedge)), vy(edge_v1(temp->parent->routingedge)),
03683             vx(edge_v2(temp->parent->routingedge)), vy(edge_v2(temp->parent->routingedge))
03684             );
03685       else 
03686         printf("temp->parent->routingedge = NULL\n");
03687 
03688       if(temp->child->routingedge)
03689         printf("temp->child->routingedge = %f,%f \t\t %f,%f\n", 
03690             vx(edge_v1(temp->child->routingedge)), vy(edge_v1(temp->child->routingedge)),
03691             vx(edge_v2(temp->child->routingedge)), vy(edge_v2(temp->child->routingedge))
03692             );
03693       else 
03694         printf("temp->child->routingedge = NULL\n");
03695 #endif
03696       goto triangle_candidate_points_from_vertex_exit;
03697     }
03698 
03699   }else{
03700     vv1 = tedge_v1(op_e);
03701 #ifdef DEBUG_ROUTE
03702     printf("nothing on e1\n");
03703 #endif
03704   }
03705   
03706   if(v == tedge_v1(e2)) {
03707     i = edge_routing_first_not_temp(e2);
03708   }else{
03709     i = edge_routing_last_not_temp(e2);
03710   }
03711 
03712   if(i) {
03713     toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data);
03714 
03715     if(temp->parent == tedge_v1(op_e) || temp->child == tedge_v1(op_e)) {
03716 #ifdef DEBUG_ROUTE
03717       printf("temp -> op_e->v2\n");
03718 #endif
03719       goto triangle_candidate_points_from_vertex_exit;
03720     }
03721 
03722     if(temp->parent->routingedge == op_e) {
03723       vv2 = temp->parent;  
03724 #ifdef DEBUG_ROUTE
03725       printf("vv2->parent\n");
03726 #endif
03727     }else if(temp->child->routingedge == op_e) {
03728       vv2 = temp->child;
03729 #ifdef DEBUG_ROUTE
03730       printf("vv2->child\n");
03731 #endif
03732 
03733     }else{
03734       // must be to e1
03735 #ifdef DEBUG_ROUTE
03736       printf("temp -> e1?\n");
03737       printf("op_e = %f,%f\t\t%f,%f\n", vx(edge_v1(op_e)), vy(edge_v1(op_e)), vx(edge_v2(op_e)), vy(edge_v2(op_e)) );
03738       if(temp->parent->routingedge)
03739         printf("temp->parent->routingedge = %f,%f \t\t %f,%f\n", 
03740             vx(edge_v1(temp->parent->routingedge)), vy(edge_v1(temp->parent->routingedge)),
03741             vx(edge_v2(temp->parent->routingedge)), vy(edge_v2(temp->parent->routingedge))
03742             );
03743       else 
03744         printf("temp->parent->routingedge = NULL\n");
03745 
03746       if(temp->child->routingedge)
03747         printf("temp->child->routingedge = %f,%f \t\t %f,%f\n", 
03748             vx(edge_v1(temp->child->routingedge)), vy(edge_v1(temp->child->routingedge)),
03749             vx(edge_v2(temp->child->routingedge)), vy(edge_v2(temp->child->routingedge))
03750             );
03751       else 
03752         printf("temp->child->routingedge = NULL\n");
03753 #endif
03754       goto triangle_candidate_points_from_vertex_exit;
03755     }
03756 
03757   }else{
03758     vv2 = tedge_v2(op_e);
03759 #ifdef DEBUG_ROUTE
03760     printf("nothing on e2\n");
03761 #endif
03762   }
03763 
03764 #ifdef DEBUG_ROUTE
03765     printf("size of e1 routing = %d e2 routing = %d op_e routing = %d\n", 
03766         g_list_length(edge_routing(e1)), g_list_length(edge_routing(e2)), g_list_length(edge_routing(op_e)));
03767 #endif
03768 
03769   if(constraintv) {
03770 #ifdef DEBUG_ROUTE
03771     print_vertex(constraintv);
03772     printf("constraintv %f,%f returning\n", vx(constraintv), vy(constraintv));
03773 #endif
03774     return g_list_prepend(NULL, constraintv);  
03775   }
03776 
03777   i = edge_routing(op_e);
03778   while(i) {
03779     toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data);
03780 
03781     if(temp->parent == v || temp->child == v) {
03782       rval = g_list_concat(rval, candidate_vertices(vv1, temp, dest, op_e)); 
03783       vv1 = temp;
03784     }
03785 
03786     i = i->next;
03787   }
03788 
03789   rval = g_list_concat(rval, candidate_vertices(vv1, vv2, dest, op_e)); 
03790 
03791   return rval; 
03792 
03793 
03794 
03795 triangle_candidate_points_from_vertex_exit:
03796   if(constraintv) //delete_vertex(constraintv);    
03797   g_hash_table_insert(routedata->alltemppoints, constraintv, constraintv);  
03798 
03799   g_list_free(rval);
03800 
03801   return NULL;
03802 }
03803 
03804 void
03805 routedata_insert_temppoints(toporouter_route_t *data, GList *temppoints) {
03806   GList *j = temppoints;
03807   while(j) {
03808     g_hash_table_insert(data->alltemppoints, j->data, j->data);  
03809     j = j->next;
03810   }
03811 }
03812 
03813 
03814 static inline gint
03815 constraint_route_test(toporouter_constraint_t *c, toporouter_route_t *routedata)
03816 {
03817   if(c->box->cluster && c->box->cluster->netlist == routedata->src->netlist) {
03818     if(c->box->cluster->c == routedata->dest->c || c->box->cluster->c == routedata->src->c) return 1;
03819   }
03820   return 0;
03821 }
03822 
03823 GList *
03824 all_candidates_on_edge(toporouter_edge_t *e, toporouter_route_t *routedata)
03825 {
03826   GList *rval = NULL;
03827   if(edge_is_blocked(e)) return NULL;
03828   
03829   if(!TOPOROUTER_IS_CONSTRAINT(e)) { 
03830     GList *i = edge_routing(e);
03831     toporouter_vertex_t *pv = tedge_v1(e);
03832 
03833     while(i) {
03834       toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
03835       if(!(v->flags & VERTEX_FLAG_TEMP)) {
03836         rval = g_list_concat(rval, candidate_vertices(pv, v, TOPOROUTER_VERTEX(routedata->destvertices->data), e));
03837         pv = v;
03838       }
03839       i = i->next;
03840     }
03841 
03842     rval = g_list_concat(rval, candidate_vertices(pv, tedge_v2(e), TOPOROUTER_VERTEX(routedata->destvertices->data), e));
03843   }else if(TOPOROUTER_CONSTRAINT(e)->box->type == BOARD) {
03844      return NULL; 
03845   }else if(constraint_route_test(TOPOROUTER_CONSTRAINT(e), routedata)) {
03846     toporouter_vertex_t *consv = new_temp_toporoutervertex_in_segment(e, tedge_v1(e), tvdistance(tedge_v1(e), tedge_v2(e)) / 2., tedge_v2(e));
03847     rval = g_list_prepend(rval, consv);
03848 //    g_hash_table_insert(routedata->alltemppoints, consv, consv);  
03849   }
03850 
03851   return rval;
03852 }
03853 
03854 GList *
03855 triangle_all_candidate_points_from_vertex(GtsTriangle *t, toporouter_vertex_t *v, toporouter_route_t *routedata)
03856 {
03857   toporouter_edge_t *op_e = TOPOROUTER_EDGE(gts_triangle_edge_opposite(t, GTS_VERTEX(v)));
03858   return all_candidates_on_edge(op_e, routedata);
03859 }
03860 
03861 GList *
03862 triangle_all_candidate_points_from_edge(toporouter_t *r, GtsTriangle *t, toporouter_edge_t *e, toporouter_route_t *routedata,
03863     toporouter_vertex_t **dest, toporouter_vertex_t *curpoint)
03864 {
03865   toporouter_vertex_t *op_v;
03866   toporouter_edge_t *e1, *e2;
03867   GList *i, *rval = NULL, *rval2 = NULL;
03868   toporouter_vertex_t *boxpoint = NULL;
03869   guint e1intcap, e2intcap;
03870 
03871   op_v = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(t, GTS_EDGE(e)));
03872   
03873     
03874   if(vertex_bbox(op_v)) boxpoint = TOPOROUTER_VERTEX(vertex_bbox(op_v)->point);
03875     
03876   if(g_list_find(routedata->destvertices, op_v)) {
03877     rval = g_list_prepend(rval, op_v);
03878     *dest = op_v;
03879     return rval;
03880   }else if(g_list_find(routedata->destvertices, boxpoint)) {
03881     *dest = boxpoint;
03882   }else if(g_list_find(routedata->srcvertices, op_v)) {
03883     rval = g_list_prepend(rval, op_v);
03884   }
03885 
03886   e1 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(op_v), edge_v1(e)));
03887   e2 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(op_v), edge_v2(e)));
03888 
03889   rval = g_list_concat(rval, all_candidates_on_edge(e1, routedata));
03890   rval = g_list_concat(rval, all_candidates_on_edge(e2, routedata));
03891 
03892   e1intcap = check_triangle_interior_capacity(t, tedge_v1(e), curpoint, e2, e, e1);
03893   e2intcap = check_triangle_interior_capacity(t, tedge_v2(e), curpoint, e1, e, e2);
03894 
03895   i = rval;
03896   while(i) {
03897     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
03898 
03899     if(!v->routingedge) 
03900       rval2 = g_list_prepend(rval2, v);
03901     else if(v->routingedge == e1 && !(!TOPOROUTER_IS_CONSTRAINT(e1) && !e1intcap))
03902       rval2 = g_list_prepend(rval2, v);
03903     else if(v->routingedge == e2 && !(!TOPOROUTER_IS_CONSTRAINT(e2) && !e2intcap))
03904       rval2 = g_list_prepend(rval2, v);
03905 
03906     i = i->next;
03907   }
03908   g_list_free(rval);
03909 
03910   return rval2;
03911 }
03912 
03913 GList *
03914 triangle_candidate_points_from_edge(toporouter_t *r, GtsTriangle *t, toporouter_edge_t *e, toporouter_vertex_t *v, toporouter_vertex_t **dest,
03915     toporouter_route_t *routedata)
03916 {
03917   toporouter_vertex_t *v1, *v2, *op_v, *vv = NULL, *e1constraintv = NULL, *e2constraintv = NULL;
03918   toporouter_edge_t *e1, *e2;
03919   GList *e1cands = NULL, *e2cands = NULL, *rval = NULL;
03920   guint noe1 = 0, noe2 = 0;
03921 
03922   op_v = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(t, GTS_EDGE(e)));
03923   
03924   e1 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(op_v), edge_v1(e)));
03925   e2 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(op_v), edge_v2(e)));
03926 
03927   g_assert(*dest);
03928 
03929   // v1 is prev dir, v2 is next dir
03930   edge_adjacent_vertices(e, v, &v1, &v2);
03931   
03932   if(TOPOROUTER_IS_CONSTRAINT(e1)) {
03933     GList *i = edge_routing(e1);
03934 
03935     if(TOPOROUTER_CONSTRAINT(e1)->box->type == BOARD) {
03936       noe1 = 1;
03937     }else if(!constraint_route_test(TOPOROUTER_CONSTRAINT(e1), routedata)) {
03938       noe1 = 1; 
03939 #ifdef DEBUG_ROUTE      
03940       printf("noe1 netlist\n");
03941 #endif      
03942     }else
03943 
03944     if(v1 == tedge_v1(e) || 
03945         (v1->parent->routingedge && v1->parent->routingedge == e1) || 
03946         (v1->child->routingedge && v1->child->routingedge == e1)) {
03947       e1constraintv = new_temp_toporoutervertex_in_segment(e1, tedge_v1(e1), gts_point_distance(GTS_POINT(edge_v1(e1)), GTS_POINT(edge_v2(e1))) / 2., tedge_v2(e1));
03948     }
03949     
03950     while(i) {
03951       toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data);
03952 
03953       if((temp->child == tedge_v2(e) || temp->parent == tedge_v2(e)) && !(temp->flags & VERTEX_FLAG_TEMP)) noe2 = 1;
03954 
03955       i = i->next;
03956     }
03957 
03958     goto triangle_candidate_points_e2;
03959   }
03960 
03961   if(edge_is_blocked(e1)) {
03962     noe1 = 1;
03963     goto triangle_candidate_points_e2;
03964   }
03965 
03966   if(v1 == tedge_v1(e)) {
03967     // continue up e1
03968     toporouter_vertex_t *vv1, *vv2;
03969     edge_adjacent_vertices(e1, v1, &vv1, &vv2);
03970 
03971 #ifdef DEBUG_ROUTE      
03972     printf("v1 == e->v1\n");
03973 #endif
03974 
03975     if(vv1) {
03976       // candidates from v1 until vv1 
03977       vv = vv1;
03978     }else{
03979       // candidates from v1 until vv2
03980       vv = vv2;
03981     }
03982     
03983     if(!e1constraintv) e1cands = candidate_vertices(v1, vv, *dest, e1);
03984 
03985     if(vv != op_v) {
03986       if(vv->parent == tedge_v2(e) || vv->child == tedge_v2(e)) {
03987 #ifdef DEBUG_ROUTE      
03988         printf("noe2 0\n");
03989 #endif
03990         noe2 = 1;
03991       }
03992     }
03993 
03994   }else if(v1->parent != op_v && v1->child != op_v) {
03995     toporouter_vertex_t *vv1 = NULL, *vv2 = NULL;
03996     
03997 #ifdef DEBUG_ROUTE      
03998     printf("v1 != e->v1\n");
03999 #endif
04000 
04001     if(v1->parent->routingedge == e1) {
04002       vv1 = v1->parent;
04003 #ifdef DEBUG_ROUTE      
04004       printf("v1 parent = e1\n");
04005 #endif
04006       if(op_v == tedge_v1(e1)) {
04007         // candidates from v1->parent until prev vertex 
04008         vv2 = edge_routing_prev_not_temp(e1, g_list_find(edge_routing(e1), v1->parent)->prev);
04009       }else{
04010         // candidates from v1->parent until next vertex 
04011         vv2 = edge_routing_next_not_temp(e1, g_list_find(edge_routing(e1), v1->parent)->next);
04012       }
04013 
04014     }else if(v1->child->routingedge == e1) {
04015       vv1 = v1->child;
04016 #ifdef DEBUG_ROUTE      
04017       printf("v1 child = e1\n");
04018 #endif
04019       if(op_v == tedge_v1(e1)) {
04020         // candidates from v1->child until prev vertex 
04021         vv2 = edge_routing_prev_not_temp(e1, g_list_find(edge_routing(e1), v1->child)->prev);
04022       }else{
04023         // candidates from v1->child until next vertex 
04024         vv2 = edge_routing_next_not_temp(e1, g_list_find(edge_routing(e1), v1->child)->next);
04025       }
04026 
04027     }else{
04028 #ifdef DEBUG_ROUTE      
04029       printf("v1 ? \n");
04030 #endif
04031       goto triangle_candidate_points_e2;
04032     }
04033 
04034     if(vv1 && vv2) {
04035       if(vv2->parent == tedge_v2(e) || vv2->child == tedge_v2(e)) {
04036 #ifdef DEBUG_ROUTE      
04037         printf("noe2 1\n");
04038 #endif
04039         noe2 = 1;
04040       }
04041 
04042       if(!e1constraintv) e1cands = candidate_vertices(vv1, vv2, *dest, e1);
04043 
04044       vv = vv2;
04045     }
04046   }
04047   
04048   if(vv && vv == op_v) {
04049     toporouter_vertex_t *boxpoint = NULL;
04050     
04051     if(vertex_bbox(op_v)) boxpoint = TOPOROUTER_VERTEX(vertex_bbox(op_v)->point);
04052     
04053     if(g_list_find(routedata->destvertices, op_v)) {
04054       rval = g_list_prepend(rval, op_v);
04055       *dest = op_v;
04056     }else if(g_list_find(routedata->destvertices, boxpoint)) {
04057       *dest = boxpoint;
04058     }else if(g_list_find(routedata->srcvertices, op_v)) {
04059       rval = g_list_prepend(rval, op_v);
04060     }
04061   }
04062 
04063 triangle_candidate_points_e2:
04064 
04065   if(noe2) {
04066 //    printf("noe2\n");
04067     goto triangle_candidate_points_finish;
04068   }
04069   
04070   if(TOPOROUTER_IS_CONSTRAINT(e2)) {
04071     GList *i = edge_routing(e2);
04072 
04073     if(TOPOROUTER_CONSTRAINT(e2)->box->type == BOARD) {
04074       noe2 = 1;
04075 //      goto triangle_candidate_points_finish;
04076     }else if(!constraint_route_test(TOPOROUTER_CONSTRAINT(e2), routedata)) {
04077 #ifdef DEBUG_ROUTE      
04078       printf("noe2 netlist\n");
04079 #endif
04080       noe2 = 1;
04081 //      goto triangle_candidate_points_finish;
04082     }else if(v2 == tedge_v2(e) ||
04083         (v2->parent->routingedge && v2->parent->routingedge == e2) || 
04084         (v2->child->routingedge && v2->child->routingedge == e2)) {
04085        
04086       e2constraintv = new_temp_toporoutervertex_in_segment(e2, tedge_v1(e2), gts_point_distance(GTS_POINT(edge_v1(e2)), GTS_POINT(edge_v2(e2))) / 2., tedge_v2(e2));
04087       
04088     }
04089     
04090     while(i) {
04091       toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data);
04092 
04093       if((temp->child == tedge_v1(e) || temp->parent == tedge_v1(e)) && !(temp->flags & VERTEX_FLAG_TEMP)) 
04094         noe1 = 1;
04095 
04096       i = i->next;
04097     }
04098 
04099 
04100 
04101     goto triangle_candidate_points_finish;
04102   }
04103   
04104   if(edge_is_blocked(e2)) {
04105     noe2 = 1;
04106     goto triangle_candidate_points_finish;
04107   }
04108   
04109   if(v2 == tedge_v2(e)) {
04110     // continue up e2
04111     toporouter_vertex_t *vv1 = NULL, *vv2 = NULL;
04112     edge_adjacent_vertices(e2, v2, &vv1, &vv2);
04113 
04114 #ifdef DEBUG_ROUTE      
04115     printf("v2 == e->v2\n");
04116 #endif
04117 
04118     if(vv1) {
04119       // candidates from v2 until vv1
04120       vv = vv1;
04121     }else{
04122       // candidates from v2 until vv2
04123       vv = vv2;
04124     }
04125     
04126     if(!e2constraintv) e2cands = candidate_vertices(v2, vv, *dest, e2);
04127 
04128     if(vv != op_v) {
04129       if(vv->parent == tedge_v1(e) || vv->child == tedge_v1(e)) {
04130 #ifdef DEBUG_ROUTE      
04131         printf("noe1 0\n");
04132 #endif
04133         noe1 = 1;
04134       }
04135     }
04136 
04137   }else if(v2->parent != op_v && v2->child != op_v) {
04138     toporouter_vertex_t *vv1 = NULL, *vv2 = NULL;
04139     
04140 #ifdef DEBUG_ROUTE      
04141     printf("v2 == e->v2\n");
04142 #endif
04143 
04144     if(v2->parent->routingedge == e2) {
04145       vv1 = v2->parent;
04146       if(op_v == tedge_v1(e2)) {
04147         // candidates from v2->parent until prev vertex 
04148         vv2 = edge_routing_prev_not_temp(e2, g_list_find(edge_routing(e2), vv1)->prev);
04149       }else{
04150         // candidates from v2->parent until next vertex 
04151         vv2 = edge_routing_next_not_temp(e2, g_list_find(edge_routing(e2), vv1)->next);
04152       }
04153 
04154     }else if(v2->child->routingedge == e2) {
04155       vv1 = v2->child;
04156       if(op_v == tedge_v1(e2)) {
04157         // candidates from v2->child until prev vertex 
04158         vv2 = edge_routing_prev_not_temp(e2, g_list_find(edge_routing(e2), vv1)->prev);
04159       }else{
04160         // candidates from v2->child until next vertex 
04161         vv2 = edge_routing_next_not_temp(e2, g_list_find(edge_routing(e2), vv1)->next);
04162       }
04163 
04164     }else{
04165       goto triangle_candidate_points_finish;
04166     }
04167 
04168     if(vv1 && vv2) {
04169       if(vv2->parent == tedge_v1(e) || vv2->child == tedge_v1(e)) {
04170 #ifdef DEBUG_ROUTE      
04171         printf("noe1 1\n");
04172 #endif
04173         noe1 = 1;
04174       }
04175 
04176       if(!e2constraintv) e2cands = candidate_vertices(vv1, vv2, *dest, e2);
04177     }
04178   }
04179 
04180 triangle_candidate_points_finish:  
04181 
04182   v1 = segment_common_vertex(GTS_SEGMENT(e), GTS_SEGMENT(e1));
04183   v2 = segment_common_vertex(GTS_SEGMENT(e), GTS_SEGMENT(e2));
04184 
04185   if(noe1 || !check_triangle_interior_capacity(t, v1, v, e2, e, e1)) {
04186 #ifdef DEBUG_ROUTE      
04187     printf("freeing e1cands\n");
04188 #endif
04189     routedata_insert_temppoints(routedata, e1cands);
04190     g_list_free(e1cands);
04191     e1cands = NULL;
04192   }
04193   
04194   if(noe2 || !check_triangle_interior_capacity(t, v2, v, e1, e, e2)) {
04195 #ifdef DEBUG_ROUTE      
04196     printf("freeing e2cands\n");
04197 #endif
04198     routedata_insert_temppoints(routedata, e2cands);
04199     g_list_free(e2cands);
04200     e2cands = NULL;
04201   }
04202 
04203   if(!noe1 && e1constraintv) {
04204     e1cands = g_list_prepend(e1cands, e1constraintv);
04205   }else if(e1constraintv) {
04206     g_hash_table_insert(routedata->alltemppoints, e1constraintv, e1constraintv);  
04207 //    delete_vertex(e1constraintv);
04208   }
04209 
04210   if(!noe2 && e2constraintv) {
04211     e2cands = g_list_prepend(e2cands, e2constraintv);
04212   }else if(e2constraintv) {
04213     g_hash_table_insert(routedata->alltemppoints, e2constraintv, e2constraintv);  
04214 //    delete_vertex(e2constraintv);
04215   }
04216   
04217   if(!noe1 && !noe2) return g_list_concat(rval, g_list_concat(e1cands, e2cands));
04218 
04219   return g_list_concat(e1cands, e2cands);
04220 }
04221 
04222 GList *
04223 compute_candidate_points(toporouter_t *tr, toporouter_layer_t *l, toporouter_vertex_t *curpoint, toporouter_route_t *data,
04224     toporouter_vertex_t **closestdest) 
04225 {
04226   GList *r = NULL, *j;
04227   toporouter_edge_t *edge = curpoint->routingedge, *tempedge;
04228   
04229   if(vertex_keepout_test(tr, curpoint)) goto compute_candidate_points_finish;
04230  
04231   /* direct connection */
04232 //  if(curpoint == TOPOROUTER_VERTEX(data->src->point))
04233   if((tempedge = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(curpoint), GTS_VERTEX(*closestdest))))) {
04234     
04235     if(TOPOROUTER_IS_CONSTRAINT(tempedge)) {
04236       goto compute_candidate_points_finish;
04237     }else{
04238       if(!tempedge->routing) {
04239         r = g_list_prepend(NULL, *closestdest);
04240         tempedge->flags |= EDGE_FLAG_DIRECTCONNECTION;
04241         goto compute_candidate_points_finish;
04242       }else{
04243 #ifdef DEBUG_ROUTE    
04244         printf("Direct connection, but has routing\n");
04245 #endif    
04246       }
04247 
04248     }
04249     /* if we get to here, there is routing blocking the direct connection,
04250      * continue as per normal */
04251   } 
04252   
04253   /* a real point origin */
04254   if(!(curpoint->flags & VERTEX_FLAG_TEMP)) {
04255     GSList *triangles, *i;
04256     i = triangles = gts_vertex_triangles(GTS_VERTEX(curpoint), NULL);
04257 #ifdef DEBUG_ROUTE    
04258     printf("triangle count = %d\n", g_slist_length(triangles));
04259 #endif    
04260     while(i) {
04261       GtsTriangle *t = GTS_TRIANGLE(i->data);
04262       GList *temppoints;
04263 
04264       if(tr->flags & TOPOROUTER_FLAG_LEASTINVALID) temppoints = triangle_all_candidate_points_from_vertex(t, curpoint, data);
04265       else temppoints = triangle_candidate_points_from_vertex(t, curpoint, *closestdest, data);
04266 
04267 #ifdef DEBUG_ROUTE     
04268       printf("\treturned %d points\n", g_list_length(temppoints));
04269 #endif      
04270       routedata_insert_temppoints(data, temppoints);
04271 
04272       r = g_list_concat(r, temppoints);
04273       i = i->next;
04274     }
04275     g_slist_free(triangles);
04276   }else /* a temp point */ {
04277     int prevwind = vertex_wind(GTS_SEGMENT(edge)->v1, GTS_SEGMENT(edge)->v2, GTS_VERTEX(curpoint->parent));
04278 //    printf("tempoint\n");
04279     
04280     GSList *i = GTS_EDGE(edge)->triangles;
04281 
04282     while(i) {
04283       GtsVertex *oppv =  gts_triangle_vertex_opposite(GTS_TRIANGLE(i->data), GTS_EDGE(edge));
04284       if(prevwind != vertex_wind(GTS_SEGMENT(edge)->v1, GTS_SEGMENT(edge)->v2, oppv)) {
04285         GList *temppoints;
04286         
04287         if(tr->flags & TOPOROUTER_FLAG_LEASTINVALID) temppoints = triangle_all_candidate_points_from_edge(tr, GTS_TRIANGLE(i->data), edge,
04288             data, closestdest, curpoint);
04289         else temppoints = triangle_candidate_points_from_edge(tr, GTS_TRIANGLE(i->data), edge, curpoint, closestdest, data);
04290 
04291         j = temppoints;
04292         while(j) {
04293           toporouter_vertex_t *tempj = TOPOROUTER_VERTEX(j->data);
04294           if(tempj->flags & VERTEX_FLAG_TEMP) 
04295             g_hash_table_insert(data->alltemppoints, j->data, j->data); 
04296 #ifdef DEBUG_ROUTE          
04297           else 
04298             printf("got cand not a temp\n");
04299 #endif
04300           j = j->next;
04301         }
04302         r = g_list_concat(r, temppoints);
04303         
04304         break;
04305       }
04306       i = i->next;
04307     }
04308   }
04309 
04310 compute_candidate_points_finish:
04311 
04312   if(vertex_bbox(curpoint) && vertex_bbox(curpoint)->cluster) {
04313     if(vertex_bbox(curpoint)->cluster->c == data->src->c) {
04314       r = g_list_concat(r, g_list_copy(data->srcvertices));
04315     }
04316   }
04317 
04318   return r;
04319 }
04320 
04321 gboolean 
04322 temp_point_clean(gpointer key, gpointer value, gpointer user_data)
04323 {
04324   toporouter_vertex_t *tv = TOPOROUTER_VERTEX(value);
04325   if(tv->flags & VERTEX_FLAG_TEMP) {
04326     if(TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) 
04327       TOPOROUTER_CONSTRAINT(tv->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(tv->routingedge)->routing, tv);
04328     else
04329       tv->routingedge->routing = g_list_remove(tv->routingedge->routing, tv);
04330     gts_object_destroy ( GTS_OBJECT(tv) );
04331   }
04332   return TRUE;
04333 }
04334 
04335 void
04336 clean_routing_edges(toporouter_t *r, toporouter_route_t *data)
04337 {
04338   g_hash_table_foreach_remove(data->alltemppoints, temp_point_clean, NULL);
04339   g_hash_table_destroy(data->alltemppoints);  
04340   data->alltemppoints = NULL;
04341 }
04342 
04343 gdouble
04344 path_score(toporouter_t *r, GList *path)
04345 {
04346   gdouble score = 0.;
04347   toporouter_vertex_t *pv = NULL;
04348   toporouter_vertex_t *v0 = NULL;
04349 
04350   if(!path) return INFINITY;
04351 
04352   v0 = TOPOROUTER_VERTEX(path->data);
04353 
04354   while(path) {
04355     toporouter_vertex_t *v = TOPOROUTER_VERTEX(path->data);
04356 
04357     if(pv) {
04358       score += gts_point_distance(GTS_POINT(pv), GTS_POINT(v));
04359       if(pv != v0 && vz(pv) != vz(v)) 
04360         if(path->next)
04361           score += r->viacost;
04362 
04363     }
04364 
04365     pv = v;
04366     path = path->next;
04367   }
04368 
04369   return score;
04370 }
04371 
04372 void
04373 print_vertices(GList *vertices)
04374 {
04375   while(vertices) {
04376     toporouter_vertex_t *v = TOPOROUTER_VERTEX(vertices->data);
04377     print_vertex(v);
04378     print_bbox(vertex_bbox(v));
04379     if(vertex_bbox(v)) {
04380       printf("has bbox\n");
04381       if(vertex_bbox(v)->cluster) 
04382         printf("has cluster\n");
04383       else
04384         printf("no cluster\n");
04385     }else printf("no bbox\n");
04386     vertices = vertices->next;
04387   }
04388 }
04389 
04390 gint       
04391 space_edge(gpointer item, gpointer data)
04392 {
04393   toporouter_edge_t *e = TOPOROUTER_EDGE(item);
04394   GList *i;
04395   gdouble *forces;
04396 
04397   if(TOPOROUTER_IS_CONSTRAINT(e)) return 0;
04398 
04399   if(!edge_routing(e) || !g_list_length(edge_routing(e))) return 0;
04400 
04401   forces = (gdouble *)malloc(sizeof(double) * g_list_length(edge_routing(e)));
04402   
04403   for(guint j=0;j<100;j++) {
04404     guint k=0;
04405     guint equilibrium = 1;
04406 
04407     i = edge_routing(e);
04408     while(i) {
04409       toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 
04410       gdouble ms, d;
04411 
04412       if(i->prev) {
04413 //        ms = min_net_net_spacing(TOPOROUTER_VERTEX(i->prev->data), v);
04414         ms = min_spacing(TOPOROUTER_VERTEX(i->prev->data), v);
04415         d = gts_point_distance(GTS_POINT(i->prev->data), GTS_POINT(v));
04416       }else{
04417 //        ms = min_vertex_net_spacing(v, tedge_v1(e));
04418         ms = min_spacing(v, tedge_v1(e));
04419         d = gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(v));
04420       }
04421 
04422       if(d < ms) forces[k] = ms - d;
04423       else forces[k] = 0.;
04424 
04425       if(i->next) {
04426 //        ms = min_net_net_spacing(TOPOROUTER_VERTEX(i->next->data), v);
04427         ms = min_spacing(TOPOROUTER_VERTEX(i->next->data), v);
04428         d = gts_point_distance(GTS_POINT(i->next->data), GTS_POINT(v));
04429       }else{
04430 //        ms = min_vertex_net_spacing(v, tedge_v2(e));
04431         ms = min_spacing(v, tedge_v2(e));
04432         d = gts_point_distance(GTS_POINT(edge_v2(e)), GTS_POINT(v));
04433       }
04434 
04435       if(d < ms) forces[k] += d - ms;
04436 
04437       k++; i = i->next;
04438     }
04439     
04440     k = 0;
04441     i = edge_routing(e);
04442     while(i) {
04443       toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 
04444       if(forces[k] > EPSILON || forces[k] < -EPSILON) equilibrium = 0;
04445       vertex_move_towards_vertex_values(GTS_VERTEX(v), edge_v2(e), forces[k] * 0.1, &(GTS_POINT(v)->x), &(GTS_POINT(v)->y));
04446       k++; i = i->next;
04447     }
04448 
04449     if(equilibrium) {
04450 //      printf("reached equilibriium at %d\n", j);
04451       break;
04452     }
04453 
04454   }
04455 
04456   free(forces);
04457   return 0;  
04458 }
04459 
04460 void
04461 swap_vertices(toporouter_vertex_t **v1, toporouter_vertex_t **v2)
04462 {
04463   toporouter_vertex_t *tempv = *v1;
04464   *v1 = *v2;
04465   *v2 = tempv;
04466 }
04467 
04468 void
04469 split_edge_routing(toporouter_vertex_t *v, GList **l1, GList **l2)
04470 {
04471   GList *base, *i;
04472 
04473   g_assert(v);
04474   g_assert(v->routingedge);
04475   
04476   base = g_list_find(vrouting(v), v);
04477 
04478   *l1 = g_list_prepend(*l1, tedge_v1(v->routingedge));
04479   *l2 = g_list_prepend(*l2, tedge_v2(v->routingedge));
04480   
04481   g_assert(base);
04482 
04483   i = base->next;
04484   while(i) {
04485     if(!(TOPOROUTER_VERTEX(i->data)->flags & VERTEX_FLAG_TEMP)) *l2 = g_list_prepend(*l2, i->data);
04486     i = i->next;
04487   }
04488 
04489   i = base->prev;
04490   while(i) {
04491     if(!(TOPOROUTER_VERTEX(i->data)->flags & VERTEX_FLAG_TEMP)) *l1 = g_list_prepend(*l1, i->data);
04492     i = i->prev;
04493   }
04494 }
04495 
04496 GList *
04497 vertices_routing_conflicts(toporouter_vertex_t *v, toporouter_vertex_t *pv)
04498 {
04499   toporouter_edge_t *e;
04500   GList *rval = NULL, *l1 = NULL, *l2 = NULL, *i;
04501 
04502   if(vz(v) != vz(pv)) return NULL;
04503   g_assert(v != pv);
04504 
04505   if(!v->routingedge && !pv->routingedge) {
04506     e = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(v), GTS_VERTEX(pv)));
04507     if(!e) return NULL;
04508     i = edge_routing(e);
04509     while(i) {
04510       rval = g_list_prepend(rval, TOPOROUTER_VERTEX(i->data)->route);
04511       i = i->next;
04512     }
04513     return rval;
04514   }
04515 
04516   if(TOPOROUTER_IS_CONSTRAINT(v->routingedge) && TOPOROUTER_IS_CONSTRAINT(pv->routingedge))
04517     return NULL;
04518 
04519   if(TOPOROUTER_IS_CONSTRAINT(pv->routingedge)) swap_vertices(&pv, &v);
04520 
04521   if(!v->routingedge) swap_vertices(&pv, &v);
04522 
04523   e = v->routingedge;
04524 
04525   split_edge_routing(v, &l1, &l2);
04526   g_assert(l2);
04527   g_assert(l1);
04528 
04529   if(!pv->routingedge) {
04530     toporouter_edge_t *e1, *e2;
04531     e1 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(pv), edge_v1(e)));
04532     e2 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(pv), edge_v2(e)));
04533    
04534     l1 = g_list_concat(l1, g_list_copy(edge_routing(e1)));
04535     l2 = g_list_concat(l2, g_list_copy(edge_routing(e2)));
04536 
04537   }else{
04538     GList *pvlist1 = NULL, *pvlist2 = NULL;
04539     toporouter_vertex_t *commonv = route_vertices_common_vertex(v, pv);
04540 
04541     g_assert(commonv);
04542 
04543     split_edge_routing(pv, &pvlist1, &pvlist2);
04544 
04545     if(commonv == tedge_v1(e)) {
04546       toporouter_edge_t *ope;
04547 
04548       if(commonv == tedge_v1(pv->routingedge)) {
04549         l1 = g_list_concat(l1, pvlist1);
04550         l2 = g_list_concat(l2, pvlist2);
04551         ope = TOPOROUTER_EDGE(gts_vertices_are_connected(edge_v2(e), edge_v2(pv->routingedge)));
04552       }else{
04553         l1 = g_list_concat(l1, pvlist2);
04554         l2 = g_list_concat(l2, pvlist1);
04555         ope = TOPOROUTER_EDGE(gts_vertices_are_connected(edge_v2(e), edge_v1(pv->routingedge)));
04556       }
04557       g_assert(ope);
04558       l2 = g_list_concat(l2, g_list_copy(edge_routing(ope)));
04559 
04560     }else{
04561       toporouter_edge_t *ope;
04562       if(commonv == tedge_v1(pv->routingedge)) {
04563         l1 = g_list_concat(l1, pvlist2);
04564         l2 = g_list_concat(l2, pvlist1);
04565         ope = TOPOROUTER_EDGE(gts_vertices_are_connected(edge_v1(e), edge_v2(pv->routingedge)));
04566       }else{
04567         l1 = g_list_concat(l1, pvlist1);
04568         l2 = g_list_concat(l2, pvlist2);
04569         ope = TOPOROUTER_EDGE(gts_vertices_are_connected(edge_v1(e), edge_v1(pv->routingedge)));
04570       }
04571       g_assert(ope);
04572       l1 = g_list_concat(l1, g_list_copy(edge_routing(ope)));
04573     }
04574   }
04575 
04576   i = l1;
04577   while(i) {
04578     toporouter_vertex_t *curv = TOPOROUTER_VERTEX(i->data);
04579 
04580     if(curv->flags & VERTEX_FLAG_ROUTE && (g_list_find(l2, curv->parent) || g_list_find(l2, curv->child))) {
04581       if(!g_list_find(rval, curv->route)) rval = g_list_prepend(rval, curv->route);
04582     }
04583     i = i->next;
04584   }
04585   i = l2;
04586   while(i) {
04587     toporouter_vertex_t *curv = TOPOROUTER_VERTEX(i->data);
04588 
04589     if(curv->flags & VERTEX_FLAG_ROUTE && (g_list_find(l1, curv->parent) || g_list_find(l1, curv->child))) {
04590       if(!g_list_find(rval, curv->route)) rval = g_list_prepend(rval, curv->route);
04591     }
04592     i = i->next;
04593   }
04594 
04595   g_list_free(l1);
04596   g_list_free(l2);
04597 
04598   return rval;
04599 }
04600 
04601 gdouble
04602 vertices_routing_conflict_cost(toporouter_t *r, toporouter_vertex_t *v, toporouter_vertex_t *pv, guint *n) 
04603 {
04604   GList *conflicts = vertices_routing_conflicts(v, pv), *i;
04605   gdouble penalty = 0.;
04606 
04607   i = conflicts;
04608   while(i) {
04609     (*n) += 1;
04610     penalty += TOPOROUTER_ROUTE(i->data)->score;
04611     i = i->next;
04612   }
04613   g_list_free(conflicts);
04614 //  if(penalty > 0.) printf("conflict penalty of %f with %f,%f %f,%f\n", penalty, vx(v), vy(v), vx(pv), vy(pv));
04615   return penalty;
04616 }
04617 
04618 gdouble
04619 gcost(toporouter_t *r, toporouter_route_t *data, toporouter_vertex_t *srcv, toporouter_vertex_t *v, toporouter_vertex_t *pv, guint *n,
04620     toporouter_netlist_t *pair)
04621 {
04622   gdouble cost = 0., segcost;
04623   
04624   *n = pv->gn;
04625 
04626   if(g_list_find(data->srcvertices, v)) return 0.; 
04627   
04628   segcost = tvdistance(pv, v);
04629 
04630   if(pair && !TOPOROUTER_IS_CONSTRAINT(v->routingedge) && v->routingedge) {
04631     GList *list = g_list_find(v->routingedge->routing, v);
04632     toporouter_vertex_t *pv = edge_routing_prev_not_temp(v->routingedge, list); 
04633     toporouter_vertex_t *nv = edge_routing_next_not_temp(v->routingedge, list); 
04634 
04635     if(pv->route && pv->route->netlist == pair) {
04636     }else if(nv->route && nv->route->netlist == pair) {
04637     }else{
04638       segcost *= 10.;
04639     }
04640   }
04641 
04642   cost = pv->gcost + segcost;
04643 
04644   if(r->flags & TOPOROUTER_FLAG_LEASTINVALID) {
04645     gdouble conflictcost = 0.;
04646     
04647     if(pv && v != pv && vz(v) == vz(pv)) conflictcost = vertices_routing_conflict_cost(r, v, pv, n);
04648     
04649     if(!(r->flags & TOPOROUTER_FLAG_DETOUR && *n == 1)) {
04650       cost += conflictcost * (pow(*n,2));
04651     }
04652   }
04653 
04654   return cost;
04655 }
04656 
04657 #define vlayer(x) (&r->layers[(int)vz(x)])
04658 
04659 guint
04660 candidate_is_available(toporouter_vertex_t *pv, toporouter_vertex_t *v)
04661 {
04662   // TODO: still needed?  
04663   while(pv) {
04664     if(pv == v) return 0;
04665     pv = pv->parent;
04666   }
04667 
04668   return 1;
04669 }
04670 
04671 GList *
04672 route(toporouter_t *r, toporouter_route_t *data, guint debug)
04673 {
04674   GtsEHeap *openlist = gts_eheap_new(route_heap_cmp, NULL);
04675   GList *closelist = NULL;
04676   GList *i, *rval = NULL;
04677   toporouter_netlist_t *pair = NULL;
04678   gint count = 0;
04679 
04680   toporouter_vertex_t *srcv = NULL, *destv = NULL, *curpoint = NULL;
04681   toporouter_layer_t *cur_layer; //, *dest_layer;
04682 
04683   g_assert(data->src->c != data->dest->c);
04684   
04685   if(data->destvertices) g_list_free(data->destvertices);
04686   if(data->srcvertices) g_list_free(data->srcvertices);
04687   
04688   data->destvertices = cluster_vertices(r, data->dest);
04689   data->srcvertices = cluster_vertices(r, data->src);
04690 
04691   closest_cluster_pair(r, data->srcvertices, data->destvertices, &curpoint, &destv);
04692 
04693   if(!curpoint || !destv) goto routing_return;
04694 
04695   srcv = curpoint;
04696   cur_layer = vlayer(curpoint);
04697   //dest_layer = vlayer(destv);
04698 
04699   data->path = NULL; 
04700   
04701   data->alltemppoints = g_hash_table_new(g_direct_hash, g_direct_equal);
04702 
04703   curpoint->parent = NULL;
04704   curpoint->child = NULL;
04705   curpoint->gcost = 0.;
04706   curpoint->gn = 0;
04707   curpoint->hcost = simple_h_cost(r, curpoint, destv);
04708  
04709   if(data->netlist && data->netlist->pair) {
04710     GList *i = r->routednets;
04711     while(i) {
04712       toporouter_route_t *curroute = TOPOROUTER_ROUTE(i->data);
04713       if(curroute->netlist == data->netlist->pair) {
04714         pair = data->netlist->pair;
04715         break;
04716       }
04717       i = i->next;
04718     }
04719   }
04720 
04721   gts_eheap_insert(openlist, curpoint);
04722   
04723   while(gts_eheap_size(openlist) > 0) {
04724     GList *candidatepoints;
04725     data->curpoint = curpoint;
04726     //draw_route_status(r, closelist, openlist, curpoint, data, count++);
04727 
04728     curpoint = TOPOROUTER_VERTEX( gts_eheap_remove_top(openlist, NULL) );
04729     if(curpoint->parent && !(curpoint->flags & VERTEX_FLAG_TEMP)) {
04730       if(vz(curpoint) != vz(destv)) {
04731         toporouter_vertex_t *tempv;
04732         cur_layer = vlayer(curpoint);//&r->layers[(int)vz(curpoint)];
04733         tempv = closest_dest_vertex(r, curpoint, data);
04734         if(tempv) {
04735           destv = tempv;
04736           //dest_layer = vlayer(destv);//&r->layers[(int)vz(destv)];
04737 
04738         }
04739       }
04740     }
04741    
04742 //    destpoint = closest_dest_vertex(r, curpoint, data);
04743 //    dest_layer = &r->layers[(int)vz(destpoint)];
04744     
04745     if(g_list_find(data->destvertices, curpoint)) {
04746       toporouter_vertex_t *temppoint = curpoint;
04747       srcv = NULL;
04748       destv = curpoint;
04749 
04750       data->path = NULL;
04751 
04752       while(temppoint) {
04753         data->path = g_list_prepend(data->path, temppoint);   
04754         if(g_list_find(data->srcvertices, temppoint)) {
04755           srcv = temppoint;
04756           if(r->flags & TOPOROUTER_FLAG_AFTERORDER) break;
04757         }
04758         temppoint = temppoint->parent;
04759       }
04760       rval = data->path;
04761       data->score = path_score(r, data->path);
04762 #ifdef DEBUG_ROUTE
04763       printf("ROUTE: path score = %f computation cost = %d\n", data->score, count);
04764 #endif
04765 
04766       if(srcv->bbox->cluster != data->src) {
04767         data->src = srcv->bbox->cluster;
04768       }
04769 
04770       if(destv->bbox->cluster != data->dest) {
04771         data->dest = destv->bbox->cluster;
04772       }
04773       goto route_finish;
04774     }
04775     closelist_insert(curpoint);
04776 #ifdef DEBUG_ROUTE
04777     printf("\n\n\n*** ROUTE COUNT = %d\n", count);
04778 #endif
04779     candidatepoints = compute_candidate_points(r, cur_layer, curpoint, data, &destv);
04780 
04781 //#ifdef DEBUG_ROUTE    
04782     /*********************
04783     if(debug && !strcmp(data->dest->netlist, "  unnamed_net2")) 
04784     {
04785       unsigned int mask = ~(VERTEX_FLAG_RED | VERTEX_FLAG_GREEN | VERTEX_FLAG_BLUE); 
04786       char buffer[256];
04787       int j;
04788 
04789       for(j=0;j<groupcount();j++) {
04790         i = r->layers[j].vertices;
04791         while(i) {
04792           TOPOROUTER_VERTEX(i->data)->flags &= mask;
04793           i = i->next;
04794         }
04795       }
04796       
04797       i = candidatepoints;
04798       while(i) {
04799         TOPOROUTER_VERTEX(i->data)->flags |= VERTEX_FLAG_GREEN;
04800 //        printf("flagged a candpoint @ %f,%f\n",
04801 //            vx(i->data), vy(i->data));
04802         i = i->next;
04803       }
04804       
04805       curpoint->flags |= VERTEX_FLAG_BLUE;
04806       if(curpoint->parent) 
04807         curpoint->parent->flags |= VERTEX_FLAG_RED;
04808 
04809 
04810       for(j=0;j<groupcount();j++) {
04811         GList *datas = g_list_prepend(NULL, data);
04812         sprintf(buffer, "route-%d-%05d.png", j, count);
04813         toporouter_draw_surface(r, r->layers[j].surface, buffer, 1024, 1024, 2, datas, j, candidatepoints);
04814         g_list_free(datas);
04815       }
04816     }
04817 //#endif    
04818     *********************/
04819     count++;
04820 //    if(count > 100) exit(0);
04821     i = candidatepoints;
04822     while(i) {
04823       toporouter_vertex_t *temppoint = TOPOROUTER_VERTEX(i->data);
04824       if(!g_list_find(closelist, temppoint) && candidate_is_available(curpoint, temppoint)) { //&& temppoint != curpoint) {
04825         toporouter_heap_search_data_t heap_search_data = { temppoint, NULL };
04826 
04827         guint temp_gn;
04828         gdouble temp_g_cost = gcost(r, data, srcv, temppoint, curpoint, &temp_gn, pair);
04829       
04830 
04831         gts_eheap_foreach(openlist,toporouter_heap_search, &heap_search_data);
04832 
04833         if(heap_search_data.result) {
04834           if(temp_g_cost < temppoint->gcost) {
04835             
04836             temppoint->gcost = temp_g_cost;
04837             temppoint->gn = temp_gn; 
04838             
04839             temppoint->parent = curpoint;
04840             curpoint->child = temppoint;
04841             
04842             gts_eheap_update(openlist);
04843           }
04844         }else{
04845           temppoint->parent = curpoint;
04846           curpoint->child = temppoint;
04847           
04848           temppoint->gcost = temp_g_cost;
04849           temppoint->gn = temp_gn;
04850 
04851           temppoint->hcost = simple_h_cost(r, temppoint, destv);
04852 //          if(cur_layer != dest_layer) temppoint->hcost += r->viacost;
04853           gts_eheap_insert(openlist, temppoint);
04854         }
04855       
04856       }
04857       i = i->next;
04858     }
04859     g_list_free(candidatepoints);
04860 
04861   }
04862 #ifdef DEBUG_ROUTE  
04863   printf("ROUTE: could not find path!\n");
04864 #endif 
04865 
04866   data->score = INFINITY;
04867   clean_routing_edges(r, data); 
04868 
04869   data->path = NULL;
04870   //TOPOROUTER_VERTEX(data->src->point)->parent = NULL;
04871   //TOPOROUTER_VERTEX(data->src->point)->child  = NULL;
04872   goto routing_return;
04873 
04874 /* 
04875   {
04876     int i;
04877     for(i=0;i<groupcount();i++) {
04878       char buffer[256];
04879       sprintf(buffer, "route-error-%d-%d.png", r->routecount, i);
04880       toporouter_draw_surface(r, r->layers[i].surface, buffer, 1280, 1280, 2, data, i, NULL);
04881     }
04882     r->routecount++;
04883   }
04884 //  exit(0);
04885 */
04886 route_finish:
04887 //  printf(" * finished a*\n");
04888 /* 
04889   {
04890     int i;
04891     for(i=0;i<groupcount();i++) {
04892       char buffer[256];
04893       sprintf(buffer, "route-preclean-%d-%d.png", i, r->routecount);
04894       toporouter_draw_surface(r, r->layers[i].surface, buffer, 1024, 1024, 2, data, i, NULL);
04895     }
04896     r->routecount++;
04897   }
04898 */
04899 /*  {
04900     i = data->path;
04901     while(i) {
04902       toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
04903       
04904       if(tv->routingedge) {
04905         GList *list = g_list_find(edge_routing(tv->routingedge), tv);
04906         toporouter_vertex_t *restartv = NULL, *boxpoint;
04907 
04908         g_assert(list);
04909 
04910         if(!list->next) {
04911           if(vertex_bbox(tedge_v2(tv->routingedge))) 
04912             boxpoint = TOPOROUTER_VERTEX(vertex_bbox(tedge_v2(tv->routingedge))->point);
04913           else
04914             boxpoint = NULL;
04915 
04916           if(tedge_v2(tv->routingedge) != srcv && g_list_find(data->srcvertices, tedge_v2(tv->routingedge))) 
04917             restartv = tedge_v2(tv->routingedge);
04918           else if(boxpoint != srcv && g_list_find(data->srcvertices, boxpoint)) 
04919             restartv = boxpoint;
04920         }
04921         
04922         if(!list->prev) {
04923           if(vertex_bbox(tedge_v1(tv->routingedge))) 
04924             boxpoint = TOPOROUTER_VERTEX(vertex_bbox(tedge_v1(tv->routingedge))->point);
04925           else
04926             boxpoint = NULL;
04927 
04928           if(tedge_v1(tv->routingedge) != srcv && g_list_find(data->srcvertices, tedge_v1(tv->routingedge))) 
04929             restartv = tedge_v1(tv->routingedge);
04930           else if(boxpoint != srcv && g_list_find(data->srcvertices, boxpoint)) 
04931             restartv = boxpoint;
04932           
04933         }
04934 
04935         if(restartv) {
04936           clean_routing_edges(r, data); 
04937           gts_eheap_destroy(openlist);     
04938           g_list_free(closelist);
04939           openlist = gts_eheap_new(route_heap_cmp, NULL);
04940           closelist = NULL;
04941           g_list_free(data->path);
04942           printf("ROUTING RESTARTING with new src %f,%f,%f\n", vx(restartv), vy(restartv), vz(restartv));
04943           curpoint = restartv;
04944           goto route_begin;
04945         }
04946       }
04947       
04948       i = i->next;
04949     }
04950   }*/
04952   {
04953     toporouter_vertex_t *pv = NULL;
04954     GList *i = data->path;
04955     while(i) {
04956       toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
04957       
04958       if(pv && g_list_find(data->srcvertices, tv)) {
04959         GList *temp = g_list_copy(i);
04960         g_list_free(data->path);
04961         data->path = temp;
04962         i = data->path;
04963       }
04964       pv = tv;
04965       i = i->next;
04966     }
04967   }
04968 //*/
04969   {
04970     toporouter_vertex_t *pv = NULL;
04971     GList *i = data->path;
04972     while(i) {
04973       toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
04974       if(tv->flags & VERTEX_FLAG_TEMP) { 
04975         tv->flags ^= VERTEX_FLAG_TEMP;
04976         tv->flags |= VERTEX_FLAG_ROUTE;
04977       }
04978       if(pv) pv->child = tv;
04979 
04980       if(tv->routingedge) tv->route = data;
04981 
04982 //      if(tv->routingedge && !TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) space_edge(tv->routingedge, NULL);
04983 
04984       pv = tv;
04985       i = i->next;
04986     }
04987   }
04988  
04989   {
04990     toporouter_vertex_t *pv = NULL, *v = NULL;
04991 
04992     GList *i = data->path;
04993     while(i) {
04994       v = TOPOROUTER_VERTEX(i->data);
04995 
04996       if(pv) {
04997         v->parent = pv;
04998         pv->child = v;
04999       }else{
05000         v->parent = NULL;
05001       }
05002 
05003       pv = v;
05004       i = i->next;
05005     }
05006 
05007     if(v) v->child = NULL;
05008   }
05009 
05010   clean_routing_edges(r, data); 
05011 // /* 
05012   {
05013     GList *i = data->path;
05014     while(i) {
05015       toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
05016 
05017       if(v->routingedge && !TOPOROUTER_IS_CONSTRAINT(v->routingedge))
05018         space_edge(v->routingedge, NULL);
05019       i = i->next;
05020     }
05021   }
05022 //  */
05023 routing_return:
05024 
05025   g_list_free(data->destvertices);
05026   g_list_free(data->srcvertices);
05027   data->destvertices = NULL;
05028   data->srcvertices = NULL;
05029   gts_eheap_destroy(openlist);     
05030   g_list_free(closelist);
05031 
05032   data->alltemppoints = NULL;
05033 
05034   return rval;
05035 }
05036 
05037 /* moves vertex v d units in the direction of vertex p */
05038 void
05039 vertex_move_towards_vertex (GtsVertex *v,
05040                             GtsVertex *p,
05041                             double d)
05042 {
05043   double theta = atan2 (GTS_POINT(p)->y - GTS_POINT(v)->y,
05044                         GTS_POINT(p)->x - GTS_POINT(v)->x);
05045 
05046   GTS_POINT(v)->x += d * cos (theta);
05047   GTS_POINT(v)->y += d * sin (theta);
05048 }
05049 
05050 
05051 gdouble
05052 pathvertex_arcing_through_constraint(toporouter_vertex_t *pathv, toporouter_vertex_t *arcv)
05053 {
05054   toporouter_vertex_t *v = pathv->child;
05055 
05056   if(!v || !v->routingedge) return 0.;
05057 
05058   while(v->flags & VERTEX_FLAG_ROUTE && (tedge_v1(v->routingedge) == arcv || tedge_v2(v->routingedge) == arcv)) {
05059     if(TOPOROUTER_IS_CONSTRAINT(v->routingedge)) 
05060       return gts_point_distance(GTS_POINT(tedge_v1(v->routingedge)), GTS_POINT(tedge_v2(v->routingedge)));
05061     v = v->child;
05062   }
05063 
05064   v = pathv->parent;
05065   while(v->flags & VERTEX_FLAG_ROUTE && (tedge_v1(v->routingedge) == arcv || tedge_v2(v->routingedge) == arcv)) {
05066     if(TOPOROUTER_IS_CONSTRAINT(v->routingedge)) 
05067       return gts_point_distance(GTS_POINT(tedge_v1(v->routingedge)), GTS_POINT(tedge_v2(v->routingedge)));
05068     v = v->parent;
05069   }
05070 
05071   return 0.;
05072 }
05073 
05074 gint
05075 vertices_connected(toporouter_vertex_t *a, toporouter_vertex_t *b)
05076 {
05077   return ((a->route->netlist == b->route->netlist && a->route->src->c == b->route->src->c) ? 1 : 0);
05078 }
05079 
05080 gdouble
05081 edge_min_spacing(GList *list, toporouter_edge_t *e, toporouter_vertex_t *v, guint debug) 
05082 {
05083   toporouter_vertex_t *origin;
05084   GList *i = list;
05085   gdouble space = 0.;
05086   toporouter_vertex_t *nextv, *prevv;
05087   //toporouter_vertex_t *edgev;
05088   //gdouble constraint_spacing;
05089 
05090   if(!list) return INFINITY;
05091  
05092 //  printf("\t CMS %f,%f - %f,%f\n", vx(tedge_v1(e)), vy(tedge_v1(e)), vx(tedge_v2(e)), vy(tedge_v2(e)));
05093  
05094   prevv = origin = TOPOROUTER_VERTEX(list->data);
05095 
05096 //  print_edge(e);
05097 
05098   i = list;
05099   if(gts_point_distance2(GTS_POINT(origin), GTS_POINT(edge_v1(e))) < gts_point_distance2(GTS_POINT(v), GTS_POINT(edge_v1(e)))) {
05100 
05101     /* towards v2 */
05102     while(i) {
05103       nextv = edge_routing_next(e, i);
05104       if(nextv->route && vertices_connected(nextv, prevv)) { i = i->next; continue; }
05105       if(!(nextv->flags & VERTEX_FLAG_TEMP)) {
05106         gdouble ms = min_spacing(prevv, nextv);
05107           if(nextv == tedge_v2(e)) {
05108             gdouble cms = pathvertex_arcing_through_constraint(TOPOROUTER_VERTEX(i->data), tedge_v2(e));
05109 //          printf("\t CMS to %f,%f = %f \t ms = %f\n", vx(tedge_v2(e)), vy(tedge_v2(e)), cms, ms);
05110 //          if(vx(tedge_v2(e)) > -EPSILON && vx(tedge_v2(e)) < EPSILON) {
05111 //            printf("\t\tPROB: ");
05112 //            print_vertex(tedge_v2(e));
05113 //          }
05114             if(cms > EPSILON) space += MIN(ms, cms / 2.);
05115             else space += ms;
05116           } else 
05117           space += ms;
05118 
05119         prevv = nextv;
05120       }
05121 //      printf("%f ", space);
05122       i = i->next;
05123     }
05124   }else{
05125 
05126     /* towards v1 */
05127     while(i) {
05128       nextv = edge_routing_prev(e, i);
05129       if(nextv->route &&  vertices_connected(nextv, prevv)) { i = i->prev; continue; }
05130       if(!(nextv->flags & VERTEX_FLAG_TEMP)) {
05131         gdouble ms = min_spacing(prevv, nextv);
05132           if(nextv == tedge_v1(e)) {
05133             gdouble cms = pathvertex_arcing_through_constraint(TOPOROUTER_VERTEX(i->data), tedge_v1(e));
05134 //          printf("\t CMS to %f,%f = %f \t ms = %f\n", vx(tedge_v1(e)), vy(tedge_v1(e)), cms, ms);
05135 //          if(vx(tedge_v1(e)) > -EPSILON && vx(tedge_v1(e)) < EPSILON) {
05136 //            printf("\t\tPROB: ");
05137 //            print_vertex(tedge_v1(e));
05138 //          }
05139             if(cms > EPSILON) space += MIN(ms, cms / 2.);
05140             else space += ms;
05141           } else 
05142           space += ms;
05143 
05144         prevv = nextv;
05145       }
05146 //      printf("%f ", space);
05147       i = i->prev;
05148     }
05149   }
05150 
05151   if(TOPOROUTER_IS_CONSTRAINT(e) && space > gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e))) / 2.)
05152     space = gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e))) / 2.;
05153   
05154 //  if(debug) printf("\tedge_min_spacing: %f\n", space);
05155   return space;
05156 }
05157 
05158 /* line segment is 1 & 2, point is 3 
05159    returns 0 if v3 is outside seg
05160 */
05161 guint
05162 vertex_line_normal_intersection(gdouble x1, gdouble y1, gdouble x2, gdouble y2, gdouble x3, gdouble y3, gdouble *x, gdouble *y)
05163 {
05164   gdouble m1 = cartesian_gradient(x1,y1,x2,y2);
05165   gdouble m2 = perpendicular_gradient(m1);
05166   gdouble c2 = (isinf(m2)) ? x3 : y3 - (m2 * x3);
05167   gdouble c1 = (isinf(m1)) ? x1 : y1 - (m1 * x1);
05168 
05169   if(isinf(m2))
05170     *x = x3;
05171   else if(isinf(m1))
05172     *x = x1;
05173   else
05174     *x = (c2 - c1) / (m1 - m2);
05175 
05176   *y = (isinf(m2)) ? y1 : (m2 * (*x)) + c2;
05177 
05178   if(*x >= MIN(x1,x2) - EPSILON && *x <= MAX(x1,x2) + EPSILON && *y >= MIN(y1,y2) - EPSILON && *y <= MAX(y1,y2) + EPSILON) 
05179     return 1;
05180   return 0;
05181 }
05182 
05183 void
05184 print_toporouter_arc(toporouter_arc_t *arc)
05185 {
05186 //  GList *i = arc->vs;
05187 
05188   printf("ARC CENTRE: %f,%f ", vx(arc->centre), vy(arc->centre));// print_vertex(arc->centre);
05189   printf("RADIUS: %f", arc->r);
05190 
05191   if(arc->dir>0) printf(" COUNTERCLOCKWISE ");
05192   else if(arc->dir<0) printf(" CLOCKWISE ");
05193   else printf(" COLINEAR(ERROR) ");
05194 /*  
05195   printf("\n\tVS: ");
05196 
05197   while(i) {
05198     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
05199     printf("%f,%f ", vx(v), vy(v));
05200 
05201     i = i->next;
05202   }
05203 */
05204 }
05205   
05206 void
05207 toporouter_arc_remove(toporouter_oproute_t *oproute, toporouter_arc_t *arc)
05208 {
05209   oproute->arcs = g_list_remove(oproute->arcs, arc);
05210 
05211   if(arc->v) arc->v->arc = NULL;
05212 }
05213 
05214 toporouter_arc_t *
05215 toporouter_arc_new(toporouter_oproute_t *oproute, toporouter_vertex_t *v1, toporouter_vertex_t *v2, toporouter_vertex_t *centre, gdouble r, gint dir)
05216 {
05217   toporouter_arc_t *arc = TOPOROUTER_ARC(gts_object_new(GTS_OBJECT_CLASS(toporouter_arc_class())));
05218   arc->centre = centre;
05219   arc->v = v1;
05220   arc->v1 = v1;
05221   arc->v2 = v2;
05222   arc->r = r;
05223   arc->dir = dir;
05224 
05225   if(v1) v1->arc = arc;
05226   arc->oproute = oproute;
05227 
05228   arc->clearance = NULL;
05229 
05230   return arc;
05231 }
05232 
05233 void
05234 path_set_oproute(GList *path, toporouter_oproute_t *oproute)
05235 {
05236   while(path) {
05237     toporouter_vertex_t *v = TOPOROUTER_VERTEX(path->data);
05238 
05239     if(v->flags & VERTEX_FLAG_ROUTE) 
05240       v->oproute = oproute;
05241 
05242     path = path->next;
05243   }
05244 }
05245 
05246 void
05247 print_oproute(toporouter_oproute_t *oproute)
05248 {
05249   GList *i = oproute->arcs;
05250 
05251   printf("Optimized Route:\n");
05252   printf("\tNetlist:\t\t%s\n\tStyle:\t\t%s\n", oproute->netlist, oproute->style);
05253  // printf("%s\n", oproute->netlist);
05254 /*
05255   i = oproute->term1->zlink;
05256   while(i) {
05257     toporouter_vertex_t *thisv = TOPOROUTER_VERTEX(i->data);
05258     printf("\tNetlist:\t\t%s\n\tStyle:\t\t%s\n", vertex_bbox(thisv)->netlist, vertex_bbox(thisv)->style);
05259     i = i->next;
05260   }
05261 */
05262   printf("\t"); print_vertex(oproute->term1); printf("\n");
05263   i = oproute->arcs;
05264   while(i) {
05265     toporouter_arc_t *arc = (toporouter_arc_t *)i->data;
05266     printf("\t"); print_toporouter_arc(arc); printf("\n");
05267     i = i->next;
05268   }
05269   printf("\t"); print_vertex(oproute->term2); printf("\n");
05270 }
05271 
05272 gdouble
05273 export_pcb_drawline(guint layer, guint x0, guint y0, guint x1, guint y1, guint thickness, guint keepaway) 
05274 {
05275   gdouble d = 0.;
05276   LineType *line;
05277   line = CreateDrawnLineOnLayer( LAYER_PTR(layer), x0, y0, x1, y1, 
05278       thickness, keepaway, 
05279       MakeFlags (AUTOFLAG | (TEST_FLAG (CLEARNEWFLAG, PCB) ? CLEARLINEFLAG : 0)));
05280 
05281   if(line) {
05282     AddObjectToCreateUndoList (LINE_TYPE, LAYER_PTR(layer), line, line);
05283     d = hypot(x0 - x1, y0 - y1);
05284   }
05285   return d;
05286 }
05287 
05288 gdouble
05289 arc_angle(toporouter_arc_t *arc) 
05290 {
05291   gdouble x0, x1, y0, y1;
05292 
05293   x0 = arc->x0 - vx(arc->centre);
05294   x1 = arc->x1 - vx(arc->centre);
05295   y0 = arc->y0 - vy(arc->centre);
05296   y1 = arc->y1 - vy(arc->centre);
05297 
05298   return fabs(acos(((x0*x1)+(y0*y1))/(hypot(x0,y0)*hypot(x1,y1))));
05299 }
05300 
05301 gdouble
05302 export_pcb_drawarc(guint layer, toporouter_arc_t *a, guint thickness, guint keepaway) 
05303 {
05304   gdouble sa, da, theta;
05305   gdouble d = 0.;
05306   ArcType *arc;
05307   gint wind;
05308 
05309   wind = coord_wind(a->x0, a->y0, a->x1, a->y1, vx(a->centre), vy(a->centre));
05310 
05311   /* NB: PCB's arcs have a funny coorindate system, with 0 degrees as the -ve X axis (left),
05312    *     continuing clockwise, with +90 degrees being along the +ve Y axis (bottom). Because
05313    *     Y+ points down, our internal angles increase clockwise from the +ve X axis.
05314    */
05315   sa = (M_PI - coord_angle (vx (a->centre), vy (a->centre), a->x0, a->y0)) * 180. / M_PI;
05316 
05317   theta = arc_angle(a);
05318 
05319   if(!a->dir || !wind) return 0.;
05320   
05321   if(a->dir != wind) theta = 2. * M_PI - theta;
05322   
05323   da = -a->dir * theta * 180. / M_PI;
05324 
05325   if(da < 1. && da > -1.) return 0.;
05326   if(da > 359. || da < -359.) return 0.;
05327 
05328   arc = CreateNewArcOnLayer(LAYER_PTR(layer), vx(a->centre), vy(a->centre), a->r, a->r,
05329     sa, da, thickness, keepaway, 
05330     MakeFlags( AUTOFLAG | (TEST_FLAG (CLEARNEWFLAG, PCB) ? CLEARLINEFLAG : 0)));
05331 
05332   if(arc) {
05333     AddObjectToCreateUndoList( ARC_TYPE, LAYER_PTR(layer), arc, arc);
05334     d = a->r * theta;
05335   }
05336   
05337   return d;
05338 }
05339 
05340 void
05341 calculate_term_to_arc(toporouter_vertex_t *v, toporouter_arc_t *arc, guint dir)
05342 {
05343   gdouble theta, a, b, bx, by, a0x, a0y, a1x, a1y;
05344   gint winddir;
05345 
05346   theta = acos(arc->r / gts_point_distance(GTS_POINT(v), GTS_POINT(arc->centre)));
05347   a = arc->r * sin(theta);
05348   b = arc->r * cos(theta);
05349 #ifdef DEBUG_EXPORT
05350   printf("drawing arc with r %f theta %f d %f centre = %f,%f\n", arc->r, theta, gts_point_distance(GTS_POINT(v), GTS_POINT(arc->centre)), vx(arc->centre), vy(arc->centre));
05351 #endif
05352   point_from_point_to_point(arc->centre, v, b, &bx, &by);
05353 
05354   coords_on_line(bx, by, perpendicular_gradient(point_gradient(GTS_POINT(v), GTS_POINT(arc->centre))), a, &a0x, &a0y, &a1x, &a1y);
05355 
05356   winddir = coord_wind(vx(v), vy(v), a0x, a0y, vx(arc->centre), vy(arc->centre));
05357 
05358   if(!winddir) {
05359     printf("!winddir @ v %f,%f arc->centre %f,%f\n", vx(v), vy(v), vx(arc->centre), vy(arc->centre));
05360     //TODO: fix hack: this shouldn't happen
05361     arc->x0 = vx(v);
05362     arc->y0 = vy(v);
05363     arc->x1 = vx(v);
05364     arc->y1 = vy(v);
05365     return;
05366   }
05367 
05368   g_assert(winddir);
05369 
05370   if(dir) winddir = -winddir;
05371 
05372   if(winddir == arc->dir) {
05373     if(!dir) { arc->x0 = a0x; arc->y0 = a0y; }
05374     else{ arc->x1 = a0x; arc->y1 = a0y; }
05375   }else{
05376     if(!dir) { arc->x0 = a1x; arc->y0 = a1y; }
05377     else{ arc->x1 = a1x; arc->y1 = a1y; }
05378   }
05379 
05380 }
05381 
05382 
05383 
05390 void
05391 arc_ortho_projections(toporouter_arc_t *arc, toporouter_arc_t *narc, gdouble *b1, gdouble *b2)
05392 {
05393   gdouble nax, nay, ax, ay, alen, c;
05394   gdouble b1x, b1y, b2x, b2y;
05395 
05396 #ifdef DEBUG_EXPORT
05397   printf("arc c = %f,%f narc c = %f,%f arc->0 = %f,%f\n", 
05398       vx(arc->centre), vy(arc->centre),
05399       vx(narc->centre), vy(narc->centre),
05400       arc->x0, arc->y0);
05401 #endif
05402 
05403   nax = vx(narc->centre) - vx(arc->centre);
05404   nay = vy(narc->centre) - vy(arc->centre);
05405   alen = hypot(nax, nay);
05406 
05407 
05408   ax = arc->x0 - vx(arc->centre);
05409   ay = arc->y0 - vy(arc->centre);
05410 
05411 #ifdef DEBUG_EXPORT
05412   printf("norm narc = %f,%f - %f\tA=%f,%f\n", nax, nay, alen, ax, ay);
05413 #endif
05414 
05415   c = ((ax*nax)+(ay*nay)) / (alen*alen);
05416 
05417   b1x = c * nax;
05418   b1y = c * nay;
05419   b2x = ax - b1x;
05420   b2y = ay - b1y;
05421 
05422 #ifdef DEBUG_EXPORT
05423   printf("proj = %f,%f perp proj = %f,%f\n", b1x, b1y, b2x, b2y);
05424 #endif
05425 
05426   *b1 = hypot(b1x,b1y);
05427   *b2 = hypot(b2x,b2y);
05428 
05429 }
05430 
05431 guint
05432 calculate_arc_to_arc(toporouter_t *ar, toporouter_arc_t *parc, toporouter_arc_t *arc)
05433 {
05434   gdouble theta, a, b, bx, by, a0x, a0y, a1x, a1y, m, preva, prevb;
05435   gint winddir;
05436   toporouter_arc_t *bigr, *smallr;
05437 
05438   if(parc->r > arc->r) {
05439     bigr = parc; smallr = arc;
05440   }else{
05441     bigr = arc; smallr = parc;
05442   }
05443 #ifdef DEBUG_EXPORT    
05444   printf("bigr centre = %f,%f smallr centre = %f,%f\n", vx(bigr->centre), vy(bigr->centre), 
05445       vx(smallr->centre), vy(smallr->centre));
05446 #endif
05447 
05448   m = perpendicular_gradient(point_gradient(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)));
05449 
05450   if(bigr->centre == smallr->centre) {
05451 
05452     printf("bigr->centre == smallr->centre @ %f,%f\n", vx(smallr->centre), vy(smallr->centre));
05453   }
05454 
05455   g_assert(bigr->centre != smallr->centre);
05456 
05457   if(parc->dir == arc->dir) {
05458 //export_arc_straight:
05459 
05460     theta = acos((bigr->r - smallr->r) / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)));
05461     a = bigr->r * sin(theta);
05462     b = bigr->r * cos(theta);
05463 
05464     point_from_point_to_point(bigr->centre, smallr->centre, b, &bx, &by);
05465 
05466     coords_on_line(bx, by, m, a, &a0x, &a0y, &a1x, &a1y);
05467 
05468     winddir = coord_wind(vx(smallr->centre), vy(smallr->centre), a0x, a0y, vx(bigr->centre), vy(bigr->centre));
05469     
05470     arc_ortho_projections(parc, arc, &prevb, &preva);
05471 //#ifdef DEBUG_EXPORT    
05472     if(!winddir) {
05473 
05474       printf("STRAIGHT:\n");
05475       printf("bigr centre = %f,%f smallr centre = %f,%f\n", vx(bigr->centre), vy(bigr->centre), 
05476           vx(smallr->centre), vy(smallr->centre));
05477       printf("theta = %f a = %f b = %f bigrr = %f d = %f po = %f\n", theta, a, b, bigr->r,
05478           gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)),
05479           bigr->r / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)));
05480       printf("bigr-r = %f smallr-r = %f ratio = %f\n",
05481           bigr->r, smallr->r, (bigr->r - smallr->r) / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)));
05482       printf("preva = %f prevb = %f\n\n", preva, prevb);
05483     
05484     }
05485 //#endif
05486     g_assert(winddir);
05487 
05488     if(bigr==parc) winddir = -winddir;
05489 
05490     if(winddir == bigr->dir) {
05491       if(bigr==arc) {
05492         bigr->x0 = a0x; 
05493         bigr->y0 = a0y;
05494       }else{
05495         bigr->x1 = a0x; 
05496         bigr->y1 = a0y;
05497       }
05498     }else{
05499       if(bigr==arc) {
05500         bigr->x0 = a1x; 
05501         bigr->y0 = a1y;
05502       }else{
05503         bigr->x1 = a1x; 
05504         bigr->y1 = a1y;
05505       }
05506     }
05507 
05508     a = smallr->r * sin(theta);
05509     b = smallr->r * cos(theta);
05510 
05511 #ifdef DEBUG_EXPORT   
05512     printf("a = %f b = %f\n", a, b);
05513 #endif    
05514     point_from_point_to_point(smallr->centre, bigr->centre, -b, &bx, &by);
05515 
05516     coords_on_line(bx, by, m, a, &a0x, &a0y, &a1x, &a1y);
05517 
05518     if(winddir == bigr->dir) {
05519       if(bigr==arc) {
05520         smallr->x1 = a0x; 
05521         smallr->y1 = a0y;
05522       }else{
05523         smallr->x0 = a0x; 
05524         smallr->y0 = a0y;
05525       }
05526     }else{
05527       if(bigr==arc) {
05528         smallr->x1 = a1x; 
05529         smallr->y1 = a1y;
05530       }else{
05531         smallr->x0 = a1x; 
05532         smallr->y0 = a1y;
05533       }
05534     }
05535 
05536   }else{
05537 
05538 //export_arc_twist:    
05539 
05540     theta = acos((bigr->r + smallr->r) / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)));
05541     a = bigr->r * sin(theta);
05542     b = bigr->r * cos(theta);
05543 
05544     point_from_point_to_point(bigr->centre, smallr->centre, b, &bx, &by);
05545 
05546     coords_on_line(bx, by, m, a, &a0x, &a0y, &a1x, &a1y);
05547 
05548     winddir = coord_wind(vx(smallr->centre), vy(smallr->centre), a0x, a0y, vx(bigr->centre), vy(bigr->centre));
05549 //#ifdef DEBUG_EXPORT   
05550   if(!winddir) {
05551     printf("TWIST:\n");
05552     printf("theta = %f a = %f b = %f r = %f d = %f po = %f\n", theta, a, b, bigr->r + smallr->r,
05553         gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)),
05554         (bigr->r+smallr->r) / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)));
05555 
05556     printf("bigr centre = %f,%f smallr centre = %f,%f\n\n", vx(bigr->centre), vy(bigr->centre), 
05557         vx(smallr->centre), vy(smallr->centre));
05558   
05559     printf("big wind = %d small wind = %d\n", bigr->dir, smallr->dir);
05560     return 1;
05561   }
05562 //#endif      
05563 /*    if(!winddir) {
05564       smallr->centre->flags |= VERTEX_FLAG_RED;
05565       bigr->centre->flags |= VERTEX_FLAG_GREEN;
05566       //bigr->centre->flags |= VERTEX_FLAG_RED;
05567       {
05568         int i;
05569         for(i=0;i<groupcount();i++) {
05570           char buffer[256];
05571           sprintf(buffer, "wind%d.png", i);
05572           toporouter_draw_surface(ar, ar->layers[i].surface, buffer, 2096, 2096, 2, NULL, i, NULL);
05573         }
05574       }
05575       return; 
05576     }
05577 */
05578     g_assert(winddir);
05579 
05580     if(bigr==parc) winddir = -winddir;
05581 
05582     if(winddir == bigr->dir) {
05583       if(bigr==arc) {
05584         bigr->x0 = a0x; 
05585         bigr->y0 = a0y;
05586       }else{
05587         bigr->x1 = a0x; 
05588         bigr->y1 = a0y;
05589       }
05590     }else{
05591       if(bigr==arc) {
05592         bigr->x0 = a1x; 
05593         bigr->y0 = a1y;
05594       }else{
05595         bigr->x1 = a1x; 
05596         bigr->y1 = a1y;
05597       }
05598     }
05599 
05600     a = smallr->r * sin(theta);
05601     b = smallr->r * cos(theta);
05602 
05603     point_from_point_to_point(smallr->centre, bigr->centre, b, &bx, &by);
05604 
05605     coords_on_line(bx, by, m, a, &a0x, &a0y, &a1x, &a1y);
05606     
05607     winddir = coord_wind(vx(smallr->centre), vy(smallr->centre), a0x, a0y, vx(bigr->centre), vy(bigr->centre));
05608 
05609     g_assert(winddir);
05610 
05611     if(bigr==parc) winddir = -winddir;
05612 
05613     if(winddir == smallr->dir) {
05614       if(bigr==arc) {
05615         smallr->x1 = a0x; 
05616         smallr->y1 = a0y;
05617       }else{
05618         smallr->x0 = a0x; 
05619         smallr->y0 = a0y;
05620       }
05621     }else{
05622       if(bigr==arc) {
05623         smallr->x1 = a1x; 
05624         smallr->y1 = a1y;
05625       }else{
05626         smallr->x0 = a1x; 
05627         smallr->y0 = a1y;
05628       }
05629     }
05630 
05631   }
05632 
05633   return 0;
05634 }
05635 
05636 void
05637 export_oproutes(toporouter_t *ar, toporouter_oproute_t *oproute)
05638 {
05639   guint layer = PCB->LayerGroups.Entries[oproute->layergroup][0];   
05640   guint thickness = lookup_thickness(oproute->style);
05641   guint keepaway = lookup_keepaway(oproute->style);
05642   GList *arcs = oproute->arcs;
05643   toporouter_arc_t *arc, *parc = NULL;
05644 
05645   if(!arcs) {
05646     ar->wiring_score += export_pcb_drawline(layer, vx(oproute->term1), vy(oproute->term1), vx(oproute->term2), vy(oproute->term2), thickness, keepaway);
05647     return;
05648   }
05649 
05650 
05651 //  calculate_term_to_arc(oproute->term1, TOPOROUTER_ARC(arcs->data), 0, layer);
05652 
05653   while(arcs) {
05654     arc = TOPOROUTER_ARC(arcs->data);
05655 
05656     if(parc && arc) {
05657       ar->wiring_score += export_pcb_drawarc(layer, parc, thickness, keepaway);
05658       ar->wiring_score += export_pcb_drawline(layer, parc->x1, parc->y1, arc->x0, arc->y0, thickness, keepaway);
05659     }else if(!parc) {
05660       ar->wiring_score += export_pcb_drawline(layer, vx(oproute->term1), vy(oproute->term1), arc->x0, arc->y0, thickness, keepaway);
05661     }
05662 
05663     parc = arc;
05664     arcs = arcs->next;
05665   }
05666   ar->wiring_score += export_pcb_drawarc(layer, arc, thickness, keepaway);
05667   ar->wiring_score += export_pcb_drawline(layer, arc->x1, arc->y1, vx(oproute->term2), vy(oproute->term2), thickness, keepaway);
05668 
05669 }
05670 
05671 
05672 
05673 void
05674 oproute_free(toporouter_oproute_t *oproute)
05675 {
05676   GList *i = oproute->arcs;
05677   while(i) {
05678     toporouter_arc_t *arc = (toporouter_arc_t *) i->data;
05679     if(arc->centre->flags & VERTEX_FLAG_TEMP) 
05680       gts_object_destroy(GTS_OBJECT(arc->centre));
05681 
05682     i = i->next;
05683   }
05684 
05685   g_list_free(oproute->arcs);
05686   free(oproute);
05687 }
05688 
05689 void
05690 oproute_calculate_tof(toporouter_oproute_t *oproute)
05691 {
05692   GList *arcs = oproute->arcs;
05693   toporouter_arc_t *parc = NULL, *arc;
05694 
05695   oproute->tof = 0.;
05696 
05697   if(!arcs) {
05698     oproute->tof = gts_point_distance(GTS_POINT(oproute->term1), GTS_POINT(oproute->term2));
05699     return;
05700   }
05701 
05702   while(arcs) {
05703     arc = TOPOROUTER_ARC(arcs->data);
05704 
05705     if(parc && arc) {
05706       oproute->tof += arc_angle(parc) * parc->r;
05707       oproute->tof += hypot(parc->x1-arc->x0,parc->y1-arc->y0);
05708     }else if(!parc) {
05709       oproute->tof += hypot(arc->x0-vx(oproute->term1), arc->y0-vy(oproute->term1));
05710     }
05711 
05712     parc = arc;
05713     arcs = arcs->next;
05714   }
05715 
05716   oproute->tof += arc_angle(parc) * parc->r;
05717   oproute->tof += hypot(arc->x1-vx(oproute->term2), arc->y1-vy(oproute->term2));
05718 
05719 }
05720 
05721 gdouble
05722 line_line_distance_at_normal(
05723     gdouble line1_x1, gdouble line1_y1,
05724     gdouble line1_x2, gdouble line1_y2,
05725     gdouble line2_x1, gdouble line2_y1,
05726     gdouble line2_x2, gdouble line2_y2,
05727     gdouble x, gdouble y)
05728 {
05729   gdouble m1 = perpendicular_gradient(cartesian_gradient(line1_x1, line1_y1, line1_x2, line1_y2));
05730   gdouble m2 = cartesian_gradient(line2_x1, line2_y1, line2_x2, line2_y2);
05731   gdouble c1 = (isinf(m1)) ? x : y - (m1 * x);
05732   gdouble c2 = (isinf(m2)) ? line2_x1 : line2_y1 - (m2 * line2_x1);
05733 
05734   gdouble intx, inty;
05735 
05736   if(isinf(m2)) intx = line2_x1;
05737   else if(isinf(m1)) intx = x;
05738   else intx = (c2 - c1) / (m1 - m2);
05739 
05740   inty = (isinf(m2)) ? (m1 * intx) + c1 : (m2 * intx) + c2;
05741 
05742   return hypot(x-intx,y-inty);
05743 }
05744 
05745 void
05746 calculate_serpintine(gdouble delta, gdouble r, gdouble initiala, gdouble *a, guint *nhalfcycles)
05747 {
05748   gdouble lhalfcycle = 2.*(initiala-r)+(M_PI*r);
05749   guint n;
05750 
05751   printf("lhalfcycle = %f r = %f\n", lhalfcycle, r);
05752 
05753   n = (delta - M_PI*r) / (lhalfcycle - 2.*r) + 1;
05754   *a = (delta + 4.*n*r - n*M_PI*r + 4.*r - M_PI*r)/(2.*n);
05755   *nhalfcycles = n;
05756 }
05757 
05758 gdouble
05759 oproute_min_spacing(toporouter_oproute_t *a, toporouter_oproute_t *b)
05760 {
05761   return lookup_thickness(a->style) / 2. + lookup_thickness(b->style) / 2. + MAX(lookup_keepaway(a->style), lookup_keepaway(b->style));
05762 }
05763 
05764 gdouble
05765 vector_angle(gdouble ox, gdouble oy, gdouble ax, gdouble ay, gdouble bx, gdouble by)
05766 {
05767   gdouble alen = hypot(ax-ox,ay-oy);
05768   gdouble blen = hypot(bx-ox,by-oy);
05769   return acos( ((ax-ox)*(bx-ox)+(ay-oy)*(by-oy)) / (alen * blen) ); 
05770 }
05771 
05772 toporouter_serpintine_t *
05773 toporouter_serpintine_new(gdouble x, gdouble y, gdouble x0, gdouble y0, gdouble x1, gdouble y1, gpointer start, gdouble halfa, gdouble
05774     radius, guint nhalfcycles)
05775 {
05776   toporouter_serpintine_t *serp = (toporouter_serpintine_t *)malloc(sizeof(toporouter_serpintine_t));
05777   serp->x = x;
05778   serp->y = y;
05779   serp->x0 = x0;
05780   serp->y0 = y0;
05781   serp->x1 = x1;
05782   serp->y1 = y1;
05783   serp->start = start;
05784   serp->halfa = halfa;
05785   serp->radius = radius;
05786   serp->nhalfcycles = nhalfcycles;
05787   serp->arcs = NULL;
05788   return serp;
05789 }
05790 
05791 //#define DEBUG_RUBBERBAND 1
05792 
05793 gdouble
05794 check_non_intersect_vertex(gdouble x0, gdouble y0, gdouble x1, gdouble y1, toporouter_vertex_t *pathv, toporouter_vertex_t *arcv,
05795     toporouter_vertex_t *opv, gint wind, gint *arcwind, gdouble *arcr, guint debug)
05796 {
05797   gdouble ms, line_int_x, line_int_y, x, y, d = 0., m;
05798   gdouble tx0, ty0, tx1, ty1;
05799   gint wind1, wind2;
05800 
05801   g_assert(pathv->routingedge);
05802 
05803   if(TOPOROUTER_IS_CONSTRAINT(pathv->routingedge)) { 
05804     gdouble d = tvdistance(tedge_v1(pathv->routingedge), tedge_v2(pathv->routingedge)) / 2.;
05805     ms = min_spacing(pathv, arcv);
05806     if(ms > d) ms = d;
05807   }else{
05808     ms = edge_min_spacing(g_list_find(edge_routing(pathv->routingedge), pathv), pathv->routingedge, arcv, debug);
05809   }
05810 
05811 
05812   if(!vertex_line_normal_intersection(x0, y0, x1, y1, vx(arcv), vy(arcv), &line_int_x, &line_int_y)) {
05813 
05814     if(hypot(x0 - line_int_x, y0 - line_int_y) < hypot(x1 - line_int_x, y1 - line_int_y)) 
05815     { line_int_x = x0; line_int_y = y0; }else{ line_int_x = x1; line_int_y = y1; }
05816 
05817     m = perpendicular_gradient(cartesian_gradient(vx(arcv), vy(arcv), line_int_x, line_int_y));
05818   }else{
05819     m = cartesian_gradient(x0, y0, x1, y1);
05820   }
05821 
05822   coords_on_line(vx(arcv), vy(arcv), m, MIL_TO_COORD (1.), &tx0, &ty0, &tx1, &ty1);
05823 
05824   wind1 = coord_wind(tx0, ty0, tx1, ty1, line_int_x, line_int_y);
05825   wind2 = coord_wind(tx0, ty0, tx1, ty1, vx(opv), vy(opv)); 
05826 
05827   if(!wind2 || wind1 == wind2) return -1.; 
05828 
05829   if(!wind) {
05830     coords_on_line(line_int_x, line_int_y, perpendicular_gradient(m), ms, &tx0, &ty0, &tx1, &ty1);
05831     if(hypot(tx0 - vx(opv), ty0 - vy(opv)) < hypot(tx1 - vx(opv), ty1 - vy(opv))) 
05832     { x = tx0; y = ty0; }else{ x = tx1; y = ty1; }
05833   }else{
05834     toporouter_vertex_t *parent = pathv->parent, *child = pathv->child;
05835     guint windtests = 0;
05836 
05837     d = hypot(vx(arcv) - line_int_x, vy(arcv) - line_int_y);
05838     coord_move_towards_coord_values(line_int_x, line_int_y, vx(arcv), vy(arcv), ms + d, &x, &y);
05839 rewind_test:    
05840     wind1 = coord_wind(line_int_x, line_int_y, x, y, vx(parent), vy(parent));
05841     wind2 = coord_wind(line_int_x, line_int_y, x, y, vx(child), vy(child));
05842     if(wind1 && wind2 && wind1 == wind2) {
05843 //      return -1.;
05844       if(windtests++ == 2) return -1.;
05845 
05846       if(parent->flags & VERTEX_FLAG_ROUTE) parent = parent->parent;
05847       if(child->flags & VERTEX_FLAG_ROUTE) child = child->child;
05848       goto rewind_test;
05849     }
05850   }
05851 
05852 
05853   *arcr = ms;
05854   *arcwind = tvertex_wind(pathv->parent, pathv, arcv);
05855 
05856 #ifdef DEBUG_RUBBERBAND
05857 //if(debug) 
05858 //  printf("non-int check %f,%f ms %f d %f arcv %f,%f opv %f,%f\n", vx(arcv), vy(arcv), ms, d + ms,
05859 //    vx(arcv), vy(arcv), vx(opv), vy(opv));
05860 #endif
05861 
05862   return d + ms;
05863 }
05864 
05865 gdouble
05866 check_intersect_vertex(gdouble x0, gdouble y0, gdouble x1, gdouble y1, toporouter_vertex_t *pathv, toporouter_vertex_t *arcv,
05867     toporouter_vertex_t *opv, gint wind, gint *arcwind, gdouble *arcr, guint debug)
05868 {
05869   gdouble ms, line_int_x, line_int_y, x, y, d = 0.;
05870 
05871   if(TOPOROUTER_IS_CONSTRAINT(pathv->routingedge)) {
05872     gdouble d = tvdistance(tedge_v1(pathv->routingedge), tedge_v2(pathv->routingedge)) / 2.;
05873     ms = min_spacing(pathv, arcv);
05874     if(ms > d) ms = d;
05875   }else {
05876     ms = edge_min_spacing(g_list_find(edge_routing(pathv->routingedge), pathv), pathv->routingedge, arcv, debug);
05877   }
05878 
05879   if(!vertex_line_normal_intersection(x0, y0, x1, y1, vx(arcv), vy(arcv), &line_int_x, &line_int_y)) 
05880     return -1.; 
05881 
05882   d = hypot(line_int_x - vx(arcv), line_int_y - vy(arcv));
05883 
05884 
05885   if(d > ms - EPSILON) 
05886     return -1.;
05887 
05888   coord_move_towards_coord_values(vx(arcv), vy(arcv), line_int_x, line_int_y, ms, &x, &y);
05889   
05890   *arcr = ms;
05891   *arcwind = tvertex_wind(pathv->parent, pathv, arcv);
05892 //  *arcwind = coord_wind(x0, y0, x, y, x1, y1);
05893 #ifdef DEBUG_RUBBERBAND
05894 //if(debug) 
05895 //  printf("int check %f,%f ms %f d %f arcv %f,%f opv %f,%f\n", vx(arcv), vy(arcv), ms, ms - d,
05896 //    vx(arcv), vy(arcv), vx(opv), vy(opv));
05897 #endif
05898 
05899   return ms - d;
05900 }
05901 
05905 guint
05906 check_arc_for_loops(gpointer t1, toporouter_arc_t *arc, gpointer t2)
05907 {
05908   gdouble x0, y0, x1, y1;
05909 
05910   if(TOPOROUTER_IS_VERTEX(t1)) { x0 = vx(TOPOROUTER_VERTEX(t1)); y0 = vy(TOPOROUTER_VERTEX(t1)); }
05911   else { x0 = TOPOROUTER_ARC(t1)->x1; y0 = TOPOROUTER_ARC(t1)->y1; }
05912 
05913   if(TOPOROUTER_IS_VERTEX(t2)) { x1 = vx(TOPOROUTER_VERTEX(t2)); y1 = vy(TOPOROUTER_VERTEX(t2)); }
05914   else { x1 = TOPOROUTER_ARC(t2)->x0; y1 = TOPOROUTER_ARC(t2)->y0; }
05915 
05916   if(coord_intersect_prop(x0, y0, arc->x0, arc->y0, arc->x1, arc->y1, x1, y1) ) {
05917 //  || 
05918 //   (arc->x0 > arc->x1 - EPSILON && arc->x0 < arc->x1 + EPSILON &&
05919 //     arc->y0 > arc->y1 - EPSILON && arc->y0 < arc->y1 + EPSILON)
05920 //    ) {
05921 #ifdef DEBUG_RUBBERBAND
05922     printf("LOOPS %f %f -> %f %f & %f %f -> %f %f\n", x0, y0, arc->x0, arc->y0, arc->x1, arc->y1, x1, y1);
05923 #endif
05924     return 1;
05925   }
05926   return 0;
05927 }
05928 
05929 toporouter_rubberband_arc_t *
05930 new_rubberband_arc(toporouter_vertex_t *pathv, toporouter_vertex_t *arcv, gdouble r, gdouble d, gint wind, GList *list)
05931 {
05932   toporouter_rubberband_arc_t *rba = (toporouter_rubberband_arc_t *)malloc(sizeof(toporouter_rubberband_arc_t));
05933   rba->pathv = pathv;
05934   rba->arcv = arcv;
05935   rba->r = r;
05936   rba->d = d;
05937   rba->wind = wind;
05938   rba->list = list;
05939   return rba;
05940 }
05941 
05942 gint
05943 compare_rubberband_arcs(toporouter_rubberband_arc_t *a, toporouter_rubberband_arc_t *b)
05944 { return b->d - a->d; }
05945 
05946 void
05947 free_list_elements(gpointer data, gpointer user_data)
05948 { free(data); }
05949 
05950 
05951 /* returns the edge opposite v from the triangle facing (x,y), or NULL if v is colinear with an edge between v and a neighbor */
05952 /*
05953 GtsEdge *
05954 vertex_edge_facing_vertex(GtsVertex *v, gdouble x, gdouble y)
05955 {
05956   GSList *ts = gts_vertex_triangles(GTS_VERTEX(n), NULL);
05957   GSList *i = ts;
05958 
05959   while(i) {
05960     GtsTriangle *t = GTS_TRIANGLE(i->data);
05961     GtsEdge *e = gts_triangle_edge_opposite(t, v);
05962 
05963     if(coord_wind(vx(edge_v1(e)), vy(edge_v1(e)), vx(v), vy(v), x, y) == vertex_wind(edge_v1(e), v, edge_v2(e)) && 
05964        coord_wind(vx(edge_v2(e)), vy(edge_v2(e)), vx(v), vy(v), x, y) == vertex_wind(edge_v2(e), v, edge_v1(e))
05965        ) {
05966      g_slist_free(ts);
05967      return e;
05968     }
05969 
05970     i = i->next;
05971   }
05972 
05973   g_slist_free(ts);
05974   return NULL;
05975 }
05976 */
05977 
05978 gdouble 
05979 check_adj_pushing_vertex(toporouter_oproute_t *oproute, gdouble x0, gdouble y0, gdouble x1, gdouble y1, toporouter_vertex_t *v, gdouble *arcr, gint *arcwind, toporouter_vertex_t **arc) 
05980 {
05981   GSList *ns = gts_vertex_neighbors(GTS_VERTEX(v), NULL, NULL);
05982   GSList *i = ns;
05983   gdouble maxd = 0.;
05984 
05985   while(i) {
05986     toporouter_vertex_t *n = TOPOROUTER_VERTEX(i->data);
05987     gdouble segintx, seginty;
05988     if(vertex_line_normal_intersection(x0, y0, x1, y1, vx(n), vy(n), &segintx, &seginty)) {
05989       toporouter_edge_t *e = tedge(n, v);
05990       gdouble ms = 0., d = hypot(segintx - vx(n), seginty - vy(n));
05991       //toporouter_vertex_t *a;
05992       toporouter_vertex_t *b;
05993       GList *closestnet = NULL;
05994 
05995       g_assert(e);
05996 
05997       if(v == tedge_v1(e)) {
05998         //a = tedge_v1(e);
05999         b = tedge_v2(e);
06000         closestnet = edge_routing(e);
06001       }else{
06002         //a = tedge_v2(e);
06003         b = tedge_v1(e);
06004         closestnet = g_list_last(edge_routing(e));
06005       }
06006 
06007       if(closestnet) {
06008         ms = edge_min_spacing(closestnet, e, b, 0);        
06009         ms += min_oproute_net_spacing(oproute, TOPOROUTER_VERTEX(closestnet->data));
06010       }else{
06011         ms = min_oproute_vertex_spacing(oproute, b);
06012       }
06013 
06014       if(ms - d > maxd) {
06015         *arcr = ms;
06016         *arc = n;
06017         maxd = ms - d;
06018         if(vx(v) == x0 && vy(v) == y0) {
06019           *arcwind = coord_wind(x0, y0, vx(n), vy(n), x1, y1);
06020         }else if(vx(v) == x1 && vy(v) == y1) {
06021           *arcwind = coord_wind(x1, y1, vx(n), vy(n), x0, y0);
06022         }else{
06023           fprintf(stderr, "ERROR: check_adj_pushing_vertex encountered bad vertex v (coordinates don't match)\n");
06024         }
06025       }
06026     }
06027 
06028     i = i->next;
06029   }
06030 
06031   g_slist_free(ns);
06032   return maxd;
06033 }
06034 
06035 
06041 GList *
06042 oproute_rubberband_segment(toporouter_t *r, toporouter_oproute_t *oproute, GList *path, gpointer t1, gpointer t2, guint debug)
06043 {
06044   gdouble x0, y0, x1, y1;
06045   toporouter_vertex_t *v1, *v2, *av1, *av2; /* v{1,2} are the vertex terminals of the segment, or arc terminal centres */
06046   toporouter_arc_t *arc1 = NULL, *arc2 = NULL, *newarc = NULL; /* arc{1,2} are the arc terminals of the segment, if they exist */
06047   GList *i = path;
06048   GList *list1, *list2;
06049 
06050   GList *arcs = NULL;
06051   toporouter_rubberband_arc_t *max = NULL;
06052     
06053   gdouble d, arcr;
06054   gint v1wind, v2wind, arcwind;
06055 
06056   if(TOPOROUTER_IS_VERTEX(t1)) {
06057     v1 = TOPOROUTER_VERTEX(t1);
06058     x0 = vx(v1); y0 = vy(v1);
06059   }else{
06060     g_assert(TOPOROUTER_IS_ARC(t1));
06061     arc1 = TOPOROUTER_ARC(t1);
06062     v1 = TOPOROUTER_VERTEX(arc1->v1);
06063     x0 = arc1->x1;
06064     y0 = arc1->y1;
06065   }
06066 
06067   if(TOPOROUTER_IS_VERTEX(t2)) {
06068     v2 = TOPOROUTER_VERTEX(t2);
06069     x1 = vx(v2); y1 = vy(v2);
06070   }else{
06071     g_assert(TOPOROUTER_IS_ARC(t2));
06072     arc2 = TOPOROUTER_ARC(t2);
06073     v2 = TOPOROUTER_VERTEX(arc2->v2);
06074     x1 = arc2->x0;
06075     y1 = arc2->y0;
06076   }
06077   
06078 #define TEST_AND_INSERT(z) if(d > EPSILON) arcs = g_list_prepend(arcs, new_rubberband_arc(v, z, arcr, d, arcwind, i));
06079 #define ARC_CHECKS(z) (!(arc1 && arc1->centre == z) && !(arc2 && arc2->centre == z) && \
06080   !(TOPOROUTER_IS_VERTEX(t1) && z == v1) && !(TOPOROUTER_IS_VERTEX(t2) && z == v2))    
06081 
06082   if(v1 == v2 || !i->next || TOPOROUTER_VERTEX(i->data) == v2) return NULL;
06083 
06084 //#ifdef DEBUG_RUBBERBAND
06085   if(debug) {
06086     printf("\nRB: line %f,%f %f,%f v1 = %f,%f v2 = %f,%f \n ", x0, y0, x1, y1, vx(v1), vy(v1), vx(v2), vy(v2)); 
06087 //    if(v1->routingedge) print_edge(v1->routingedge);
06088 //    if(v2->routingedge) print_edge(v2->routingedge);
06089 
06090   }
06091 //#endif
06092   
06093   /* check the vectices adjacent to the terminal vectices for push against the segment */
06094 //if(TOPOROUTER_IS_VERTEX(t1)) {
06095 //  toporouter_vertex_t *arcc = NULL;
06096 //  d = check_adj_pushing_vertex(oproute, x0, y0, x1, y1, v1, &arcr, &arcwind, &arcc); 
06097 //  g_assert(arcc != v1);
06098 //  if(ARC_CHECKS(arcc) && d > EPSILON) arcs = g_list_prepend(arcs, new_rubberband_arc(v1, arcc, arcr, d, arcwind, path->next));
06099 //}
06100 //
06101 //if(TOPOROUTER_IS_VERTEX(t2)) {
06102 //  toporouter_vertex_t *arcc = NULL;
06103 //  d = check_adj_pushing_vertex(oproute, x0, y0, x1, y1, v2, &arcr, &arcwind, &arcc);
06104 //  g_assert(arcc != v2);
06105 //  if(ARC_CHECKS(arcc) && d > EPSILON) arcs = g_list_prepend(arcs, new_rubberband_arc(v2, arcc, arcr, d, arcwind, g_list_last(path)->prev));
06106 //}
06107   
06108   i = i->next;
06109   while(i) {
06110     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
06111 
06112     if(v == v2 || v == v1 || !v->routingedge) break;
06113 
06114 #ifdef DEBUG_RUBBERBAND
06115 //  if(debug) 
06116 //  printf("current v %f,%f - edge %f,%f %f,%f\n", vx(v), vy(v),
06117 //    vx(tedge_v1(v->routingedge)), vy(tedge_v1(v->routingedge)),
06118 //    vx(tedge_v2(v->routingedge)), vy(tedge_v2(v->routingedge))
06119 //    );
06120 #endif
06121     g_assert(v->routingedge);
06122    
06123     v1wind = coord_wind(x0, y0, x1, y1, vx(tedge_v1(v->routingedge)), vy(tedge_v1(v->routingedge)));
06124     v2wind = coord_wind(x0, y0, x1, y1, vx(tedge_v2(v->routingedge)), vy(tedge_v2(v->routingedge)));
06125 //    if(debug) printf("\twinds: %d %d\n", v1wind, v2wind);
06126     if(!v1wind && !v2wind) { i = i->next; continue; }
06127 
06128 
06129     if(v1wind && v2wind && v1wind != v2wind) { /* edge is cutting through the current segment */ 
06130       
06131       if(ARC_CHECKS(tedge_v1(v->routingedge)) ){ /* edge v1 is not the centre of an arc terminal */
06132         d = check_intersect_vertex(x0, y0, x1, y1, v, tedge_v1(v->routingedge), tedge_v2(v->routingedge), v1wind, &arcwind, &arcr, debug); 
06133         TEST_AND_INSERT(tedge_v1(v->routingedge));
06134       }
06135 
06136       if(ARC_CHECKS(tedge_v2(v->routingedge)) ){ /* edge v2 is not the centre of an arc terminal */
06137         d = check_intersect_vertex(x0, y0, x1, y1, v, tedge_v2(v->routingedge), tedge_v1(v->routingedge), v2wind, &arcwind, &arcr, debug);  
06138         TEST_AND_INSERT(tedge_v2(v->routingedge));
06139       }
06140     }else{ /* edge is on one side of the segment */
06141       
06142       if(ARC_CHECKS(tedge_v1(v->routingedge)) ){ /* edge v1 is not the centre of an arc terminal */
06143         d = check_non_intersect_vertex(x0, y0, x1, y1, v, tedge_v1(v->routingedge), tedge_v2(v->routingedge), v1wind, &arcwind, &arcr, debug);  
06144         TEST_AND_INSERT(tedge_v1(v->routingedge));
06145       }
06146 
06147       if(ARC_CHECKS(tedge_v2(v->routingedge)) ){ /* edge v2 is not the centre of an arc terminal */
06148         d = check_non_intersect_vertex(x0, y0, x1, y1, v, tedge_v2(v->routingedge), tedge_v1(v->routingedge), v2wind, &arcwind, &arcr, debug);  
06149         TEST_AND_INSERT(tedge_v2(v->routingedge));
06150       }
06151     }
06152 
06153     i = i->next;
06154   }
06155 
06156   arcs = g_list_sort(arcs, (GCompareFunc) compare_rubberband_arcs);
06157 //rubberband_insert_maxarc:
06158   if(!arcs) return NULL;
06159   max = TOPOROUTER_RUBBERBAND_ARC(arcs->data); 
06160   
06161   av2 = max->pathv; i = max->list->next;
06162   while(i) {
06163     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
06164     if(v->routingedge && (tedge_v1(v->routingedge) == max->arcv || tedge_v2(v->routingedge) == max->arcv)) {
06165       av2 = v; i = i->next; continue;
06166     }
06167     break;
06168   }
06169   
06170   av1 = max->pathv; i = max->list->prev;
06171   while(i) {
06172     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
06173     if(v->routingedge && (tedge_v1(v->routingedge) == max->arcv || tedge_v2(v->routingedge) == max->arcv)) {
06174       av1 = v; i = i->prev; continue;
06175     }
06176     break;
06177   }
06178 //#ifdef DEBUG_RUBBERBAND
06179   if(debug) 
06180     printf("newarc @ %f,%f \t v1 = %f,%f v2 = %f,%f r = %f\n", vx(max->arcv), vy(max->arcv), vx(av1), vy(av1), vx(av2), vy(av2), max->r);
06181 //#endif
06182   newarc = toporouter_arc_new(oproute, av1, av2, max->arcv, max->r, max->wind);
06183 
06184   if(TOPOROUTER_IS_VERTEX(t1)) 
06185     calculate_term_to_arc(TOPOROUTER_VERTEX(t1), newarc, 0);
06186   else if(calculate_arc_to_arc(r, TOPOROUTER_ARC(t1), newarc)) { 
06187     printf("\tERROR: best:  r = %f d = %f\n", max->r, max->d); 
06188     printf("\tOPROUTE: %s\n", oproute->netlist);
06189     print_vertex(oproute->term1);
06190     print_vertex(oproute->term2);
06191     return NULL; 
06192   }
06193 
06194   if(TOPOROUTER_IS_VERTEX(t2)) 
06195     calculate_term_to_arc(TOPOROUTER_VERTEX(t2), newarc, 1);
06196   else if(calculate_arc_to_arc(r, newarc, TOPOROUTER_ARC(t2))) { 
06197     printf("\tERROR: best: r = %f d = %f\n", max->r, max->d); 
06198     printf("\tOPROUTE: %s\n", oproute->netlist);
06199     print_vertex(oproute->term1);
06200     print_vertex(oproute->term2);
06201     return NULL; 
06202   }
06203 
06204 //if(check_arc_for_loops(t1, newarc, t2)) {
06205 //  if(arc1 && arc2) calculate_arc_to_arc(r, arc1, arc2);
06206 //  else if(arc1) calculate_term_to_arc(TOPOROUTER_VERTEX(t2), arc1, 1);
06207 //  else if(arc2) calculate_term_to_arc(TOPOROUTER_VERTEX(t1), arc2, 0);
06208 
06209 //#ifdef DEBUG_RUBBERBAND
06210 //  printf("REMOVING NEW ARC @ %f,%f\n", vx(newarc->centre), vy(newarc->centre));
06211 //  //TODO: properly remove newarc
06212 //#endif
06213 
06214 //  arcs = g_list_remove(arcs, max);
06215 //  free(max);
06216 //  goto rubberband_insert_maxarc;
06217 //}
06218 
06219 
06220   list1 = oproute_rubberband_segment(r, oproute, path, t1, newarc, debug);
06221   list2 = oproute_rubberband_segment(r, oproute, i->next, newarc, t2, debug);
06222 
06223   if(list1) {
06224     GList *list = g_list_last(list1);
06225     toporouter_arc_t *testarc = TOPOROUTER_ARC(list->data);
06226     toporouter_arc_t *parc = list->prev ? TOPOROUTER_ARC(list->prev->data) : arc1;
06227     gdouble px = parc ? parc->x1 : vx(TOPOROUTER_VERTEX(t1)), py = parc ? parc->y1 : vy(TOPOROUTER_VERTEX(t1));
06228 
06229     if(coord_intersect_prop(px, py, testarc->x0, testarc->y0, testarc->x1, testarc->y1, newarc->x0, newarc->y0)) {
06230       list1 = g_list_remove(list1, testarc);
06231       if(parc) calculate_arc_to_arc(r, parc, newarc);
06232       else calculate_term_to_arc(TOPOROUTER_VERTEX(t1), newarc, 0);
06233 //#ifdef DEBUG_RUBBERBAND
06234     if(debug)
06235       printf("REMOVING ARC @ %f,%f\n", vx(testarc->centre), vy(testarc->centre));
06236 //#endif
06237     }
06238   }
06239   if(list2) {
06240     toporouter_arc_t *testarc = TOPOROUTER_ARC(list2->data);
06241     toporouter_arc_t *narc = list2->next ? TOPOROUTER_ARC(list2->next->data) : arc2;
06242     gdouble nx = narc ? narc->x0 : vx(TOPOROUTER_VERTEX(t2)), ny = narc ? narc->y0 : vy(TOPOROUTER_VERTEX(t2));
06243 
06244     if(coord_intersect_prop(newarc->x1, newarc->y1, testarc->x0, testarc->y0, testarc->x1, testarc->y1, nx, ny)) {
06245       list2 = g_list_remove(list2, testarc);
06246       if(narc) calculate_arc_to_arc(r, newarc, narc);
06247       else calculate_term_to_arc(TOPOROUTER_VERTEX(t2), newarc, 1);
06248     
06249 //#ifdef DEBUG_RUBBERBAND
06250     if(debug)
06251       printf("REMOVING ARC @ %f,%f\n", vx(testarc->centre), vy(testarc->centre));
06252 //#endif
06253     }
06254   }
06255 
06256   g_list_foreach(arcs, free_list_elements, NULL);
06257   g_list_free(arcs);
06258 
06259   return g_list_concat(list1, g_list_prepend(list2, newarc));
06260 }
06261   
06262 void
06263 oproute_check_all_loops(toporouter_t *r, toporouter_oproute_t *oproute)
06264 {
06265   GList *i; 
06266   gpointer t1;
06267 
06268 loopcheck_restart:
06269   t1 = oproute->term1;
06270   i = oproute->arcs;
06271   while(i) {
06272     toporouter_arc_t *arc = TOPOROUTER_ARC(i->data);
06273     gpointer t2 = i->next ? i->next->data : oproute->term2;
06274 
06275     if(check_arc_for_loops(t1, arc, t2)) {
06276       
06277       if(TOPOROUTER_IS_ARC(t1) && TOPOROUTER_IS_ARC(t2)) 
06278         calculate_arc_to_arc(r, TOPOROUTER_ARC(t1), TOPOROUTER_ARC(t2));
06279       else if(TOPOROUTER_IS_ARC(t1)) 
06280         calculate_term_to_arc(TOPOROUTER_VERTEX(t2), TOPOROUTER_ARC(t1), 1);
06281       else if(TOPOROUTER_IS_ARC(t2)) 
06282         calculate_term_to_arc(TOPOROUTER_VERTEX(t1), TOPOROUTER_ARC(t2), 0);
06283 
06284       oproute->arcs = g_list_remove(oproute->arcs, arc);
06285       goto loopcheck_restart;
06286     }
06287 
06288     t1 = arc;
06289 
06290     i = i->next;
06291   }
06292 
06293 }
06294 
06295 GtsTriangle *
06296 opposite_triangle(GtsTriangle *t, toporouter_edge_t *e)
06297 {
06298   GSList *i = GTS_EDGE(e)->triangles;
06299 
06300   g_assert(e && t);
06301 
06302   while(i) {
06303     if(GTS_TRIANGLE(i->data) != t) return GTS_TRIANGLE(i->data);
06304     i = i->next;
06305   }
06306   
06307   return NULL;
06308 }
06309 
06310 
06311 void
06312 speccut_edge_routing_from_edge(GList *i, toporouter_edge_t *e)
06313 {
06314   g_assert(TOPOROUTER_IS_EDGE(e));
06315   while(i) {
06316     toporouter_vertex_t *curv = TOPOROUTER_VERTEX(i->data);
06317     
06318     if(!(curv->flags & VERTEX_FLAG_TEMP)) {
06319       toporouter_vertex_t *newv = tvertex_intersect(curv, curv->parent, tedge_v1(e), tedge_v2(e));
06320         
06321 //      printf("\nCURV:\n");
06322 //      print_vertex(curv);
06323 //      
06324 //      printf("CURV child:\n");
06325 //      if(curv->child) 
06326 //        print_vertex(curv->child);
06327 //      else 
06328 //        printf("NULL\n");
06329 //      
06330 //      printf("CURV parent:\n");
06331 //      if(curv->parent)
06332 //        print_vertex(curv->parent);
06333 //      else 
06334 //        printf("NULL\n");
06335 
06336       if(newv) {
06337         gint index;
06338         newv->flags |= VERTEX_FLAG_ROUTE; 
06339         newv->flags |= VERTEX_FLAG_SPECCUT; 
06340         e->routing = g_list_insert_sorted_with_data(e->routing, newv, routing_edge_insert, e);
06341         newv->route = curv->route; 
06342         newv->oproute = curv->oproute;
06343         newv->routingedge = e;
06344         GTS_POINT(newv)->z = vz(curv);
06345 
06346         newv->parent = curv->parent;
06347         newv->child = curv;
06348 
06349 //        curv->parent = newv;
06350 
06351         index = g_list_index(newv->route->path, curv);
06352 
06353         newv->route->path = g_list_insert(newv->route->path, newv, index);
06354 
06355 
06356         if(newv->oproute) newv->oproute->path = newv->route->path;
06357       }
06358 
06359       if(!(curv->child->routingedge)) {
06360         newv = tvertex_intersect(curv, curv->child, tedge_v1(e), tedge_v2(e));
06361 
06362         if(newv) {
06363           gint index;
06364           newv->flags |= VERTEX_FLAG_ROUTE; 
06365           newv->flags |= VERTEX_FLAG_SPECCUT; 
06366           e->routing = g_list_insert_sorted_with_data(e->routing, newv, routing_edge_insert, e);
06367           newv->route = curv->route; 
06368           newv->oproute = curv->oproute;
06369           newv->routingedge = e;
06370           GTS_POINT(newv)->z = vz(curv);
06371 
06372           newv->parent = curv;
06373           newv->child = curv->child;
06374 
06375 //          curv->child = newv;
06376 
06377           index = g_list_index(newv->route->path, curv);
06378 
06379           newv->route->path = g_list_insert(newv->route->path, newv, index+1);
06380 
06381 
06382           if(newv->oproute) newv->oproute->path = newv->route->path;
06383         }
06384 
06385       }
06386 
06387     }
06388     i = i->next;
06389   }
06390 
06391 }
06392 
06393 void
06394 speccut_edge_patch_links(toporouter_edge_t *e)
06395 {
06396   GList *i = e->routing;
06397   g_assert(TOPOROUTER_IS_EDGE(e));
06398   while(i) {
06399     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
06400     v->parent->child = v;
06401     v->child->parent = v;
06402     i = i->next;
06403   }
06404 }
06405 
06406 gint
06407 check_speccut(toporouter_oproute_t *oproute, toporouter_vertex_t *v1, toporouter_vertex_t *v2, toporouter_edge_t *e, toporouter_edge_t *e1, toporouter_edge_t *e2)
06408 {
06409   GtsTriangle *t, *opt;
06410   toporouter_vertex_t *opv, *opv2;
06411   toporouter_edge_t *ope1, *ope2;
06412   gdouble cap, flow, line_int_x, line_int_y;
06413  
06414   if(TOPOROUTER_IS_CONSTRAINT(e)) return 0;
06415 
06416   if(!(t = gts_triangle_use_edges(GTS_EDGE(e), GTS_EDGE(e1), GTS_EDGE(e2)))) {
06417     printf("check_speccut: NULL t\n");
06418     return 0;
06419   }
06420    
06421   if(!(opt = opposite_triangle(t, e))) {
06422 //    printf("check_speccut: NULL opt\n");
06423     return 0;
06424   }
06425 
06426   if(!(opv = segment_common_vertex(GTS_SEGMENT(e1), GTS_SEGMENT(e2)))) {
06427     printf("check_speccut: NULL opv\n");
06428     return 0;
06429   }
06430   
06431   if(!(opv2 = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(opt, GTS_EDGE(e))))) {
06432     printf("check_speccut: NULL opv2\n");
06433     return 0;
06434   }
06435  
06436   //TODO: shifting it out of the way would be better
06437   if(e->routing) {
06438     GList *i = e->routing;
06439     while(i) {
06440       toporouter_vertex_t *ev = TOPOROUTER_VERTEX(i->data);
06441       if(!tvertex_wind(opv, ev, opv2)) return 0;    
06442       i = i->next;
06443     }
06444 
06445   }
06446 
06447   ope1 = tedge(opv2, tedge_v1(e));
06448   ope2 = tedge(opv2, tedge_v2(e));
06449 
06450  //this fixes the weird pad exits in r8c board
06451 //  if(TOPOROUTER_IS_CONSTRAINT(ope1)) return 0;
06452   if(TOPOROUTER_IS_CONSTRAINT(ope2)) return 0;
06453 
06454   if(!tvertex_wind(opv2, tedge_v1(e), opv)) return 0;
06455   if(!tvertex_wind(opv2, tedge_v2(e), opv)) return 0;
06456   
06457   if(!vertex_line_normal_intersection(
06458       vx(tedge_v1(e)), vy(tedge_v1(e)), 
06459       vx(tedge_v2(e)), vy(tedge_v2(e)), 
06460       vx(opv2), vy(opv2), 
06461       &line_int_x, &line_int_y)) return 0;
06462   
06463 
06464 //  return 0;
06465 //if(vertex_line_normal_intersection(tev1x(e), tev1y(e), tev2x(e), tev2y(e), vx(opv), vy(opv), &line_int_x, &line_int_y))
06466 //  return 0;
06467 
06468   g_assert(opt && opv2);
06469  
06470   /* this is just temp, for the purposes of determining flow */
06471   if(tedge_v1(ope1) == opv2) {
06472     if(TOPOROUTER_IS_CONSTRAINT(ope1)) 
06473       TOPOROUTER_CONSTRAINT(ope1)->routing = g_list_append(TOPOROUTER_CONSTRAINT(ope1)->routing, v1);
06474     else
06475       ope1->routing = g_list_append(ope1->routing, v1);
06476   }else{
06477     if(TOPOROUTER_IS_CONSTRAINT(ope1)) 
06478       TOPOROUTER_CONSTRAINT(ope1)->routing = g_list_prepend(TOPOROUTER_CONSTRAINT(ope1)->routing, v1);
06479     else
06480       ope1->routing = g_list_prepend(ope1->routing, v1);
06481   }
06482 
06483   cap = triangle_interior_capacity(opt, opv2);
06484   flow = flow_from_edge_to_edge(opt, tedge(opv2, tedge_v1(e)), tedge(opv2, tedge_v2(e)), opv2, v1);
06485   
06486   /* temp v1 removed */
06487   if(TOPOROUTER_IS_CONSTRAINT(ope1)) 
06488     TOPOROUTER_CONSTRAINT(ope1)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(ope1)->routing, v1);
06489   else
06490     ope1->routing = g_list_remove(ope1->routing, v1);
06491 
06492   if(flow >= cap) {
06493     toporouter_edge_t *newe = TOPOROUTER_EDGE(gts_edge_new(GTS_EDGE_CLASS(toporouter_edge_class()), GTS_VERTEX(opv), GTS_VERTEX(opv2)));
06494 
06495     speccut_edge_routing_from_edge(edge_routing(e1), newe);
06496     speccut_edge_routing_from_edge(edge_routing(e2), newe);
06497     speccut_edge_routing_from_edge(edge_routing(ope1), newe);
06498     speccut_edge_routing_from_edge(edge_routing(ope2), newe);
06499 
06500     speccut_edge_patch_links(newe);
06501 /*
06502     printf("SPECCUT WITH v %f,%f for seg %f,%f %f,%f detected\n", vx(opv2), vy(opv2),
06503         vx(v1), vy(v1), 
06504         vx(v2), vy(v2));
06505     printf("\tflow %f cap %f\n", flow, cap);
06506     print_edge(newe);
06507   */  
06508     if(newe->routing) return 1;
06509   }
06510 
06511 
06512   return 0;
06513 }
06514       
06515 
06516 gint
06517 oproute_path_speccut(toporouter_oproute_t *oproute)
06518 {
06519   GList *i;
06520   toporouter_vertex_t *pv; 
06521 path_speccut_restart:
06522   i = oproute->path;
06523   pv = NULL;
06524   while(i) {
06525     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
06526 
06527 
06528     if(pv && (v->routingedge || pv->routingedge) && !(pv->flags & VERTEX_FLAG_SPECCUT) && !(v->flags & VERTEX_FLAG_SPECCUT)) {
06529       
06530       if(!v->routingedge) {
06531         if(check_speccut(oproute, pv, v, tedge(tedge_v1(pv->routingedge), v), pv->routingedge, tedge(tedge_v2(pv->routingedge), v)))
06532           goto path_speccut_restart;
06533         if(check_speccut(oproute, pv, v, tedge(tedge_v2(pv->routingedge), v), pv->routingedge, tedge(tedge_v1(pv->routingedge), v))) 
06534           goto path_speccut_restart;
06535       }else if(!pv->routingedge) {
06536         if(check_speccut(oproute, v, pv, tedge(tedge_v1(v->routingedge), pv), v->routingedge, tedge(tedge_v2(v->routingedge), pv)))
06537           goto path_speccut_restart;
06538         if(check_speccut(oproute, v, pv, tedge(tedge_v2(v->routingedge), pv), v->routingedge, tedge(tedge_v1(v->routingedge), pv))) 
06539           goto path_speccut_restart;
06540       }else{
06541         toporouter_vertex_t *v1 = NULL, *v2 = NULL;
06542         edges_third_edge(GTS_SEGMENT(v->routingedge), GTS_SEGMENT(pv->routingedge), &v1, &v2); 
06543         if(check_speccut(oproute, v, pv, tedge(v1, v2), v->routingedge, pv->routingedge)) 
06544           goto path_speccut_restart;
06545       }
06546     }
06547 
06548 
06549     pv = v;
06550     i = i->next;
06551   }
06552 
06553   return 0;
06554 }
06555 
06556 toporouter_oproute_t *
06557 oproute_rubberband(toporouter_t *r, GList *path)
06558 {
06559   toporouter_oproute_t *oproute = (toporouter_oproute_t *)malloc(sizeof(toporouter_oproute_t)); 
06560 
06561   g_assert(path);
06562 
06563   oproute->term1 = TOPOROUTER_VERTEX(path->data);
06564   oproute->term2 = TOPOROUTER_VERTEX(g_list_last(path)->data);
06565   oproute->arcs = NULL;
06566   oproute->style = vertex_bbox(oproute->term1)->cluster->netlist->style;
06567   oproute->netlist = vertex_bbox(oproute->term1)->cluster->netlist->netlist;
06568   oproute->layergroup = vz(oproute->term1);
06569   oproute->path = path;
06570   oproute->serp = NULL;
06571 
06572   oproute->term1->parent = NULL;
06573   oproute->term2->child = NULL;
06574 
06575   path_set_oproute(path, oproute);
06576 
06577 //  if(!strcmp(oproute->netlist, "  unnamed_net1")) 
06578   oproute_path_speccut(oproute);
06579 
06580 #ifdef DEBUG_RUBBERBAND
06581   if(strcmp(oproute->netlist, "  VCC3V3" == 0) &&
06582      vx(oproute->term1) == MIL_TO_COORD (957.) &&
06583      vy(oproute->term1) == MIL_TO_COORD (708.) &&
06584      vx(oproute->term2) == MIL_TO_COORD (1967.) &&
06585      vy(oproute->term2) == MIL_TO_COORD (673.))
06586   {
06587 //    printf("OPROUTE %s - %f,%f %f,%f\n", oproute->netlist, vx(oproute->term1), vy(oproute->term1), vx(oproute->term2), vy(oproute->term2));
06588 //    print_path(path);
06589     oproute->arcs = oproute_rubberband_segment(r, oproute, path, oproute->term1, oproute->term2, 1);
06590   }else
06591 #endif    
06592     oproute->arcs = oproute_rubberband_segment(r, oproute, path, oproute->term1, oproute->term2, 0);
06593 
06594   oproute_check_all_loops(r, oproute);
06595   return oproute;
06596 
06597 }
06598 
06599 void
06600 toporouter_export(toporouter_t *r) 
06601 {
06602   GList *i = r->routednets;
06603   GList *oproutes = NULL;
06604 
06605   while(i) {
06606     toporouter_route_t *routedata = TOPOROUTER_ROUTE(i->data);
06607     toporouter_oproute_t *oproute = oproute_rubberband(r, routedata->path);
06608     oproutes = g_list_prepend(oproutes, oproute);
06609     i = i->next;
06610   }
06611 
06612   i = oproutes;
06613   while(i) {
06614     toporouter_oproute_t *oproute = (toporouter_oproute_t *) i->data;
06615     export_oproutes(r, oproute);
06616     oproute_free(oproute);
06617     i = i->next;
06618   }
06619 
06620   Message (_("Reticulating splines... successful\n\n"));
06621   /* NB: We could use the %$mS specifier to print these distances, but we would
06622    *     have to cast to Coord, which might overflow for complex routing when
06623    *     PCB is built with Coord as a 32-bit integer.
06624    */
06625   Message (_("Wiring cost: %f inches\n"), COORD_TO_INCH (r->wiring_score));
06626   printf (_("Wiring cost: %f inches\n"), COORD_TO_INCH (r->wiring_score));
06627 
06628   g_list_free(oproutes);
06629 
06630 }
06631 
06632 toporouter_route_t *
06633 routedata_create(void)
06634 {
06635   toporouter_route_t *routedata = (toporouter_route_t *)malloc(sizeof(toporouter_route_t));
06636   routedata->netlist = NULL;
06637   routedata->alltemppoints = NULL;
06638   routedata->path = NULL;
06639   routedata->curpoint = NULL;
06640   routedata->pscore = routedata->score = 0.;
06641   routedata->flags = 0;
06642   routedata->src = routedata->dest = NULL;
06643   routedata->psrc = routedata->pdest = NULL;
06644   routedata->ppath = routedata->topopath = NULL;
06645 
06646   routedata->ppathindices = NULL;
06647 
06648   routedata->destvertices = routedata->srcvertices = NULL;
06649   return routedata;
06650 }
06651 /*
06652 void
06653 print_routedata(toporouter_route_t *routedata)
06654 {
06655   GList *srcvertices = cluster_vertices(routedata->src);
06656   GList *destvertices = cluster_vertices(routedata->dest);
06657 
06658   printf("ROUTEDATA:\n");
06659   printf("SRCVERTICES:\n");
06660   print_vertices(srcvertices);
06661   printf("DESTVERTICES:\n");
06662   print_vertices(destvertices);
06663 
06664   g_list_free(srcvertices);
06665   g_list_free(destvertices);
06666 }*/
06667 
06668 toporouter_route_t *
06669 import_route(toporouter_t *r, RatType *line)
06670 {
06671   toporouter_route_t *routedata = routedata_create();
06672 
06673   routedata->src = cluster_find(r, line->Point1.X, line->Point1.Y, line->group1);
06674   routedata->dest = cluster_find(r, line->Point2.X, line->Point2.Y, line->group2);
06675 
06676   if(!routedata->src) printf("couldn't locate src\n");
06677   if(!routedata->dest) printf("couldn't locate dest\n");
06678 
06679   if(!routedata->src || !routedata->dest) {
06680     pcb_printf("PROBLEM: couldn't locate rat src or dest for rat %#mD, %d -> %#mD, %d\n",
06681         line->Point1.X, line->Point1.Y, line->group1, line->Point2.X, line->Point2.Y, line->group2);
06682     free(routedata);
06683     return NULL;
06684   }
06685 
06686   routedata->netlist = routedata->src->netlist;
06687 
06688   g_assert(routedata->src->netlist == routedata->dest->netlist);
06689 
06690   g_ptr_array_add(r->routes, routedata);
06691   g_ptr_array_add(routedata->netlist->routes, routedata);
06692 
06693   r->failednets = g_list_prepend(r->failednets, routedata);
06694 
06695   return routedata;
06696 }
06697 
06698 void
06699 delete_route(toporouter_route_t *routedata, guint destroy)
06700 {
06701   GList *i = routedata->path;
06702   toporouter_vertex_t *pv = NULL;
06703   
06704   while(i) {
06705     toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
06706 
06707     g_assert(tv);
06708 
06709     if(tv && pv && !(tv->flags & VERTEX_FLAG_ROUTE) && !(pv->flags & VERTEX_FLAG_ROUTE)) {
06710       toporouter_edge_t *e = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(tv), GTS_VERTEX(pv)));
06711 
06712       if(e && (e->flags & EDGE_FLAG_DIRECTCONNECTION)) {
06713         e->flags ^= EDGE_FLAG_DIRECTCONNECTION;
06714       }
06715     }
06716     pv = tv;
06717     i = i->next;
06718   }
06719 
06720   i = routedata->path;
06721   while(i) {
06722     toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
06723 
06724     tv->parent = NULL;
06725     tv->child = NULL;
06726 
06727     if(tv->routingedge) {
06728       if(TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) 
06729         TOPOROUTER_CONSTRAINT(tv->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(tv->routingedge)->routing, tv);
06730       else
06731         tv->routingedge->routing = g_list_remove(tv->routingedge->routing, tv);
06732       if(destroy) gts_object_destroy ( GTS_OBJECT(tv) );
06733     }
06734 
06735     i = i->next;
06736   }
06737 
06738   if(routedata->path) g_list_free(routedata->path);
06739   routedata->path = NULL;
06740   routedata->curpoint = NULL;
06741   routedata->score = INFINITY;
06742   routedata->alltemppoints = NULL;
06743 }
06744 
06748 void
06749 remove_route(GList *path)
06750 {
06751   GList *i = path;
06752 
06753   while(i) {
06754     toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
06755     
06756     tv->parent = NULL;
06757     tv->child = NULL;
06758 
06759 //    if(tv->flags & VERTEX_FLAG_ROUTE) g_assert(tv->route == routedata);
06760 
06761     if(tv->routingedge) {
06762 
06763       if(TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) 
06764         TOPOROUTER_CONSTRAINT(tv->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(tv->routingedge)->routing, tv);
06765       else
06766         tv->routingedge->routing = g_list_remove(tv->routingedge->routing, tv);
06767     }
06768     i = i->next;
06769   }
06770 
06771 }
06772 
06773 gint
06774 apply_route(GList *path, toporouter_route_t *routedata)
06775 {
06776   GList *i = path;
06777   toporouter_vertex_t *pv = NULL;
06778   gint count = 0;
06779 
06780   if(!path) return 0;
06781 //  g_assert(path);
06782 
06783   while(i) {
06784     toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
06785 
06786     if(tv->routingedge) {
06787       if(TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) 
06788         TOPOROUTER_CONSTRAINT(tv->routingedge)->routing = g_list_insert_sorted_with_data(
06789               TOPOROUTER_CONSTRAINT(tv->routingedge)->routing, 
06790               tv, 
06791               routing_edge_insert, 
06792               tv->routingedge);
06793       else
06794         tv->routingedge->routing = g_list_insert_sorted_with_data(
06795               tv->routingedge->routing, 
06796               tv, 
06797               routing_edge_insert, 
06798               tv->routingedge);
06799     
06800       count++;
06801     }
06802 
06803     if(pv) {
06804       pv->child = tv;
06805       tv->parent = pv;
06806     }
06807 
06808     if(tv->flags & VERTEX_FLAG_ROUTE) g_assert(tv->route == routedata);
06809 
06810     pv = tv;
06811     i = i->next;
06812   }
06813 
06814   TOPOROUTER_VERTEX(path->data)->parent = NULL;
06815   pv->child = NULL;
06816 
06817   return count;
06818 }
06819 
06820 
06821 gint               
06822 compare_routedata_ascending(gconstpointer a, gconstpointer b)
06823 {
06824   toporouter_route_t *ra = (toporouter_route_t *)a;
06825   toporouter_route_t *rb = (toporouter_route_t *)b;
06826   return ra->score - rb->score;
06827 }
06828 
06829 void
06830 print_costmatrix(gdouble *m, guint n) 
06831 {
06832   printf("COST MATRIX:\n");  
06833   for(guint i = 0;i<n;i++) {
06834     for(guint j = 0;j<n;j++) {
06835       printf("%f ", m[(i*n)+j]);
06836     }
06837     printf("\n");
06838   }
06839 }
06840 
06841 
06842 static inline void
06843 init_cost_matrix(gdouble *m, guint n) 
06844 {
06845   for(guint i=0;i<n;i++) {
06846     for(guint j=0;j<n;j++) {
06847       m[(i*n)+j] = INFINITY;
06848     }
06849   }
06850 }
06851 
06852 
06853 toporouter_netscore_t *
06854 netscore_create(toporouter_t *r, toporouter_route_t *routedata, guint n, guint id)
06855 {
06856   toporouter_netscore_t *netscore = (toporouter_netscore_t *)malloc(sizeof(toporouter_netscore_t));
06857   GList *path = route(r, routedata, 0);
06858   
06859   netscore->id = id;
06860 
06861   netscore->routedata = routedata;
06862   routedata->detourscore = netscore->score = routedata->score;
06863 
06864   if(!isfinite(routedata->detourscore)) {
06865     printf("WARNING: !isfinite(detourscore)\n");
06866     print_cluster(routedata->src);
06867     print_cluster(routedata->dest);
06868     return NULL;
06869   }
06870 
06871   netscore->pairwise_nodetour = (guint *)malloc(n * sizeof(guint));
06872 
06873   for(guint i=0;i<n;i++) {
06874     netscore->pairwise_nodetour[i] = 0;
06875   }
06876 
06877   netscore->pairwise_detour_sum = 0.;
06878   netscore->pairwise_fails = 0;
06879 
06880   netscore->r = r;
06881 
06882   if(path) {
06883     routedata->topopath = g_list_copy(routedata->path);
06884     delete_route(routedata, 0);
06885   }
06886 
06887   return netscore;
06888 }
06889 
06890 static inline void
06891 netscore_destroy(toporouter_netscore_t *netscore)
06892 {
06893   free(netscore->pairwise_nodetour);
06894   free(netscore);
06895 }
06896 
06897 void
06898 print_netscores(GPtrArray* netscores)
06899 {
06900   printf("NETSCORES: \n\n");
06901   printf("     %15s %15s %15s\n----------------------------------------------------\n", "Score", "Detour Sum", "Pairwise Fails");
06902 
06903   for(toporouter_netscore_t **i = (toporouter_netscore_t **) netscores->pdata; i < (toporouter_netscore_t **) netscores->pdata + netscores->len; i++) {
06904 #ifdef DEBUG_NETSCORES    
06905         printf("%4d %15f %15f %15d %15x\n", (*i)->id, (*i)->score, (*i)->pairwise_detour_sum, (*i)->pairwise_fails, (guint)*i);
06906 #endif 
06907   }
06908 
06909   printf("\n");
06910 }
06911 
06912 void
06913 netscore_pairwise_calculation(toporouter_netscore_t *netscore, GPtrArray *netscores)
06914 {
06915   toporouter_netscore_t **netscores_base = (toporouter_netscore_t **) (netscores->pdata); 
06916   toporouter_route_t *temproutedata = routedata_create();
06917 
06918   //route(netscore->r, netscore->routedata, 0);
06919   apply_route(netscore->routedata->topopath, netscore->routedata);
06920 
06921   for(toporouter_netscore_t **i = netscores_base; i < netscores_base + netscores->len; i++) {
06922         
06923     if(!netscore->pairwise_nodetour[i-netscores_base] && *i != netscore && (*i)->routedata->netlist != netscore->routedata->netlist) {
06924       
06925       temproutedata->src = (*i)->routedata->src;
06926       temproutedata->dest = (*i)->routedata->dest;
06927   
06928       route(netscore->r, temproutedata, 0);
06929 
06930       if(temproutedata->score == (*i)->score) {
06931         netscore->pairwise_nodetour[i-netscores_base] = 1;
06932         (*i)->pairwise_nodetour[netscore->id] = 1;
06933       }else 
06934       if(!isfinite(temproutedata->score)) {
06935         netscore->pairwise_fails += 1;
06936       }else{
06937         netscore->pairwise_detour_sum += temproutedata->score - (*i)->score;
06938       }
06939 
06940       delete_route(temproutedata, 1);
06941     }
06942     
06943   }
06944 
06945 //  delete_route(netscore->routedata, 1);
06946   remove_route(netscore->routedata->topopath);
06947 
06948   free(temproutedata);
06949 }
06950 
06951 gint
06952 netscore_pairwise_size_compare(toporouter_netscore_t **a, toporouter_netscore_t **b)
06953 {
06954   // infinite scores are last
06955   if(!isfinite((*a)->score) && !isfinite((*b)->score)) return 0;
06956   if(isfinite((*a)->score) && !isfinite((*b)->score)) return -1;
06957   if(isfinite((*b)->score) && !isfinite((*a)->score)) return 1;
06958 
06959   // order by pairwise fails
06960   if((*a)->pairwise_fails < (*b)->pairwise_fails) return -1;
06961   if((*b)->pairwise_fails < (*a)->pairwise_fails) return 1;
06962 
06963   // order by pairwise detour
06964   if((*a)->pairwise_detour_sum < (*b)->pairwise_detour_sum) return -1;
06965   if((*b)->pairwise_detour_sum < (*a)->pairwise_detour_sum) return 1;
06966 
06967   // order by score
06968   if((*a)->score < (*b)->score) return -1;
06969   if((*b)->score < (*a)->score) return 1;
06970 
06971   return 0;
06972 }
06973 
06974 gint
06975 netscore_pairwise_compare(toporouter_netscore_t **a, toporouter_netscore_t **b)
06976 {
06977   // infinite scores are last
06978   if(!isfinite((*a)->score) && !isfinite((*b)->score)) return 0;
06979   if(isfinite((*a)->score) && !isfinite((*b)->score)) return -1;
06980   if(isfinite((*b)->score) && !isfinite((*a)->score)) return 1;
06981 
06982   // order by pairwise fails
06983   if((*a)->pairwise_fails < (*b)->pairwise_fails) return -1;
06984   if((*b)->pairwise_fails < (*a)->pairwise_fails) return 1;
06985 
06986   // order by pairwise detour
06987   if((*a)->pairwise_detour_sum < (*b)->pairwise_detour_sum) return -1;
06988   if((*b)->pairwise_detour_sum < (*a)->pairwise_detour_sum) return 1;
06989 
06990   return 0;
06991 }
06992 
06993 guint
06994 order_nets_preroute_greedy(toporouter_t *r, GList *nets, GList **rnets) 
06995 {
06996   gint len = g_list_length(nets);
06997   GPtrArray* netscores = g_ptr_array_sized_new(len);
06998   guint failcount = 0;
06999 
07000   while(nets) {
07001     toporouter_netscore_t *ns = netscore_create(r, TOPOROUTER_ROUTE(nets->data), len, failcount++);
07002     if(ns) g_ptr_array_add(netscores, ns);
07003     nets = nets->next;
07004   } 
07005 
07006   failcount = 0;
07007   
07008   g_ptr_array_foreach(netscores, (GFunc) netscore_pairwise_calculation, netscores);
07009   
07010   g_ptr_array_sort(netscores, (GCompareFunc) r->netsort);
07011 
07012 #ifdef DEBUG_ORDERING
07013   print_netscores(netscores);
07014 #endif
07015 
07016   *rnets = NULL;
07017   FOREACH_NETSCORE(netscores) {
07018     *rnets = g_list_prepend(*rnets, netscore->routedata);
07019     if(!isfinite(netscore->score)) failcount++;
07020     netscore_destroy(netscore);
07021   } FOREACH_END;
07022 
07023   g_ptr_array_free(netscores, TRUE);
07024 
07025   return failcount;
07026 }
07027 
07028 toporouter_vertex_t *
07029 edge_closest_vertex(toporouter_edge_t *e, toporouter_vertex_t *v)
07030 {
07031   GList *i = v->routingedge ? edge_routing(v->routingedge) : NULL;
07032   gdouble closestd = 0.;
07033   toporouter_vertex_t *closestv = NULL;
07034 
07035   while(i) {
07036     toporouter_vertex_t *ev = TOPOROUTER_VERTEX(i->data);
07037     gdouble tempd = gts_point_distance2(GTS_POINT(ev), GTS_POINT(v));
07038 
07039     if(!closestv || (tempd < closestd)) {
07040       closestd = tempd;
07041       closestv = ev;
07042     }
07043 
07044     i = i->next;
07045   }
07046 
07047   return closestv;
07048 }
07049 
07050 void
07051 snapshot(toporouter_t *r, char *name, GList *datas) 
07052 {
07054   {
07055     int i;
07056     for(i=0;i<groupcount();i++) {
07057       char buffer[256];
07058       sprintf(buffer, "route-%s-%d.png", name, i);
07059       toporouter_draw_surface(r, r->layers[i].surface, buffer, 2048, 2048, 2, datas, i, NULL);
07060     }
07061   }
07062 //*/
07063 
07064 }
07065 /*
07066 gdouble
07067 route_conflict(toporouter_t *r, toporouter_route_t *route, guint *n)
07068 {
07069   GList *i = route->path;
07070   toporouter_vertex_t *pv = NULL;
07071   gdouble cost = 0.;
07072 
07073   while(i) {
07074     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
07075     if(pv && vz(v) == vz(pv))
07076       cost += vertices_routing_conflict_cost(r, v, pv, n);
07077     pv = v;
07078     i = i->next;
07079   }
07080 
07081   return cost;
07082 }
07083 */
07084 GList *
07085 route_conflicts(toporouter_route_t *route)
07086 {
07087   GList *conflicts = NULL, *i = route->path;
07088   toporouter_vertex_t *pv = NULL;
07089 
07090   while(i) {
07091     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
07092 
07093     if(pv && vz(pv) == vz(v)) {
07094       GList *temp = vertices_routing_conflicts(pv, v), *j;
07095      
07096       j = temp;
07097       while(j) {
07098         toporouter_route_t *conroute = TOPOROUTER_ROUTE(j->data);
07099         if(!g_list_find(conflicts, conroute)) 
07100           conflicts = g_list_prepend(conflicts, conroute);
07101         j = j->next;
07102       }
07103 
07104       if(temp) g_list_free(temp);
07105     }
07106 
07107     pv = v;
07108     i = i->next;
07109   }
07110   return conflicts;
07111 }
07112 
07113 gint       
07114 spread_edge(gpointer item, gpointer data)
07115 {
07116   toporouter_edge_t *e = TOPOROUTER_EDGE(item);
07117   toporouter_vertex_t *v;
07118   gdouble spacing, s;
07119   GList *i;
07120 
07121   if(TOPOROUTER_IS_CONSTRAINT(e)) return 0;
07122 
07123   i = edge_routing(e);
07124 
07125   if(!g_list_length(i)) return 0;
07126 
07127   if(g_list_length(i) == 1) {
07128     v = TOPOROUTER_VERTEX(i->data);
07129     GTS_POINT(v)->x = (vx(edge_v1(e)) + vx(edge_v2(e))) / 2.;
07130     GTS_POINT(v)->y = (vy(edge_v1(e)) + vy(edge_v2(e))) / 2.;
07131     return 0;
07132   }
07133   
07134   s = spacing = (gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e))) ) / (g_list_length(i) + 1);
07135   
07136   while(i) {
07137     v = TOPOROUTER_VERTEX(i->data); 
07138     vertex_move_towards_vertex_values(edge_v1(e), edge_v2(e), s, &(GTS_POINT(v)->x), &(GTS_POINT(v)->y));
07139 
07140     s += spacing;
07141     i = i->next;
07142   }
07143 
07144   return 0;  
07145 }
07146 
07147 void
07148 route_checkpoint(toporouter_route_t *route, toporouter_route_t *temproute)
07149 {
07150   GList *i = g_list_last(route->path);
07151   gint n = g_list_length(route->path);
07152 
07153   if(route->ppathindices) free(route->ppathindices);
07154   route->ppathindices = (gint *)malloc(sizeof(gint)*n);
07155 
07156 //  n = 0;
07157   while(i) {
07158     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
07159     n--;
07160 
07161     if(v->routingedge) {
07162       GList *j = g_list_find(edge_routing(v->routingedge), v)->prev;
07163       gint tempindex = g_list_index(edge_routing(v->routingedge), v);
07164 
07165       while(j) {
07166         if(TOPOROUTER_VERTEX(j->data)->route == temproute) tempindex--;
07167         j = j->prev;
07168       }
07169 
07170       route->ppathindices[n] = tempindex; 
07171 
07172       if(TOPOROUTER_IS_CONSTRAINT(v->routingedge)) 
07173         TOPOROUTER_CONSTRAINT(v->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(v->routingedge)->routing, v);
07174       else
07175         v->routingedge->routing = g_list_remove(v->routingedge->routing, v);
07176     }
07177 
07178     i = i->prev;
07179   }
07180 
07181   route->pscore = route->score;
07182   route->ppath = route->path;
07183   remove_route(route->path);      
07184   route->path = NULL;
07185   route->psrc = route->src;
07186   route->pdest = route->dest;
07187 //route->src->pc = route->src->c;
07188 //route->dest->pc = route->dest->c;
07189 }
07190 
07191 void
07192 route_restore(toporouter_route_t *route)
07193 {
07194   GList *i;
07195   toporouter_vertex_t *pv = NULL;
07196   gint n = 0;
07197 
07198   g_assert(route->ppath);
07199   g_assert(route->ppathindices);
07200 
07201   route->path = route->ppath;
07202   i = route->ppath;
07203   while(i) {
07204     toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
07205 
07206     if(v->routingedge) {
07207       if(TOPOROUTER_IS_CONSTRAINT(v->routingedge)) 
07208         TOPOROUTER_CONSTRAINT(v->routingedge)->routing = g_list_insert(TOPOROUTER_CONSTRAINT(v->routingedge)->routing, v, route->ppathindices[n]);
07209       else
07210         v->routingedge->routing = g_list_insert(v->routingedge->routing, v, route->ppathindices[n]);
07211 
07212       //      space_edge(v->routingedge, NULL);
07213     }
07214 
07215     if(pv) {
07216       pv->child = v;
07217       v->parent = pv;
07218     }
07219 
07220     n++;
07221     pv = v;
07222     i = i->next;
07223   }
07224 
07225   route->score = route->pscore;
07226   route->src = route->psrc;
07227   route->dest = route->pdest;
07228 //route->src->c = route->src->pc;
07229 //route->dest->c = route->dest->pc;
07230 
07231 }
07232 
07233 void
07234 cluster_merge(toporouter_route_t *routedata)
07235 {
07236   gint oldc = routedata->dest->c, newc = routedata->src->c;
07237 
07238   FOREACH_CLUSTER(routedata->netlist->clusters) {
07239     if(cluster->c == oldc) 
07240       cluster->c = newc;
07241   } FOREACH_END;
07242 
07243 }
07244 
07245 void
07246 netlist_recalculate(toporouter_netlist_t *netlist, GList *ignore)
07247 {
07248   GList *i = g_list_last(netlist->routed);
07249   gint n = netlist->clusters->len-1;
07250 
07251   FOREACH_CLUSTER(netlist->clusters) {
07252     cluster->c = n--;
07253   } FOREACH_END;
07254 
07255   while(i) {
07256     if(!ignore || !g_list_find(ignore, i->data)) cluster_merge(TOPOROUTER_ROUTE(i->data));
07257     i = i->prev;
07258   }
07259 
07260 }
07261 
07262 void
07263 netlists_recalculate(GList *netlists, GList *ignore)
07264 {
07265   GList *i = netlists;
07266   while(i) {
07267     netlist_recalculate(TOPOROUTER_NETLIST(i->data), ignore);
07268     i = i->next;
07269   }
07270 }
07271 
07272 void
07273 netlists_rollback(GList *netlists) 
07274 {
07275 //  netlists_recalculate(netlists, NULL);
07276   while(netlists) {
07277     toporouter_netlist_t *netlist = TOPOROUTER_NETLIST(netlists->data);
07278    
07279     FOREACH_CLUSTER(netlist->clusters) {
07280       cluster->c = cluster->pc;
07281     } FOREACH_END;
07282 
07283     netlists = netlists->next;
07284   }
07285 }
07286 
07287 void
07288 print_netlist(toporouter_netlist_t *netlist)
07289 {
07290 
07291   printf("NETLIST %s: ", netlist->netlist);
07292 
07293   FOREACH_CLUSTER(netlist->clusters) {
07294     printf("%d ", cluster->c);
07295 
07296   } FOREACH_END;
07297   printf("\n");
07298 }
07299 
07300 #define REMOVE_ROUTING(x) x->netlist->routed = g_list_remove(x->netlist->routed, x); \
07301   r->routednets = g_list_remove(r->routednets, x); \
07302   r->failednets = g_list_prepend(r->failednets, x)
07303 
07304 #define INSERT_ROUTING(x) x->netlist->routed = g_list_prepend(x->netlist->routed, x); \
07305   r->routednets = g_list_prepend(r->routednets, x); \
07306   r->failednets = g_list_remove(r->failednets, x)
07307 
07308 gint
07309 roar_route(toporouter_t *r, toporouter_route_t *routedata, gint threshold)
07310 {
07311   gint intfails = 0;
07312   GList *netlists = NULL, *routed = NULL;
07313   
07314   g_assert(!routedata->path);
07315 
07316   if(routedata->src->c == routedata->dest->c) {
07317     printf("ERROR: attempt to route already complete route\n");
07318     g_assert(routedata->src->c != routedata->dest->c);
07319   }
07320 
07321   routedata->src->pc = routedata->src->c;
07322   routedata->dest->pc = routedata->dest->c;
07323   routedata->psrc = routedata->src;
07324   routedata->pdest = routedata->dest;
07325 
07326   r->flags |= TOPOROUTER_FLAG_LEASTINVALID;
07327   if(route(r, routedata, 0)) {
07328     GList *conflicts, *j;
07329 
07330     INSERT_ROUTING(routedata);
07331 
07332     conflicts = route_conflicts(routedata);
07333     cluster_merge(routedata);
07334 
07335     r->flags &= ~TOPOROUTER_FLAG_LEASTINVALID;
07336 
07337     j = conflicts;
07338     while(j) {
07339       toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data);
07340       if(!g_list_find(netlists, conflict->netlist)) 
07341         netlists = g_list_prepend(netlists, conflict->netlist);
07342       
07343       route_checkpoint(conflict, routedata);
07344 
07345       REMOVE_ROUTING(conflict);
07346       j = j->next;
07347     }
07348 
07349     netlists = g_list_prepend(netlists, routedata->netlist);
07350     netlists_recalculate(netlists, NULL);
07351 
07352     j = conflicts;
07353     while(j) {
07354       toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data);
07355       g_assert(conflict->src->c != conflict->dest->c);
07356       if(route(r, conflict, 0)) { 
07357         cluster_merge(conflict);
07358         
07359         routed = g_list_prepend(routed, conflict);
07360       
07361         INSERT_ROUTING(conflict);
07362 
07363         netlist_recalculate(conflict->netlist, NULL);
07364         
07365       }else{
07366         if(++intfails >= threshold) {
07367           GList *i = routed;
07368           while(i) {
07369             toporouter_route_t *intconflict = TOPOROUTER_ROUTE(i->data);
07370             REMOVE_ROUTING(intconflict);
07371             delete_route(intconflict, 1);
07372             i = i->next;
07373           }
07374           delete_route(routedata, 1);
07375           i = g_list_last(conflicts);
07376           while(i) {
07377             toporouter_route_t *intconflict = TOPOROUTER_ROUTE(i->data);
07378             
07379             route_restore(intconflict);
07380             INSERT_ROUTING(intconflict);
07381 
07382             i = i->prev;
07383           }
07384           REMOVE_ROUTING(routedata);
07385           intfails = 0;
07386           netlists_recalculate(netlists, NULL);
07387           goto roar_route_end;
07388         }
07389 
07390       }
07391       j = j->next;
07392     }
07393 
07394 
07395     netlists_recalculate(netlists, NULL);
07396 
07397     intfails--;
07398 roar_route_end:    
07399     g_list_free(conflicts);
07400     g_list_free(netlists);
07401 
07402   }else{
07403     r->flags &= ~TOPOROUTER_FLAG_LEASTINVALID;
07404   }
07405 
07406   g_list_free(routed);
07407   return intfails;
07408 }
07409 
07410 gint
07411 roar_router(toporouter_t *r, gint failcount, gint threshold)
07412 {
07413   gint pfailcount = failcount +1;
07414 
07415   Message(_("ROAR router: "));
07416   for(guint j=0;j<6;j++) {
07417     GList *failed = g_list_copy(r->failednets), *k = failed;
07418 
07419     k = failed;
07420     while(k) {
07421       failcount += roar_route(r, TOPOROUTER_ROUTE(k->data), threshold);
07422       k = k->next;
07423     }
07424     g_list_free(failed);
07425     
07426     printf("\tROAR pass %d - %d routed -  %d failed\n", j, g_list_length(r->routednets), g_list_length(r->failednets));
07427 
07428     if(!failcount || failcount >= pfailcount) {
07429       Message(_("%d nets remaining\n"), failcount);
07430       break;
07431     }
07432     Message(_("%d -> "), failcount);
07433     pfailcount = failcount;
07434   }
07435 
07436   return failcount;
07437 }
07438 
07439 gint
07440 route_detour_compare(toporouter_route_t **a, toporouter_route_t **b)
07441 { return ((*b)->score - (*b)->detourscore) - ((*a)->score - (*a)->detourscore); }
07442 
07443 
07444 
07445 void
07446 roar_detour_route(toporouter_t *r, toporouter_route_t *data)
07447 {
07448   gdouble pscore = data->score, nscore = 0.; 
07449   GList *netlists = NULL;
07450 
07451   route_checkpoint(data, NULL);
07452 
07453   REMOVE_ROUTING(data);
07454 
07455   netlists = g_list_prepend(NULL, data->netlist);
07456   netlists_recalculate(netlists, NULL);
07457 
07458   r->flags |= TOPOROUTER_FLAG_LEASTINVALID;
07459   if(route(r, data, 0)) {
07460     GList *conflicts, *j;  
07461 
07462     nscore = data->score;
07463     conflicts = route_conflicts(data);
07464 
07465     INSERT_ROUTING(data);
07466 
07467     r->flags &= ~TOPOROUTER_FLAG_LEASTINVALID;
07468 
07469     j = conflicts;
07470     while(j) {
07471       toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data);
07472       
07473       if(!g_list_find(netlists, conflict->netlist)) 
07474         netlists = g_list_prepend(netlists, conflict->netlist);
07475       pscore += conflict->score;
07476       
07477       route_checkpoint(conflict, NULL);
07478       REMOVE_ROUTING(conflict);
07479 
07480       j = j->next;
07481     }
07482     netlists_recalculate(netlists, NULL);
07483     
07484     j = conflicts;
07485     while(j) {
07486       toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data);
07487 
07488       if(route(r, conflict, 0)) { 
07489         cluster_merge(conflict);
07490         INSERT_ROUTING(conflict);
07491         nscore += conflict->score;
07492       }else{
07493         j = j->prev;
07494         goto roar_detour_route_rollback_int;
07495       }
07496       j = j->next;
07497     }
07498 
07499     if(nscore > pscore) {
07500       j = g_list_last(conflicts);
07501 roar_detour_route_rollback_int:     
07502       REMOVE_ROUTING(data);
07503 
07504       while(j) {
07505         toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data);
07506         REMOVE_ROUTING(conflict);
07507         delete_route(conflict, 1);
07508         j = j->prev;
07509       }
07510 
07511       j = g_list_last(conflicts);
07512       while(j) {
07513         toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data);
07514         route_restore(conflict);
07515         INSERT_ROUTING(conflict);
07516         j = j->prev;
07517       }
07518       delete_route(data, 1);
07519 
07520       goto roar_detour_route_rollback_exit;
07521 
07522     }
07523 
07524     g_list_free(conflicts);
07525   }else{
07526     r->flags &= ~TOPOROUTER_FLAG_LEASTINVALID;
07527 roar_detour_route_rollback_exit:    
07528     route_restore(data);
07529     INSERT_ROUTING(data);
07530   }
07531   netlists_recalculate(netlists, NULL);
07532 
07533   g_list_free(netlists);
07534 }
07535 
07536 void
07537 detour_router(toporouter_t *r) 
07538 {
07539   GList *i = r->routednets;
07540   guint n = g_list_length(r->routednets);
07541   GPtrArray* scores =  g_ptr_array_sized_new(n);
07542 
07543   while(i) {
07544     toporouter_route_t *curroute = TOPOROUTER_ROUTE(i->data);
07545     curroute->score = path_score(r, curroute->path);
07546     g_ptr_array_add(scores, i->data);
07547     i = i->next;
07548   }
07549   
07550   g_ptr_array_sort(scores, (GCompareFunc) route_detour_compare);
07551 
07552   r->flags |= TOPOROUTER_FLAG_DETOUR;
07553 
07554   for(toporouter_route_t **i = (toporouter_route_t **) scores->pdata; i < (toporouter_route_t **) scores->pdata + scores->len; i++) {
07555     toporouter_route_t *curroute = (*i);
07556    
07557     if(isfinite(curroute->score) && isfinite(curroute->detourscore)) {
07558 //    printf("%15s %15f \t %8f,%8f - %8f,%8f\n", (*i)->src->netlist + 2, (*i)->score - (*i)->detourscore,
07559 //        vx(curroute->mergebox1->point), vy(curroute->mergebox1->point),
07560 //        vx(curroute->mergebox2->point), vy(curroute->mergebox2->point));
07561 
07562       if(curroute->score - curroute->detourscore > ROAR_DETOUR_THRESHOLD) {
07563         roar_detour_route(r, curroute);
07564       }else break;
07565 
07566     }
07567   }
07568   printf("\n");
07569   
07570   r->flags ^= TOPOROUTER_FLAG_DETOUR;
07571 
07572   g_ptr_array_free(scores, TRUE);
07573 
07574 }
07575 
07576 gint
07577 rubix_router(toporouter_t *r, gint failcount)
07578 {
07579   GList *i, *ordering;
07580   order_nets_preroute_greedy(r, r->failednets, &ordering); 
07581 
07582   i = ordering;
07583   while(i) {
07584     toporouter_route_t *data = TOPOROUTER_ROUTE(i->data); 
07585     
07586     if(route(r, data, 0)) { 
07587       INSERT_ROUTING(data);
07588       cluster_merge(data);
07589       failcount--;
07590     }
07591 
07592     i = i->next;
07593   } 
07594 
07595   g_list_free(ordering);
07596 
07597   return failcount;
07598 }
07599 
07600 guint
07601 hybrid_router(toporouter_t *r)
07602 {
07603   gint failcount = g_list_length(r->failednets);
07604   r->flags |= TOPOROUTER_FLAG_AFTERORDER;
07605   r->flags |= TOPOROUTER_FLAG_AFTERRUBIX;
07606   failcount = rubix_router(r, failcount);
07607 
07608   Message(_("RUBIX router: %d nets remaining\n"), failcount);
07609   printf(_("RUBIX router: %d nets remaining\n"), failcount);
07610 
07611   r->flags |= TOPOROUTER_FLAG_GOFAR;
07612   
07613   for(guint i=0;i<6 && failcount;i++) {
07614     if(i % 2 == 1) { 
07615       failcount = roar_router(r, failcount, 5);
07616   //    printf("THRESH 5\n");
07617     }else{
07618       failcount = roar_router(r, failcount, 2);
07619   //    printf("THRESH 2\n");
07620     }
07621 
07622     detour_router(r);
07623   }
07624 
07625   failcount = roar_router(r, failcount, 2);
07626   detour_router(r);
07627   
07628   return failcount;
07629 }
07630 
07631 void
07632 parse_arguments(toporouter_t *r, int argc, char **argv) 
07633 {
07634   int i, tempint;
07635   for(i=0;i<argc;i++) {
07636     if(sscanf(argv[i], "viacost=%d", &tempint)) {
07637       /* XXX: We should be using PCB's generic value with unit parsing here */
07638       r->viacost = (double)tempint;
07639     }else if(sscanf(argv[i], "l%d", &tempint)) {
07640       gdouble *layer = (gdouble *)malloc(sizeof(gdouble));
07641       *layer = (double)tempint;
07642       r->keepoutlayers = g_list_prepend(r->keepoutlayers, layer);
07643     }
07644   }
07645   
07646   for (guint group = 0; group < max_group; group++)
07647     for (i = 0; i < PCB->LayerGroups.Number[group]; i++) 
07648       if ((PCB->LayerGroups.Entries[group][i] < max_copper_layer) && !(PCB->Data->Layer[PCB->LayerGroups.Entries[group][i]].On)) {
07649         gdouble *layer = (gdouble *)malloc(sizeof(gdouble));
07650         *layer = (double)group;
07651         r->keepoutlayers = g_list_prepend(r->keepoutlayers, layer);
07652       }
07653 
07654 }
07655 
07656 toporouter_t *
07657 toporouter_new(void) 
07658 {
07659   toporouter_t *r = (toporouter_t *)calloc(1, sizeof(toporouter_t));
07660   time_t ltime; 
07661 
07662   gettimeofday(&r->starttime, NULL);  
07663 
07664   r->netsort = netscore_pairwise_compare;
07665 
07666   r->destboxes = NULL;
07667   r->consumeddestboxes = NULL;
07668 
07669   r->paths = NULL;
07670 
07671   r->layers = NULL;
07672   r->flags = 0;
07673   r->viacost = VIA_COST_AS_DISTANCE;
07674 
07675   r->wiring_score = 0.;
07676 
07677   r->bboxes = NULL;
07678   r->bboxtree = NULL;
07679 
07680   r->netlists = g_ptr_array_new();
07681   r->routes = g_ptr_array_new();
07682 
07683   r->keepoutlayers = NULL;
07684 
07685   r->routednets = NULL;
07686   r->failednets = NULL;
07687 
07688   ltime=time(NULL); 
07689 
07690   gts_predicates_init();
07691 
07692   Message(_("Topological Autorouter\n"));
07693   Message(_("Started %s"),asctime(localtime(&ltime)));  
07694   Message(_("-------------------------------------\n"));
07695   return r;
07696 }
07697 
07698 void
07699 acquire_twonets(toporouter_t *r)
07700 {
07701   RAT_LOOP(PCB->Data);
07702     if( TEST_FLAG(SELECTEDFLAG, line) ) import_route(r, line);
07703   END_LOOP;
07704 //  /*
07705   if(!r->routes->len) {
07706     RAT_LOOP(PCB->Data);
07707       import_route(r, line);
07708     END_LOOP;
07709   }
07710 //     */    
07711 
07712 }
07713 
07714 toporouter_netlist_t *
07715 find_netlist_by_name(toporouter_t *r, char *name)
07716 {
07717   FOREACH_NETLIST(r->netlists) {
07718     if(!strcmp(netlist->netlist, name)) return netlist;
07719   } FOREACH_END;
07720   return NULL;
07721 }
07722 
07723 gint 
07724 toporouter_set_pair(toporouter_t *r, toporouter_netlist_t *n1, toporouter_netlist_t *n2)
07725 {
07726   if(!n1 || !n2) return 0;
07727   n1->pair = n2;
07728   n2->pair = n1;
07729   return 1;
07730 }
07731 
07732 static int 
07733 toporouter (int argc, char **argv, Coord x, Coord y)
07734 {
07735   toporouter_t *r = toporouter_new();
07736   parse_arguments(r, argc, argv);
07737   import_geometry(r);
07738   acquire_twonets(r);
07739 
07740 //if(!toporouter_set_pair(r, find_netlist_by_name(r, "  DRAM_DQS_N"), find_netlist_by_name(r, "  DRAM_DQS"))) {
07741 //  printf("Couldn't associate pair\n");
07742 //}
07743 
07744   hybrid_router(r);
07745 /*
07746   for(gint i=0;i<groupcount();i++) {
07747    gts_surface_foreach_edge(r->layers[i].surface, space_edge, NULL);
07748   }
07749   {
07750     int i;
07751     for(i=0;i<groupcount();i++) {
07752       char buffer[256];
07753       sprintf(buffer, "route%d.png", i);
07754       toporouter_draw_surface(r, r->layers[i].surface, buffer, 1024, 1024, 2, NULL, i, NULL);
07755     }
07756   }
07757 */
07758   toporouter_export(r);
07759   toporouter_free(r);
07760   
07761   SaveUndoSerialNumber ();
07762   DeleteRats (false);
07763   RestoreUndoSerialNumber ();
07764   AddAllRats (false, NULL);
07765   RestoreUndoSerialNumber ();
07766   IncrementUndoSerialNumber ();
07767   Redraw ();
07768 
07769   return 0;
07770 }
07771 
07772 static int 
07773 escape (int argc, char **argv, Coord x, Coord y)
07774 {
07775   guint dir, viax, viay;
07776   gdouble pitch, dx, dy;
07777 
07778   if(argc != 1) return 0;
07779 
07780   dir = atoi(argv[0]);
07781 
07782 
07783   ALLPAD_LOOP(PCB->Data);
07784   {
07785     if( TEST_FLAG(SELECTEDFLAG, pad) ) {
07786       PinType *via;
07787       LineType *line;
07788 
07789       PadType *pad0 = element->Pad->data;
07790       PadType *pad1 = g_list_next (element->Pad)->data;
07791 
07792       pitch = hypot (pad0->Point1.X - pad1->Point1.X, pad0->Point1.Y - pad1->Point1.Y);
07793 
07794       dx = pitch / 2;
07795       dy = pitch / 2;
07796 
07797       switch(dir) {
07798         case 1:
07799           viax = pad->Point1.X - dx;
07800           viay = pad->Point1.Y + dy;
07801           break;
07802         case 3:
07803           viax = pad->Point1.X + dx;
07804           viay = pad->Point1.Y + dy;
07805           break;
07806         case 9:
07807           viax = pad->Point1.X + dx;
07808           viay = pad->Point1.Y - dy;
07809           break;
07810         case 7:
07811           viax = pad->Point1.X - dx;
07812           viay = pad->Point1.Y - dy;
07813           break;
07814         case 2:
07815           viax = pad->Point1.X;
07816           viay = pad->Point1.Y + dy;
07817           break;
07818         case 8:
07819           viax = pad->Point1.X;
07820           viay = pad->Point1.Y - dy;
07821           break;
07822         case 4:
07823           viax = pad->Point1.X - dx;
07824           viay = pad->Point1.Y;
07825           break;
07826         case 6:
07827           viax = pad->Point1.X + dx;
07828           viay = pad->Point1.Y;
07829           break;
07830         default:
07831           printf("ERROR: escape() with bad direction (%d)\n", dir);
07832           return 1;
07833       }
07834       
07835       if ((via = CreateNewVia (PCB->Data, viax, viay,
07836               Settings.ViaThickness, 2 * Settings.Keepaway,
07837               0, Settings.ViaDrillingHole, NULL,
07838               NoFlags ())) != NULL)
07839       {
07840         AddObjectToCreateUndoList (VIA_TYPE, via, via, via);
07841 //        if (gui->shift_is_pressed ())
07842 //          ChangeObjectThermal (VIA_TYPE, via, via, via, PCB->ThermStyle);
07843         DrawVia (via);
07844         if((line = CreateDrawnLineOnLayer (CURRENT, pad->Point1.X + 1., pad->Point1.Y + 1., viax + 1., viay + 1.,
07845                 Settings.LineThickness, 2 * Settings.Keepaway,
07846                 NoFlags())))        
07847         {
07848 
07849           AddObjectToCreateUndoList (LINE_TYPE, CURRENT, line, line);
07850           DrawLine (CURRENT, line);
07851 
07852         }
07853       
07854       }
07855    
07856     }
07857   }
07858   END_LOOP;
07859   END_LOOP;
07860 
07861   IncrementUndoSerialNumber ();
07862   Draw ();
07863   return 0;
07864 }
07865 
07866 static HID_Action toporouter_action_list[] = {
07867   {"Escape", N_("Select a set of pads"), escape,
07868     N_("Pad escape"), N_("Escape()")},
07869   {"Toporouter", N_("Select net(s)"), toporouter,
07870     N_("Topological autorouter"), N_("Toporouter()")}
07871 };
07872 
07873 REGISTER_ACTIONS (toporouter_action_list)
07874 
07875 void hid_toporouter_init()
07876 {
07877   register_toporouter_action_list();
07878 }
07879