Introduce POLYGONHOLE_MODE for creating holes in polygons
[geda-pcb/gde.git] / src / toporouter.c
blobfa57635b19443f044ffbda174608d7d2602d4066
1 /*
2 * COPYRIGHT
4 * Topological Autorouter for
5 * PCB, interactive printed circuit board design
6 * Copyright (C) 2009 Anthony Blake
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * Contact addresses for email:
23 * Anthony Blake, tonyb33@gmail.com
27 * This is *EXPERIMENTAL* code.
29 * As the code is experimental, the algorithms and code
30 * are likely to change. Which means it isn't documented
31 * or optimized. If you would like to learn about Topological
32 * Autorouters, the following papers are good starting points:
34 * This file implements a topological autorouter, and uses techniques from the
35 * following publications:
37 * Dayan, T. and Dai, W.W.M., "Layer Assignment for a Rubber Band Router" Tech
38 * Report UCSC-CRL-92-50, Univ. of California, Santa Cruz, 1992.
40 * Dai, W.W.M and Dayan, T. and Staepelaere, D., "Topological Routing in SURF:
41 * Generating a Rubber-Band Sketch" Proc. 28th ACM/IEEE Design Automation
42 * Conference, 1991, pp. 39-44.
44 * David Staepelaere, Jeffrey Jue, Tal Dayan, Wayne Wei-Ming Dai, "SURF:
45 * Rubber-Band Routing System for Multichip Modules," IEEE Design and Test of
46 * Computers ,vol. 10, no. 4, pp. 18-26, October/December, 1993.
48 * Dayan, T., "Rubber-band based topological router" PhD Thesis, Univ. of
49 * California, Santa Cruz, 1997.
51 * David Staepelaere, "Geometric transformations for a rubber-band sketch"
52 * Master's thesis, Univ. of California, Santa Cruz, September 1992.
57 #include "toporouter.h"
59 static void
60 toporouter_edge_init (toporouter_edge_t *edge)
62 edge->routing = NULL;
63 edge->flags = 0;
66 toporouter_edge_class_t *
67 toporouter_edge_class(void)
69 static toporouter_edge_class_t *class = NULL;
71 if (class == NULL) {
72 GtsObjectClassInfo constraint_info = {
73 "toporouter_edge_t",
74 sizeof (toporouter_edge_t),
75 sizeof (toporouter_edge_class_t),
76 (GtsObjectClassInitFunc) NULL,
77 (GtsObjectInitFunc) toporouter_edge_init,
78 (GtsArgSetFunc) NULL,
79 (GtsArgGetFunc) NULL
81 class = gts_object_class_new (GTS_OBJECT_CLASS (gts_edge_class ()), &constraint_info);
84 return class;
87 static void
88 toporouter_bbox_init (toporouter_bbox_t *box)
90 box->data = NULL;
91 box->type = OTHER;
92 box->constraints = NULL;
93 box->cluster = NULL;
96 toporouter_bbox_class_t *
97 toporouter_bbox_class(void)
99 static toporouter_bbox_class_t *class = NULL;
101 if (class == NULL) {
102 GtsObjectClassInfo constraint_info = {
103 "toporouter_bbox_t",
104 sizeof (toporouter_bbox_t),
105 sizeof (toporouter_bbox_class_t),
106 (GtsObjectClassInitFunc) NULL,
107 (GtsObjectInitFunc) toporouter_bbox_init,
108 (GtsArgSetFunc) NULL,
109 (GtsArgGetFunc) NULL
111 class = gts_object_class_new (GTS_OBJECT_CLASS (gts_bbox_class ()), &constraint_info);
114 return class;
117 static void
118 toporouter_vertex_class_init (toporouter_vertex_class_t *klass)
123 static void
124 toporouter_vertex_init (toporouter_vertex_t *vertex)
126 vertex->bbox = NULL;
127 vertex->parent = NULL;
128 vertex->child = NULL;
129 vertex->flags = 0;
130 vertex->routingedge = NULL;
131 vertex->arc = NULL;
132 vertex->oproute = NULL;
133 vertex->route = NULL;
135 vertex->gcost = 0.;
136 vertex->hcost = 0.;
137 vertex->gn = 0;
140 toporouter_vertex_class_t *
141 toporouter_vertex_class(void)
143 static toporouter_vertex_class_t *klass = NULL;
145 if (klass == NULL) {
146 GtsObjectClassInfo constraint_info = {
147 "toporouter_vertex_t",
148 sizeof (toporouter_vertex_t),
149 sizeof (toporouter_vertex_class_t),
150 (GtsObjectClassInitFunc) toporouter_vertex_class_init,
151 (GtsObjectInitFunc) toporouter_vertex_init,
152 (GtsArgSetFunc) NULL,
153 (GtsArgGetFunc) NULL
155 klass = gts_object_class_new (GTS_OBJECT_CLASS (gts_vertex_class ()), &constraint_info);
158 return klass;
161 static void
162 toporouter_constraint_class_init (toporouter_constraint_class_t *klass)
167 static void
168 toporouter_constraint_init (toporouter_constraint_t *constraint)
170 constraint->box = NULL;
171 constraint->routing = NULL;
174 toporouter_constraint_class_t *
175 toporouter_constraint_class(void)
177 static toporouter_constraint_class_t *klass = NULL;
179 if (klass == NULL) {
180 GtsObjectClassInfo constraint_info = {
181 "toporouter_constraint_t",
182 sizeof (toporouter_constraint_t),
183 sizeof (toporouter_constraint_class_t),
184 (GtsObjectClassInitFunc) toporouter_constraint_class_init,
185 (GtsObjectInitFunc) toporouter_constraint_init,
186 (GtsArgSetFunc) NULL,
187 (GtsArgGetFunc) NULL
189 klass = gts_object_class_new (GTS_OBJECT_CLASS (gts_constraint_class ()), &constraint_info);
192 return klass;
195 static void
196 toporouter_arc_init (toporouter_arc_t *arc)
198 arc->x0 = -1.;
199 arc->y0 = -1.;
200 arc->x1 = -1.;
201 arc->y1 = -1.;
202 arc->centre = NULL;
203 arc->v = NULL;
204 arc->v1 = NULL;
205 arc->v2 = NULL;
206 arc->r = -1.;
207 arc->dir = 31337;
208 arc->clearance = NULL;
209 arc->oproute = NULL;
212 toporouter_arc_class_t *
213 toporouter_arc_class(void)
215 static toporouter_arc_class_t *klass = NULL;
217 if (klass == NULL) {
218 GtsObjectClassInfo constraint_info = {
219 "toporouter_arc_t",
220 sizeof (toporouter_arc_t),
221 sizeof (toporouter_arc_class_t),
222 (GtsObjectClassInitFunc) NULL,
223 (GtsObjectInitFunc) toporouter_arc_init,
224 (GtsArgSetFunc) NULL,
225 (GtsArgGetFunc) NULL
227 klass = gts_object_class_new (GTS_OBJECT_CLASS (gts_constraint_class ()), &constraint_info);
230 return klass;
233 #define MARGIN 10.0f
235 drawing_context_t *
236 toporouter_output_init(int w, int h, char *filename)
238 drawing_context_t *dc;
240 dc = malloc(sizeof(drawing_context_t));
242 dc->iw = w;
243 dc->ih = h;
244 dc->filename = filename;
246 /* Calculate scaling to maintain aspect ratio */
247 if(PCB->MaxWidth > PCB->MaxHeight) {
248 /* Scale board width to match image width minus 2xMARGIN */
249 dc->s = ((double)dc->iw - (2 * MARGIN)) / (double)PCB->MaxWidth;
250 dc->ih = (double)PCB->MaxHeight * dc->s + (2 * MARGIN);
251 }else{
252 /* Scale board height to match image height minus 2xMARGIN */
253 dc->s = ((double)dc->ih - (2 * MARGIN)) / (double)PCB->MaxHeight;
254 dc->iw = (double)PCB->MaxWidth * dc->s + (2 * MARGIN);
257 #if TOPO_OUTPUT_ENABLED
258 dc->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dc->iw, dc->ih);
259 dc->cr = cairo_create (dc->surface);
261 cairo_rectangle (dc->cr, 0, 0, dc->iw, dc->ih);
262 cairo_set_source_rgb (dc->cr, 0, 0, 0);
263 cairo_fill (dc->cr);
265 #endif
267 return dc;
270 void
271 toporouter_output_close(drawing_context_t *dc)
273 #if TOPO_OUTPUT_ENABLED
274 cairo_surface_write_to_png (dc->surface, dc->filename);
275 cairo_destroy (dc->cr);
276 cairo_surface_destroy (dc->surface);
277 #endif
280 gdouble
281 lookup_keepaway(char *name)
283 if(name)
284 STYLE_LOOP(PCB);
286 // if(!strcmp(style->Name, name)) return style->Keepaway + 1.;
287 if(!strcmp(style->Name, name)) return style->Keepaway;
289 END_LOOP;
290 // return Settings.Keepaway + 1.;
291 return Settings.Keepaway ;
294 gdouble
295 lookup_thickness(char *name)
297 if(name)
298 STYLE_LOOP(PCB);
300 if(!strcmp(style->Name, name)) return style->Thick;
302 END_LOOP;
303 return Settings.LineThickness;
306 inline gdouble
307 cluster_keepaway(toporouter_cluster_t *cluster)
309 if(cluster) return lookup_keepaway(cluster->netlist->style);
310 return lookup_keepaway(NULL);
313 inline gdouble
314 cluster_thickness(toporouter_cluster_t *cluster)
316 if(cluster) return lookup_thickness(cluster->netlist->style);
317 return lookup_thickness(NULL);
320 gint
321 toporouter_draw_vertex(gpointer item, gpointer data)
323 #if TOPO_OUTPUT_ENABLED
324 drawing_context_t *dc = (drawing_context_t *) data;
325 toporouter_vertex_t *tv;
326 PinType *pin;
327 PadType *pad;
328 gdouble blue;
330 if(TOPOROUTER_IS_VERTEX((GtsObject*)item)) {
331 tv = TOPOROUTER_VERTEX((GtsObject*)item);
333 if(tv->flags & VERTEX_FLAG_RED) {
334 cairo_set_source_rgba(dc->cr, 1., 0., 0., 0.8f);
335 cairo_arc(dc->cr,
336 tv->v.p.x * dc->s + MARGIN,
337 tv->v.p.y * dc->s + MARGIN,
338 500. * dc->s, 0, 2 * M_PI);
339 cairo_fill(dc->cr);
341 }else if(tv->flags & VERTEX_FLAG_GREEN) {
342 cairo_set_source_rgba(dc->cr, 0., 1., 0., 0.8f);
343 cairo_arc(dc->cr,
344 tv->v.p.x * dc->s + MARGIN,
345 tv->v.p.y * dc->s + MARGIN,
346 500. * dc->s, 0, 2 * M_PI);
347 cairo_fill(dc->cr);
349 }else if(tv->flags & VERTEX_FLAG_BLUE) {
350 cairo_set_source_rgba(dc->cr, 0., 0., 1., 0.8f);
351 cairo_arc(dc->cr,
352 tv->v.p.x * dc->s + MARGIN,
353 tv->v.p.y * dc->s + MARGIN,
354 500. * dc->s, 0, 2 * M_PI);
355 cairo_fill(dc->cr);
359 //printf("tv->type = %d\n", tv->type);
360 if(!dc->mode) {
361 if(tv->bbox) {
362 pin = (PinType*) tv->bbox->data;
363 pad = (PadType*) tv->bbox->data;
365 blue = 0.0f;
366 switch(tv->bbox->type) {
367 case PIN:
368 cairo_set_source_rgba(dc->cr, 1.0f, 0., 0.0f, 0.2f);
369 cairo_arc(dc->cr,
370 tv->v.p.x * dc->s + MARGIN,
371 tv->v.p.y * dc->s + MARGIN,
372 (((gdouble)pin->Thickness / 2.0f) + (gdouble)lookup_keepaway(pin->Name) ) * dc->s, 0, 2 * M_PI);
373 cairo_fill(dc->cr);
375 cairo_set_source_rgba(dc->cr, 1.0f, 0., 0., 0.4f);
376 cairo_arc(dc->cr,
377 tv->v.p.x * dc->s + MARGIN,
378 tv->v.p.y * dc->s + MARGIN,
379 (gdouble)(pin->Thickness) / 2.0f * dc->s,
380 0, 2 * M_PI);
381 cairo_fill(dc->cr);
383 break;
384 case VIA:
385 cairo_set_source_rgba(dc->cr, 0.0f, 0., 1., 0.2f);
386 cairo_arc(dc->cr,
387 tv->v.p.x * dc->s + MARGIN,
388 tv->v.p.y * dc->s + MARGIN,
389 (((gdouble)pin->Thickness / 2.0f) + (gdouble)lookup_keepaway(pin->Name) ) * dc->s, 0, 2 * M_PI);
390 cairo_fill(dc->cr);
392 cairo_set_source_rgba(dc->cr, 0.0f, 0., 1., 0.4f);
393 cairo_arc(dc->cr,
394 tv->v.p.x * dc->s + MARGIN,
395 tv->v.p.y * dc->s + MARGIN,
396 (gdouble)(pin->Thickness) / 2.0f * dc->s,
397 0, 2 * M_PI);
398 cairo_fill(dc->cr);
400 break;
401 case PAD:
402 cairo_set_source_rgba(dc->cr, 0.0f, 1., 0., 0.5f);
403 cairo_arc(dc->cr,
404 tv->v.p.x * dc->s + MARGIN,
405 tv->v.p.y * dc->s + MARGIN,
406 400. * dc->s, 0, 2 * M_PI);
407 cairo_fill(dc->cr);
409 break;
410 default:
411 break;
414 }else{
415 if(tv->flags & VERTEX_FLAG_BLUE) {
416 cairo_set_source_rgba(dc->cr, 0., 0., 1., 0.8f);
417 cairo_arc(dc->cr,
418 tv->v.p.x * dc->s + MARGIN,
419 tv->v.p.y * dc->s + MARGIN,
420 500. * dc->s, 0, 2 * M_PI);
421 cairo_fill(dc->cr);
422 }else if(tv->flags & VERTEX_FLAG_RED) {
423 cairo_set_source_rgba(dc->cr, 1., 0., 0., 0.8f);
424 cairo_arc(dc->cr,
425 tv->v.p.x * dc->s + MARGIN,
426 tv->v.p.y * dc->s + MARGIN,
427 500. * dc->s, 0, 2 * M_PI);
428 cairo_fill(dc->cr);
430 }else if(tv->flags & VERTEX_FLAG_GREEN) {
431 cairo_set_source_rgba(dc->cr, 0., 1., 0., 0.8f);
432 cairo_arc(dc->cr,
433 tv->v.p.x * dc->s + MARGIN,
434 tv->v.p.y * dc->s + MARGIN,
435 500. * dc->s, 0, 2 * M_PI);
436 cairo_fill(dc->cr);
440 }else{
441 fprintf(stderr, "Unknown data passed to toporouter_draw_vertex, aborting foreach\n");
442 return -1;
444 return 0;
445 #else
446 return -1;
447 #endif
450 gint
451 toporouter_draw_edge(gpointer item, gpointer data)
453 #if TOPO_OUTPUT_ENABLED
454 drawing_context_t *dc = (drawing_context_t *) data;
455 toporouter_edge_t *te;
456 toporouter_constraint_t *tc;
458 if(TOPOROUTER_IS_EDGE((GtsObject*)item)) {
459 te = TOPOROUTER_EDGE((GtsObject*)item);
460 cairo_set_source_rgba(dc->cr, 1.0f, 1.0f, 1.0f, 0.5f);
461 cairo_move_to(dc->cr,
462 te->e.segment.v1->p.x * dc->s + MARGIN,
463 te->e.segment.v1->p.y * dc->s + MARGIN);
464 cairo_line_to(dc->cr,
465 te->e.segment.v2->p.x * dc->s + MARGIN,
466 te->e.segment.v2->p.y * dc->s + MARGIN);
467 cairo_stroke(dc->cr);
468 }else if(TOPOROUTER_IS_CONSTRAINT((GtsObject*)item)) {
469 tc = TOPOROUTER_CONSTRAINT((GtsObject*)item);
470 if(tc->box) {
471 switch(tc->box->type) {
472 case BOARD:
473 cairo_set_source_rgba(dc->cr, 1.0f, 0.0f, 1.0f, 0.9f);
474 cairo_move_to(dc->cr,
475 tc->c.edge.segment.v1->p.x * dc->s + MARGIN,
476 tc->c.edge.segment.v1->p.y * dc->s + MARGIN);
477 cairo_line_to(dc->cr,
478 tc->c.edge.segment.v2->p.x * dc->s + MARGIN,
479 tc->c.edge.segment.v2->p.y * dc->s + MARGIN);
480 cairo_stroke(dc->cr);
481 break;
482 case PIN:
483 case PAD:
484 cairo_set_source_rgba(dc->cr, 1.0f, 0.0f, 0.0f, 0.9f);
485 cairo_move_to(dc->cr,
486 tc->c.edge.segment.v1->p.x * dc->s + MARGIN,
487 tc->c.edge.segment.v1->p.y * dc->s + MARGIN);
488 cairo_line_to(dc->cr,
489 tc->c.edge.segment.v2->p.x * dc->s + MARGIN,
490 tc->c.edge.segment.v2->p.y * dc->s + MARGIN);
491 cairo_stroke(dc->cr);
492 break;
493 case LINE:
494 cairo_set_source_rgba(dc->cr, 0.0f, 1.0f, 0.0f, 0.9f);
495 cairo_move_to(dc->cr,
496 tc->c.edge.segment.v1->p.x * dc->s + MARGIN,
497 tc->c.edge.segment.v1->p.y * dc->s + MARGIN);
498 cairo_line_to(dc->cr,
499 tc->c.edge.segment.v2->p.x * dc->s + MARGIN,
500 tc->c.edge.segment.v2->p.y * dc->s + MARGIN);
501 cairo_stroke(dc->cr);
502 break;
504 default:
505 cairo_set_source_rgba(dc->cr, 1.0f, 1.0f, 0.0f, 0.9f);
506 cairo_move_to(dc->cr,
507 tc->c.edge.segment.v1->p.x * dc->s + MARGIN,
508 tc->c.edge.segment.v1->p.y * dc->s + MARGIN);
509 cairo_line_to(dc->cr,
510 tc->c.edge.segment.v2->p.x * dc->s + MARGIN,
511 tc->c.edge.segment.v2->p.y * dc->s + MARGIN);
512 cairo_stroke(dc->cr);
513 break;
515 }else{
516 printf("CONSTRAINT without box\n");
519 }else{
520 fprintf(stderr, "Unknown data passed to toporouter_draw_edge, aborting foreach\n");
521 return -1;
524 return 0;
525 #else
526 return -1;
527 #endif
530 //#define vertex_bbox(v) (v->bbox)
531 ///*
532 toporouter_bbox_t *
533 vertex_bbox(toporouter_vertex_t *v)
535 return v ? v->bbox : NULL;
537 //*/
538 char *
539 vertex_netlist(toporouter_vertex_t *v)
541 toporouter_bbox_t *box = vertex_bbox(v);
543 if(box && box->cluster) return box->cluster->netlist->netlist;
545 return NULL;
548 char *
549 constraint_netlist(toporouter_constraint_t *c)
551 toporouter_bbox_t *box = c->box;
553 if(box && box->cluster) return box->cluster->netlist->netlist;
555 return NULL;
558 inline guint
559 epsilon_equals(gdouble a, gdouble b)
561 if(a > b - EPSILON && a < b + EPSILON) return 1;
562 return 0;
565 void
566 print_bbox(toporouter_bbox_t *box)
568 printf("[BBOX ");
569 switch(box->type) {
570 case PAD:
571 printf("PAD "); break;
572 case PIN:
573 printf("PIN "); break;
574 case VIA:
575 printf("VIA "); break;
576 case LINE:
577 printf("LINE "); break;
578 case BOARD:
579 printf("BOARD "); break;
580 case POLYGON:
581 printf("POLYGON "); break;
582 default:
583 printf("UNKNOWN "); break;
586 if(box->point)
587 printf("P: %f,%f,%f ", vx(box->point), vy(box->point), vz(box->point));
588 else
589 printf("P: NONE ");
591 printf("LAYER: %d ", box->layer);
592 printf("CLUSTER: %d]\n", box->cluster ? box->cluster->c : -1);
596 void
597 print_vertex(toporouter_vertex_t *v)
599 if(v)
600 printf("[V %f,%f,%f ", vx(v), vy(v), vz(v));
601 else
602 printf("[V (null) ");
604 printf("%s ", vertex_netlist(v));
605 if(v->route && v->route->netlist)
606 printf("%s ", v->route->netlist->netlist);
608 if(v->routingedge) {
609 guint n = g_list_length(edge_routing(v->routingedge));
610 guint pos = g_list_index(edge_routing(v->routingedge), v);
612 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge))
613 printf("[CONST ");
614 else
615 printf("[EDGE ");
617 printf("%d/%d] ", pos, n);
622 if(v->flags & VERTEX_FLAG_TEMP) printf("TEMP ");
623 if(v->flags & VERTEX_FLAG_ROUTE) printf("ROUTE ");
624 if(v->flags & VERTEX_FLAG_SPECCUT) printf("SPECCUT ");
625 if(v->flags & VERTEX_FLAG_FAKE) printf("FAKE ");
627 printf("]\n");
631 gdouble
632 vertex_net_thickness(toporouter_vertex_t *v)
634 toporouter_bbox_t *box = vertex_bbox(v);
636 if(!box) {
638 while(v && (v->flags & VERTEX_FLAG_TEMP || v->flags & VERTEX_FLAG_ROUTE)) {
639 v = v->parent;
642 box = vertex_bbox(v);
644 }else{
645 if(box->type == PIN || box->type == VIA) {
646 PinType *pin = (PinType *)box->data;
647 if(TEST_FLAG(SQUAREFLAG, pin) || TEST_FLAG(OCTAGONFLAG, pin)) {
648 return 0.;
650 // return ((PinType *)box->data)->Thickness + 1.;
651 return ((PinType *)box->data)->Thickness;
652 }else if(box->type == PAD) {
653 PadType *pad = (PadType *)box->data;
654 if(pad->Point1.X == pad->Point2.X && pad->Point1.Y == pad->Point2.Y && !TEST_FLAG(SQUAREFLAG, pad)) {
655 return pad->Thickness;
657 return 0.;
658 }else if(box->type == BOARD) {
659 return 0.;
660 }else if(box->type == LINE) {
661 LineType *line = (LineType *) box->data;
662 return line->Thickness;
663 }else if(box->type == POLYGON) {
664 return 0.;
667 printf("Unrecognized type in thickness lookup..\n");
670 // if(!box || !box->cluster) return Settings.LineThickness + 1.;
671 if(!box || !box->cluster) return Settings.LineThickness;
673 return cluster_thickness(box->cluster);
676 gdouble
677 vertex_net_keepaway(toporouter_vertex_t *v)
679 toporouter_bbox_t *box = vertex_bbox(v);
680 if(!box) {
682 while(v && (v->flags & VERTEX_FLAG_TEMP || v->flags & VERTEX_FLAG_ROUTE)) {
683 v = v->parent;
685 box = vertex_bbox(v);
687 else{
688 // if(box->type == PIN || box->type == VIA)
689 // return ((PinType *)box->data)->Clearance;
690 // else if(box->type == PAD)
691 // return ((PadType *)box->data)->Clearance;
695 // if(!box || !box->cluster) return Settings.Keepaway + 1.;
696 if(!box || !box->cluster) return Settings.Keepaway;
697 return cluster_keepaway(box->cluster);
700 void
701 print_trace (void)
703 void *array[10];
704 size_t size;
705 char **strings;
706 size_t i;
708 size = backtrace (array, 10);
709 strings = backtrace_symbols (array, size);
711 printf ("Obtained %zd stack frames.\n", size);
713 for (i = 0; i < size; i++)
714 printf ("%s\n", strings[i]);
716 free (strings);
719 /* fills in x and y with coordinates of point from a towards b of distance d */
720 void
721 point_from_point_to_point(toporouter_vertex_t *a, toporouter_vertex_t *b, gdouble d, gdouble *x, gdouble *y)
723 gdouble dx = vx(b) - vx(a);
724 gdouble dy = vy(b) - vy(a);
725 gdouble theta = atan(fabs(dy/dx));
727 //#ifdef DEBUG_EXPORT
728 if(!finite(theta)) {
729 // printf("!finte(theta): a = %f,%f b = %f,%f d = %f\n", vx(a), vy(a), vx(b), vy(b), d);
730 // print_trace();
731 //TODO: this shouldn't happen, fix the hack
732 *x = vx(a);
733 *y = vy(a);
734 return;
736 //#endif
738 g_assert(finite(theta));
740 *x = vx(a); *y = vy(a);
742 if( dx >= 0. ) {
744 if( dy >= 0. ) {
745 *x += d * cos(theta);
746 *y += d * sin(theta);
747 }else{
748 *x += d * cos(theta);
749 *y -= d * sin(theta);
752 }else{
754 if( dy >= 0. ) {
755 *x -= d * cos(theta);
756 *y += d * sin(theta);
757 }else{
758 *x -= d * cos(theta);
759 *y -= d * sin(theta);
766 inline gint
767 coord_wind(gdouble ax, gdouble ay, gdouble bx, gdouble by, gdouble cx, gdouble cy)
769 gdouble rval, dx1, dx2, dy1, dy2;
770 dx1 = bx - ax; dy1 = by - ay;
771 dx2 = cx - bx; dy2 = cy - by;
772 rval = (dx1*dy2)-(dy1*dx2);
773 return (rval > EPSILON) ? 1 : ((rval < -EPSILON) ? -1 : 0);
776 /* wind_v:
777 * returns 1,0,-1 for counterclockwise, collinear or clockwise, respectively.
779 int
780 point_wind(GtsPoint *a, GtsPoint *b, GtsPoint *c)
782 gdouble rval, dx1, dx2, dy1, dy2;
783 dx1 = b->x - a->x; dy1 = b->y - a->y;
784 dx2 = c->x - b->x; dy2 = c->y - b->y;
785 rval = (dx1*dy2)-(dy1*dx2);
786 return (rval > EPSILON) ? 1 : ((rval < -EPSILON) ? -1 : 0);
789 inline int
790 vertex_wind(GtsVertex *a, GtsVertex *b, GtsVertex *c)
792 return point_wind(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c));
795 inline int
796 tvertex_wind(toporouter_vertex_t *a, toporouter_vertex_t *b, toporouter_vertex_t *c)
798 return point_wind(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c));
801 int
802 sloppy_point_wind(GtsPoint *a, GtsPoint *b, GtsPoint *c)
804 gdouble rval, dx1, dx2, dy1, dy2;
805 dx1 = b->x - a->x; dy1 = b->y - a->y;
806 dx2 = c->x - b->x; dy2 = c->y - b->y;
807 rval = (dx1*dy2)-(dy1*dx2);
808 return (rval > 10.) ? 1 : ((rval < -10.) ? -1 : 0);
811 inline int
812 sloppy_vertex_wind(GtsVertex *a, GtsVertex *b, GtsVertex *c)
814 return point_wind(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c));
817 /* moves vertex v d units in the direction of vertex p */
818 void
819 coord_move_towards_coord_values(gdouble ax, gdouble ay, gdouble px, gdouble py, gdouble d, gdouble *x, gdouble *y)
821 gdouble dx = px - ax;
822 gdouble dy = py - ay;
823 gdouble theta = atan(fabs(dy/dx));
826 if(!finite(theta)) {
827 printf("!finite(theta) a = %f,%f p = %f,%f d = %f\n",
828 ax, ay, px, py, d);
832 g_assert(finite(theta));
834 if( dx >= 0. ) {
836 if( dy >= 0. ) {
837 *x = ax + (d * cos(theta));
838 *y = ay + (d * sin(theta));
839 }else{
840 *x = ax + (d * cos(theta));
841 *y = ay - (d * sin(theta));
844 }else{
846 if( dy >= 0. ) {
847 *x = ax - (d * cos(theta));
848 *y = ay + (d * sin(theta));
849 }else{
850 *x = ax - (d * cos(theta));
851 *y = ay - (d * sin(theta));
858 /* moves vertex v d units in the direction of vertex p */
859 void
860 vertex_move_towards_point_values(GtsVertex *v, gdouble px, gdouble py, gdouble d, gdouble *x, gdouble *y)
862 gdouble dx = px - GTS_POINT(v)->x;
863 gdouble dy = py - GTS_POINT(v)->y;
864 gdouble theta = atan(fabs(dy/dx));
866 g_assert(finite(theta));
868 if( dx >= 0. ) {
870 if( dy >= 0. ) {
871 *x = GTS_POINT(v)->x + (d * cos(theta));
872 *y = GTS_POINT(v)->y + (d * sin(theta));
873 }else{
874 *x = GTS_POINT(v)->x + (d * cos(theta));
875 *y = GTS_POINT(v)->y - (d * sin(theta));
878 }else{
880 if( dy >= 0. ) {
881 *x = GTS_POINT(v)->x - (d * cos(theta));
882 *y = GTS_POINT(v)->y + (d * sin(theta));
883 }else{
884 *x = GTS_POINT(v)->x - (d * cos(theta));
885 *y = GTS_POINT(v)->y - (d * sin(theta));
892 /* moves vertex v d units in the direction of vertex p */
893 void
894 vertex_move_towards_vertex_values(GtsVertex *v, GtsVertex *p, gdouble d, gdouble *x, gdouble *y)
896 gdouble dx = GTS_POINT(p)->x - GTS_POINT(v)->x;
897 gdouble dy = GTS_POINT(p)->y - GTS_POINT(v)->y;
898 gdouble theta = atan(fabs(dy/dx));
900 g_assert(finite(theta));
902 if( dx >= 0. ) {
904 if( dy >= 0. ) {
905 *x = GTS_POINT(v)->x + (d * cos(theta));
906 *y = GTS_POINT(v)->y + (d * sin(theta));
907 }else{
908 *x = GTS_POINT(v)->x + (d * cos(theta));
909 *y = GTS_POINT(v)->y - (d * sin(theta));
912 }else{
914 if( dy >= 0. ) {
915 *x = GTS_POINT(v)->x - (d * cos(theta));
916 *y = GTS_POINT(v)->y + (d * sin(theta));
917 }else{
918 *x = GTS_POINT(v)->x - (d * cos(theta));
919 *y = GTS_POINT(v)->y - (d * sin(theta));
926 #define tv_on_layer(v,l) (l == TOPOROUTER_BBOX(TOPOROUTER_VERTEX(v)->boxes->data)->layer)
928 inline gdouble
929 min_spacing(toporouter_vertex_t *v1, toporouter_vertex_t *v2)
932 gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms;
933 // toporouter_edge_t *e = v1->routingedge;
935 v1halfthick = vertex_net_thickness(TOPOROUTER_VERTEX(v1)) / 2.;
936 v2halfthick = vertex_net_thickness(TOPOROUTER_VERTEX(v2)) / 2.;
938 v1keepaway = vertex_net_keepaway(TOPOROUTER_VERTEX(v1));
939 v2keepaway = vertex_net_keepaway(TOPOROUTER_VERTEX(v2));
941 ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway);
943 #ifdef SPACING_DEBUG
944 printf("v1halfthick = %f v2halfthick = %f v1keepaway = %f v2keepaway = %f ms = %f\n",
945 v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms);
946 #endif
948 return ms;
951 // v1 is a vertex in the CDT, and v2 is a net... other way around?
952 inline gdouble
953 min_vertex_net_spacing(toporouter_vertex_t *v1, toporouter_vertex_t *v2)
956 gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms;
958 v1halfthick = vertex_net_thickness(TOPOROUTER_VERTEX(v1)) / 2.;
959 v2halfthick = cluster_thickness(vertex_bbox(v2)->cluster) / 2.;
961 v1keepaway = vertex_net_keepaway(TOPOROUTER_VERTEX(v1));
962 v2keepaway = cluster_keepaway(vertex_bbox(v2)->cluster);
964 ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway);
966 return ms;
969 inline gdouble
970 min_oproute_vertex_spacing(toporouter_oproute_t *oproute, toporouter_vertex_t *v2)
973 gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms;
975 v1halfthick = lookup_thickness(oproute->style) / 2.;
976 v2halfthick = vertex_net_thickness(v2) / 2.;
978 v1keepaway = lookup_keepaway(oproute->style);
979 v2keepaway = vertex_net_keepaway(v2);
981 ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway);
983 return ms;
986 gdouble
987 min_oproute_net_spacing(toporouter_oproute_t *oproute, toporouter_vertex_t *v2)
990 gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms;
992 v1halfthick = lookup_thickness(oproute->style) / 2.;
993 v2halfthick = cluster_thickness(v2->route->src) / 2.;
995 v1keepaway = lookup_keepaway(oproute->style);
996 v2keepaway = cluster_keepaway(v2->route->src);
998 ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway);
1000 return ms;
1003 gdouble
1004 min_net_net_spacing(toporouter_vertex_t *v1, toporouter_vertex_t *v2)
1007 gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms;
1009 v1halfthick = cluster_thickness(v1->route->src) / 2.;
1010 v2halfthick = cluster_thickness(v2->route->src) / 2.;
1012 v1keepaway = cluster_keepaway(v1->route->src);
1013 v2keepaway = cluster_keepaway(v2->route->src);
1015 ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway);
1017 return ms;
1020 void
1021 toporouter_draw_cluster(toporouter_t *r, drawing_context_t *dc, toporouter_cluster_t *cluster, gdouble red, gdouble green, gdouble blue, guint layer)
1023 #if TOPO_OUTPUT_ENABLED
1024 //GList *i = cluster->i;
1026 //while(i) {
1027 // toporouter_bbox_t *box = TOPOROUTER_BBOX(i->data);
1029 // if(box->point && vz(box->point) == layer) {
1030 // cairo_set_source_rgba(dc->cr, red, green, blue, 0.8f);
1031 // cairo_arc(dc->cr, vx(box->point) * dc->s + MARGIN, vy(box->point) * dc->s + MARGIN, 500. * dc->s, 0, 2 * M_PI);
1032 // cairo_fill(dc->cr);
1033 // }
1035 // i = i->next;
1037 #endif
1040 void
1041 toporouter_draw_surface(toporouter_t *r, GtsSurface *s, char *filename, int w, int h, int mode, GList *datas, int layer, GList *candidatepoints)
1043 #if TOPO_OUTPUT_ENABLED
1044 drawing_context_t *dc;
1045 GList *i;
1046 toporouter_vertex_t *tv, *tv2 = NULL;
1048 dc = toporouter_output_init(w, h, filename);
1049 dc->mode = mode;
1050 dc->data = NULL;
1052 gts_surface_foreach_edge(s, toporouter_draw_edge, dc);
1053 gts_surface_foreach_vertex(s, toporouter_draw_vertex, dc);
1055 i = r->routednets;
1056 while(i) {
1057 GList *j = TOPOROUTER_ROUTE(i->data)->path;
1058 tv2 = NULL;
1059 while(j) {
1060 tv = TOPOROUTER_VERTEX(j->data);
1061 if(GTS_POINT(tv)->z == layer) {
1062 if(tv && tv2) {
1063 cairo_set_source_rgba(dc->cr, 0.0f, 1.0f, 0.0f, 0.8f);
1064 cairo_move_to(dc->cr,
1065 GTS_POINT(tv)->x * dc->s + MARGIN,
1066 GTS_POINT(tv)->y * dc->s + MARGIN);
1067 cairo_line_to(dc->cr,
1068 GTS_POINT(tv2)->x * dc->s + MARGIN,
1069 GTS_POINT(tv2)->y * dc->s + MARGIN);
1070 cairo_stroke(dc->cr);
1073 if(tv->flags & VERTEX_FLAG_RED) {
1074 cairo_set_source_rgba(dc->cr, 1., 0., 0., 0.8f);
1075 cairo_arc(dc->cr,
1076 tv->v.p.x * dc->s + MARGIN,
1077 tv->v.p.y * dc->s + MARGIN,
1078 500. * dc->s, 0, 2 * M_PI);
1079 cairo_fill(dc->cr);
1081 }else if(tv->flags & VERTEX_FLAG_GREEN) {
1082 cairo_set_source_rgba(dc->cr, 0., 1., 0., 0.8f);
1083 cairo_arc(dc->cr,
1084 tv->v.p.x * dc->s + MARGIN,
1085 tv->v.p.y * dc->s + MARGIN,
1086 500. * dc->s, 0, 2 * M_PI);
1087 cairo_fill(dc->cr);
1089 }else if(tv->flags & VERTEX_FLAG_BLUE) {
1090 cairo_set_source_rgba(dc->cr, 0., 0., 1., 0.8f);
1091 cairo_arc(dc->cr,
1092 tv->v.p.x * dc->s + MARGIN,
1093 tv->v.p.y * dc->s + MARGIN,
1094 500. * dc->s, 0, 2 * M_PI);
1095 cairo_fill(dc->cr);
1098 else {
1100 cairo_set_source_rgba(dc->cr, 1., 1., 1., 0.8f);
1101 cairo_arc(dc->cr,
1102 tv->v.p.x * dc->s + MARGIN,
1103 tv->v.p.y * dc->s + MARGIN,
1104 500. * dc->s, 0, 2 * M_PI);
1105 cairo_fill(dc->cr);
1110 if(tv->routingedge && !TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) {
1111 gdouble tempx, tempy, nms, pms;
1112 GList *i = g_list_find(edge_routing(tv->routingedge), tv);
1113 toporouter_vertex_t *nextv, *prevv;
1115 nextv = edge_routing_next(tv->routingedge,i);
1116 prevv = edge_routing_prev(tv->routingedge,i);
1118 nms = min_spacing(tv,nextv);
1119 pms = min_spacing(tv,prevv);
1121 g_assert(finite(nms)); g_assert(finite(pms));
1123 point_from_point_to_point(tv, nextv, nms, &tempx, &tempy);
1125 cairo_set_source_rgba(dc->cr, 0.0f, 1.0f, 1.0f, 0.8f);
1126 cairo_move_to(dc->cr, vx(tv) * dc->s + MARGIN, vy(tv) * dc->s + MARGIN);
1127 cairo_line_to(dc->cr, tempx * dc->s + MARGIN, tempy * dc->s + MARGIN);
1128 cairo_stroke(dc->cr);
1130 point_from_point_to_point(tv, prevv, pms, &tempx, &tempy);
1132 cairo_move_to(dc->cr, vx(tv) * dc->s + MARGIN, vy(tv) * dc->s + MARGIN);
1133 cairo_line_to(dc->cr, tempx * dc->s + MARGIN, tempy * dc->s + MARGIN);
1134 cairo_stroke(dc->cr);
1143 tv2 = tv;
1144 j = j->next;
1146 i = i->next;
1149 while(datas) {
1150 toporouter_route_t *routedata = (toporouter_route_t *) datas->data;
1152 GList *i;//, *k;
1154 toporouter_draw_cluster(r, dc, routedata->src, 1., 0., 0., layer);
1155 toporouter_draw_cluster(r, dc, routedata->dest, 0., 0., 1., layer);
1157 tv2 = NULL;
1158 i = routedata->path;
1159 while(i) {
1160 tv = TOPOROUTER_VERTEX(i->data);
1161 if(GTS_POINT(tv)->z == layer) {
1162 if(tv && tv2) {
1163 cairo_set_source_rgba(dc->cr, 0.0f, 1.0f, 0.0f, 0.8f);
1164 cairo_move_to(dc->cr,
1165 GTS_POINT(tv)->x * dc->s + MARGIN,
1166 GTS_POINT(tv)->y * dc->s + MARGIN);
1167 cairo_line_to(dc->cr,
1168 GTS_POINT(tv2)->x * dc->s + MARGIN,
1169 GTS_POINT(tv2)->y * dc->s + MARGIN);
1170 cairo_stroke(dc->cr);
1173 tv2 = tv;
1174 i = i->next;
1178 if(routedata->alltemppoints) {
1179 GList *i, *j;
1180 i = j = g_hash_table_get_keys (routedata->alltemppoints);
1181 while(i) {
1182 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
1184 if(GTS_POINT(tv)->z != layer) {
1185 i = i->next;
1186 continue;
1188 if(tv->flags & VERTEX_FLAG_BLUE) {
1189 cairo_set_source_rgba(dc->cr, 0., 0., 1., 0.8f);
1190 cairo_arc(dc->cr,
1191 tv->v.p.x * dc->s + MARGIN,
1192 tv->v.p.y * dc->s + MARGIN,
1193 500. * dc->s, 0, 2 * M_PI);
1194 cairo_fill(dc->cr);
1195 }else if(tv->flags & VERTEX_FLAG_RED) {
1196 cairo_set_source_rgba(dc->cr, 1., 0., 0., 0.8f);
1197 cairo_arc(dc->cr,
1198 tv->v.p.x * dc->s + MARGIN,
1199 tv->v.p.y * dc->s + MARGIN,
1200 500. * dc->s, 0, 2 * M_PI);
1201 cairo_fill(dc->cr);
1203 }else if(tv->flags & VERTEX_FLAG_GREEN) {
1204 cairo_set_source_rgba(dc->cr, 0., 1., 0., 0.8f);
1205 cairo_arc(dc->cr,
1206 tv->v.p.x * dc->s + MARGIN,
1207 tv->v.p.y * dc->s + MARGIN,
1208 500. * dc->s, 0, 2 * M_PI);
1209 cairo_fill(dc->cr);
1210 }else{
1211 cairo_set_source_rgba(dc->cr, 1., 1., 1., 0.8f);
1212 cairo_arc(dc->cr,
1213 tv->v.p.x * dc->s + MARGIN,
1214 tv->v.p.y * dc->s + MARGIN,
1215 500. * dc->s, 0, 2 * M_PI);
1216 cairo_fill(dc->cr);
1218 i = i->next;
1220 g_list_free(j);
1222 datas = datas->next;
1224 toporouter_output_close(dc);
1225 #endif
1229 void
1230 toporouter_layer_free(toporouter_layer_t *l)
1232 g_list_free(l->vertices);
1233 g_list_free(l->constraints);
1237 guint
1238 groupcount(void)
1240 int group;
1241 guint count = 0;
1243 for (group = 0; group < max_layer; group++) {
1244 if(PCB->LayerGroups.Number[group] > 0) count++;
1247 return count;
1250 void
1251 toporouter_free(toporouter_t *r)
1253 struct timeval endtime;
1254 int secs, usecs;
1256 int i;
1257 for(i=0;i<groupcount();i++) {
1258 toporouter_layer_free(&r->layers[i]);
1262 gettimeofday(&endtime, NULL);
1264 secs = (int)(endtime.tv_sec - r->starttime.tv_sec);
1265 usecs = (int)((endtime.tv_usec - r->starttime.tv_usec) / 1000);
1267 if(usecs < 0) {
1268 secs -= 1;
1269 usecs += 1000;
1272 Message(_("Elapsed time: %d.%02d seconds\n"), secs, usecs);
1273 free(r->layers);
1274 free(r);
1278 /* wind:
1279 * returns 1,0,-1 for counterclockwise, collinear or clockwise, respectively.
1281 int
1282 wind(toporouter_spoint_t *p1, toporouter_spoint_t *p2, toporouter_spoint_t *p3)
1284 double rval, dx1, dx2, dy1, dy2;
1285 dx1 = p2->x - p1->x; dy1 = p2->y - p1->y;
1286 dx2 = p3->x - p2->x; dy2 = p3->y - p2->y;
1287 rval = (dx1*dy2)-(dy1*dx2);
1288 return (rval > 0.0001) ? 1 : ((rval < -0.0001) ? -1 : 0);
1291 /* wind_double:
1292 * returns 1,0,-1 for counterclockwise, collinear or clockwise, respectively.
1294 int
1295 wind_double(gdouble p1_x, gdouble p1_y, gdouble p2_x, gdouble p2_y, gdouble p3_x, gdouble p3_y)
1297 double rval, dx1, dx2, dy1, dy2;
1298 dx1 = p2_x - p1_x; dy1 = p2_y - p1_y;
1299 dx2 = p3_x - p2_x; dy2 = p3_y - p2_y;
1300 rval = (dx1*dy2)-(dy1*dx2);
1301 return (rval > 0.0001) ? 1 : ((rval < -0.0001) ? -1 : 0);
1304 inline void
1305 print_toporouter_constraint(toporouter_constraint_t *tc)
1307 printf("%f,%f -> %f,%f ",
1308 tc->c.edge.segment.v1->p.x,
1309 tc->c.edge.segment.v1->p.y,
1310 tc->c.edge.segment.v2->p.x,
1311 tc->c.edge.segment.v2->p.y);
1314 inline void
1315 print_toporouter_vertex(toporouter_vertex_t *tv)
1317 printf("%f,%f ", tv->v.p.x, tv->v.p.y);
1322 * vertices_on_line:
1323 * Given vertex a, gradient m, and radius r:
1325 * Return vertices on line of a & m at r from a
1327 void
1328 vertices_on_line(toporouter_spoint_t *a, gdouble m, gdouble r, toporouter_spoint_t *b0, toporouter_spoint_t *b1)
1331 gdouble c, temp;
1333 if(m == INFINITY || m == -INFINITY) {
1334 b0->y = a->y + r;
1335 b1->y = a->y - r;
1337 b0->x = a->x;
1338 b1->x = a->x;
1340 return;
1343 c = a->y - (m * a->x);
1345 temp = sqrt( pow(r, 2) / ( 1 + pow(m, 2) ) );
1347 b0->x = a->x + temp;
1348 b1->x = a->x - temp;
1350 b0->y = b0->x * m + c;
1351 b1->y = b1->x * m + c;
1356 * vertices_on_line:
1357 * Given vertex a, gradient m, and radius r:
1359 * Return vertices on line of a & m at r from a
1361 void
1362 coords_on_line(gdouble ax, gdouble ay, gdouble m, gdouble r, gdouble *b0x, gdouble *b0y, gdouble *b1x, gdouble *b1y)
1365 gdouble c, temp;
1367 if(m == INFINITY || m == -INFINITY) {
1368 *b0y = ay + r;
1369 *b1y = ay - r;
1371 *b0x = ax;
1372 *b1x = ax;
1374 return;
1377 c = ay - (m * ax);
1379 temp = sqrt( pow(r, 2) / ( 1 + pow(m, 2) ) );
1381 *b0x = ax + temp;
1382 *b1x = ax - temp;
1384 *b0y = *b0x * m + c;
1385 *b1y = *b1x * m + c;
1390 * vertices_on_line:
1391 * Given vertex a, gradient m, and radius r:
1393 * Return vertices on line of a & m at r from a
1395 void
1396 points_on_line(GtsPoint *a, gdouble m, gdouble r, GtsPoint *b0, GtsPoint *b1)
1399 gdouble c, temp;
1401 if(m == INFINITY || m == -INFINITY) {
1402 b0->y = a->y + r;
1403 b1->y = a->y - r;
1405 b0->x = a->x;
1406 b1->x = a->x;
1408 return;
1411 c = a->y - (m * a->x);
1413 temp = sqrt( pow(r, 2) / ( 1 + pow(m, 2) ) );
1415 b0->x = a->x + temp;
1416 b1->x = a->x - temp;
1418 b0->y = b0->x * m + c;
1419 b1->y = b1->x * m + c;
1424 * Returns gradient of segment given by a & b
1426 gdouble
1427 vertex_gradient(toporouter_spoint_t *a, toporouter_spoint_t *b)
1429 if(a->x == b->x) return INFINITY;
1431 return ((b->y - a->y) / (b->x - a->x));
1435 * Returns gradient of segment given by (x0,y0) & (x1,y1)
1437 inline gdouble
1438 cartesian_gradient(gdouble x0, gdouble y0, gdouble x1, gdouble y1)
1440 if(epsilon_equals(x0,x1)) return INFINITY;
1442 return ((y1 - y0) / (x1 - x0));
1446 * Returns gradient of segment given by (x0,y0) & (x1,y1)
1448 inline gdouble
1449 point_gradient(GtsPoint *a, GtsPoint *b)
1451 return cartesian_gradient(a->x, a->y, b->x, b->y);
1454 gdouble
1455 segment_gradient(GtsSegment *s)
1457 return cartesian_gradient(
1458 GTS_POINT(s->v1)->x,
1459 GTS_POINT(s->v1)->y,
1460 GTS_POINT(s->v2)->x,
1461 GTS_POINT(s->v2)->y);
1465 * Returns gradient perpendicular to m
1467 gdouble
1468 perpendicular_gradient(gdouble m)
1470 if(isinf(m)) return 0.0f;
1471 if(m < EPSILON && m > -EPSILON) return INFINITY;
1472 return -1.0f/m;
1476 * Returns the distance between two vertices in the x-y plane
1478 gdouble
1479 vertices_plane_distance(toporouter_spoint_t *a, toporouter_spoint_t *b) {
1480 return sqrt( pow(a->x - b->x, 2) + pow(a->y - b->y, 2) );
1484 * Finds the point p distance r away from a on the line segment of a & b
1486 inline void
1487 vertex_outside_segment(toporouter_spoint_t *a, toporouter_spoint_t *b, gdouble r, toporouter_spoint_t *p)
1489 gdouble m;
1490 toporouter_spoint_t temp[2];
1492 m = vertex_gradient(a,b);
1494 vertices_on_line(a, vertex_gradient(a,b), r, &temp[0], &temp[1]);
1496 if(vertices_plane_distance(&temp[0], b) > vertices_plane_distance(&temp[1], b)) {
1497 p->x = temp[0].x;
1498 p->y = temp[0].y;
1499 }else{
1500 p->x = temp[1].x;
1501 p->y = temp[1].y;
1506 /* proper intersection:
1507 * AB and CD must share a point interior to both segments.
1508 * returns TRUE if AB properly intersects CD.
1510 gint
1511 coord_intersect_prop(gdouble ax, gdouble ay, gdouble bx, gdouble by, gdouble cx, gdouble cy, gdouble dx, gdouble dy)
1513 gint wind_abc = coord_wind(ax, ay, bx, by, cx, cy);
1514 gint wind_abd = coord_wind(ax, ay, bx, by, dx, dy);
1515 gint wind_cda = coord_wind(cx, cy, dx, dy, ax, ay);
1516 gint wind_cdb = coord_wind(cx, cy, dx, dy, bx, by);
1518 if( !wind_abc || !wind_abd || !wind_cda || !wind_cdb ) return 0;
1520 return ( wind_abc ^ wind_abd ) && ( wind_cda ^ wind_cdb );
1523 /* proper intersection:
1524 * AB and CD must share a point interior to both segments.
1525 * returns TRUE if AB properly intersects CD.
1528 point_intersect_prop(GtsPoint *a, GtsPoint *b, GtsPoint *c, GtsPoint *d)
1531 if( point_wind(a, b, c) == 0 ||
1532 point_wind(a, b, d) == 0 ||
1533 point_wind(c, d, a) == 0 ||
1534 point_wind(c, d, b) == 0 ) return 0;
1536 return ( point_wind(a, b, c) ^ point_wind(a, b, d) ) &&
1537 ( point_wind(c, d, a) ^ point_wind(c, d, b) );
1540 inline int
1541 vertex_intersect_prop(GtsVertex *a, GtsVertex *b, GtsVertex *c, GtsVertex *d)
1543 return point_intersect_prop(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c), GTS_POINT(d));
1546 inline int
1547 tvertex_intersect_prop(toporouter_vertex_t *a, toporouter_vertex_t *b, toporouter_vertex_t *c, toporouter_vertex_t *d)
1549 return point_intersect_prop(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c), GTS_POINT(d));
1552 inline int
1553 tvertex_intersect(toporouter_vertex_t *a, toporouter_vertex_t *b, toporouter_vertex_t *c, toporouter_vertex_t *d)
1555 if( !point_wind(GTS_POINT(a), GTS_POINT(d), GTS_POINT(b)) || !point_wind(GTS_POINT(a), GTS_POINT(c), GTS_POINT(b)) ) return 1;
1557 return
1558 ( point_wind(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c)) ^ point_wind(GTS_POINT(a), GTS_POINT(b), GTS_POINT(d)) ) &&
1559 ( point_wind(GTS_POINT(c), GTS_POINT(d), GTS_POINT(a)) ^ point_wind(GTS_POINT(c), GTS_POINT(d), GTS_POINT(b)) );
1563 /* intersection vertex:
1564 * AB and CD must share a point interior to both segments.
1565 * returns vertex at intersection of AB and CD.
1567 GtsVertex *
1568 vertex_intersect(GtsVertex *a, GtsVertex *b, GtsVertex *c, GtsVertex *d)
1570 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
1571 GtsVertex *rval;
1572 gdouble ua_top, ua_bot, ua, rx, ry;
1574 /* TODO: this could be done more efficiently without duplicating computation */
1575 if(!vertex_intersect_prop(a, b, c, d)) return NULL;
1577 ua_top = ((d->p.x - c->p.x) * (a->p.y - c->p.y)) -
1578 ((d->p.y - c->p.y) * (a->p.x - c->p.x));
1579 ua_bot = ((d->p.y - c->p.y) * (b->p.x - a->p.x)) -
1580 ((d->p.x - c->p.x) * (b->p.y - a->p.y));
1581 ua = ua_top / ua_bot;
1582 rx = a->p.x + (ua * (b->p.x - a->p.x));
1583 ry = a->p.y + (ua * (b->p.y - a->p.y));
1585 rval = gts_vertex_new (vertex_class, rx, ry, 0.0f);
1587 return rval;
1590 /* intersection vertex:
1591 * AB and CD must share a point interior to both segments.
1592 * returns vertex at intersection of AB and CD.
1594 void
1595 coord_intersect(gdouble ax, gdouble ay, gdouble bx, gdouble by, gdouble cx, gdouble cy, gdouble dx, gdouble dy, gdouble *rx, gdouble *ry)
1597 gdouble ua_top, ua_bot, ua;
1599 ua_top = ((dx - cx) * (ay - cy)) - ((dy - cy) * (ax - cx));
1600 ua_bot = ((dy - cy) * (bx - ax)) - ((dx - cx) * (by - ay));
1601 ua = ua_top / ua_bot;
1602 *rx = ax + (ua * (bx - ax));
1603 *ry = ay + (ua * (by - ay));
1609 * returns true if c is between a and b
1612 point_between(GtsPoint *a, GtsPoint *b, GtsPoint *c)
1614 if( point_wind(a, b, c) != 0 ) return 0;
1616 if( a->x != b->x ) {
1617 return ((a->x <= c->x) &&
1618 (c->x <= b->x)) ||
1619 ((a->x >= c->x) &&
1620 (c->x >= b->x));
1622 return ((a->y <= c->y) &&
1623 (c->y <= b->y)) ||
1624 ((a->y >= c->y) &&
1625 (c->y >= b->y));
1628 inline int
1629 vertex_between(GtsVertex *a, GtsVertex *b, GtsVertex *c)
1631 return point_between(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c));
1634 void
1635 delaunay_create_from_vertices(GList *vertices, GtsSurface **surface, GtsTriangle **t)
1637 GList *i = vertices;
1638 GtsVertex *v1, *v2, *v3;
1639 GSList *vertices_slist = NULL;
1641 while (i) {
1642 vertices_slist = g_slist_prepend(vertices_slist, i->data);
1643 i = i->next;
1646 // TODO: just work this out from the board outline
1647 *t = gts_triangle_enclosing (gts_triangle_class (), vertices_slist, 100000.0f);
1648 gts_triangle_vertices (*t, &v1, &v2, &v3);
1650 *surface = gts_surface_new (gts_surface_class (), gts_face_class (),
1651 GTS_EDGE_CLASS(toporouter_edge_class ()), GTS_VERTEX_CLASS(toporouter_vertex_class ()) );
1653 gts_surface_add_face (*surface, gts_face_new (gts_face_class (), (*t)->e1, (*t)->e2, (*t)->e3));
1655 i = vertices;
1656 while (i) {
1657 toporouter_vertex_t *v = TOPOROUTER_VERTEX(gts_delaunay_add_vertex (*surface, i->data, NULL));
1659 if(v) {
1660 printf("ERROR: vertex could not be added to CDT ");
1661 print_vertex(v);
1664 i = i->next;
1667 gts_allow_floating_vertices = TRUE;
1668 gts_object_destroy (GTS_OBJECT (v1));
1669 gts_object_destroy (GTS_OBJECT (v2));
1670 gts_object_destroy (GTS_OBJECT (v3));
1671 gts_allow_floating_vertices = FALSE;
1673 g_slist_free(vertices_slist);
1674 // return surface;
1677 GSList *
1678 list_to_slist(GList *i)
1680 GSList *rval = NULL;
1681 while(i) {
1682 rval = g_slist_prepend(rval, i->data);
1683 i = i->next;
1685 return rval;
1688 toporouter_bbox_t *
1689 toporouter_bbox_create_from_points(int layer, GList *vertices, toporouter_term_t type, gpointer data)
1691 toporouter_bbox_t *bbox;
1692 GSList *vertices_slist = list_to_slist(vertices);
1694 // delaunay_create_from_vertices(vertices, &s, &t);
1695 bbox = TOPOROUTER_BBOX( gts_bbox_points(GTS_BBOX_CLASS(toporouter_bbox_class()), vertices_slist) );
1696 bbox->type = type;
1697 bbox->data = data;
1699 bbox->surface = NULL;
1700 bbox->enclosing = NULL;
1702 bbox->layer = layer;
1704 bbox->point = NULL;
1705 bbox->realpoint = NULL;
1707 g_slist_free(vertices_slist);
1708 return bbox;
1711 toporouter_bbox_t *
1712 toporouter_bbox_create(int layer, GList *vertices, toporouter_term_t type, gpointer data)
1714 toporouter_bbox_t *bbox;
1715 GtsSurface *s;
1716 GtsTriangle *t;
1718 delaunay_create_from_vertices(vertices, &s, &t);
1719 bbox = TOPOROUTER_BBOX( gts_bbox_surface(GTS_BBOX_CLASS(toporouter_bbox_class()), s) );
1720 bbox->type = type;
1721 bbox->data = data;
1723 bbox->surface = s;
1724 bbox->enclosing = t;
1726 bbox->layer = layer;
1728 return bbox;
1731 GtsVertex *
1732 insert_vertex(toporouter_t *r, toporouter_layer_t *l, gdouble x, gdouble y, toporouter_bbox_t *box)
1734 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
1735 GtsVertex *v;
1736 GList *i;
1738 i = l->vertices;
1739 while (i) {
1740 v = i->data;
1741 if(v->p.x == x && v->p.y == y) {
1742 TOPOROUTER_VERTEX(v)->bbox = box;
1743 return v;
1745 i = i->next;
1748 v = gts_vertex_new (vertex_class , x, y, l - r->layers);
1749 TOPOROUTER_VERTEX(v)->bbox = box;
1750 l->vertices = g_list_prepend(l->vertices, v);
1752 return v;
1755 GList *
1756 insert_constraint_edge(toporouter_t *r, toporouter_layer_t *l, gdouble x1, gdouble y1, guint flags1,
1757 gdouble x2, gdouble y2, guint flags2, toporouter_bbox_t *box)
1759 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
1760 GtsEdgeClass *edge_class = GTS_EDGE_CLASS (toporouter_constraint_class ());
1761 GtsVertex *p[2];
1762 GtsVertex *v;
1763 GList *i;
1764 GtsEdge *e;
1766 p[0] = p[1] = NULL;
1768 /* insert or find points */
1770 i = l->vertices;
1771 while (i) {
1772 v = i->data;
1773 if(v->p.x == x1 && v->p.y == y1)
1774 p[0] = v;
1775 if(v->p.x == x2 && v->p.y == y2)
1776 p[1] = v;
1777 i = i->next;
1780 if(p[0] == NULL) {
1781 p[0] = gts_vertex_new (vertex_class, x1, y1, l - r->layers);
1782 TOPOROUTER_VERTEX(p[0])->bbox = box;
1783 l->vertices = g_list_prepend(l->vertices, p[0]);
1785 if(p[1] == NULL) {
1786 p[1] = gts_vertex_new (vertex_class, x2, y2, l - r->layers);
1787 TOPOROUTER_VERTEX(p[1])->bbox = box;
1788 l->vertices = g_list_prepend(l->vertices, p[1]);
1791 TOPOROUTER_VERTEX(p[0])->flags = flags1;
1792 TOPOROUTER_VERTEX(p[1])->flags = flags2;
1794 e = gts_edge_new (edge_class, p[0], p[1]);
1795 TOPOROUTER_CONSTRAINT(e)->box = box;
1796 l->constraints = g_list_prepend (l->constraints, e);
1797 // return insert_constraint_edge_rec(r, l, p, box);
1798 return g_list_prepend(NULL, e);
1802 void
1803 insert_constraints_from_list(toporouter_t *r, toporouter_layer_t *l, GList *vlist, toporouter_bbox_t *box)
1805 GList *i = vlist;
1806 toporouter_vertex_t *pv = NULL, *v;
1808 while(i) {
1809 v = TOPOROUTER_VERTEX(i->data);
1811 if(pv) {
1812 box->constraints =
1813 g_list_concat(box->constraints, insert_constraint_edge(r, l, vx(v), vy(v), v->flags, vx(pv), vy(pv), pv->flags, box));
1816 pv = v;
1817 i = i->next;
1820 v = TOPOROUTER_VERTEX(vlist->data);
1821 box->constraints =
1822 g_list_concat(box->constraints, insert_constraint_edge(r, l, vx(v), vy(v), v->flags, vx(pv), vy(pv), pv->flags, box));
1826 void
1827 insert_centre_point(toporouter_t *r, toporouter_layer_t *l, gdouble x, gdouble y)
1829 GList *i;
1830 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
1832 i = l->vertices;
1833 while (i) {
1834 GtsPoint *p = GTS_POINT(i->data);
1835 if(p->x == x && p->y == y)
1836 return;
1837 i = i->next;
1840 l->vertices = g_list_prepend(l->vertices, gts_vertex_new(vertex_class, x, y, 0.0f));
1843 GtsPoint *
1844 midpoint(GtsPoint *a, GtsPoint *b)
1846 return gts_point_new(gts_point_class(), (a->x + b->x) / 2., (a->y + b->y) / 2., 0.);
1849 inline gdouble
1850 pad_rad(PadType *pad)
1852 return (lookup_thickness(pad->Name) / 2.) + lookup_keepaway(pad->Name);
1855 inline gdouble
1856 pin_rad(PinType *pin)
1858 return (lookup_thickness(pin->Name) / 2.) + lookup_keepaway(pin->Name);
1861 GList *
1862 rect_with_attachments(gdouble rad,
1863 gdouble x0, gdouble y0,
1864 gdouble x1, gdouble y1,
1865 gdouble x2, gdouble y2,
1866 gdouble x3, gdouble y3,
1867 gdouble z)
1869 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
1870 GList *r = NULL, *rr = NULL, *i;
1871 toporouter_vertex_t *curpoint, *temppoint;
1874 curpoint = TOPOROUTER_VERTEX(gts_vertex_new (vertex_class, x0, y0, z));
1876 r = g_list_prepend(NULL, curpoint);
1877 r = g_list_prepend(r, gts_vertex_new (vertex_class, x1, y1, z));
1878 r = g_list_prepend(r, gts_vertex_new (vertex_class, x2, y2, z));
1879 r = g_list_prepend(r, gts_vertex_new (vertex_class, x3, y3, z));
1881 i = r;
1882 while(i) {
1883 temppoint = TOPOROUTER_VERTEX(i->data);
1884 rr = g_list_prepend(rr, curpoint);
1886 curpoint = temppoint;
1887 i = i->next;
1890 g_list_free(r);
1892 return rr;
1895 #define VERTEX_CENTRE(x) TOPOROUTER_VERTEX( vertex_bbox(x)->point )
1898 * Read pad data from layer into toporouter_layer_t struct
1900 * Inserts points and constraints into GLists
1903 read_pads(toporouter_t *r, toporouter_layer_t *l, guint layer)
1905 toporouter_spoint_t p[2], rv[5];
1906 gdouble x[2], y[2], t, m;
1907 GList *objectconstraints;
1909 GList *vlist = NULL;
1910 toporouter_bbox_t *bbox = NULL;
1912 guint front = GetLayerGroupNumberByNumber (max_layer + COMPONENT_LAYER);
1913 guint back = GetLayerGroupNumberByNumber (max_layer + SOLDER_LAYER);
1915 // printf("read_pads: front = %d back = %d layer = %d\n",
1916 // front, back, layer);
1918 /* If its not the top or bottom layer, there are no pads to read */
1919 if(l - r->layers != front && l - r->layers != back) return 0;
1921 ELEMENT_LOOP(PCB->Data);
1923 PAD_LOOP(element);
1925 if( (l - r->layers == back && TEST_FLAG(ONSOLDERFLAG, pad)) ||
1926 (l - r->layers == front && !TEST_FLAG(ONSOLDERFLAG, pad)) ) {
1929 objectconstraints = NULL;
1930 t = (gdouble)pad->Thickness / 2.0f;
1931 x[0] = pad->Point1.X;
1932 x[1] = pad->Point2.X;
1933 y[0] = pad->Point1.Y;
1934 y[1] = pad->Point2.Y;
1937 if(TEST_FLAG(SQUAREFLAG, pad)) {
1938 /* Square or oblong pad. Four points and four constraint edges are
1939 * used */
1941 if(x[0] == x[1] && y[0] == y[1]) {
1942 /* Pad is square */
1944 // vlist = g_list_prepend(NULL, gts_vertex_new (vertex_class, x[0]-t, y[0]-t, 0.));
1945 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, x[0]-t, y[0]+t, 0.));
1946 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, x[0]+t, y[0]+t, 0.));
1947 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, x[0]+t, y[0]-t, 0.));
1948 vlist = rect_with_attachments(pad_rad(pad),
1949 x[0]-t, y[0]-t,
1950 x[0]-t, y[0]+t,
1951 x[0]+t, y[0]+t,
1952 x[0]+t, y[0]-t,
1953 l - r->layers);
1954 bbox = toporouter_bbox_create(l - r->layers, vlist, PAD, pad);
1955 r->bboxes = g_slist_prepend(r->bboxes, bbox);
1956 insert_constraints_from_list(r, l, vlist, bbox);
1957 g_list_free(vlist);
1959 //bbox->point = GTS_POINT( gts_vertex_new(vertex_class, x[0], y[0], 0.) );
1960 bbox->point = GTS_POINT( insert_vertex(r, l, x[0], y[0], bbox) );
1961 g_assert(TOPOROUTER_VERTEX(bbox->point)->bbox == bbox);
1962 }else {
1963 /* Pad is diagonal oblong or othogonal oblong */
1965 m = cartesian_gradient(x[0], y[0], x[1], y[1]);
1967 p[0].x = x[0]; p[0].y = y[0];
1968 p[1].x = x[1]; p[1].y = y[1];
1970 vertex_outside_segment(&p[0], &p[1], t, &rv[0]);
1971 vertices_on_line(&rv[0], perpendicular_gradient(m), t, &rv[1], &rv[2]);
1973 vertex_outside_segment(&p[1], &p[0], t, &rv[0]);
1974 vertices_on_line(&rv[0], perpendicular_gradient(m), t, &rv[3], &rv[4]);
1976 if(wind(&rv[1], &rv[2], &rv[3]) != wind(&rv[2], &rv[3], &rv[4])) {
1977 rv[0].x = rv[3].x; rv[0].y = rv[3].y;
1978 rv[3].x = rv[4].x; rv[3].y = rv[4].y;
1979 rv[4].x = rv[0].x; rv[4].y = rv[0].y;
1982 // vlist = g_list_prepend(NULL, gts_vertex_new (vertex_class, rv[1].x, rv[1].y, 0.));
1983 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, rv[2].x, rv[2].y, 0.));
1984 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, rv[3].x, rv[3].y, 0.));
1985 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, rv[4].x, rv[4].y, 0.));
1986 vlist = rect_with_attachments(pad_rad(pad),
1987 rv[1].x, rv[1].y,
1988 rv[2].x, rv[2].y,
1989 rv[3].x, rv[3].y,
1990 rv[4].x, rv[4].y,
1991 l - r->layers);
1992 bbox = toporouter_bbox_create(l - r->layers, vlist, PAD, pad);
1993 r->bboxes = g_slist_prepend(r->bboxes, bbox);
1994 insert_constraints_from_list(r, l, vlist, bbox);
1995 g_list_free(vlist);
1997 //bbox->point = GTS_POINT( gts_vertex_new(vertex_class, (x[0] + x[1]) / 2., (y[0] + y[1]) / 2., 0.) );
1998 bbox->point = GTS_POINT( insert_vertex(r, l, (x[0] + x[1]) / 2., (y[0] + y[1]) / 2., bbox) );
1999 g_assert(TOPOROUTER_VERTEX(bbox->point)->bbox == bbox);
2003 }else {
2004 /* Either round pad or pad with curved edges */
2006 if(x[0] == x[1] && y[0] == y[1]) {
2007 /* One point */
2009 /* bounding box same as square pad */
2010 vlist = rect_with_attachments(pad_rad(pad),
2011 x[0]-t, y[0]-t,
2012 x[0]-t, y[0]+t,
2013 x[0]+t, y[0]+t,
2014 x[0]+t, y[0]-t,
2015 l - r->layers);
2016 bbox = toporouter_bbox_create(l - r->layers, vlist, PAD, pad);
2017 r->bboxes = g_slist_prepend(r->bboxes, bbox);
2018 g_list_free(vlist);
2020 //bbox->point = GTS_POINT( insert_vertex(r, l, x[0], y[0], bbox) );
2021 bbox->point = GTS_POINT( insert_vertex(r, l, x[0], y[0], bbox) );
2023 }else{
2024 /* Two points and one constraint edge */
2026 /* the rest is just for bounding box */
2027 m = cartesian_gradient(x[0], y[0], x[1], y[1]);
2029 p[0].x = x[0]; p[0].y = y[0];
2030 p[1].x = x[1]; p[1].y = y[1];
2032 vertex_outside_segment(&p[0], &p[1], t, &rv[0]);
2033 vertices_on_line(&rv[0], perpendicular_gradient(m), t, &rv[1], &rv[2]);
2035 vertex_outside_segment(&p[1], &p[0], t, &rv[0]);
2036 vertices_on_line(&rv[0], perpendicular_gradient(m), t, &rv[3], &rv[4]);
2038 if(wind(&rv[1], &rv[2], &rv[3]) != wind(&rv[2], &rv[3], &rv[4])) {
2039 rv[0].x = rv[3].x; rv[0].y = rv[3].y;
2040 rv[3].x = rv[4].x; rv[3].y = rv[4].y;
2041 rv[4].x = rv[0].x; rv[4].y = rv[0].y;
2044 vlist = rect_with_attachments(pad_rad(pad),
2045 rv[1].x, rv[1].y,
2046 rv[2].x, rv[2].y,
2047 rv[3].x, rv[3].y,
2048 rv[4].x, rv[4].y,
2049 l - r->layers);
2050 bbox = toporouter_bbox_create(l - r->layers, vlist, PAD, pad);
2051 r->bboxes = g_slist_prepend(r->bboxes, bbox);
2052 insert_constraints_from_list(r, l, vlist, bbox);
2053 g_list_free(vlist);
2055 //bbox->point = GTS_POINT( gts_vertex_new(vertex_class, (x[0] + x[1]) / 2., (y[0] + y[1]) / 2., 0.) );
2056 bbox->point = GTS_POINT( insert_vertex(r, l, (x[0] + x[1]) / 2., (y[0] + y[1]) / 2., bbox) );
2058 //bbox->constraints = g_list_concat(bbox->constraints, insert_constraint_edge(r, l, x[0], y[0], x[1], y[1], bbox));
2067 END_LOOP;
2069 END_LOOP;
2071 return 0;
2075 * Read points data (all layers) into GList
2077 * Inserts pin and via points
2080 read_points(toporouter_t *r, toporouter_layer_t *l, int layer)
2082 gdouble x, y, t;
2084 GList *vlist = NULL;
2085 toporouter_bbox_t *bbox = NULL;
2087 ELEMENT_LOOP(PCB->Data);
2089 PIN_LOOP(element);
2092 t = (gdouble)pin->Thickness / 2.0f;
2093 x = pin->X;
2094 y = pin->Y;
2096 if(TEST_FLAG (SQUAREFLAG, pin)) {
2098 vlist = rect_with_attachments(pin_rad(pin),
2099 x-t, y-t,
2100 x-t, y+t,
2101 x+t, y+t,
2102 x+t, y-t,
2103 l - r->layers);
2104 bbox = toporouter_bbox_create(l - r->layers, vlist, PIN, pin);
2105 r->bboxes = g_slist_prepend(r->bboxes, bbox);
2106 insert_constraints_from_list(r, l, vlist, bbox);
2107 g_list_free(vlist);
2108 bbox->point = GTS_POINT( insert_vertex(r, l, x, y, bbox) );
2110 }else if(TEST_FLAG(OCTAGONFLAG, pin)){
2111 /* TODO: Handle octagon pins */
2112 fprintf(stderr, "No support for octagon pins yet\n");
2113 }else{
2114 vlist = rect_with_attachments(pin_rad(pin),
2115 x-t, y-t,
2116 x-t, y+t,
2117 x+t, y+t,
2118 x+t, y-t,
2119 l - r->layers);
2120 bbox = toporouter_bbox_create(l - r->layers, vlist, PIN, pin);
2121 r->bboxes = g_slist_prepend(r->bboxes, bbox);
2122 g_list_free(vlist);
2123 bbox->point = GTS_POINT( insert_vertex(r, l, x, y, bbox) );
2126 END_LOOP;
2128 END_LOOP;
2130 VIA_LOOP(PCB->Data);
2133 t = (gdouble)via->Thickness / 2.0f;
2134 x = via->X;
2135 y = via->Y;
2137 if(TEST_FLAG (SQUAREFLAG, via)) {
2139 vlist = rect_with_attachments(pin_rad((PinType*)via),
2140 x-t, y-t,
2141 x-t, y+t,
2142 x+t, y+t,
2143 x+t, y-t,
2144 l - r->layers);
2145 bbox = toporouter_bbox_create(l - r->layers, vlist, VIA, via);
2146 r->bboxes = g_slist_prepend(r->bboxes, bbox);
2147 insert_constraints_from_list(r, l, vlist, bbox);
2148 g_list_free(vlist);
2149 bbox->point = GTS_POINT( insert_vertex(r, l, x, y, bbox) );
2151 }else if(TEST_FLAG(OCTAGONFLAG, via)){
2152 /* TODO: Handle octagon vias */
2153 fprintf(stderr, "No support for octagon vias yet\n");
2154 }else{
2156 vlist = rect_with_attachments(pin_rad((PinType*)via),
2157 x-t, y-t,
2158 x-t, y+t,
2159 x+t, y+t,
2160 x+t, y-t,
2161 l - r->layers);
2162 bbox = toporouter_bbox_create(l - r->layers, vlist, VIA, via);
2163 r->bboxes = g_slist_prepend(r->bboxes, bbox);
2164 g_list_free(vlist);
2166 bbox->point = GTS_POINT( insert_vertex(r, l, x, y, bbox) );
2170 END_LOOP;
2171 return 0;
2175 * Read line data from layer into toporouter_layer_t struct
2177 * Inserts points and constraints into GLists
2180 read_lines(toporouter_t *r, toporouter_layer_t *l, LayerType *layer, int ln)
2182 gdouble xs[2], ys[2];
2184 GList *vlist = NULL;
2185 toporouter_bbox_t *bbox = NULL;
2187 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
2189 LINE_LOOP(layer);
2191 xs[0] = line->Point1.X;
2192 xs[1] = line->Point2.X;
2193 ys[0] = line->Point1.Y;
2194 ys[1] = line->Point2.Y;
2195 if(!(xs[0] == xs[1] && ys[0] == ys[1])) {
2196 vlist = g_list_prepend(NULL, gts_vertex_new (vertex_class, xs[0], ys[0], l - r->layers));
2197 vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, xs[1], ys[1], l - r->layers));
2198 // TODO: replace this with surface version
2199 bbox = toporouter_bbox_create_from_points(GetLayerGroupNumberByNumber(ln), vlist, LINE, line);
2200 r->bboxes = g_slist_prepend(r->bboxes, bbox);
2201 //new;;
2202 //insert_constraints_from_list(r, l, vlist, bbox);
2203 g_list_free(vlist);
2204 // bbox->point = GTS_POINT( insert_vertex(r, l, (xs[0]+xs[1])/2., (ys[0]+ys[1])/2., bbox) );
2206 bbox->constraints = g_list_concat(bbox->constraints, insert_constraint_edge(r, l, xs[0], ys[0], 0, xs[1], ys[1], 0, bbox));
2209 END_LOOP;
2211 return 0;
2214 void
2215 create_board_edge(gdouble x0, gdouble y0, gdouble x1, gdouble y1, gdouble max, gint layer, GList **vlist)
2217 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
2218 gdouble d = sqrt(pow(x0-x1,2) + pow(y0-y1,2));
2219 guint n = d / max, count = 1;
2220 gdouble inc = n ? d / n : d;
2221 gdouble x = x0, y = y0;
2223 *vlist = g_list_prepend(*vlist, gts_vertex_new (vertex_class, x0, y0, layer));
2225 while(count < n) {
2226 coord_move_towards_coord_values(x0, y0, x1, y1, inc, &x, &y);
2227 *vlist = g_list_prepend(*vlist, gts_vertex_new (vertex_class, x, y, layer));
2229 x0 = x; y0 = y;
2230 count++;
2237 read_board_constraints(toporouter_t *r, toporouter_layer_t *l, int layer)
2239 // GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
2240 GList *vlist = NULL;
2241 toporouter_bbox_t *bbox = NULL;
2243 /* Add points for corners of board, and constrain those edges */
2244 // vlist = g_list_prepend(NULL, gts_vertex_new (vertex_class, 0., 0., layer));
2245 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, PCB->MaxWidth, 0., layer));
2246 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, PCB->MaxWidth, PCB->MaxHeight, layer));
2247 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, 0., PCB->MaxHeight, layer));
2249 create_board_edge(0., 0., PCB->MaxWidth, 0., 10000., layer, &vlist);
2250 create_board_edge(PCB->MaxWidth, 0., PCB->MaxWidth, PCB->MaxHeight, 10000., layer, &vlist);
2251 create_board_edge(PCB->MaxWidth, PCB->MaxHeight, 0., PCB->MaxHeight, 10000., layer, &vlist);
2252 create_board_edge(0., PCB->MaxHeight, 0., 0., 10000., layer, &vlist);
2254 bbox = toporouter_bbox_create(layer, vlist, BOARD, NULL);
2255 r->bboxes = g_slist_prepend(r->bboxes, bbox);
2256 insert_constraints_from_list(r, l, vlist, bbox);
2257 g_list_free(vlist);
2259 return 0;
2262 gdouble
2263 triangle_cost(GtsTriangle *t, gpointer *data){
2265 gdouble *min_quality = data[0];
2266 gdouble *max_area = data[1];
2267 gdouble quality = gts_triangle_quality(t);
2268 gdouble area = gts_triangle_area(t);
2270 if (quality < *min_quality || area > *max_area)
2271 return quality;
2272 return 0.0;
2276 void
2277 print_constraint(toporouter_constraint_t *e)
2279 printf("CONSTRAINT:\n");
2280 print_vertex(tedge_v1(e));
2281 print_vertex(tedge_v2(e));
2284 void
2285 print_edge(toporouter_edge_t *e)
2287 GList *i = edge_routing(e);
2289 printf("EDGE:\n");
2291 print_vertex(tedge_v1(e));
2293 while(i) {
2294 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
2295 print_vertex(v);
2296 i = i->next;
2299 print_vertex(tedge_v2(e));
2301 static void pick_first_face (GtsFace * f, GtsFace ** first)
2303 if (*first == NULL)
2304 *first = f;
2307 void
2308 unconstrain(toporouter_layer_t *l, toporouter_constraint_t *c)
2310 toporouter_edge_t *e;
2312 gts_allow_floating_vertices = TRUE;
2313 e = TOPOROUTER_EDGE(gts_edge_new (GTS_EDGE_CLASS (toporouter_edge_class ()), GTS_SEGMENT(c)->v1, GTS_SEGMENT(c)->v2));
2314 gts_edge_replace(GTS_EDGE(c), GTS_EDGE(e));
2315 l->constraints = g_list_remove(l->constraints, c);
2316 c->box->constraints = g_list_remove(c->box->constraints, c);
2317 c->box = NULL;
2318 gts_object_destroy (GTS_OBJECT (c));
2319 gts_allow_floating_vertices = FALSE;
2322 void
2323 build_cdt(toporouter_t *r, toporouter_layer_t *l)
2325 /* TODO: generalize into surface *cdt_create(vertices, constraints) */
2326 GList *i;
2327 //GtsEdge *temp;
2328 //GtsVertex *v;
2329 GtsTriangle *t;
2330 GtsVertex *v1, *v2, *v3;
2331 GSList *vertices_slist;
2333 vertices_slist = list_to_slist(l->vertices);
2335 if(l->surface) {
2336 GtsFace * first = NULL;
2337 gts_surface_foreach_face (l->surface, (GtsFunc) pick_first_face, &first);
2338 gts_surface_traverse_destroy(gts_surface_traverse_new (l->surface, first));
2341 t = gts_triangle_enclosing (gts_triangle_class (), vertices_slist, 1000.0f);
2342 gts_triangle_vertices (t, &v1, &v2, &v3);
2344 g_slist_free(vertices_slist);
2346 l->surface = gts_surface_new (gts_surface_class (), gts_face_class (),
2347 GTS_EDGE_CLASS(toporouter_edge_class ()), GTS_VERTEX_CLASS(toporouter_vertex_class ()) );
2349 gts_surface_add_face (l->surface, gts_face_new (gts_face_class (), t->e1, t->e2, t->e3));
2352 // fprintf(stderr, "ADDED VERTICES\n");
2354 GtsFace *debugface;
2356 if((debugface = gts_delaunay_check(l->surface))) {
2357 fprintf(stderr, "WARNING: Delaunay check failed\n");
2358 fprintf(stderr, "\tViolating triangle:\n");
2359 fprintf(stderr, "\t%f,%f %f,%f\n",
2360 debugface->triangle.e1->segment.v1->p.x,
2361 debugface->triangle.e1->segment.v1->p.y,
2362 debugface->triangle.e1->segment.v2->p.x,
2363 debugface->triangle.e1->segment.v2->p.y
2365 fprintf(stderr, "\t%f,%f %f,%f\n",
2366 debugface->triangle.e2->segment.v1->p.x,
2367 debugface->triangle.e2->segment.v1->p.y,
2368 debugface->triangle.e2->segment.v2->p.x,
2369 debugface->triangle.e2->segment.v2->p.y
2371 fprintf(stderr, "\t%f,%f %f,%f\n",
2372 debugface->triangle.e3->segment.v1->p.x,
2373 debugface->triangle.e3->segment.v1->p.y,
2374 debugface->triangle.e3->segment.v2->p.x,
2375 debugface->triangle.e3->segment.v2->p.y
2377 // toporouter_draw_surface(r, l->surface, "debug.png", 4096, 4096);
2379 int i;
2380 for(i=0;i<groupcount();i++) {
2381 char buffer[256];
2382 sprintf(buffer, "debug-%d.png", i);
2383 toporouter_draw_surface(r, r->layers[i].surface, buffer, 2048, 2048, 2, NULL, i, NULL);
2389 check_cons_continuation:
2390 i = l->constraints;
2391 while (i) {
2392 toporouter_constraint_t *c1 = TOPOROUTER_CONSTRAINT(i->data);
2393 GList *j = i->next;
2394 // printf("adding cons: "); print_constraint(c1);
2396 while(j) {
2397 toporouter_constraint_t *c2 = TOPOROUTER_CONSTRAINT(j->data);
2398 guint rem = 0;
2399 GList *temp;
2401 // printf("\tconflict: "); print_constraint(c2);
2402 toporouter_bbox_t *c1box = c1->box, *c2box = c2->box;
2403 toporouter_vertex_t *c1v1 = tedge_v1(c1);
2404 toporouter_vertex_t *c1v2 = tedge_v2(c1);
2405 toporouter_vertex_t *c2v1 = tedge_v1(c2);
2406 toporouter_vertex_t *c2v2 = tedge_v2(c2);
2408 if(gts_segments_are_intersecting(GTS_SEGMENT(c1), GTS_SEGMENT(c2)) == GTS_IN) {
2409 toporouter_vertex_t *v;
2410 unconstrain(l, c1); unconstrain(l, c2);
2411 rem = 1;
2412 // proper intersection
2413 v = TOPOROUTER_VERTEX(vertex_intersect(
2414 GTS_VERTEX(c1v1),
2415 GTS_VERTEX(c1v2),
2416 GTS_VERTEX(c2v1),
2417 GTS_VERTEX(c2v2)));
2419 // remove both constraints
2420 // replace with 4x constraints
2421 // insert new intersection vertex
2422 GTS_POINT(v)->z = vz(c1v1);
2424 l->vertices = g_list_prepend(l->vertices, v);
2425 // gts_delaunay_add_vertex (l->surface, GTS_VERTEX(v), NULL);
2427 v->bbox = c1box;
2429 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(v), vy(v), 0, c1box);
2430 c1box->constraints = g_list_concat(c1box->constraints, temp);
2432 temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(v), vy(v), 0, c1box);
2433 c1box->constraints = g_list_concat(c1box->constraints, temp);
2435 temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(v), vy(v), 0, c2box);
2436 c2box->constraints = g_list_concat(c2box->constraints, temp);
2438 temp = insert_constraint_edge(r, l, vx(c2v2), vy(c2v2), 0, vx(v), vy(v), 0, c2box);
2439 c2box->constraints = g_list_concat(c2box->constraints, temp);
2441 }else if(gts_segments_are_intersecting(GTS_SEGMENT(c1), GTS_SEGMENT(c2)) == GTS_ON ||
2442 gts_segments_are_intersecting(GTS_SEGMENT(c2), GTS_SEGMENT(c1)) == GTS_ON) {
2444 if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v1(c1)) && vertex_between(edge_v1(c2), edge_v2(c2), edge_v2(c1))) {
2445 unconstrain(l, c1); unconstrain(l, c2);
2446 rem = 1;
2447 // remove c1
2448 temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c2v2), vy(c2v2), 0, c2box);
2449 c2box->constraints = g_list_concat(c2box->constraints, temp);
2451 }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
2452 unconstrain(l, c1); unconstrain(l, c2);
2453 rem = 1;
2454 // remove c2
2455 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box);
2456 c1box->constraints = g_list_concat(c1box->constraints, temp);
2458 //}else if(!vertex_wind(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && !vertex_wind(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
2459 /* }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2)) || vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2))) {
2460 unconstrain(l, c1); unconstrain(l, c2);
2461 rem = 1;
2462 printf("all colinear\n");
2463 // exit(1);
2464 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box);
2465 c1box->constraints = g_list_concat(c1box->constraints, temp);
2467 if(vertex_between(GTS_VERTEX(c1v1), GTS_VERTEX(c1v2), GTS_VERTEX(c2v2))) {
2468 // v2 of c2 is inner
2469 if(vertex_between(GTS_VERTEX(c2v1), GTS_VERTEX(c2v2), GTS_VERTEX(c1v2))) {
2470 // v2 of c1 is inner
2471 // c2 = c1.v2 -> c2.v1
2472 temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v1), vy(c2v1), 0, c2box);
2473 c2box->constraints = g_list_concat(c2box->constraints, temp);
2474 }else{
2475 // v1 of c1 is inner
2476 // c2 = c1.v1 -> c2.v1
2477 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v1), vy(c2v1), 0, c2box);
2478 c2box->constraints = g_list_concat(c2box->constraints, temp);
2480 }else{
2481 // v1 of c2 is inner
2482 if(vertex_between(GTS_VERTEX(c2v1), GTS_VERTEX(c2v2), GTS_VERTEX(c1v2))) {
2483 // v2 of c1 is inner
2484 // c2 = c1.v2 -> c2.v2
2485 temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v2), vy(c2v2), 0, c2box);
2486 c2box->constraints = g_list_concat(c2box->constraints, temp);
2487 }else{
2488 // v1 of c1 is inner
2489 // c2 = c1.v1 -> c2.v2
2490 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v2), vy(c2v2), 0, c2box);
2491 c2box->constraints = g_list_concat(c2box->constraints, temp);
2494 }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v1(c1)) && c1v1 != c2v1 && c1v1 != c2v2) {
2495 unconstrain(l, c1); unconstrain(l, c2);
2496 rem = 1;
2497 //v1 of c1 is on c2
2498 printf("v1 of c1 on c2\n");
2500 // replace with 2x constraints
2501 temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c1v1), vy(c1v1), 0, c2box);
2502 c2box->constraints = g_list_concat(c2box->constraints, temp);
2503 temp = insert_constraint_edge(r, l, vx(c2v2), vy(c2v2), 0, vx(c1v1), vy(c1v1), 0, c2box);
2504 c2box->constraints = g_list_concat(c2box->constraints, temp);
2506 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box);
2507 c1box->constraints = g_list_concat(c1box->constraints, temp);
2509 // restore c1
2510 //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);
2511 //c2->box->constraints = g_list_concat(c2->box->constraints, temp);
2513 }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v2(c1)) && c1v2 != c2v1 && c1v2 != c2v2) {
2514 unconstrain(l, c1); unconstrain(l, c2);
2515 rem = 1;
2516 //v2 of c1 is on c2
2517 printf("v2 of c1 on c2\n");
2519 // replace with 2x constraints
2520 temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c1v2), vy(c1v2), 0, c2box);
2521 c2box->constraints = g_list_concat(c2box->constraints, temp);
2522 temp = insert_constraint_edge(r, l, vx(c2v2), vy(c2v2), 0, vx(c1v2), vy(c1v2), 0, c2box);
2523 c2box->constraints = g_list_concat(c2box->constraints, temp);
2525 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box);
2526 c1box->constraints = g_list_concat(c1box->constraints, temp);
2528 }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && c2v1 != c1v1 && c2v1 != c1v2) {
2529 unconstrain(l, c1); unconstrain(l, c2);
2530 rem = 1;
2531 //v1 of c2 is on c1
2532 printf("v1 of c2 on c1\n");
2534 // replace with 2x constraints
2535 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v1), vy(c2v1), 0, c1box);
2536 c1box->constraints = g_list_concat(c1box->constraints, temp);
2537 temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v1), vy(c2v1), 0, c1box);
2538 c1box->constraints = g_list_concat(c1box->constraints, temp);
2540 temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c2v2), vy(c2v2), 0, c2box);
2541 c2box->constraints = g_list_concat(c2box->constraints, temp);
2542 }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2)) && c2v2 != c1v1 && c2v2 != c1v2) {
2543 unconstrain(l, c1); unconstrain(l, c2);
2544 rem = 1;
2545 //v2 of c2 is on c1
2546 printf("v2 of c2 on c1\n");
2548 // replace with 2x constraints
2549 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v2), vy(c2v2), 0, c1box);
2550 c1box->constraints = g_list_concat(c1box->constraints, temp);
2551 temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v2), vy(c2v2), 0, c1box);
2552 c1box->constraints = g_list_concat(c1box->constraints, temp);
2554 temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c2v2), vy(c2v2), 0, c2box);
2555 c2box->constraints = g_list_concat(c2box->constraints, temp);
2558 if(rem) goto check_cons_continuation;
2560 j = j->next;
2563 i = i->next;
2566 i = l->vertices;
2567 while (i) {
2568 //v = i->data;
2569 //if(r->flags & TOPOROUTER_FLAG_DEBUG_CDTS)
2570 // fprintf(stderr, "\tadding vertex %f,%f\n", v->p.x, v->p.y);
2571 toporouter_vertex_t *v = TOPOROUTER_VERTEX(gts_delaunay_add_vertex (l->surface, i->data, NULL));
2572 if(v) {
2573 printf("conflict: "); print_vertex(v);
2576 i = i->next;
2578 i = l->constraints;
2579 while (i) {
2581 toporouter_constraint_t *c1 = TOPOROUTER_CONSTRAINT(i->data);
2583 // printf("adding cons: "); print_constraint(c1);
2585 GSList *conflicts = gts_delaunay_add_constraint (l->surface, i->data);
2586 GSList *j = conflicts;
2587 while(j) {
2588 if(TOPOROUTER_IS_CONSTRAINT(j->data)) {
2589 toporouter_constraint_t *c2 = TOPOROUTER_CONSTRAINT(j->data);
2591 printf("\tconflict: "); print_constraint(c2);
2594 j = j->next;
2596 g_slist_free(conflicts);
2598 i = i->next;
2601 // if(rerun)
2602 // goto build_cdt_continuation;
2603 // fprintf(stderr, "ADDED CONSTRAINTS\n");
2604 gts_allow_floating_vertices = TRUE;
2605 gts_object_destroy (GTS_OBJECT (v1));
2606 gts_object_destroy (GTS_OBJECT (v2));
2607 gts_object_destroy (GTS_OBJECT (v3));
2608 gts_allow_floating_vertices = FALSE;
2612 gpointer data[2];
2613 gdouble quality = 0.50, area = G_MAXDOUBLE;
2614 guint num = gts_delaunay_conform(l->surface, -1, (GtsEncroachFunc) gts_vertex_encroaches_edge, NULL);
2616 if (num == 0){
2617 data[0] = &quality;
2618 data[1] = &area;
2619 num = gts_delaunay_refine(l->surface, -1, (GtsEncroachFunc) gts_vertex_encroaches_edge, NULL, (GtsKeyFunc) triangle_cost, data);
2623 #ifdef DEBUG_IMPORT
2624 gts_surface_print_stats(l->surface, stderr);
2625 #endif
2628 char buffer[64];
2629 FILE *fout2;
2630 sprintf(buffer, "surface%d.gts", l - r->layers);
2631 fout2 = fopen(buffer, "w");
2632 gts_surface_write(l->surface, fout2);
2637 gint
2638 visited_cmp(gconstpointer a, gconstpointer b)
2640 if(a<b) return -1;
2641 if(a>b) return 1;
2642 return 0;
2645 gdouble
2646 coord_xangle(gdouble ax, gdouble ay, gdouble bx, gdouble by)
2648 gdouble dx, dy, theta;
2650 dx = fabs(ax - bx);
2651 dy = fabs(ay - by);
2653 if(dx < EPSILON) {
2654 theta = M_PI / 2.;
2655 } else theta = atan(dy/dx);
2657 if(by <= ay) {
2658 if(bx < ax) theta = M_PI - theta;
2659 }else{
2660 if(bx < ax) theta += M_PI;
2661 else theta = (2 * M_PI) - theta;
2664 return theta;
2667 gdouble
2668 point_xangle(GtsPoint *a, GtsPoint *b)
2670 gdouble dx, dy, theta;
2672 dx = fabs(a->x - b->x);
2673 dy = fabs(a->y - b->y);
2675 if(dx < EPSILON) {
2676 theta = M_PI / 2.;
2677 } else theta = atan(dy/dx);
2679 if(b->y >= a->y) {
2680 if(b->x < a->x) theta = M_PI - theta;
2681 }else{
2682 if(b->x < a->x) theta += M_PI;
2683 else theta = (2 * M_PI) - theta;
2686 return theta;
2690 GList *
2691 cluster_vertices(toporouter_t *r, toporouter_cluster_t *c)
2693 GList *rval = NULL;
2695 if(!c) return NULL;
2697 FOREACH_CLUSTER(c->netlist->clusters) {
2698 if((r->flags & TOPOROUTER_FLAG_AFTERRUBIX && cluster->c == c->c) || (!(r->flags & TOPOROUTER_FLAG_AFTERRUBIX) && cluster == c)) {
2699 FOREACH_BBOX(cluster->boxes) {
2700 if(box->type == LINE) {
2701 g_assert(box->constraints->data);
2702 rval = g_list_prepend(rval, tedge_v1(box->constraints->data));
2703 rval = g_list_prepend(rval, tedge_v2(box->constraints->data));
2704 }else if(box->point) {
2705 rval = g_list_prepend(rval, TOPOROUTER_VERTEX(box->point));
2706 //g_assert(vertex_bbox(TOPOROUTER_VERTEX(box->point)) == box);
2707 }else {
2708 printf("WARNING: cluster_vertices: unhandled bbox type\n");
2711 } FOREACH_END;
2716 } FOREACH_END;
2718 return rval;
2721 void
2722 print_cluster(toporouter_cluster_t *c)
2725 if(!c) {
2726 printf("[CLUSTER (NULL)]\n");
2727 return;
2730 printf("CLUSTER %d: NETLIST = %s STYLE = %s\n", c->c, c->netlist->netlist, c->netlist->style);
2732 FOREACH_BBOX(c->boxes) {
2733 print_bbox(box);
2734 } FOREACH_END;
2738 toporouter_cluster_t *
2739 cluster_create(toporouter_t *r, toporouter_netlist_t *netlist)
2741 toporouter_cluster_t *c = malloc(sizeof(toporouter_cluster_t));
2743 c->c = c->pc = netlist->clusters->len;
2744 g_ptr_array_add(netlist->clusters, c);
2745 c->netlist = netlist;
2746 c->boxes = g_ptr_array_new();
2748 return c;
2751 toporouter_bbox_t *
2752 toporouter_bbox_locate(toporouter_t *r, toporouter_term_t type, void *data, gdouble x, gdouble y, guint layergroup)
2754 GtsPoint *p = gts_point_new(gts_point_class(), x, y, layergroup);
2755 GSList *boxes = gts_bb_tree_stabbed(r->bboxtree, p), *i = boxes;
2757 gts_object_destroy(GTS_OBJECT(p));
2759 while(i) {
2760 toporouter_bbox_t *box = TOPOROUTER_BBOX(i->data);
2762 if(box->type == type && box->data == data) {
2763 g_slist_free(boxes);
2764 return box;
2767 i = i->next;
2770 g_slist_free(boxes);
2771 return NULL;
2774 void
2775 cluster_join_bbox(toporouter_cluster_t *cluster, toporouter_bbox_t *box)
2777 if(box) {
2778 g_ptr_array_add(cluster->boxes, box);
2779 box->cluster = cluster;
2783 toporouter_netlist_t *
2784 netlist_create(toporouter_t *r, char *netlist, char *style)
2786 toporouter_netlist_t *nl = malloc(sizeof(toporouter_netlist_t));
2787 nl->netlist = netlist;
2788 nl->style = style;
2789 nl->clusters = g_ptr_array_new();
2790 nl->routes = g_ptr_array_new();
2791 nl->routed = NULL;
2792 nl->pair = NULL;
2793 g_ptr_array_add(r->netlists, nl);
2794 return nl;
2797 void
2798 import_clusters(toporouter_t *r)
2800 NetListListType nets;
2801 ResetFoundPinsViasAndPads (false);
2802 ResetFoundLinesAndPolygons (false);
2803 nets = CollectSubnets(false);
2804 NETLIST_LOOP(&nets);
2806 if(netlist->NetN > 0) {
2807 toporouter_netlist_t *nl = netlist_create(r, netlist->Net->Connection->menu->Name, netlist->Net->Connection->menu->Style);
2809 NET_LOOP(netlist);
2812 toporouter_cluster_t *cluster = cluster_create(r, nl);
2813 #ifdef DEBUG_MERGING
2814 printf("NET:\n");
2815 #endif
2816 CONNECTION_LOOP (net);
2819 if(connection->type == LINE_TYPE) {
2820 LineType *line = (LineType *) connection->ptr2;
2821 toporouter_bbox_t *box = toporouter_bbox_locate(r, LINE, line, connection->X, connection->Y, connection->group);
2822 cluster_join_bbox(cluster, box);
2824 #ifdef DEBUG_MERGING
2825 printf("\tLINE %d,%d\n", connection->X, connection->Y);
2826 #endif
2827 }else if(connection->type == PAD_TYPE) {
2828 PadType *pad = (PadType *) connection->ptr2;
2829 toporouter_bbox_t *box = toporouter_bbox_locate(r, PAD, pad, connection->X, connection->Y, connection->group);
2830 cluster_join_bbox(cluster, box);
2832 #ifdef DEBUG_MERGING
2833 printf("\tPAD %d,%d\n", connection->X, connection->Y);
2834 #endif
2835 }else if(connection->type == PIN_TYPE) {
2837 for(guint m=0;m<groupcount();m++) {
2838 PinType *pin = (PinType *) connection->ptr2;
2839 toporouter_bbox_t *box = toporouter_bbox_locate(r, PIN, pin, connection->X, connection->Y, m);
2840 cluster_join_bbox(cluster, box);
2843 #ifdef DEBUG_MERGING
2844 printf("\tPIN %d,%d\n", connection->X, connection->Y);
2845 #endif
2846 }else if(connection->type == VIA_TYPE) {
2848 for(guint m=0;m<groupcount();m++) {
2849 PinType *pin = (PinType *) connection->ptr2;
2850 toporouter_bbox_t *box = toporouter_bbox_locate(r, VIA, pin, connection->X, connection->Y, m);
2851 cluster_join_bbox(cluster, box);
2854 #ifdef DEBUG_MERGING
2855 printf("\tVIA %d,%d\n", connection->X, connection->Y);
2856 #endif
2857 }else if(connection->type == POLYGON_TYPE) {
2858 PolygonType *polygon = (PolygonType *) connection->ptr2;
2859 toporouter_bbox_t *box = toporouter_bbox_locate(r, POLYGON, polygon, connection->X, connection->Y, connection->group);
2860 cluster_join_bbox(cluster, box);
2862 #ifdef DEBUG_MERGING
2863 printf("\tPOLYGON %d,%d\n", connection->X, connection->Y);
2864 #endif
2868 END_LOOP;
2869 #ifdef DEBUG_MERGING
2870 printf("\n");
2871 #endif
2873 END_LOOP;
2877 END_LOOP;
2878 FreeNetListListMemory(&nets);
2881 void
2882 import_geometry(toporouter_t *r)
2884 toporouter_layer_t *cur_layer;
2886 int group;
2888 #ifdef DEBUG_IMPORT
2889 for (group = 0; group < max_layer; group++) {
2890 printf("Group %d: Number %d:\n", group, PCB->LayerGroups.Number[group]);
2892 for (int entry = 0; entry < PCB->LayerGroups.Number[group]; entry++) {
2893 printf("\tEntry %d\n", PCB->LayerGroups.Entries[group][entry]);
2896 #endif
2897 /* Allocate space for per layer struct */
2898 cur_layer = r->layers = malloc(groupcount() * sizeof(toporouter_layer_t));
2900 /* Foreach layer, read in pad vertices and constraints, and build CDT */
2901 for (group = 0; group < max_layer; group++) {
2902 #ifdef DEBUG_IMPORT
2903 printf("*** LAYER GROUP %d ***\n", group);
2904 #endif
2905 if(PCB->LayerGroups.Number[group] > 0){
2906 cur_layer->vertices = NULL;
2907 cur_layer->constraints = NULL;
2909 #ifdef DEBUG_IMPORT
2910 printf("reading board constraints from layer %d into group %d\n", PCB->LayerGroups.Entries[group][0], group);
2911 #endif
2912 read_board_constraints(r, cur_layer, PCB->LayerGroups.Entries[group][0]);
2913 #ifdef DEBUG_IMPORT
2914 printf("reading points from layer %d into group %d \n",PCB->LayerGroups.Entries[group][0], group);
2915 #endif
2916 read_points(r, cur_layer, PCB->LayerGroups.Entries[group][0]);
2918 //#ifdef DEBUG_IMPORT
2919 // printf("reading pads from layer %d into group %d\n", number, group);
2920 //#endif
2921 read_pads(r, cur_layer, group);
2923 GROUP_LOOP(PCB->Data, group)
2926 #ifdef DEBUG_IMPORT
2927 printf("reading lines from layer %d into group %d\n", number, group);
2928 #endif
2929 read_lines(r, cur_layer, layer, number);
2932 END_LOOP;
2936 #ifdef DEBUG_IMPORT
2937 printf("building CDT\n");
2938 #endif
2939 build_cdt(r, cur_layer);
2940 printf("finished\n");
2941 /* {
2942 int i;
2943 for(i=0;i<groupcount();i++) {
2944 char buffer[256];
2945 sprintf(buffer, "build%d.png", i);
2946 toporouter_draw_surface(r, r->layers[i].surface, buffer, 2048, 2048, 2, NULL, i, NULL);
2949 #ifdef DEBUG_IMPORT
2950 printf("finished building CDT\n");
2951 #endif
2952 cur_layer++;
2956 r->bboxtree = gts_bb_tree_new(r->bboxes);
2958 import_clusters(r);
2960 #ifdef DEBUG_IMPORT
2961 printf("finished import!\n");
2962 #endif
2966 gint
2967 compare_points(gconstpointer a, gconstpointer b)
2969 GtsPoint *i = GTS_POINT(a);
2970 GtsPoint *j = GTS_POINT(b);
2972 if(i->x == j->x) {
2973 if(i->y == j->y) return 0;
2974 if(i->y < j->y) return -1;
2975 return 1;
2977 if(i->x < j->x) return -1;
2978 return 1;
2981 gint
2982 compare_segments(gconstpointer a, gconstpointer b)
2984 if(a == b) return 0;
2985 if(a < b) return -1;
2986 return 1;
2988 #define DEBUG_CLUSTER_FIND 1
2989 toporouter_cluster_t *
2990 cluster_find(toporouter_t *r, gdouble x, gdouble y, gdouble z)
2992 GtsPoint *p = gts_point_new(gts_point_class(), x, y, z);
2993 GSList *hits = gts_bb_tree_stabbed(r->bboxtree, p);
2994 toporouter_cluster_t *rval = NULL;
2996 #ifdef DEBUG_CLUSTER_FIND
2997 printf("FINDING %f,%f,%f\n\n", x, y, z);
2998 #endif
3000 while(hits) {
3001 toporouter_bbox_t *box = TOPOROUTER_BBOX(hits->data);
3003 #ifdef DEBUG_CLUSTER_FIND
3004 printf("HIT BOX: "); print_bbox(box);
3005 #endif
3007 if(box->layer == (int)z) {
3008 if(box->type != BOARD) {
3009 if(box->type == LINE) {
3010 LineType *line = (LineType *)box->data;
3011 gint linewind = coord_wind(line->Point1.X, line->Point1.Y, x, y, line->Point2.X, line->Point2.Y);
3013 if(line->Point1.X > x - EPSILON && line->Point1.X < x + EPSILON &&
3014 line->Point1.Y > y - EPSILON && line->Point1.Y < y + EPSILON) {
3015 rval = box->cluster;
3016 // break;
3018 if(line->Point2.X > x - EPSILON && line->Point2.X < x + EPSILON &&
3019 line->Point2.Y > y - EPSILON && line->Point2.Y < y + EPSILON) {
3020 rval = box->cluster;
3021 // break;
3023 if(!linewind) {
3024 rval = box->cluster;
3025 // break;
3028 }else if(box->surface) {
3030 if(gts_point_locate(p, box->surface, NULL)) {
3031 rval = box->cluster;
3032 break;
3038 hits = hits->next;
3041 gts_object_destroy(GTS_OBJECT(p));
3044 #ifdef DEBUG_CLUSTER_FIND
3045 printf("cluster_find: %f,%f,%f: ", x, y, z);
3046 print_cluster(rval);
3047 #endif
3049 return rval;
3052 gdouble
3053 simple_h_cost(toporouter_t *r, toporouter_vertex_t *curpoint, toporouter_vertex_t *destpoint)
3055 gdouble layerpenalty = (vz(curpoint) == vz(destpoint)) ? 0. : r->viacost;
3057 return gts_point_distance(GTS_POINT(curpoint), GTS_POINT(destpoint)) + layerpenalty;
3060 #define FCOST(x) (x->gcost + x->hcost)
3061 gdouble
3062 route_heap_cmp(gpointer item, gpointer data)
3064 return FCOST(TOPOROUTER_VERTEX(item));
3067 #define closelist_insert(p) closelist = g_list_prepend(closelist, p)
3069 typedef struct {
3070 toporouter_vertex_t *key;
3071 toporouter_vertex_t *result;
3072 }toporouter_heap_search_data_t;
3074 void
3075 toporouter_heap_search(gpointer data, gpointer user_data)
3077 toporouter_vertex_t *v = TOPOROUTER_VERTEX(data);
3078 toporouter_heap_search_data_t *heap_search_data = (toporouter_heap_search_data_t *)user_data;
3079 if(v == heap_search_data->key) heap_search_data->result = v;
3082 void
3083 toporouter_heap_color(gpointer data, gpointer user_data)
3085 toporouter_vertex_t *v = TOPOROUTER_VERTEX(data);
3086 v->flags |= (guint) user_data;
3089 inline gdouble
3090 angle_span(gdouble a1, gdouble a2)
3092 if(a1 > a2)
3093 return ((2*M_PI)-a1 + a2);
3094 return a2-a1;
3097 gdouble
3098 region_span(toporouter_vertex_region_t *region)
3100 gdouble a1,a2;
3102 g_assert(region->v1 != NULL);
3103 g_assert(region->v2 != NULL);
3104 g_assert(region->origin != NULL);
3106 a1 = point_xangle(GTS_POINT(region->origin), GTS_POINT(region->v1));
3107 a2 = point_xangle(GTS_POINT(region->origin), GTS_POINT(region->v2));
3109 return angle_span(a1, a2);
3112 gdouble
3113 edge_capacity(toporouter_edge_t *e)
3115 return gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e)));
3118 gdouble
3119 edge_flow(toporouter_edge_t *e, toporouter_vertex_t *v1, toporouter_vertex_t *v2, toporouter_vertex_t *dest)
3121 GList *i = edge_routing(e);
3122 toporouter_vertex_t *pv = tedge_v1(e), *v = NULL;
3123 gdouble flow = 0.;
3124 guint waiting = 1;
3126 if((pv == v1 || pv == v2) && waiting) {
3127 flow += min_vertex_net_spacing(pv, dest);
3128 pv = dest;
3129 waiting = 0;
3132 g_assert(v1 != v2);
3134 while(i) {
3135 v = TOPOROUTER_VERTEX(i->data);
3138 if(pv == dest)
3139 flow += min_vertex_net_spacing(v, pv);
3140 else
3141 flow += min_spacing(v, pv);
3143 if((v == v1 || v == v2) && waiting) {
3144 flow += min_vertex_net_spacing(v, dest);
3145 pv = dest;
3146 waiting = 0;
3147 }else{
3148 pv = v;
3150 i = i->next;
3153 if(pv == dest)
3154 flow += min_vertex_net_spacing(tedge_v2(e), pv);
3155 else
3156 flow += min_spacing(tedge_v2(e), pv);
3158 return flow;
3161 void
3162 print_path(GList *path)
3164 GList *i = path;
3166 printf("PATH:\n");
3167 while(i) {
3168 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
3169 // printf("[V %f,%f,%f]\n", vx(v), vy(v), vz(v));
3170 print_vertex(v);
3172 if(v->child && !g_list_find(path, v->child))
3173 printf("\t CHILD NOT IN LIST\n");
3174 if(v->parent && !g_list_find(path, v->parent))
3175 printf("\t parent NOT IN LIST\n");
3176 i = i->next;
3182 GList *
3183 split_path(GList *path)
3185 toporouter_vertex_t *pv = NULL;
3186 GList *curpath = NULL, *i, *paths = NULL;
3187 #ifdef DEBUG_ROUTE
3188 printf("PATH:\n");
3189 #endif
3190 i = path;
3191 while(i) {
3192 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
3194 #ifdef DEBUG_ROUTE
3195 printf("v = %f,%f ", vx(v), vy(v));
3196 if(v->parent) printf("parent = %f,%f ", vx(v->parent), vy(v->parent));
3197 if(v->child) printf("child = %f,%f ", vx(v->child), vy(v->child));
3198 printf("\n");
3199 #endif
3200 // printf("***\n");
3201 // if(v) printf("v = %f,%f\n", GTS_POINT(v)->x, GTS_POINT(v)->y);
3202 // if(pv) printf("pv = %f,%f\n", GTS_POINT(pv)->x, GTS_POINT(pv)->y);
3205 if(pv)
3206 if(GTS_POINT(v)->x == GTS_POINT(pv)->x && GTS_POINT(v)->y == GTS_POINT(pv)->y) {
3207 if(g_list_length(curpath) > 1) paths = g_list_prepend(paths, curpath);
3208 curpath = NULL;
3210 pv->child = NULL;
3211 v->parent = NULL;
3214 curpath = g_list_append(curpath, v);
3216 pv = v;
3217 i = i->next;
3220 if(g_list_length(curpath) > 1)
3221 paths = g_list_prepend(paths, curpath);
3223 return paths;
3228 #define edge_gradient(e) (cartesian_gradient(GTS_POINT(GTS_SEGMENT(e)->v1)->x, GTS_POINT(GTS_SEGMENT(e)->v1)->y, \
3229 GTS_POINT(GTS_SEGMENT(e)->v2)->x, GTS_POINT(GTS_SEGMENT(e)->v2)->y))
3232 /* sorting into ascending distance from v1 */
3233 gint
3234 routing_edge_insert(gconstpointer a, gconstpointer b, gpointer user_data)
3236 GtsPoint *v1 = GTS_POINT(edge_v1(user_data));
3238 if(gts_point_distance2(v1, GTS_POINT(a)) < gts_point_distance2(v1, GTS_POINT(b)) - EPSILON)
3239 return -1;
3240 if(gts_point_distance2(v1, GTS_POINT(a)) > gts_point_distance2(v1, GTS_POINT(b)) + EPSILON)
3241 return 1;
3243 printf("a = %x b = %x\n", (int) a, (int) b);
3245 printf("WARNING: routing_edge_insert() with same points..\n \
3246 v1 @ %f,%f\n\
3247 a @ %f,%f\n\
3248 b @ %f,%f\n",
3249 v1->x, v1->y,
3250 vx(a), vy(a),
3251 vx(a), vy(b));
3252 printf("A: "); print_vertex(TOPOROUTER_VERTEX(a));
3253 printf("B: "); print_vertex(TOPOROUTER_VERTEX(b));
3255 TOPOROUTER_VERTEX(a)->flags |= VERTEX_FLAG_RED;
3256 TOPOROUTER_VERTEX(b)->flags |= VERTEX_FLAG_RED;
3258 return 0;
3262 toporouter_vertex_t *
3263 new_temp_toporoutervertex(gdouble x, gdouble y, toporouter_edge_t *e)
3265 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ());
3266 GList *i = edge_routing(e);
3267 toporouter_vertex_t *r;
3268 ///*
3269 while(i) {
3270 r = TOPOROUTER_VERTEX(i->data);
3271 if(epsilon_equals(vx(r),x) && epsilon_equals(vy(r),y)) {
3272 if(r->flags & VERTEX_FLAG_TEMP) return r;
3274 i = i->next;
3276 //*/
3277 r = TOPOROUTER_VERTEX( gts_vertex_new (vertex_class, x, y, vz(edge_v1(e))) );
3278 r->flags |= VERTEX_FLAG_TEMP;
3279 r->routingedge = e;
3281 if(TOPOROUTER_IS_CONSTRAINT(e))
3282 TOPOROUTER_CONSTRAINT(e)->routing = g_list_insert_sorted_with_data(edge_routing(e), r, routing_edge_insert, e);
3283 else
3284 e->routing = g_list_insert_sorted_with_data(edge_routing(e), r, routing_edge_insert, e);
3286 return r;
3290 /* create vertex on edge e at radius r from v, closest to ref */
3291 toporouter_vertex_t *
3292 new_temp_toporoutervertex_in_segment(toporouter_edge_t *e, toporouter_vertex_t *v, gdouble r, toporouter_vertex_t *ref)
3294 gdouble m = edge_gradient(e);
3295 toporouter_spoint_t p, np1, np2;
3296 // toporouter_vertex_t *b = TOPOROUTER_VERTEX((GTS_VERTEX(v) == edge_v1(e)) ? edge_v2(e) : edge_v1(e));
3297 toporouter_vertex_t *rval = NULL;
3298 p.x = vx(v); p.y = vy(v);
3300 vertices_on_line(&p, m, r, &np1, &np2);
3302 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)) )
3303 rval = new_temp_toporoutervertex(np1.x, np1.y, e);
3304 else
3305 rval = new_temp_toporoutervertex(np2.x, np2.y, e);
3307 return rval;
3310 gint
3311 vertex_keepout_test(toporouter_t *r, toporouter_vertex_t *v)
3313 GList *i = r->keepoutlayers;
3314 while(i) {
3315 gdouble keepout = *((double *) i->data);
3316 if(vz(v) == keepout) return 1;
3317 i = i->next;
3319 return 0;
3322 void
3323 closest_cluster_pair(toporouter_t *r, GList *src_vertices, GList *dest_vertices, toporouter_vertex_t **a, toporouter_vertex_t **b)
3325 GList *i = src_vertices, *j = dest_vertices;
3327 gdouble min = 0.;
3328 *a = NULL; *b = NULL;
3330 i = src_vertices;
3331 while(i) {
3332 toporouter_vertex_t *v1 = TOPOROUTER_VERTEX(i->data);
3334 if(vertex_keepout_test(r, v1)) { i = i->next; continue; }
3336 j = dest_vertices;
3337 while(j) {
3338 toporouter_vertex_t *v2 = TOPOROUTER_VERTEX(j->data);
3339 if(vertex_keepout_test(r, v2) || vz(v2) != vz(v1)) { j = j->next; continue; }
3341 if(!*a) {
3342 *a = v1; *b = v2; min = simple_h_cost(r, *a, *b);
3343 }else{
3344 gdouble tempd = simple_h_cost(r, v1, v2);
3345 if(r->flags & TOPOROUTER_FLAG_GOFAR && tempd > min) {
3346 *a = v1; *b = v2; min = tempd;
3347 }else
3348 if(tempd < min) {
3349 *a = v1; *b = v2; min = tempd;
3353 j = j->next;
3356 i = i->next;
3359 // g_list_free(src_vertices);
3360 // g_list_free(dest_vertices);
3364 toporouter_vertex_t *
3365 closest_dest_vertex(toporouter_t *r, toporouter_vertex_t *v, toporouter_route_t *routedata)
3367 GList //*vertices = cluster_vertices(r, routedata->dest),
3368 *i = routedata->destvertices;
3369 toporouter_vertex_t *closest = NULL;
3370 gdouble closest_distance = 0.;
3372 // if(routedata->flags & TOPOROUTER_FLAG_FLEX) i = r->destboxes;
3374 while(i) {
3375 toporouter_vertex_t *cv = TOPOROUTER_VERTEX(i->data);
3377 if(vz(cv) != vz(v)) { i = i->next; continue; }
3379 if(!closest) {
3380 closest = cv; closest_distance = simple_h_cost(r, v, closest);
3381 }else{
3382 gdouble tempd = simple_h_cost(r, v, cv);
3383 if(r->flags & TOPOROUTER_FLAG_GOFAR && tempd > closest_distance) {
3384 closest = cv; closest_distance = tempd;
3385 }else
3386 if(tempd < closest_distance) {
3387 closest = cv; closest_distance = tempd;
3390 i = i->next;
3393 // g_list_free(vertices);
3395 #ifdef DEBUG_ROUTE
3396 printf("CLOSEST = %f,%f,%f\n", vx(closest), vy(closest), vz(closest));
3397 #endif
3398 return closest;
3401 #define toporouter_edge_gradient(e) (cartesian_gradient(vx(edge_v1(e)), vy(edge_v1(e)), vx(edge_v2(e)), vy(edge_v2(e))))
3404 /* returns the capacity of the triangle cut through v */
3405 gdouble
3406 triangle_interior_capacity(GtsTriangle *t, toporouter_vertex_t *v)
3408 toporouter_edge_t *e = TOPOROUTER_EDGE(gts_triangle_edge_opposite(t, GTS_VERTEX(v)));
3409 gdouble x, y, m1, m2, c2, c1, len;
3411 g_assert(e);
3413 m1 = toporouter_edge_gradient(e);
3414 m2 = perpendicular_gradient(m1);
3415 c2 = (isinf(m2)) ? vx(v) : vy(v) - (m2 * vx(v));
3416 c1 = (isinf(m1)) ? vx(edge_v1(e)) : vy(edge_v1(e)) - (m1 * vx(edge_v1(e)));
3418 if(isinf(m2))
3419 x = vx(v);
3420 else if(isinf(m1))
3421 x = vx(edge_v1(e));
3422 else
3423 x = (c2 - c1) / (m1 - m2);
3425 y = (isinf(m2)) ? vy(edge_v1(e)) : (m2 * x) + c2;
3427 len = gts_point_distance2(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e)));
3429 #ifdef DEBUG_ROUTE
3430 printf("%f,%f len = %f v = %f,%f\n", x, y, len, vx(v), vy(v));
3431 #endif
3433 if(epsilon_equals(x,vx(edge_v1(e))) && epsilon_equals(y,vy(edge_v1(e)))) return INFINITY;
3434 if(epsilon_equals(x,vx(edge_v2(e))) && epsilon_equals(y,vy(edge_v2(e)))) return INFINITY;
3436 if(x >= MIN(vx(edge_v1(e)),vx(edge_v2(e))) &&
3437 x <= MAX(vx(edge_v1(e)),vx(edge_v2(e))) &&
3438 y >= MIN(vy(edge_v1(e)),vy(edge_v2(e))) &&
3439 y <= MAX(vy(edge_v1(e)),vy(edge_v2(e))))
3441 // 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 )
3442 return sqrt(pow(vx(v) - x, 2) + pow(vy(v) - y, 2));
3444 return INFINITY;
3447 inline toporouter_vertex_t *
3448 segment_common_vertex(GtsSegment *s1, GtsSegment *s2)
3450 if(!s1 || !s2) return NULL;
3451 if(s1->v1 == s2->v1) return TOPOROUTER_VERTEX(s1->v1);
3452 if(s1->v2 == s2->v1) return TOPOROUTER_VERTEX(s1->v2);
3453 if(s1->v1 == s2->v2) return TOPOROUTER_VERTEX(s1->v1);
3454 if(s1->v2 == s2->v2) return TOPOROUTER_VERTEX(s1->v2);
3455 return NULL;
3458 inline toporouter_vertex_t *
3459 route_vertices_common_vertex(toporouter_vertex_t *v1, toporouter_vertex_t *v2)
3461 return segment_common_vertex(GTS_SEGMENT(v1->routingedge), GTS_SEGMENT(v2->routingedge));
3465 inline guint
3466 edges_third_edge(GtsSegment *s1, GtsSegment *s2, toporouter_vertex_t **v1, toporouter_vertex_t **v2)
3468 if(!s1 || !s2) return 0;
3469 if(s1->v1 == s2->v1) {
3470 *v1 = TOPOROUTER_VERTEX(s1->v2);
3471 *v2 = TOPOROUTER_VERTEX(s2->v2);
3472 return 1;
3474 if(s1->v2 == s2->v1) {
3475 *v1 = TOPOROUTER_VERTEX(s1->v1);
3476 *v2 = TOPOROUTER_VERTEX(s2->v2);
3477 return 1;
3479 if(s1->v1 == s2->v2) {
3480 *v1 = TOPOROUTER_VERTEX(s1->v2);
3481 *v2 = TOPOROUTER_VERTEX(s2->v1);
3482 return 1;
3484 if(s1->v2 == s2->v2) {
3485 *v1 = TOPOROUTER_VERTEX(s1->v1);
3486 *v2 = TOPOROUTER_VERTEX(s2->v1);
3487 return 1;
3489 return 0;
3492 /* returns the flow from e1 to e2, and the flow from the vertex oppisate e1 to
3493 * e1 and the vertex oppisate e2 to e2 */
3494 gdouble
3495 flow_from_edge_to_edge(GtsTriangle *t, toporouter_edge_t *e1, toporouter_edge_t *e2,
3496 toporouter_vertex_t *common_v, toporouter_vertex_t *curpoint)
3498 gdouble r = 0.;
3499 toporouter_vertex_t *pv = common_v, *v;
3500 toporouter_edge_t *op_edge;
3502 GList *i = edge_routing(e1);
3503 while(i) {
3504 v = TOPOROUTER_VERTEX(i->data);
3506 if(v == curpoint) {
3507 r += min_spacing(v, pv);
3508 pv = v;
3509 i = i->next; continue;
3511 // if(!(v->flags & VERTEX_FLAG_TEMP)) {
3512 if((v->flags & VERTEX_FLAG_ROUTE)) {
3513 if(v->parent)
3514 if(v->parent->routingedge == e2) {
3515 r += min_spacing(v, pv);
3516 pv = v;
3517 i = i->next; continue;
3520 if(v->child)
3521 if(v->child->routingedge == e2) {
3522 r += min_spacing(v, pv);
3523 pv = v;
3524 i = i->next; continue;
3527 i = i->next;
3530 op_edge = TOPOROUTER_EDGE(gts_triangle_edge_opposite(t, GTS_VERTEX(common_v)));
3532 g_assert(op_edge);
3533 g_assert(e1);
3534 g_assert(e2);
3536 v = segment_common_vertex(GTS_SEGMENT(e2), GTS_SEGMENT(op_edge));
3537 g_assert(v);
3539 //v = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(t, GTS_EDGE(e1)));
3540 if(v->flags & VERTEX_FLAG_ROUTE && v->parent && v->parent->routingedge) {
3541 if(v->parent->routingedge == e1)
3542 r += min_spacing(v, pv);
3545 v = segment_common_vertex(GTS_SEGMENT(e1), GTS_SEGMENT(op_edge));
3546 g_assert(v);
3548 //v = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(t, GTS_EDGE(e2)));
3549 if(v->flags & VERTEX_FLAG_ROUTE && v->parent && v->parent->routingedge) {
3550 if(v->parent->routingedge == e1)
3551 r += min_spacing(v, pv);
3554 if(TOPOROUTER_IS_CONSTRAINT(op_edge)) {
3555 toporouter_bbox_t *box = vertex_bbox(TOPOROUTER_VERTEX(edge_v1(op_edge)));
3556 r += vertex_net_thickness(v) / 2.;
3557 if(box) {
3558 r += MAX(vertex_net_keepaway(v), cluster_keepaway(box->cluster));
3559 r += cluster_thickness(box->cluster) / 2.;
3560 }else{
3561 r += vertex_net_keepaway(v);
3566 return r;
3571 guint
3572 check_triangle_interior_capacity(GtsTriangle *t, toporouter_vertex_t *v, toporouter_vertex_t *curpoint,
3573 toporouter_edge_t *op_edge, toporouter_edge_t *adj_edge1, toporouter_edge_t *adj_edge2)
3575 gdouble ic = triangle_interior_capacity(t, v);
3576 gdouble flow = flow_from_edge_to_edge(t, adj_edge1, adj_edge2, v, curpoint);
3578 if(TOPOROUTER_IS_CONSTRAINT(adj_edge1) || TOPOROUTER_IS_CONSTRAINT(adj_edge2)) return 1;
3581 if(flow > ic) {
3582 #ifdef DEBUG_ROUTE
3583 printf("fail interior capacity flow = %f ic = %f\n", flow, ic);
3584 #endif
3585 return 0;
3588 return 1;
3591 toporouter_vertex_t *
3592 edge_routing_next_not_temp(toporouter_edge_t *e, GList *list)
3594 if(!TOPOROUTER_IS_CONSTRAINT(e)) {
3595 while(list) {
3596 toporouter_vertex_t *v = TOPOROUTER_VERTEX(list->data);
3597 if(!(v->flags & VERTEX_FLAG_TEMP))
3598 return v;
3600 list = list->next;
3603 return tedge_v2(e);
3606 toporouter_vertex_t *
3607 edge_routing_prev_not_temp(toporouter_edge_t *e, GList *list)
3609 if(!TOPOROUTER_IS_CONSTRAINT(e)) {
3610 while(list) {
3611 toporouter_vertex_t *v = TOPOROUTER_VERTEX(list->data);
3612 if(!(v->flags & VERTEX_FLAG_TEMP))
3613 return v;
3615 list = list->prev;
3618 return tedge_v1(e);
3621 void
3622 edge_adjacent_vertices(toporouter_edge_t *e, toporouter_vertex_t *v, toporouter_vertex_t **v1, toporouter_vertex_t **v2)
3624 GList *r = g_list_find(edge_routing(e), v);
3626 if(v == tedge_v1(e)) {
3627 *v1 = NULL;
3628 *v2 = edge_routing_next_not_temp(e, edge_routing(e));
3629 }else if(v == tedge_v2(e)) {
3630 *v1 = edge_routing_prev_not_temp(e, g_list_last(edge_routing(e)));
3631 *v2 = NULL;
3632 }else{
3633 // r = g_list_find(r, v);
3634 *v1 = edge_routing_prev_not_temp(e, r);
3635 *v2 = edge_routing_next_not_temp(e, r);
3642 GList *
3643 candidate_vertices(toporouter_vertex_t *v1, toporouter_vertex_t *v2, toporouter_vertex_t *dest, toporouter_edge_t *e)
3645 gdouble totald, v1ms, v2ms, flow, capacity, ms;
3646 GList *vs = NULL;
3648 g_assert(v1);
3649 g_assert(v2);
3650 g_assert(dest);
3652 g_assert(!(v1->flags & VERTEX_FLAG_TEMP));
3653 g_assert(!(v2->flags & VERTEX_FLAG_TEMP));
3654 #ifdef DEBUG_ROUTE
3655 printf("starting candidate vertices\n");
3656 printf("v1 = %f,%f v2 = %f,%f dest = %f,%f\n", vx(v1), vy(v1), vx(v2), vy(v2), vx(dest), vy(dest));
3657 #endif
3658 totald = gts_point_distance(GTS_POINT(v1), GTS_POINT(v2));
3659 v1ms = min_spacing(v1, dest);
3660 v2ms = min_spacing(v2, dest);
3661 ms = min_spacing(dest, dest);
3662 flow = TOPOROUTER_IS_CONSTRAINT(e) ? 0. : edge_flow(e, v1, v2, dest);
3663 capacity = edge_capacity(e);
3665 #ifdef DEBUG_ROUTE
3666 g_assert(totald > 0);
3668 printf("v1ms = %f v2ms = %f totald = %f ms = %f capacity = %f flow = %f\n", v1ms, v2ms, totald, ms, capacity, flow);
3669 #endif
3671 if(flow >= capacity) return NULL;
3674 if(v1ms + v2ms + ms >= totald) {
3675 vs = g_list_prepend(vs, new_temp_toporoutervertex((vx(v1)+vx(v2)) / 2., (vy(v1)+vy(v2)) / 2., e));
3676 }else{
3677 gdouble x0, y0, x1, y1, d;
3679 vertex_move_towards_vertex_values(GTS_VERTEX(v1), GTS_VERTEX(v2), v1ms, &x0, &y0);
3681 vs = g_list_prepend(vs, new_temp_toporoutervertex(x0, y0, e));
3683 vertex_move_towards_vertex_values(GTS_VERTEX(v2), GTS_VERTEX(v1), v2ms, &x1, &y1);
3685 vs = g_list_prepend(vs, new_temp_toporoutervertex(x1, y1, e));
3687 d = sqrt(pow(x0-x1,2) + pow(y0-y1,2));
3689 if(ms < d) {
3690 // guint nint = d / ms;
3691 // gdouble dif = d / (nint + 1);
3692 gdouble dif = d / 2;
3694 // for(guint j=0;j<nint;j++) {
3695 gdouble x, y;
3697 // coord_move_towards_coord_values(x0, y0, x1, y1, dif * j, &x, &y);
3698 coord_move_towards_coord_values(x0, y0, x1, y1, dif, &x, &y);
3700 vs = g_list_prepend(vs, new_temp_toporoutervertex(x, y, e));
3702 // }
3707 #ifdef DEBUG_ROUTE
3708 printf("candidate vertices returning %d\n", g_list_length(vs));
3709 #endif
3710 return vs;
3713 GList *
3714 edge_routing_first_not_temp(toporouter_edge_t *e)
3716 GList *i = edge_routing(e);
3717 toporouter_vertex_t *v;
3719 while(i) {
3720 v = TOPOROUTER_VERTEX(i->data);
3721 if(!(v->flags & VERTEX_FLAG_TEMP)) return i;
3723 i = i->next;
3726 return NULL;
3729 GList *
3730 edge_routing_last_not_temp(toporouter_edge_t *e)
3732 GList *i = edge_routing(e), *last = NULL;
3733 toporouter_vertex_t *v;
3735 while(i) {
3736 v = TOPOROUTER_VERTEX(i->data);
3737 if(!(v->flags & VERTEX_FLAG_TEMP)) last = i;
3739 i = i->next;
3742 return last;
3745 void
3746 delete_vertex(toporouter_vertex_t *v)
3749 if(v->flags & VERTEX_FLAG_TEMP) {
3750 if(v->routingedge) {
3751 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge))
3752 TOPOROUTER_CONSTRAINT(v->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(v->routingedge)->routing, v);
3753 else
3754 v->routingedge->routing = g_list_remove(v->routingedge->routing, v);
3757 gts_object_destroy ( GTS_OBJECT(v) );
3761 #define edge_is_blocked(e) (TOPOROUTER_IS_EDGE(e) ? (e->flags & EDGE_FLAG_DIRECTCONNECTION) : 0)
3763 GList *
3764 triangle_candidate_points_from_vertex(GtsTriangle *t, toporouter_vertex_t *v, toporouter_vertex_t *dest, toporouter_route_t *routedata)
3766 toporouter_edge_t *op_e = TOPOROUTER_EDGE(gts_triangle_edge_opposite(t, GTS_VERTEX(v)));
3767 toporouter_vertex_t *vv1, *vv2, *constraintv = NULL;
3768 toporouter_edge_t *e1, *e2;
3769 GList *i;
3770 GList *rval = NULL;
3772 #ifdef DEBUG_ROUTE
3773 printf("\tTRIANGLE CAND POINT FROM VERTEX\n");
3775 g_assert(op_e);
3776 #endif
3778 e1 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(v), edge_v1(op_e)));
3779 e2 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(v), edge_v2(op_e)));
3782 if(TOPOROUTER_IS_CONSTRAINT(op_e)) {
3783 if(TOPOROUTER_CONSTRAINT(op_e)->box->type == BOARD) {
3784 #ifdef DEBUG_ROUTE
3785 printf("BOARD constraint\n");
3786 #endif
3787 return NULL;
3789 if(constraint_netlist(TOPOROUTER_CONSTRAINT(op_e)) != vertex_netlist(dest)) { // || TOPOROUTER_CONSTRAINT(op_e)->routing) {
3790 #ifdef DEBUG_ROUTE
3791 printf("op_e routing:\n");
3792 print_edge(op_e);
3793 #endif
3794 return NULL;
3796 #ifdef DEBUG_ROUTE
3797 printf("RETURNING CONSTRAINT POING\n");
3798 #endif
3799 constraintv = new_temp_toporoutervertex_in_segment(op_e, TOPOROUTER_VERTEX(edge_v1(op_e)),
3800 gts_point_distance(GTS_POINT(edge_v1(op_e)), GTS_POINT(edge_v2(op_e))) / 2., TOPOROUTER_VERTEX(edge_v2(op_e)));
3801 // return g_list_prepend(NULL, vv1);
3806 if(edge_is_blocked(op_e)) {
3807 goto triangle_candidate_points_from_vertex_exit;
3809 // v1 = tedge_v1(op_e);
3810 // v2 = tedge_v2(op_e);
3812 if(v == tedge_v1(e1)) {
3813 i = edge_routing_first_not_temp(e1);
3814 }else{
3815 i = edge_routing_last_not_temp(e1);
3818 if(i) {
3819 toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data);
3821 if(temp->parent == tedge_v2(op_e) || temp->child == tedge_v2(op_e)) {
3822 #ifdef DEBUG_ROUTE
3823 printf("temp -> op_e->v2\n");
3824 #endif
3825 goto triangle_candidate_points_from_vertex_exit;
3827 if(temp->parent->routingedge == op_e) {
3828 vv1 = temp->parent;
3829 #ifdef DEBUG_ROUTE
3830 printf("vv1->parent\n");
3831 #endif
3833 }else if(temp->child->routingedge == op_e) {
3834 vv1 = temp->child;
3835 #ifdef DEBUG_ROUTE
3836 printf("vv1->child\n");
3837 #endif
3839 }else{
3840 // must be to e2
3841 #ifdef DEBUG_ROUTE
3842 printf("temp -> e2?\n");
3843 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)) );
3844 if(temp->parent->routingedge)
3845 printf("temp->parent->routingedge = %f,%f \t\t %f,%f\n",
3846 vx(edge_v1(temp->parent->routingedge)), vy(edge_v1(temp->parent->routingedge)),
3847 vx(edge_v2(temp->parent->routingedge)), vy(edge_v2(temp->parent->routingedge))
3849 else
3850 printf("temp->parent->routingedge = NULL\n");
3852 if(temp->child->routingedge)
3853 printf("temp->child->routingedge = %f,%f \t\t %f,%f\n",
3854 vx(edge_v1(temp->child->routingedge)), vy(edge_v1(temp->child->routingedge)),
3855 vx(edge_v2(temp->child->routingedge)), vy(edge_v2(temp->child->routingedge))
3857 else
3858 printf("temp->child->routingedge = NULL\n");
3859 #endif
3860 goto triangle_candidate_points_from_vertex_exit;
3863 }else{
3864 vv1 = tedge_v1(op_e);
3865 #ifdef DEBUG_ROUTE
3866 printf("nothing on e1\n");
3867 #endif
3870 if(v == tedge_v1(e2)) {
3871 i = edge_routing_first_not_temp(e2);
3872 }else{
3873 i = edge_routing_last_not_temp(e2);
3876 if(i) {
3877 toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data);
3879 if(temp->parent == tedge_v1(op_e) || temp->child == tedge_v1(op_e)) {
3880 #ifdef DEBUG_ROUTE
3881 printf("temp -> op_e->v2\n");
3882 #endif
3883 goto triangle_candidate_points_from_vertex_exit;
3886 if(temp->parent->routingedge == op_e) {
3887 vv2 = temp->parent;
3888 #ifdef DEBUG_ROUTE
3889 printf("vv2->parent\n");
3890 #endif
3891 }else if(temp->child->routingedge == op_e) {
3892 vv2 = temp->child;
3893 #ifdef DEBUG_ROUTE
3894 printf("vv2->child\n");
3895 #endif
3897 }else{
3898 // must be to e1
3899 #ifdef DEBUG_ROUTE
3900 printf("temp -> e1?\n");
3901 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)) );
3902 if(temp->parent->routingedge)
3903 printf("temp->parent->routingedge = %f,%f \t\t %f,%f\n",
3904 vx(edge_v1(temp->parent->routingedge)), vy(edge_v1(temp->parent->routingedge)),
3905 vx(edge_v2(temp->parent->routingedge)), vy(edge_v2(temp->parent->routingedge))
3907 else
3908 printf("temp->parent->routingedge = NULL\n");
3910 if(temp->child->routingedge)
3911 printf("temp->child->routingedge = %f,%f \t\t %f,%f\n",
3912 vx(edge_v1(temp->child->routingedge)), vy(edge_v1(temp->child->routingedge)),
3913 vx(edge_v2(temp->child->routingedge)), vy(edge_v2(temp->child->routingedge))
3915 else
3916 printf("temp->child->routingedge = NULL\n");
3917 #endif
3918 goto triangle_candidate_points_from_vertex_exit;
3921 }else{
3922 vv2 = tedge_v2(op_e);
3923 #ifdef DEBUG_ROUTE
3924 printf("nothing on e2\n");
3925 #endif
3928 #ifdef DEBUG_ROUTE
3929 printf("size of e1 routing = %d e2 routing = %d op_e routing = %d\n",
3930 g_list_length(edge_routing(e1)), g_list_length(edge_routing(e2)), g_list_length(edge_routing(op_e)));
3931 #endif
3933 if(constraintv) {
3934 #ifdef DEBUG_ROUTE
3935 print_vertex(constraintv);
3936 printf("constraintv %f,%f returning\n", vx(constraintv), vy(constraintv));
3937 #endif
3938 return g_list_prepend(NULL, constraintv);
3941 i = edge_routing(op_e);
3942 while(i) {
3943 toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data);
3945 if(temp->parent == v || temp->child == v) {
3946 rval = g_list_concat(rval, candidate_vertices(vv1, temp, dest, op_e));
3947 vv1 = temp;
3950 i = i->next;
3953 rval = g_list_concat(rval, candidate_vertices(vv1, vv2, dest, op_e));
3955 return rval;
3959 triangle_candidate_points_from_vertex_exit:
3960 if(constraintv) //delete_vertex(constraintv);
3961 g_hash_table_insert(routedata->alltemppoints, constraintv, constraintv);
3963 g_list_free(rval);
3965 return NULL;
3968 void
3969 routedata_insert_temppoints(toporouter_route_t *data, GList *temppoints) {
3970 GList *j = temppoints;
3971 while(j) {
3972 g_hash_table_insert(data->alltemppoints, j->data, j->data);
3973 j = j->next;
3978 inline gint
3979 constraint_route_test(toporouter_constraint_t *c, toporouter_route_t *routedata)
3981 if(c->box->cluster && c->box->cluster->netlist == routedata->src->netlist) {
3982 if(c->box->cluster->c == routedata->dest->c || c->box->cluster->c == routedata->src->c) return 1;
3984 return 0;
3987 GList *
3988 all_candidates_on_edge(toporouter_edge_t *e, toporouter_route_t *routedata)
3990 GList *rval = NULL;
3991 if(edge_is_blocked(e)) return NULL;
3993 if(!TOPOROUTER_IS_CONSTRAINT(e)) {
3994 GList *i = edge_routing(e);
3995 toporouter_vertex_t *pv = tedge_v1(e);
3997 while(i) {
3998 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
3999 if(!(v->flags & VERTEX_FLAG_TEMP)) {
4000 rval = g_list_concat(rval, candidate_vertices(pv, v, TOPOROUTER_VERTEX(routedata->destvertices->data), e));
4001 pv = v;
4003 i = i->next;
4006 rval = g_list_concat(rval, candidate_vertices(pv, tedge_v2(e), TOPOROUTER_VERTEX(routedata->destvertices->data), e));
4007 }else if(TOPOROUTER_CONSTRAINT(e)->box->type == BOARD) {
4008 return NULL;
4009 }else if(constraint_route_test(TOPOROUTER_CONSTRAINT(e), routedata)) {
4010 toporouter_vertex_t *consv = new_temp_toporoutervertex_in_segment(e, tedge_v1(e), tvdistance(tedge_v1(e), tedge_v2(e)) / 2., tedge_v2(e));
4011 rval = g_list_prepend(rval, consv);
4012 // g_hash_table_insert(routedata->alltemppoints, consv, consv);
4015 return rval;
4018 GList *
4019 triangle_all_candidate_points_from_vertex(GtsTriangle *t, toporouter_vertex_t *v, toporouter_route_t *routedata)
4021 toporouter_edge_t *op_e = TOPOROUTER_EDGE(gts_triangle_edge_opposite(t, GTS_VERTEX(v)));
4022 return all_candidates_on_edge(op_e, routedata);
4025 GList *
4026 triangle_all_candidate_points_from_edge(toporouter_t *r, GtsTriangle *t, toporouter_edge_t *e, toporouter_route_t *routedata,
4027 toporouter_vertex_t **dest, toporouter_vertex_t *curpoint)
4029 toporouter_vertex_t *op_v;
4030 toporouter_edge_t *e1, *e2;
4031 GList *i, *rval = NULL, *rval2 = NULL;
4032 toporouter_vertex_t *boxpoint = NULL;
4033 guint e1intcap, e2intcap;
4035 op_v = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(t, GTS_EDGE(e)));
4038 if(vertex_bbox(op_v)) boxpoint = TOPOROUTER_VERTEX(vertex_bbox(op_v)->point);
4040 if(g_list_find(routedata->destvertices, op_v)) {
4041 rval = g_list_prepend(rval, op_v);
4042 *dest = op_v;
4043 return rval;
4044 }else if(g_list_find(routedata->destvertices, boxpoint)) {
4045 *dest = boxpoint;
4046 }else if(g_list_find(routedata->srcvertices, op_v)) {
4047 rval = g_list_prepend(rval, op_v);
4050 e1 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(op_v), edge_v1(e)));
4051 e2 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(op_v), edge_v2(e)));
4053 rval = g_list_concat(rval, all_candidates_on_edge(e1, routedata));
4054 rval = g_list_concat(rval, all_candidates_on_edge(e2, routedata));
4056 e1intcap = check_triangle_interior_capacity(t, tedge_v1(e), curpoint, e2, e, e1);
4057 e2intcap = check_triangle_interior_capacity(t, tedge_v2(e), curpoint, e1, e, e2);
4059 i = rval;
4060 while(i) {
4061 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
4063 if(!v->routingedge)
4064 rval2 = g_list_prepend(rval2, v);
4065 else if(v->routingedge == e1 && !(!TOPOROUTER_IS_CONSTRAINT(e1) && !e1intcap))
4066 rval2 = g_list_prepend(rval2, v);
4067 else if(v->routingedge == e2 && !(!TOPOROUTER_IS_CONSTRAINT(e2) && !e2intcap))
4068 rval2 = g_list_prepend(rval2, v);
4070 i = i->next;
4072 g_list_free(rval);
4074 return rval2;
4077 GList *
4078 triangle_candidate_points_from_edge(toporouter_t *r, GtsTriangle *t, toporouter_edge_t *e, toporouter_vertex_t *v, toporouter_vertex_t **dest,
4079 toporouter_route_t *routedata)
4081 toporouter_vertex_t *v1, *v2, *op_v, *vv = NULL, *e1constraintv = NULL, *e2constraintv = NULL;
4082 toporouter_edge_t *e1, *e2;
4083 GList *e1cands = NULL, *e2cands = NULL, *rval = NULL;
4084 guint noe1 = 0, noe2 = 0;
4086 op_v = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(t, GTS_EDGE(e)));
4088 e1 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(op_v), edge_v1(e)));
4089 e2 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(op_v), edge_v2(e)));
4091 g_assert(*dest);
4093 // v1 is prev dir, v2 is next dir
4094 edge_adjacent_vertices(e, v, &v1, &v2);
4096 if(TOPOROUTER_IS_CONSTRAINT(e1)) {
4097 GList *i = edge_routing(e1);
4099 if(TOPOROUTER_CONSTRAINT(e1)->box->type == BOARD) {
4100 noe1 = 1;
4101 }else if(!constraint_route_test(TOPOROUTER_CONSTRAINT(e1), routedata)) {
4102 noe1 = 1;
4103 #ifdef DEBUG_ROUTE
4104 printf("noe1 netlist\n");
4105 #endif
4106 }else
4108 if(v1 == tedge_v1(e) ||
4109 (v1->parent->routingedge && v1->parent->routingedge == e1) ||
4110 (v1->child->routingedge && v1->child->routingedge == e1)) {
4111 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));
4114 while(i) {
4115 toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data);
4117 if((temp->child == tedge_v2(e) || temp->parent == tedge_v2(e)) && !(temp->flags & VERTEX_FLAG_TEMP)) noe2 = 1;
4119 i = i->next;
4122 goto triangle_candidate_points_e2;
4125 if(edge_is_blocked(e1)) {
4126 noe1 = 1;
4127 goto triangle_candidate_points_e2;
4130 if(v1 == tedge_v1(e)) {
4131 // continue up e1
4132 toporouter_vertex_t *vv1, *vv2;
4133 edge_adjacent_vertices(e1, v1, &vv1, &vv2);
4135 #ifdef DEBUG_ROUTE
4136 printf("v1 == e->v1\n");
4137 #endif
4139 if(vv1) {
4140 // candidates from v1 until vv1
4141 vv = vv1;
4142 }else{
4143 // candidates from v1 until vv2
4144 vv = vv2;
4147 if(!e1constraintv) e1cands = candidate_vertices(v1, vv, *dest, e1);
4149 if(vv != op_v) {
4150 if(vv->parent == tedge_v2(e) || vv->child == tedge_v2(e)) {
4151 #ifdef DEBUG_ROUTE
4152 printf("noe2 0\n");
4153 #endif
4154 noe2 = 1;
4158 }else if(v1->parent != op_v && v1->child != op_v) {
4159 toporouter_vertex_t *vv1 = NULL, *vv2 = NULL;
4161 #ifdef DEBUG_ROUTE
4162 printf("v1 != e->v1\n");
4163 #endif
4165 if(v1->parent->routingedge == e1) {
4166 vv1 = v1->parent;
4167 #ifdef DEBUG_ROUTE
4168 printf("v1 parent = e1\n");
4169 #endif
4170 if(op_v == tedge_v1(e1)) {
4171 // candidates from v1->parent until prev vertex
4172 vv2 = edge_routing_prev_not_temp(e1, g_list_find(edge_routing(e1), v1->parent)->prev);
4173 }else{
4174 // candidates from v1->parent until next vertex
4175 vv2 = edge_routing_next_not_temp(e1, g_list_find(edge_routing(e1), v1->parent)->next);
4178 }else if(v1->child->routingedge == e1) {
4179 vv1 = v1->child;
4180 #ifdef DEBUG_ROUTE
4181 printf("v1 child = e1\n");
4182 #endif
4183 if(op_v == tedge_v1(e1)) {
4184 // candidates from v1->child until prev vertex
4185 vv2 = edge_routing_prev_not_temp(e1, g_list_find(edge_routing(e1), v1->child)->prev);
4186 }else{
4187 // candidates from v1->child until next vertex
4188 vv2 = edge_routing_next_not_temp(e1, g_list_find(edge_routing(e1), v1->child)->next);
4191 }else{
4192 #ifdef DEBUG_ROUTE
4193 printf("v1 ? \n");
4194 #endif
4195 goto triangle_candidate_points_e2;
4198 if(vv1 && vv2) {
4199 if(vv2->parent == tedge_v2(e) || vv2->child == tedge_v2(e)) {
4200 #ifdef DEBUG_ROUTE
4201 printf("noe2 1\n");
4202 #endif
4203 noe2 = 1;
4206 if(!e1constraintv) e1cands = candidate_vertices(vv1, vv2, *dest, e1);
4208 vv = vv2;
4212 if(vv && vv == op_v) {
4213 toporouter_vertex_t *boxpoint = NULL;
4215 if(vertex_bbox(op_v)) boxpoint = TOPOROUTER_VERTEX(vertex_bbox(op_v)->point);
4217 if(g_list_find(routedata->destvertices, op_v)) {
4218 rval = g_list_prepend(rval, op_v);
4219 *dest = op_v;
4220 }else if(g_list_find(routedata->destvertices, boxpoint)) {
4221 *dest = boxpoint;
4222 }else if(g_list_find(routedata->srcvertices, op_v)) {
4223 rval = g_list_prepend(rval, op_v);
4227 triangle_candidate_points_e2:
4229 if(noe2) {
4230 // printf("noe2\n");
4231 goto triangle_candidate_points_finish;
4234 if(TOPOROUTER_IS_CONSTRAINT(e2)) {
4235 GList *i = edge_routing(e2);
4237 if(TOPOROUTER_CONSTRAINT(e2)->box->type == BOARD) {
4238 noe2 = 1;
4239 // goto triangle_candidate_points_finish;
4240 }else if(!constraint_route_test(TOPOROUTER_CONSTRAINT(e2), routedata)) {
4241 #ifdef DEBUG_ROUTE
4242 printf("noe2 netlist\n");
4243 #endif
4244 noe2 = 1;
4245 // goto triangle_candidate_points_finish;
4246 }else if(v2 == tedge_v2(e) ||
4247 (v2->parent->routingedge && v2->parent->routingedge == e2) ||
4248 (v2->child->routingedge && v2->child->routingedge == e2)) {
4250 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));
4254 while(i) {
4255 toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data);
4257 if((temp->child == tedge_v1(e) || temp->parent == tedge_v1(e)) && !(temp->flags & VERTEX_FLAG_TEMP))
4258 noe1 = 1;
4260 i = i->next;
4265 goto triangle_candidate_points_finish;
4268 if(edge_is_blocked(e2)) {
4269 noe2 = 1;
4270 goto triangle_candidate_points_finish;
4273 if(v2 == tedge_v2(e)) {
4274 // continue up e2
4275 toporouter_vertex_t *vv1 = NULL, *vv2 = NULL;
4276 edge_adjacent_vertices(e2, v2, &vv1, &vv2);
4278 #ifdef DEBUG_ROUTE
4279 printf("v2 == e->v2\n");
4280 #endif
4282 if(vv1) {
4283 // candidates from v2 until vv1
4284 vv = vv1;
4285 }else{
4286 // candidates from v2 until vv2
4287 vv = vv2;
4290 if(!e2constraintv) e2cands = candidate_vertices(v2, vv, *dest, e2);
4292 if(vv != op_v) {
4293 if(vv->parent == tedge_v1(e) || vv->child == tedge_v1(e)) {
4294 #ifdef DEBUG_ROUTE
4295 printf("noe1 0\n");
4296 #endif
4297 noe1 = 1;
4301 }else if(v2->parent != op_v && v2->child != op_v) {
4302 toporouter_vertex_t *vv1 = NULL, *vv2 = NULL;
4304 #ifdef DEBUG_ROUTE
4305 printf("v2 == e->v2\n");
4306 #endif
4308 if(v2->parent->routingedge == e2) {
4309 vv1 = v2->parent;
4310 if(op_v == tedge_v1(e2)) {
4311 // candidates from v2->parent until prev vertex
4312 vv2 = edge_routing_prev_not_temp(e2, g_list_find(edge_routing(e2), vv1)->prev);
4313 }else{
4314 // candidates from v2->parent until next vertex
4315 vv2 = edge_routing_next_not_temp(e2, g_list_find(edge_routing(e2), vv1)->next);
4318 }else if(v2->child->routingedge == e2) {
4319 vv1 = v2->child;
4320 if(op_v == tedge_v1(e2)) {
4321 // candidates from v2->child until prev vertex
4322 vv2 = edge_routing_prev_not_temp(e2, g_list_find(edge_routing(e2), vv1)->prev);
4323 }else{
4324 // candidates from v2->child until next vertex
4325 vv2 = edge_routing_next_not_temp(e2, g_list_find(edge_routing(e2), vv1)->next);
4328 }else{
4329 goto triangle_candidate_points_finish;
4332 if(vv1 && vv2) {
4333 if(vv2->parent == tedge_v1(e) || vv2->child == tedge_v1(e)) {
4334 #ifdef DEBUG_ROUTE
4335 printf("noe1 1\n");
4336 #endif
4337 noe1 = 1;
4340 if(!e2constraintv) e2cands = candidate_vertices(vv1, vv2, *dest, e2);
4344 triangle_candidate_points_finish:
4346 v1 = segment_common_vertex(GTS_SEGMENT(e), GTS_SEGMENT(e1));
4347 v2 = segment_common_vertex(GTS_SEGMENT(e), GTS_SEGMENT(e2));
4349 if(noe1 || !check_triangle_interior_capacity(t, v1, v, e2, e, e1)) {
4350 #ifdef DEBUG_ROUTE
4351 printf("freeing e1cands\n");
4352 #endif
4353 routedata_insert_temppoints(routedata, e1cands);
4354 g_list_free(e1cands);
4355 e1cands = NULL;
4358 if(noe2 || !check_triangle_interior_capacity(t, v2, v, e1, e, e2)) {
4359 #ifdef DEBUG_ROUTE
4360 printf("freeing e2cands\n");
4361 #endif
4362 routedata_insert_temppoints(routedata, e2cands);
4363 g_list_free(e2cands);
4364 e2cands = NULL;
4367 if(!noe1 && e1constraintv) {
4368 e1cands = g_list_prepend(e1cands, e1constraintv);
4369 }else if(e1constraintv) {
4370 g_hash_table_insert(routedata->alltemppoints, e1constraintv, e1constraintv);
4371 // delete_vertex(e1constraintv);
4374 if(!noe2 && e2constraintv) {
4375 e2cands = g_list_prepend(e2cands, e2constraintv);
4376 }else if(e2constraintv) {
4377 g_hash_table_insert(routedata->alltemppoints, e2constraintv, e2constraintv);
4378 // delete_vertex(e2constraintv);
4381 if(!noe1 && !noe2) return g_list_concat(rval, g_list_concat(e1cands, e2cands));
4383 return g_list_concat(e1cands, e2cands);
4386 GList *
4387 compute_candidate_points(toporouter_t *tr, toporouter_layer_t *l, toporouter_vertex_t *curpoint, toporouter_route_t *data,
4388 toporouter_vertex_t **closestdest)
4390 GList *r = NULL, *j;
4391 toporouter_edge_t *edge = curpoint->routingedge, *tempedge;
4393 if(vertex_keepout_test(tr, curpoint)) goto compute_candidate_points_finish;
4395 /* direct connection */
4396 // if(curpoint == TOPOROUTER_VERTEX(data->src->point))
4397 if((tempedge = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(curpoint), GTS_VERTEX(*closestdest))))) {
4399 if(TOPOROUTER_IS_CONSTRAINT(tempedge)) {
4400 goto compute_candidate_points_finish;
4401 }else{
4402 if(!tempedge->routing) {
4403 r = g_list_prepend(NULL, *closestdest);
4404 tempedge->flags |= EDGE_FLAG_DIRECTCONNECTION;
4405 goto compute_candidate_points_finish;
4406 }else{
4407 #ifdef DEBUG_ROUTE
4408 printf("Direct connection, but has routing\n");
4409 #endif
4413 /* if we get to here, there is routing blocking the direct connection,
4414 * continue as per normal */
4417 /* a real point origin */
4418 if(!(curpoint->flags & VERTEX_FLAG_TEMP)) {
4419 GSList *triangles, *i;
4420 i = triangles = gts_vertex_triangles(GTS_VERTEX(curpoint), NULL);
4421 #ifdef DEBUG_ROUTE
4422 printf("triangle count = %d\n", g_slist_length(triangles));
4423 #endif
4424 while(i) {
4425 GtsTriangle *t = GTS_TRIANGLE(i->data);
4426 GList *temppoints;
4428 if(tr->flags & TOPOROUTER_FLAG_LEASTINVALID) temppoints = triangle_all_candidate_points_from_vertex(t, curpoint, data);
4429 else temppoints = triangle_candidate_points_from_vertex(t, curpoint, *closestdest, data);
4431 #ifdef DEBUG_ROUTE
4432 printf("\treturned %d points\n", g_list_length(temppoints));
4433 #endif
4434 routedata_insert_temppoints(data, temppoints);
4436 r = g_list_concat(r, temppoints);
4437 i = i->next;
4439 g_slist_free(triangles);
4440 }else /* a temp point */ {
4441 int prevwind = vertex_wind(GTS_SEGMENT(edge)->v1, GTS_SEGMENT(edge)->v2, GTS_VERTEX(curpoint->parent));
4442 // printf("tempoint\n");
4444 GSList *i = GTS_EDGE(edge)->triangles;
4446 while(i) {
4447 GtsVertex *oppv = gts_triangle_vertex_opposite(GTS_TRIANGLE(i->data), GTS_EDGE(edge));
4448 if(prevwind != vertex_wind(GTS_SEGMENT(edge)->v1, GTS_SEGMENT(edge)->v2, oppv)) {
4449 GList *temppoints;
4451 if(tr->flags & TOPOROUTER_FLAG_LEASTINVALID) temppoints = triangle_all_candidate_points_from_edge(tr, GTS_TRIANGLE(i->data), edge,
4452 data, closestdest, curpoint);
4453 else temppoints = triangle_candidate_points_from_edge(tr, GTS_TRIANGLE(i->data), edge, curpoint, closestdest, data);
4455 j = temppoints;
4456 while(j) {
4457 toporouter_vertex_t *tempj = TOPOROUTER_VERTEX(j->data);
4458 if(tempj->flags & VERTEX_FLAG_TEMP)
4459 g_hash_table_insert(data->alltemppoints, j->data, j->data);
4460 #ifdef DEBUG_ROUTE
4461 else
4462 printf("got cand not a temp\n");
4463 #endif
4464 j = j->next;
4466 r = g_list_concat(r, temppoints);
4468 break;
4470 i = i->next;
4474 compute_candidate_points_finish:
4476 if(vertex_bbox(curpoint) && vertex_bbox(curpoint)->cluster) {
4477 if(vertex_bbox(curpoint)->cluster->c == data->src->c) {
4478 r = g_list_concat(r, g_list_copy(data->srcvertices));
4482 return r;
4485 gboolean
4486 temp_point_clean(gpointer key, gpointer value, gpointer user_data)
4488 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(value);
4489 if(tv->flags & VERTEX_FLAG_TEMP) {
4490 if(TOPOROUTER_IS_CONSTRAINT(tv->routingedge))
4491 TOPOROUTER_CONSTRAINT(tv->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(tv->routingedge)->routing, tv);
4492 else
4493 tv->routingedge->routing = g_list_remove(tv->routingedge->routing, tv);
4494 gts_object_destroy ( GTS_OBJECT(tv) );
4496 return TRUE;
4499 void
4500 clean_routing_edges(toporouter_t *r, toporouter_route_t *data)
4502 g_hash_table_foreach_remove(data->alltemppoints, temp_point_clean, NULL);
4503 g_hash_table_destroy(data->alltemppoints);
4504 data->alltemppoints = NULL;
4507 gdouble
4508 path_score(toporouter_t *r, GList *path)
4510 gdouble score = 0.;
4511 toporouter_vertex_t *pv = NULL;
4512 toporouter_vertex_t *v0 = NULL;
4514 if(!path) return INFINITY;
4516 v0 = TOPOROUTER_VERTEX(path->data);
4518 while(path) {
4519 toporouter_vertex_t *v = TOPOROUTER_VERTEX(path->data);
4521 if(pv) {
4522 score += gts_point_distance(GTS_POINT(pv), GTS_POINT(v));
4523 if(pv != v0 && vz(pv) != vz(v))
4524 if(path->next)
4525 score += r->viacost;
4529 pv = v;
4530 path = path->next;
4533 return score;
4536 void
4537 print_vertices(GList *vertices)
4539 while(vertices) {
4540 toporouter_vertex_t *v = TOPOROUTER_VERTEX(vertices->data);
4541 print_vertex(v);
4542 print_bbox(vertex_bbox(v));
4543 if(vertex_bbox(v)) {
4544 printf("has bbox\n");
4545 if(vertex_bbox(v)->cluster)
4546 printf("has cluster\n");
4547 else
4548 printf("no cluster\n");
4549 }else printf("no bbox\n");
4550 vertices = vertices->next;
4554 gint
4555 space_edge(gpointer item, gpointer data)
4557 toporouter_edge_t *e = TOPOROUTER_EDGE(item);
4558 GList *i;
4559 gdouble *forces;
4561 if(TOPOROUTER_IS_CONSTRAINT(e)) return 0;
4563 if(!edge_routing(e) || !g_list_length(edge_routing(e))) return 0;
4565 forces = malloc(sizeof(double) * g_list_length(edge_routing(e)));
4567 for(guint j=0;j<100;j++) {
4568 guint k=0;
4569 guint equilibrium = 1;
4571 i = edge_routing(e);
4572 while(i) {
4573 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
4574 gdouble ms, d;
4576 if(i->prev) {
4577 // ms = min_net_net_spacing(TOPOROUTER_VERTEX(i->prev->data), v);
4578 ms = min_spacing(TOPOROUTER_VERTEX(i->prev->data), v);
4579 d = gts_point_distance(GTS_POINT(i->prev->data), GTS_POINT(v));
4580 }else{
4581 // ms = min_vertex_net_spacing(v, tedge_v1(e));
4582 ms = min_spacing(v, tedge_v1(e));
4583 d = gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(v));
4586 if(d < ms) forces[k] = ms - d;
4587 else forces[k] = 0.;
4589 if(i->next) {
4590 // ms = min_net_net_spacing(TOPOROUTER_VERTEX(i->next->data), v);
4591 ms = min_spacing(TOPOROUTER_VERTEX(i->next->data), v);
4592 d = gts_point_distance(GTS_POINT(i->next->data), GTS_POINT(v));
4593 }else{
4594 // ms = min_vertex_net_spacing(v, tedge_v2(e));
4595 ms = min_spacing(v, tedge_v2(e));
4596 d = gts_point_distance(GTS_POINT(edge_v2(e)), GTS_POINT(v));
4599 if(d < ms) forces[k] += d - ms;
4601 k++; i = i->next;
4604 k = 0;
4605 i = edge_routing(e);
4606 while(i) {
4607 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
4608 if(forces[k] > EPSILON || forces[k] < -EPSILON) equilibrium = 0;
4609 vertex_move_towards_vertex_values(GTS_VERTEX(v), edge_v2(e), forces[k] * 0.1, &(GTS_POINT(v)->x), &(GTS_POINT(v)->y));
4610 k++; i = i->next;
4613 if(equilibrium) {
4614 // printf("reached equilibriium at %d\n", j);
4615 break;
4620 free(forces);
4621 return 0;
4624 void
4625 swap_vertices(toporouter_vertex_t **v1, toporouter_vertex_t **v2)
4627 toporouter_vertex_t *tempv = *v1;
4628 *v1 = *v2;
4629 *v2 = tempv;
4632 void
4633 split_edge_routing(toporouter_vertex_t *v, GList **l1, GList **l2)
4635 GList *base, *i;
4637 g_assert(v);
4638 g_assert(v->routingedge);
4640 base = g_list_find(vrouting(v), v);
4642 *l1 = g_list_prepend(*l1, tedge_v1(v->routingedge));
4643 *l2 = g_list_prepend(*l2, tedge_v2(v->routingedge));
4645 g_assert(base);
4647 i = base->next;
4648 while(i) {
4649 if(!(TOPOROUTER_VERTEX(i->data)->flags & VERTEX_FLAG_TEMP)) *l2 = g_list_prepend(*l2, i->data);
4650 i = i->next;
4653 i = base->prev;
4654 while(i) {
4655 if(!(TOPOROUTER_VERTEX(i->data)->flags & VERTEX_FLAG_TEMP)) *l1 = g_list_prepend(*l1, i->data);
4656 i = i->prev;
4660 GList *
4661 vertices_routing_conflicts(toporouter_vertex_t *v, toporouter_vertex_t *pv)
4663 toporouter_edge_t *e;
4664 GList *rval = NULL, *l1 = NULL, *l2 = NULL, *i;
4666 if(vz(v) != vz(pv)) return NULL;
4667 g_assert(v != pv);
4669 if(!v->routingedge && !pv->routingedge) {
4670 e = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(v), GTS_VERTEX(pv)));
4671 if(!e) return NULL;
4672 i = edge_routing(e);
4673 while(i) {
4674 rval = g_list_prepend(rval, TOPOROUTER_VERTEX(i->data)->route);
4675 i = i->next;
4677 return rval;
4680 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge) && TOPOROUTER_IS_CONSTRAINT(pv->routingedge))
4681 return NULL;
4683 if(TOPOROUTER_IS_CONSTRAINT(pv->routingedge)) swap_vertices(&pv, &v);
4685 if(!v->routingedge) swap_vertices(&pv, &v);
4687 e = v->routingedge;
4689 split_edge_routing(v, &l1, &l2);
4690 g_assert(l2);
4691 g_assert(l1);
4693 if(!pv->routingedge) {
4694 toporouter_edge_t *e1, *e2;
4695 e1 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(pv), edge_v1(e)));
4696 e2 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(pv), edge_v2(e)));
4698 l1 = g_list_concat(l1, g_list_copy(edge_routing(e1)));
4699 l2 = g_list_concat(l2, g_list_copy(edge_routing(e2)));
4701 }else{
4702 GList *pvlist1 = NULL, *pvlist2 = NULL;
4703 toporouter_vertex_t *commonv = route_vertices_common_vertex(v, pv);
4705 g_assert(commonv);
4707 split_edge_routing(pv, &pvlist1, &pvlist2);
4709 if(commonv == tedge_v1(e)) {
4710 toporouter_edge_t *ope;
4712 if(commonv == tedge_v1(pv->routingedge)) {
4713 l1 = g_list_concat(l1, pvlist1);
4714 l2 = g_list_concat(l2, pvlist2);
4715 ope = TOPOROUTER_EDGE(gts_vertices_are_connected(edge_v2(e), edge_v2(pv->routingedge)));
4716 }else{
4717 l1 = g_list_concat(l1, pvlist2);
4718 l2 = g_list_concat(l2, pvlist1);
4719 ope = TOPOROUTER_EDGE(gts_vertices_are_connected(edge_v2(e), edge_v1(pv->routingedge)));
4721 g_assert(ope);
4722 l2 = g_list_concat(l2, g_list_copy(edge_routing(ope)));
4724 }else{
4725 toporouter_edge_t *ope;
4726 if(commonv == tedge_v1(pv->routingedge)) {
4727 l1 = g_list_concat(l1, pvlist2);
4728 l2 = g_list_concat(l2, pvlist1);
4729 ope = TOPOROUTER_EDGE(gts_vertices_are_connected(edge_v1(e), edge_v2(pv->routingedge)));
4730 }else{
4731 l1 = g_list_concat(l1, pvlist1);
4732 l2 = g_list_concat(l2, pvlist2);
4733 ope = TOPOROUTER_EDGE(gts_vertices_are_connected(edge_v1(e), edge_v1(pv->routingedge)));
4735 g_assert(ope);
4736 l1 = g_list_concat(l1, g_list_copy(edge_routing(ope)));
4740 i = l1;
4741 while(i) {
4742 toporouter_vertex_t *curv = TOPOROUTER_VERTEX(i->data);
4744 if(curv->flags & VERTEX_FLAG_ROUTE && (g_list_find(l2, curv->parent) || g_list_find(l2, curv->child))) {
4745 if(!g_list_find(rval, curv->route)) rval = g_list_prepend(rval, curv->route);
4747 i = i->next;
4749 i = l2;
4750 while(i) {
4751 toporouter_vertex_t *curv = TOPOROUTER_VERTEX(i->data);
4753 if(curv->flags & VERTEX_FLAG_ROUTE && (g_list_find(l1, curv->parent) || g_list_find(l1, curv->child))) {
4754 if(!g_list_find(rval, curv->route)) rval = g_list_prepend(rval, curv->route);
4756 i = i->next;
4759 g_list_free(l1);
4760 g_list_free(l2);
4762 return rval;
4765 gdouble
4766 vertices_routing_conflict_cost(toporouter_t *r, toporouter_vertex_t *v, toporouter_vertex_t *pv, guint *n)
4768 GList *conflicts = vertices_routing_conflicts(v, pv), *i;
4769 gdouble penalty = 0.;
4771 i = conflicts;
4772 while(i) {
4773 (*n) += 1;
4774 penalty += TOPOROUTER_ROUTE(i->data)->score;
4775 i = i->next;
4777 g_list_free(conflicts);
4778 // if(penalty > 0.) printf("conflict penalty of %f with %f,%f %f,%f\n", penalty, vx(v), vy(v), vx(pv), vy(pv));
4779 return penalty;
4782 gdouble
4783 gcost(toporouter_t *r, toporouter_route_t *data, toporouter_vertex_t *srcv, toporouter_vertex_t *v, toporouter_vertex_t *pv, guint *n,
4784 toporouter_netlist_t *pair)
4786 gdouble cost = 0., segcost;
4788 *n = pv->gn;
4790 if(g_list_find(data->srcvertices, v)) return 0.;
4792 segcost = tvdistance(pv, v);
4794 if(pair && !TOPOROUTER_IS_CONSTRAINT(v->routingedge) && v->routingedge) {
4795 GList *list = g_list_find(v->routingedge->routing, v);
4796 toporouter_vertex_t *pv = edge_routing_prev_not_temp(v->routingedge, list);
4797 toporouter_vertex_t *nv = edge_routing_next_not_temp(v->routingedge, list);
4799 if(pv->route && pv->route->netlist == pair) {
4800 }else if(nv->route && nv->route->netlist == pair) {
4801 }else{
4802 segcost *= 10.;
4806 cost = pv->gcost + segcost;
4808 if(r->flags & TOPOROUTER_FLAG_LEASTINVALID) {
4809 gdouble conflictcost = 0.;
4811 if(pv && v != pv && vz(v) == vz(pv)) conflictcost = vertices_routing_conflict_cost(r, v, pv, n);
4813 if(!(r->flags & TOPOROUTER_FLAG_DETOUR && *n == 1)) {
4814 cost += conflictcost * (pow(*n,2));
4818 return cost;
4821 #define vlayer(x) (&r->layers[(int)vz(x)])
4823 guint
4824 candidate_is_available(toporouter_vertex_t *pv, toporouter_vertex_t *v)
4826 // TODO: still needed?
4827 while(pv) {
4828 if(pv == v) return 0;
4829 pv = pv->parent;
4832 return 1;
4835 GList *
4836 route(toporouter_t *r, toporouter_route_t *data, guint debug)
4838 GtsEHeap *openlist = gts_eheap_new(route_heap_cmp, NULL);
4839 GList *closelist = NULL;
4840 GList *i, *rval = NULL;
4841 toporouter_netlist_t *pair = NULL;
4842 gint count = 0;
4844 toporouter_vertex_t *srcv = NULL, *destv = NULL, *curpoint = NULL;
4845 toporouter_layer_t *cur_layer, *dest_layer;
4847 g_assert(data->src->c != data->dest->c);
4849 if(data->destvertices) g_list_free(data->destvertices);
4850 if(data->srcvertices) g_list_free(data->srcvertices);
4852 data->destvertices = cluster_vertices(r, data->dest);
4853 data->srcvertices = cluster_vertices(r, data->src);
4855 closest_cluster_pair(r, data->srcvertices, data->destvertices, &curpoint, &destv);
4857 if(!curpoint || !destv) goto routing_return;
4859 srcv = curpoint;
4860 cur_layer = vlayer(curpoint); dest_layer = vlayer(destv);
4862 data->path = NULL;
4864 data->alltemppoints = g_hash_table_new(g_direct_hash, g_direct_equal);
4866 curpoint->parent = NULL;
4867 curpoint->child = NULL;
4868 curpoint->gcost = 0.;
4869 curpoint->gn = 0;
4870 curpoint->hcost = simple_h_cost(r, curpoint, destv);
4872 if(data->netlist && data->netlist->pair) {
4873 GList *i = r->routednets;
4874 while(i) {
4875 toporouter_route_t *curroute = TOPOROUTER_ROUTE(i->data);
4876 if(curroute->netlist == data->netlist->pair) {
4877 pair = data->netlist->pair;
4878 break;
4880 i = i->next;
4884 gts_eheap_insert(openlist, curpoint);
4886 while(gts_eheap_size(openlist) > 0) {
4887 GList *candidatepoints;
4888 data->curpoint = curpoint;
4889 //draw_route_status(r, closelist, openlist, curpoint, data, count++);
4891 curpoint = TOPOROUTER_VERTEX( gts_eheap_remove_top(openlist, NULL) );
4892 if(curpoint->parent && !(curpoint->flags & VERTEX_FLAG_TEMP)) {
4893 if(vz(curpoint) != vz(destv)) {
4894 toporouter_vertex_t *tempv;
4895 cur_layer = vlayer(curpoint);//&r->layers[(int)vz(curpoint)];
4896 tempv = closest_dest_vertex(r, curpoint, data);
4897 if(tempv) {
4898 destv = tempv;
4899 dest_layer = vlayer(destv);//&r->layers[(int)vz(destv)];
4905 // destpoint = closest_dest_vertex(r, curpoint, data);
4906 // dest_layer = &r->layers[(int)vz(destpoint)];
4908 if(g_list_find(data->destvertices, curpoint)) {
4909 toporouter_vertex_t *temppoint = curpoint;
4910 srcv = NULL;
4911 destv = curpoint;
4913 data->path = NULL;
4915 while(temppoint) {
4916 data->path = g_list_prepend(data->path, temppoint);
4917 if(g_list_find(data->srcvertices, temppoint)) {
4918 srcv = temppoint;
4919 if(r->flags & TOPOROUTER_FLAG_AFTERORDER) break;
4921 temppoint = temppoint->parent;
4923 rval = data->path;
4924 data->score = path_score(r, data->path);
4925 #ifdef DEBUG_ROUTE
4926 printf("ROUTE: path score = %f computation cost = %d\n", data->score, count);
4927 #endif
4929 if(srcv->bbox->cluster != data->src) {
4930 data->src = srcv->bbox->cluster;
4933 if(destv->bbox->cluster != data->dest) {
4934 data->dest = destv->bbox->cluster;
4936 goto route_finish;
4938 closelist_insert(curpoint);
4939 #ifdef DEBUG_ROUTE
4940 printf("\n\n\n*** ROUTE COUNT = %d\n", count);
4941 #endif
4942 candidatepoints = compute_candidate_points(r, cur_layer, curpoint, data, &destv);
4944 //#ifdef DEBUG_ROUTE
4945 /*********************
4946 if(debug && !strcmp(data->dest->netlist, " unnamed_net2"))
4948 unsigned int mask = ~(VERTEX_FLAG_RED | VERTEX_FLAG_GREEN | VERTEX_FLAG_BLUE);
4949 char buffer[256];
4950 int j;
4952 for(j=0;j<groupcount();j++) {
4953 i = r->layers[j].vertices;
4954 while(i) {
4955 TOPOROUTER_VERTEX(i->data)->flags &= mask;
4956 i = i->next;
4960 i = candidatepoints;
4961 while(i) {
4962 TOPOROUTER_VERTEX(i->data)->flags |= VERTEX_FLAG_GREEN;
4963 // printf("flagged a candpoint @ %f,%f\n",
4964 // vx(i->data), vy(i->data));
4965 i = i->next;
4968 curpoint->flags |= VERTEX_FLAG_BLUE;
4969 if(curpoint->parent)
4970 curpoint->parent->flags |= VERTEX_FLAG_RED;
4973 for(j=0;j<groupcount();j++) {
4974 GList *datas = g_list_prepend(NULL, data);
4975 sprintf(buffer, "route-%d-%05d.png", j, count);
4976 toporouter_draw_surface(r, r->layers[j].surface, buffer, 1024, 1024, 2, datas, j, candidatepoints);
4977 g_list_free(datas);
4980 //#endif
4981 *********************/
4982 count++;
4983 // if(count > 100) exit(0);
4984 i = candidatepoints;
4985 while(i) {
4986 toporouter_vertex_t *temppoint = TOPOROUTER_VERTEX(i->data);
4987 if(!g_list_find(closelist, temppoint) && candidate_is_available(curpoint, temppoint)) { //&& temppoint != curpoint) {
4988 toporouter_heap_search_data_t heap_search_data = { temppoint, NULL };
4990 guint temp_gn;
4991 gdouble temp_g_cost = gcost(r, data, srcv, temppoint, curpoint, &temp_gn, pair);
4994 gts_eheap_foreach(openlist,toporouter_heap_search, &heap_search_data);
4996 if(heap_search_data.result) {
4997 if(temp_g_cost < temppoint->gcost) {
4999 temppoint->gcost = temp_g_cost;
5000 temppoint->gn = temp_gn;
5002 temppoint->parent = curpoint;
5003 curpoint->child = temppoint;
5005 gts_eheap_update(openlist);
5007 }else{
5008 temppoint->parent = curpoint;
5009 curpoint->child = temppoint;
5011 temppoint->gcost = temp_g_cost;
5012 temppoint->gn = temp_gn;
5014 temppoint->hcost = simple_h_cost(r, temppoint, destv);
5015 // if(cur_layer != dest_layer) temppoint->hcost += r->viacost;
5016 gts_eheap_insert(openlist, temppoint);
5020 i = i->next;
5022 g_list_free(candidatepoints);
5025 #ifdef DEBUG_ROUTE
5026 printf("ROUTE: could not find path!\n");
5027 #endif
5029 data->score = INFINITY;
5030 clean_routing_edges(r, data);
5032 data->path = NULL;
5033 //TOPOROUTER_VERTEX(data->src->point)->parent = NULL;
5034 //TOPOROUTER_VERTEX(data->src->point)->child = NULL;
5035 goto routing_return;
5039 int i;
5040 for(i=0;i<groupcount();i++) {
5041 char buffer[256];
5042 sprintf(buffer, "route-error-%d-%d.png", r->routecount, i);
5043 toporouter_draw_surface(r, r->layers[i].surface, buffer, 1280, 1280, 2, data, i, NULL);
5045 r->routecount++;
5047 // exit(0);
5049 route_finish:
5050 // printf(" * finished a*\n");
5053 int i;
5054 for(i=0;i<groupcount();i++) {
5055 char buffer[256];
5056 sprintf(buffer, "route-preclean-%d-%d.png", i, r->routecount);
5057 toporouter_draw_surface(r, r->layers[i].surface, buffer, 1024, 1024, 2, data, i, NULL);
5059 r->routecount++;
5062 /* {
5063 i = data->path;
5064 while(i) {
5065 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
5067 if(tv->routingedge) {
5068 GList *list = g_list_find(edge_routing(tv->routingedge), tv);
5069 toporouter_vertex_t *restartv = NULL, *boxpoint;
5071 g_assert(list);
5073 if(!list->next) {
5074 if(vertex_bbox(tedge_v2(tv->routingedge)))
5075 boxpoint = TOPOROUTER_VERTEX(vertex_bbox(tedge_v2(tv->routingedge))->point);
5076 else
5077 boxpoint = NULL;
5079 if(tedge_v2(tv->routingedge) != srcv && g_list_find(data->srcvertices, tedge_v2(tv->routingedge)))
5080 restartv = tedge_v2(tv->routingedge);
5081 else if(boxpoint != srcv && g_list_find(data->srcvertices, boxpoint))
5082 restartv = boxpoint;
5085 if(!list->prev) {
5086 if(vertex_bbox(tedge_v1(tv->routingedge)))
5087 boxpoint = TOPOROUTER_VERTEX(vertex_bbox(tedge_v1(tv->routingedge))->point);
5088 else
5089 boxpoint = NULL;
5091 if(tedge_v1(tv->routingedge) != srcv && g_list_find(data->srcvertices, tedge_v1(tv->routingedge)))
5092 restartv = tedge_v1(tv->routingedge);
5093 else if(boxpoint != srcv && g_list_find(data->srcvertices, boxpoint))
5094 restartv = boxpoint;
5098 if(restartv) {
5099 clean_routing_edges(r, data);
5100 gts_eheap_destroy(openlist);
5101 g_list_free(closelist);
5102 openlist = gts_eheap_new(route_heap_cmp, NULL);
5103 closelist = NULL;
5104 g_list_free(data->path);
5105 printf("ROUTING RESTARTING with new src %f,%f,%f\n", vx(restartv), vy(restartv), vz(restartv));
5106 curpoint = restartv;
5107 goto route_begin;
5111 i = i->next;
5114 ///*
5116 toporouter_vertex_t *pv = NULL;
5117 GList *i = data->path;
5118 while(i) {
5119 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
5121 if(pv && g_list_find(data->srcvertices, tv)) {
5122 GList *temp = g_list_copy(i);
5123 g_list_free(data->path);
5124 data->path = temp;
5125 i = data->path;
5127 pv = tv;
5128 i = i->next;
5131 //*/
5133 toporouter_vertex_t *pv = NULL;
5134 GList *i = data->path;
5135 while(i) {
5136 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
5137 if(tv->flags & VERTEX_FLAG_TEMP) {
5138 tv->flags ^= VERTEX_FLAG_TEMP;
5139 tv->flags |= VERTEX_FLAG_ROUTE;
5141 if(pv) pv->child = tv;
5143 if(tv->routingedge) tv->route = data;
5145 // if(tv->routingedge && !TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) space_edge(tv->routingedge, NULL);
5147 pv = tv;
5148 i = i->next;
5153 toporouter_vertex_t *pv = NULL, *v = NULL;
5155 GList *i = data->path;
5156 while(i) {
5157 v = TOPOROUTER_VERTEX(i->data);
5159 if(pv) {
5160 v->parent = pv;
5161 pv->child = v;
5162 }else{
5163 v->parent = NULL;
5166 pv = v;
5167 i = i->next;
5170 if(v) v->child = NULL;
5173 clean_routing_edges(r, data);
5174 // /*
5176 GList *i = data->path;
5177 while(i) {
5178 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
5180 if(v->routingedge && !TOPOROUTER_IS_CONSTRAINT(v->routingedge))
5181 space_edge(v->routingedge, NULL);
5182 i = i->next;
5185 // */
5186 routing_return:
5188 g_list_free(data->destvertices);
5189 g_list_free(data->srcvertices);
5190 data->destvertices = NULL;
5191 data->srcvertices = NULL;
5192 gts_eheap_destroy(openlist);
5193 g_list_free(closelist);
5195 data->alltemppoints = NULL;
5197 return rval;
5200 /* moves vertex v d units in the direction of vertex p */
5201 void
5202 vertex_move_towards_point(GtsVertex *v, gdouble px, gdouble py, gdouble d)
5204 gdouble dx = px - GTS_POINT(v)->x;
5205 gdouble dy = py - GTS_POINT(v)->y;
5206 gdouble theta = atan(fabs(dy/dx));
5208 g_assert(finite(theta));
5210 if( dx >= 0. ) {
5212 if( dy >= 0. ) {
5213 GTS_POINT(v)->x += d * cos(theta);
5214 GTS_POINT(v)->y += d * sin(theta);
5215 }else{
5216 GTS_POINT(v)->x += d * cos(theta);
5217 GTS_POINT(v)->y -= d * sin(theta);
5220 }else{
5222 if( dy >= 0. ) {
5223 GTS_POINT(v)->x -= d * cos(theta);
5224 GTS_POINT(v)->y += d * sin(theta);
5225 }else{
5226 GTS_POINT(v)->x -= d * cos(theta);
5227 GTS_POINT(v)->y -= d * sin(theta);
5234 /* moves vertex v d units in the direction of vertex p */
5235 void
5236 vertex_move_towards_vertex(GtsVertex *v, GtsVertex *p, gdouble d)
5238 gdouble dx = GTS_POINT(p)->x - GTS_POINT(v)->x;
5239 gdouble dy = GTS_POINT(p)->y - GTS_POINT(v)->y;
5240 gdouble theta = atan(fabs(dy/dx));
5242 g_assert(finite(theta));
5244 if( dx >= 0. ) {
5246 if( dy >= 0. ) {
5247 GTS_POINT(v)->x += d * cos(theta);
5248 GTS_POINT(v)->y += d * sin(theta);
5249 }else{
5250 GTS_POINT(v)->x += d * cos(theta);
5251 GTS_POINT(v)->y -= d * sin(theta);
5254 }else{
5256 if( dy >= 0. ) {
5257 GTS_POINT(v)->x -= d * cos(theta);
5258 GTS_POINT(v)->y += d * sin(theta);
5259 }else{
5260 GTS_POINT(v)->x -= d * cos(theta);
5261 GTS_POINT(v)->y -= d * sin(theta);
5269 gdouble
5270 pathvertex_arcing_through_constraint(toporouter_vertex_t *pathv, toporouter_vertex_t *arcv)
5272 toporouter_vertex_t *v = pathv->child;
5274 if(!v || !v->routingedge) return 0.;
5276 while(v->flags & VERTEX_FLAG_ROUTE && (tedge_v1(v->routingedge) == arcv || tedge_v2(v->routingedge) == arcv)) {
5277 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge))
5278 return gts_point_distance(GTS_POINT(tedge_v1(v->routingedge)), GTS_POINT(tedge_v2(v->routingedge)));
5279 v = v->child;
5282 v = pathv->parent;
5283 while(v->flags & VERTEX_FLAG_ROUTE && (tedge_v1(v->routingedge) == arcv || tedge_v2(v->routingedge) == arcv)) {
5284 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge))
5285 return gts_point_distance(GTS_POINT(tedge_v1(v->routingedge)), GTS_POINT(tedge_v2(v->routingedge)));
5286 v = v->parent;
5289 return 0.;
5292 gint
5293 vertices_connected(toporouter_vertex_t *a, toporouter_vertex_t *b)
5295 return ((a->route->netlist == b->route->netlist && a->route->src->c == b->route->src->c) ? 1 : 0);
5298 gdouble
5299 edge_min_spacing(GList *list, toporouter_edge_t *e, toporouter_vertex_t *v, guint debug)
5301 toporouter_vertex_t *origin;
5302 GList *i = list;
5303 gdouble space = 0.;
5304 toporouter_vertex_t *nextv, *prevv;
5305 //toporouter_vertex_t *edgev;
5306 //gdouble constraint_spacing;
5308 if(!list) return INFINITY;
5310 // printf("\t CMS %f,%f - %f,%f\n", vx(tedge_v1(e)), vy(tedge_v1(e)), vx(tedge_v2(e)), vy(tedge_v2(e)));
5312 prevv = origin = TOPOROUTER_VERTEX(list->data);
5314 // print_edge(e);
5316 i = list;
5317 if(gts_point_distance2(GTS_POINT(origin), GTS_POINT(edge_v1(e))) < gts_point_distance2(GTS_POINT(v), GTS_POINT(edge_v1(e)))) {
5319 /* towards v2 */
5320 while(i) {
5321 nextv = edge_routing_next(e, i);
5322 if(nextv->route && vertices_connected(nextv, prevv)) { i = i->next; continue; }
5323 if(!(nextv->flags & VERTEX_FLAG_TEMP)) {
5324 gdouble ms = min_spacing(prevv, nextv);
5325 if(nextv == tedge_v2(e)) {
5326 gdouble cms = pathvertex_arcing_through_constraint(TOPOROUTER_VERTEX(i->data), tedge_v2(e));
5327 // printf("\t CMS to %f,%f = %f \t ms = %f\n", vx(tedge_v2(e)), vy(tedge_v2(e)), cms, ms);
5328 // if(vx(tedge_v2(e)) > -EPSILON && vx(tedge_v2(e)) < EPSILON) {
5329 // printf("\t\tPROB: ");
5330 // print_vertex(tedge_v2(e));
5331 // }
5332 if(cms > EPSILON) space += MIN(ms, cms / 2.);
5333 else space += ms;
5334 } else
5335 space += ms;
5337 prevv = nextv;
5339 // printf("%f ", space);
5340 i = i->next;
5342 }else{
5344 /* towards v1 */
5345 while(i) {
5346 nextv = edge_routing_prev(e, i);
5347 if(nextv->route && vertices_connected(nextv, prevv)) { i = i->prev; continue; }
5348 if(!(nextv->flags & VERTEX_FLAG_TEMP)) {
5349 gdouble ms = min_spacing(prevv, nextv);
5350 if(nextv == tedge_v1(e)) {
5351 gdouble cms = pathvertex_arcing_through_constraint(TOPOROUTER_VERTEX(i->data), tedge_v1(e));
5352 // printf("\t CMS to %f,%f = %f \t ms = %f\n", vx(tedge_v1(e)), vy(tedge_v1(e)), cms, ms);
5353 // if(vx(tedge_v1(e)) > -EPSILON && vx(tedge_v1(e)) < EPSILON) {
5354 // printf("\t\tPROB: ");
5355 // print_vertex(tedge_v1(e));
5356 // }
5357 if(cms > EPSILON) space += MIN(ms, cms / 2.);
5358 else space += ms;
5359 } else
5360 space += ms;
5362 prevv = nextv;
5364 // printf("%f ", space);
5365 i = i->prev;
5369 if(TOPOROUTER_IS_CONSTRAINT(e) && space > gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e))) / 2.)
5370 space = gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e))) / 2.;
5372 // if(debug) printf("\tedge_min_spacing: %f\n", space);
5373 return space;
5376 /* line segment is 1 & 2, point is 3
5377 returns 0 if v3 is outside seg
5379 guint
5380 vertex_line_normal_intersection(gdouble x1, gdouble y1, gdouble x2, gdouble y2, gdouble x3, gdouble y3, gdouble *x, gdouble *y)
5382 gdouble m1 = cartesian_gradient(x1,y1,x2,y2);
5383 gdouble m2 = perpendicular_gradient(m1);
5384 gdouble c2 = (isinf(m2)) ? x3 : y3 - (m2 * x3);
5385 gdouble c1 = (isinf(m1)) ? x1 : y1 - (m1 * x1);
5387 if(isinf(m2))
5388 *x = x3;
5389 else if(isinf(m1))
5390 *x = x1;
5391 else
5392 *x = (c2 - c1) / (m1 - m2);
5394 *y = (isinf(m2)) ? y1 : (m2 * (*x)) + c2;
5396 if(*x >= MIN(x1,x2) - EPSILON && *x <= MAX(x1,x2) + EPSILON && *y >= MIN(y1,y2) - EPSILON && *y <= MAX(y1,y2) + EPSILON)
5397 return 1;
5398 return 0;
5401 void
5402 print_toporouter_arc(toporouter_arc_t *arc)
5404 // GList *i = arc->vs;
5406 printf("ARC CENTRE: %f,%f ", vx(arc->centre), vy(arc->centre));// print_vertex(arc->centre);
5407 printf("RADIUS: %f", arc->r);
5409 if(arc->dir>0) printf(" COUNTERCLOCKWISE ");
5410 else if(arc->dir<0) printf(" CLOCKWISE ");
5411 else printf(" COLINEAR(ERROR) ");
5413 printf("\n\tVS: ");
5415 while(i) {
5416 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
5417 printf("%f,%f ", vx(v), vy(v));
5419 i = i->next;
5424 void
5425 toporouter_arc_remove(toporouter_oproute_t *oproute, toporouter_arc_t *arc)
5427 oproute->arcs = g_list_remove(oproute->arcs, arc);
5429 if(arc->v) arc->v->arc = NULL;
5432 toporouter_arc_t *
5433 toporouter_arc_new(toporouter_oproute_t *oproute, toporouter_vertex_t *v1, toporouter_vertex_t *v2, toporouter_vertex_t *centre, gdouble r, gint dir)
5435 toporouter_arc_t *arc = TOPOROUTER_ARC(gts_object_new(GTS_OBJECT_CLASS(toporouter_arc_class())));
5436 arc->centre = centre;
5437 arc->v = v1;
5438 arc->v1 = v1;
5439 arc->v2 = v2;
5440 arc->r = r;
5441 arc->dir = dir;
5443 if(v1) v1->arc = arc;
5444 arc->oproute = oproute;
5446 arc->clearance = NULL;
5448 return arc;
5451 void
5452 path_set_oproute(GList *path, toporouter_oproute_t *oproute)
5454 while(path) {
5455 toporouter_vertex_t *v = TOPOROUTER_VERTEX(path->data);
5457 if(v->flags & VERTEX_FLAG_ROUTE)
5458 v->oproute = oproute;
5460 path = path->next;
5464 void
5465 print_oproute(toporouter_oproute_t *oproute)
5467 GList *i = oproute->arcs;
5469 printf("Optimized Route:\n");
5470 printf("\tNetlist:\t\t%s\n\tStyle:\t\t%s\n", oproute->netlist, oproute->style);
5471 // printf("%s\n", oproute->netlist);
5473 i = oproute->term1->zlink;
5474 while(i) {
5475 toporouter_vertex_t *thisv = TOPOROUTER_VERTEX(i->data);
5476 printf("\tNetlist:\t\t%s\n\tStyle:\t\t%s\n", vertex_bbox(thisv)->netlist, vertex_bbox(thisv)->style);
5477 i = i->next;
5480 printf("\t"); print_vertex(oproute->term1); printf("\n");
5481 i = oproute->arcs;
5482 while(i) {
5483 toporouter_arc_t *arc = (toporouter_arc_t *)i->data;
5484 printf("\t"); print_toporouter_arc(arc); printf("\n");
5485 i = i->next;
5487 printf("\t"); print_vertex(oproute->term2); printf("\n");
5490 gdouble
5491 export_pcb_drawline(guint layer, guint x0, guint y0, guint x1, guint y1, guint thickness, guint keepaway)
5493 gdouble d = 0.;
5494 LineTypePtr line;
5495 line = CreateDrawnLineOnLayer( LAYER_PTR(layer), x0, y0, x1, y1,
5496 thickness, keepaway,
5497 MakeFlags (AUTOFLAG | (TEST_FLAG (CLEARNEWFLAG, PCB) ? CLEARLINEFLAG : 0)));
5499 if(line) {
5500 AddObjectToCreateUndoList (LINE_TYPE, LAYER_PTR(layer), line, line);
5501 d = coord_distance((double)x0, (double)y0, (double)x1, (double)y1) / 100.;
5503 return d;
5506 gdouble
5507 arc_angle(toporouter_arc_t *arc)
5509 gdouble x0, x1, y0, y1;
5511 x0 = arc->x0 - vx(arc->centre);
5512 x1 = arc->x1 - vx(arc->centre);
5513 y0 = arc->y0 - vy(arc->centre);
5514 y1 = arc->y1 - vy(arc->centre);
5516 return fabs(acos(((x0*x1)+(y0*y1))/(sqrt(pow(x0,2)+pow(y0,2))*sqrt(pow(x1,2)+pow(y1,2)))));
5519 gdouble
5520 export_pcb_drawarc(guint layer, toporouter_arc_t *a, guint thickness, guint keepaway)
5522 gdouble sa, da, theta;
5523 gdouble x0, y0, x1, y1, d=0.;
5524 ArcTypePtr arc;
5525 gint wind;
5527 wind = coord_wind(a->x0, a->y0, a->x1, a->y1, vx(a->centre), vy(a->centre));
5529 sa = coord_xangle(a->x0, a->y0, vx(a->centre), vy(a->centre)) * 180. / M_PI;
5531 x0 = a->x0 - vx(a->centre);
5532 x1 = a->x1 - vx(a->centre);
5533 y0 = a->y0 - vy(a->centre);
5534 y1 = a->y1 - vy(a->centre);
5536 theta = arc_angle(a);
5538 if(!a->dir || !wind) return 0.;
5540 if(a->dir != wind) theta = 2. * M_PI - theta;
5542 da = -a->dir * theta * 180. / M_PI;
5544 if(da < 1. && da > -1.) return 0.;
5545 if(da > 359. || da < -359.) return 0.;
5547 arc = CreateNewArcOnLayer(LAYER_PTR(layer), vx(a->centre), vy(a->centre), a->r, a->r,
5548 sa, da, thickness, keepaway,
5549 MakeFlags( AUTOFLAG | (TEST_FLAG (CLEARNEWFLAG, PCB) ? CLEARLINEFLAG : 0)));
5551 if(arc) {
5552 AddObjectToCreateUndoList( ARC_TYPE, LAYER_PTR(layer), arc, arc);
5553 d = a->r * theta / 100.;
5556 return d;
5559 void
5560 calculate_term_to_arc(toporouter_vertex_t *v, toporouter_arc_t *arc, guint dir)
5562 gdouble theta, a, b, bx, by, a0x, a0y, a1x, a1y;
5563 gint winddir;
5565 theta = acos(arc->r / gts_point_distance(GTS_POINT(v), GTS_POINT(arc->centre)));
5566 a = arc->r * sin(theta);
5567 b = arc->r * cos(theta);
5568 #ifdef DEBUG_EXPORT
5569 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));
5570 #endif
5571 point_from_point_to_point(arc->centre, v, b, &bx, &by);
5573 coords_on_line(bx, by, perpendicular_gradient(point_gradient(GTS_POINT(v), GTS_POINT(arc->centre))), a, &a0x, &a0y, &a1x, &a1y);
5575 winddir = coord_wind(vx(v), vy(v), a0x, a0y, vx(arc->centre), vy(arc->centre));
5577 if(!winddir) {
5578 printf("!winddir @ v %f,%f arc->centre %f,%f\n", vx(v), vy(v), vx(arc->centre), vy(arc->centre));
5579 //TODO: fix hack: this shouldn't happen
5580 arc->x0 = vx(v);
5581 arc->y0 = vy(v);
5582 arc->x1 = vx(v);
5583 arc->y1 = vy(v);
5584 return;
5587 g_assert(winddir);
5589 if(dir) winddir = -winddir;
5591 if(winddir == arc->dir) {
5592 if(!dir) { arc->x0 = a0x; arc->y0 = a0y; }
5593 else{ arc->x1 = a0x; arc->y1 = a0y; }
5594 }else{
5595 if(!dir) { arc->x0 = a1x; arc->y0 = a1y; }
5596 else{ arc->x1 = a1x; arc->y1 = a1y; }
5603 // b1 is the projection in the direction of narc, while b2 is the perpendicular projection
5604 void
5605 arc_ortho_projections(toporouter_arc_t *arc, toporouter_arc_t *narc, gdouble *b1, gdouble *b2)
5607 gdouble nax, nay, ax, ay, alen2, c;
5608 gdouble b1x, b1y, b2x, b2y;
5610 #ifdef DEBUG_EXPORT
5611 printf("arc c = %f,%f narc c = %f,%f arc->0 = %f,%f\n",
5612 vx(arc->centre), vy(arc->centre),
5613 vx(narc->centre), vy(narc->centre),
5614 arc->x0, arc->y0);
5615 #endif
5617 nax = vx(narc->centre) - vx(arc->centre);
5618 nay = vy(narc->centre) - vy(arc->centre);
5619 alen2 = pow(nax,2) + pow(nay,2);
5622 ax = arc->x0 - vx(arc->centre);
5623 ay = arc->y0 - vy(arc->centre);
5625 #ifdef DEBUG_EXPORT
5626 printf("norm narc = %f,%f - %f\tA=%f,%f\n", nax, nay, sqrt(alen2), ax, ay);
5627 #endif
5629 c = ((ax*nax)+(ay*nay)) / alen2;
5631 b1x = c * nax;
5632 b1y = c * nay;
5633 b2x = ax - b1x;
5634 b2y = ay - b1y;
5636 #ifdef DEBUG_EXPORT
5637 printf("proj = %f,%f perp proj = %f,%f\n", b1x, b1y, b2x, b2y);
5638 #endif
5640 *b1 = sqrt(pow(b1x,2) + pow(b1y,2));
5641 *b2 = sqrt(pow(b2x,2) + pow(b2y,2));
5645 guint
5646 calculate_arc_to_arc(toporouter_t *ar, toporouter_arc_t *parc, toporouter_arc_t *arc)
5648 gdouble theta, a, b, bx, by, a0x, a0y, a1x, a1y, m, preva, prevb;
5649 gint winddir;
5650 toporouter_arc_t *bigr, *smallr;
5652 if(parc->r > arc->r) {
5653 bigr = parc; smallr = arc;
5654 }else{
5655 bigr = arc; smallr = parc;
5657 #ifdef DEBUG_EXPORT
5658 printf("bigr centre = %f,%f smallr centre = %f,%f\n", vx(bigr->centre), vy(bigr->centre),
5659 vx(smallr->centre), vy(smallr->centre));
5660 #endif
5662 m = perpendicular_gradient(point_gradient(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)));
5664 if(bigr->centre == smallr->centre) {
5666 printf("bigr->centre == smallr->centre @ %f,%f\n", vx(smallr->centre), vy(smallr->centre));
5669 g_assert(bigr->centre != smallr->centre);
5671 if(parc->dir == arc->dir) {
5672 //export_arc_straight:
5674 theta = acos((bigr->r - smallr->r) / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)));
5675 a = bigr->r * sin(theta);
5676 b = bigr->r * cos(theta);
5678 point_from_point_to_point(bigr->centre, smallr->centre, b, &bx, &by);
5680 coords_on_line(bx, by, m, a, &a0x, &a0y, &a1x, &a1y);
5682 winddir = coord_wind(vx(smallr->centre), vy(smallr->centre), a0x, a0y, vx(bigr->centre), vy(bigr->centre));
5684 arc_ortho_projections(parc, arc, &prevb, &preva);
5685 //#ifdef DEBUG_EXPORT
5686 if(!winddir) {
5688 printf("STRAIGHT:\n");
5689 printf("bigr centre = %f,%f smallr centre = %f,%f\n", vx(bigr->centre), vy(bigr->centre),
5690 vx(smallr->centre), vy(smallr->centre));
5691 printf("theta = %f a = %f b = %f bigrr = %f d = %f po = %f\n", theta, a, b, bigr->r,
5692 gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)),
5693 bigr->r / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)));
5694 printf("bigr-r = %f smallr-r = %f ratio = %f\n",
5695 bigr->r, smallr->r, (bigr->r - smallr->r) / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)));
5696 printf("preva = %f prevb = %f\n\n", preva, prevb);
5699 //#endif
5700 g_assert(winddir);
5702 if(bigr==parc) winddir = -winddir;
5704 if(winddir == bigr->dir) {
5705 if(bigr==arc) {
5706 bigr->x0 = a0x;
5707 bigr->y0 = a0y;
5708 }else{
5709 bigr->x1 = a0x;
5710 bigr->y1 = a0y;
5712 }else{
5713 if(bigr==arc) {
5714 bigr->x0 = a1x;
5715 bigr->y0 = a1y;
5716 }else{
5717 bigr->x1 = a1x;
5718 bigr->y1 = a1y;
5722 a = smallr->r * sin(theta);
5723 b = smallr->r * cos(theta);
5725 #ifdef DEBUG_EXPORT
5726 printf("a = %f b = %f\n", a, b);
5727 #endif
5728 point_from_point_to_point(smallr->centre, bigr->centre, -b, &bx, &by);
5730 coords_on_line(bx, by, m, a, &a0x, &a0y, &a1x, &a1y);
5732 if(winddir == bigr->dir) {
5733 if(bigr==arc) {
5734 smallr->x1 = a0x;
5735 smallr->y1 = a0y;
5736 }else{
5737 smallr->x0 = a0x;
5738 smallr->y0 = a0y;
5740 }else{
5741 if(bigr==arc) {
5742 smallr->x1 = a1x;
5743 smallr->y1 = a1y;
5744 }else{
5745 smallr->x0 = a1x;
5746 smallr->y0 = a1y;
5750 }else{
5752 //export_arc_twist:
5754 theta = acos((bigr->r + smallr->r) / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)));
5755 a = bigr->r * sin(theta);
5756 b = bigr->r * cos(theta);
5758 point_from_point_to_point(bigr->centre, smallr->centre, b, &bx, &by);
5760 coords_on_line(bx, by, m, a, &a0x, &a0y, &a1x, &a1y);
5762 winddir = coord_wind(vx(smallr->centre), vy(smallr->centre), a0x, a0y, vx(bigr->centre), vy(bigr->centre));
5763 //#ifdef DEBUG_EXPORT
5764 if(!winddir) {
5765 printf("TWIST:\n");
5766 printf("theta = %f a = %f b = %f r = %f d = %f po = %f\n", theta, a, b, bigr->r + smallr->r,
5767 gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)),
5768 (bigr->r+smallr->r) / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)));
5770 printf("bigr centre = %f,%f smallr centre = %f,%f\n\n", vx(bigr->centre), vy(bigr->centre),
5771 vx(smallr->centre), vy(smallr->centre));
5773 printf("big wind = %d small wind = %d\n", bigr->dir, smallr->dir);
5774 return 1;
5776 //#endif
5777 /* if(!winddir) {
5778 smallr->centre->flags |= VERTEX_FLAG_RED;
5779 bigr->centre->flags |= VERTEX_FLAG_GREEN;
5780 //bigr->centre->flags |= VERTEX_FLAG_RED;
5782 int i;
5783 for(i=0;i<groupcount();i++) {
5784 char buffer[256];
5785 sprintf(buffer, "wind%d.png", i);
5786 toporouter_draw_surface(ar, ar->layers[i].surface, buffer, 2096, 2096, 2, NULL, i, NULL);
5789 return;
5792 g_assert(winddir);
5794 if(bigr==parc) winddir = -winddir;
5796 if(winddir == bigr->dir) {
5797 if(bigr==arc) {
5798 bigr->x0 = a0x;
5799 bigr->y0 = a0y;
5800 }else{
5801 bigr->x1 = a0x;
5802 bigr->y1 = a0y;
5804 }else{
5805 if(bigr==arc) {
5806 bigr->x0 = a1x;
5807 bigr->y0 = a1y;
5808 }else{
5809 bigr->x1 = a1x;
5810 bigr->y1 = a1y;
5814 a = smallr->r * sin(theta);
5815 b = smallr->r * cos(theta);
5817 point_from_point_to_point(smallr->centre, bigr->centre, b, &bx, &by);
5819 coords_on_line(bx, by, m, a, &a0x, &a0y, &a1x, &a1y);
5821 winddir = coord_wind(vx(smallr->centre), vy(smallr->centre), a0x, a0y, vx(bigr->centre), vy(bigr->centre));
5823 g_assert(winddir);
5825 if(bigr==parc) winddir = -winddir;
5827 if(winddir == smallr->dir) {
5828 if(bigr==arc) {
5829 smallr->x1 = a0x;
5830 smallr->y1 = a0y;
5831 }else{
5832 smallr->x0 = a0x;
5833 smallr->y0 = a0y;
5835 }else{
5836 if(bigr==arc) {
5837 smallr->x1 = a1x;
5838 smallr->y1 = a1y;
5839 }else{
5840 smallr->x0 = a1x;
5841 smallr->y0 = a1y;
5847 return 0;
5850 void
5851 export_oproutes(toporouter_t *ar, toporouter_oproute_t *oproute)
5853 guint layer = PCB->LayerGroups.Entries[oproute->layergroup][0];
5854 guint thickness = lookup_thickness(oproute->style);
5855 guint keepaway = lookup_keepaway(oproute->style);
5856 GList *arcs = oproute->arcs;
5857 toporouter_arc_t *arc, *parc = NULL;
5859 if(!arcs) {
5860 ar->wiring_score += export_pcb_drawline(layer, vx(oproute->term1), vy(oproute->term1), vx(oproute->term2), vy(oproute->term2), thickness, keepaway);
5861 return;
5865 // calculate_term_to_arc(oproute->term1, TOPOROUTER_ARC(arcs->data), 0, layer);
5867 while(arcs) {
5868 arc = TOPOROUTER_ARC(arcs->data);
5870 if(parc && arc) {
5871 ar->wiring_score += export_pcb_drawarc(layer, parc, thickness, keepaway);
5872 ar->wiring_score += export_pcb_drawline(layer, parc->x1, parc->y1, arc->x0, arc->y0, thickness, keepaway);
5873 }else if(!parc) {
5874 ar->wiring_score += export_pcb_drawline(layer, vx(oproute->term1), vy(oproute->term1), arc->x0, arc->y0, thickness, keepaway);
5877 parc = arc;
5878 arcs = arcs->next;
5880 ar->wiring_score += export_pcb_drawarc(layer, arc, thickness, keepaway);
5881 ar->wiring_score += export_pcb_drawline(layer, arc->x1, arc->y1, vx(oproute->term2), vy(oproute->term2), thickness, keepaway);
5887 void
5888 oproute_free(toporouter_oproute_t *oproute)
5890 GList *i = oproute->arcs;
5891 while(i) {
5892 toporouter_arc_t *arc = (toporouter_arc_t *) i->data;
5893 if(arc->centre->flags & VERTEX_FLAG_TEMP)
5894 gts_object_destroy(GTS_OBJECT(arc->centre));
5896 i = i->next;
5899 g_list_free(oproute->arcs);
5900 free(oproute);
5903 void
5904 oproute_calculate_tof(toporouter_oproute_t *oproute)
5906 GList *arcs = oproute->arcs;
5907 toporouter_arc_t *parc = NULL, *arc;
5909 oproute->tof = 0.;
5911 if(!arcs) {
5912 oproute->tof = gts_point_distance(GTS_POINT(oproute->term1), GTS_POINT(oproute->term2));
5913 return;
5916 while(arcs) {
5917 arc = TOPOROUTER_ARC(arcs->data);
5919 if(parc && arc) {
5920 oproute->tof += arc_angle(parc) * parc->r;
5921 oproute->tof += sqrt(pow(parc->x1-arc->x0,2)+pow(parc->y1-arc->y0,2));
5922 }else if(!parc) {
5923 oproute->tof += sqrt(pow(arc->x0-vx(oproute->term1),2)+pow(arc->y0-vy(oproute->term1),2));
5926 parc = arc;
5927 arcs = arcs->next;
5930 oproute->tof += arc_angle(parc) * parc->r;
5931 oproute->tof += sqrt(pow(arc->x1-vx(oproute->term2),2)+pow(arc->y1-vy(oproute->term2),2));
5935 gdouble
5936 line_line_distance_at_normal(
5937 gdouble line1_x1, gdouble line1_y1,
5938 gdouble line1_x2, gdouble line1_y2,
5939 gdouble line2_x1, gdouble line2_y1,
5940 gdouble line2_x2, gdouble line2_y2,
5941 gdouble x, gdouble y)
5943 gdouble m1 = perpendicular_gradient(cartesian_gradient(line1_x1, line1_y1, line1_x2, line1_y2));
5944 gdouble m2 = cartesian_gradient(line2_x1, line2_y1, line2_x2, line2_y2);
5945 gdouble c1 = (isinf(m1)) ? x : y - (m1 * x);
5946 gdouble c2 = (isinf(m2)) ? line2_x1 : line2_y1 - (m2 * line2_x1);
5948 gdouble intx, inty;
5950 if(isinf(m2)) intx = line2_x1;
5951 else if(isinf(m1)) intx = x;
5952 else intx = (c2 - c1) / (m1 - m2);
5954 inty = (isinf(m2)) ? (m1 * intx) + c1 : (m2 * intx) + c2;
5956 return sqrt(pow(x-intx,2)+pow(y-inty,2));
5959 void
5960 calculate_serpintine(gdouble delta, gdouble r, gdouble initiala, gdouble *a, guint *nhalfcycles)
5962 gdouble lhalfcycle = 2.*(initiala-r)+(M_PI*r);
5963 guint n;
5965 printf("lhalfcycle = %f r = %f\n", lhalfcycle, r);
5967 n = (delta - M_PI*r) / (lhalfcycle - 2.*r) + 1;
5968 *a = (delta + 4.*n*r - n*M_PI*r + 4.*r - M_PI*r)/(2.*n);
5969 *nhalfcycles = n;
5972 gdouble
5973 oproute_min_spacing(toporouter_oproute_t *a, toporouter_oproute_t *b)
5975 return lookup_thickness(a->style) / 2. + lookup_thickness(b->style) / 2. + MAX(lookup_keepaway(a->style), lookup_keepaway(b->style));
5978 gdouble
5979 vector_angle(gdouble ox, gdouble oy, gdouble ax, gdouble ay, gdouble bx, gdouble by)
5981 gdouble alen = sqrt(pow(ax-ox,2)+pow(ay-oy,2));
5982 gdouble blen = sqrt(pow(bx-ox,2)+pow(by-oy,2));
5983 return acos( ((ax-ox)*(bx-ox)+(ay-oy)*(by-oy)) / (alen * blen) );
5986 toporouter_serpintine_t *
5987 toporouter_serpintine_new(gdouble x, gdouble y, gdouble x0, gdouble y0, gdouble x1, gdouble y1, gpointer start, gdouble halfa, gdouble
5988 radius, guint nhalfcycles)
5990 toporouter_serpintine_t *serp = malloc(sizeof(toporouter_serpintine_t));
5991 serp->x = x;
5992 serp->y = y;
5993 serp->x0 = x0;
5994 serp->y0 = y0;
5995 serp->x1 = x1;
5996 serp->y1 = y1;
5997 serp->start = start;
5998 serp->halfa = halfa;
5999 serp->radius = radius;
6000 serp->nhalfcycles = nhalfcycles;
6001 serp->arcs = NULL;
6002 return serp;
6005 //#define DEBUG_RUBBERBAND 1
6007 gdouble
6008 check_non_intersect_vertex(gdouble x0, gdouble y0, gdouble x1, gdouble y1, toporouter_vertex_t *pathv, toporouter_vertex_t *arcv,
6009 toporouter_vertex_t *opv, gint wind, gint *arcwind, gdouble *arcr, guint debug)
6011 gdouble ms, line_int_x, line_int_y, x, y, d = 0., m;
6012 gdouble tx0, ty0, tx1, ty1;
6013 gint wind1, wind2;
6015 g_assert(pathv->routingedge);
6017 if(TOPOROUTER_IS_CONSTRAINT(pathv->routingedge)) {
6018 gdouble d = tvdistance(tedge_v1(pathv->routingedge), tedge_v2(pathv->routingedge)) / 2.;
6019 ms = min_spacing(pathv, arcv);
6020 if(ms > d) ms = d;
6021 }else{
6022 ms = edge_min_spacing(g_list_find(edge_routing(pathv->routingedge), pathv), pathv->routingedge, arcv, debug);
6026 if(!vertex_line_normal_intersection(x0, y0, x1, y1, vx(arcv), vy(arcv), &line_int_x, &line_int_y)) {
6028 if(coord_distance2(x0, y0, line_int_x, line_int_y) < coord_distance2(x1, y1, line_int_x, line_int_y))
6029 { line_int_x = x0; line_int_y = y0; }else{ line_int_x = x1; line_int_y = y1; }
6031 m = perpendicular_gradient(cartesian_gradient(vx(arcv), vy(arcv), line_int_x, line_int_y));
6032 }else{
6033 m = cartesian_gradient(x0, y0, x1, y1);
6036 coords_on_line(vx(arcv), vy(arcv), m, 100., &tx0, &ty0, &tx1, &ty1);
6038 wind1 = coord_wind(tx0, ty0, tx1, ty1, line_int_x, line_int_y);
6039 wind2 = coord_wind(tx0, ty0, tx1, ty1, vx(opv), vy(opv));
6041 if(!wind2 || wind1 == wind2) return -1.;
6043 if(!wind) {
6044 coords_on_line(line_int_x, line_int_y, perpendicular_gradient(m), ms, &tx0, &ty0, &tx1, &ty1);
6045 if(coord_distance2(tx0, ty0, vx(opv), vy(opv)) < coord_distance2(tx1, ty1, vx(opv), vy(opv)))
6046 { x = tx0; y = ty0; }else{ x = tx1; y = ty1; }
6047 }else{
6048 toporouter_vertex_t *parent = pathv->parent, *child = pathv->child;
6049 guint windtests = 0;
6051 d = coord_distance(vx(arcv), vy(arcv), line_int_x, line_int_y);
6052 coord_move_towards_coord_values(line_int_x, line_int_y, vx(arcv), vy(arcv), ms + d, &x, &y);
6053 rewind_test:
6054 wind1 = coord_wind(line_int_x, line_int_y, x, y, vx(parent), vy(parent));
6055 wind2 = coord_wind(line_int_x, line_int_y, x, y, vx(child), vy(child));
6056 if(wind1 && wind2 && wind1 == wind2) {
6057 // return -1.;
6058 if(windtests++ == 2) return -1.;
6060 if(parent->flags & VERTEX_FLAG_ROUTE) parent = parent->parent;
6061 if(child->flags & VERTEX_FLAG_ROUTE) child = child->child;
6062 goto rewind_test;
6067 *arcr = ms;
6068 *arcwind = tvertex_wind(pathv->parent, pathv, arcv);
6070 #ifdef DEBUG_RUBBERBAND
6071 //if(debug)
6072 // printf("non-int check %f,%f ms %f d %f arcv %f,%f opv %f,%f\n", vx(arcv), vy(arcv), ms, d + ms,
6073 // vx(arcv), vy(arcv), vx(opv), vy(opv));
6074 #endif
6076 return d + ms;
6079 gdouble
6080 check_intersect_vertex(gdouble x0, gdouble y0, gdouble x1, gdouble y1, toporouter_vertex_t *pathv, toporouter_vertex_t *arcv,
6081 toporouter_vertex_t *opv, gint wind, gint *arcwind, gdouble *arcr, guint debug)
6083 gdouble ms, line_int_x, line_int_y, x, y, d = 0.;
6085 if(TOPOROUTER_IS_CONSTRAINT(pathv->routingedge)) {
6086 gdouble d = tvdistance(tedge_v1(pathv->routingedge), tedge_v2(pathv->routingedge)) / 2.;
6087 ms = min_spacing(pathv, arcv);
6088 if(ms > d) ms = d;
6089 }else {
6090 ms = edge_min_spacing(g_list_find(edge_routing(pathv->routingedge), pathv), pathv->routingedge, arcv, debug);
6093 if(!vertex_line_normal_intersection(x0, y0, x1, y1, vx(arcv), vy(arcv), &line_int_x, &line_int_y))
6094 return -1.;
6096 d = coord_distance(line_int_x, line_int_y, vx(arcv), vy(arcv));
6099 if(d > ms - EPSILON)
6100 return -1.;
6102 coord_move_towards_coord_values(vx(arcv), vy(arcv), line_int_x, line_int_y, ms, &x, &y);
6104 *arcr = ms;
6105 *arcwind = tvertex_wind(pathv->parent, pathv, arcv);
6106 // *arcwind = coord_wind(x0, y0, x, y, x1, y1);
6107 #ifdef DEBUG_RUBBERBAND
6108 //if(debug)
6109 // printf("int check %f,%f ms %f d %f arcv %f,%f opv %f,%f\n", vx(arcv), vy(arcv), ms, ms - d,
6110 // vx(arcv), vy(arcv), vx(opv), vy(opv));
6111 #endif
6113 return ms - d;
6116 /* returns non-zero if arc has loops */
6117 guint
6118 check_arc_for_loops(gpointer t1, toporouter_arc_t *arc, gpointer t2)
6120 gdouble x0, y0, x1, y1;
6122 if(TOPOROUTER_IS_VERTEX(t1)) { x0 = vx(TOPOROUTER_VERTEX(t1)); y0 = vy(TOPOROUTER_VERTEX(t1)); }
6123 else { x0 = TOPOROUTER_ARC(t1)->x1; y0 = TOPOROUTER_ARC(t1)->y1; }
6125 if(TOPOROUTER_IS_VERTEX(t2)) { x1 = vx(TOPOROUTER_VERTEX(t2)); y1 = vy(TOPOROUTER_VERTEX(t2)); }
6126 else { x1 = TOPOROUTER_ARC(t2)->x0; y1 = TOPOROUTER_ARC(t2)->y0; }
6128 if(coord_intersect_prop(x0, y0, arc->x0, arc->y0, arc->x1, arc->y1, x1, y1) ) {
6129 // ||
6130 // (arc->x0 > arc->x1 - EPSILON && arc->x0 < arc->x1 + EPSILON &&
6131 // arc->y0 > arc->y1 - EPSILON && arc->y0 < arc->y1 + EPSILON)
6132 // ) {
6133 #ifdef DEBUG_RUBBERBAND
6134 printf("LOOPS %f %f -> %f %f & %f %f -> %f %f\n", x0, y0, arc->x0, arc->y0, arc->x1, arc->y1, x1, y1);
6135 #endif
6136 return 1;
6138 return 0;
6141 toporouter_rubberband_arc_t *
6142 new_rubberband_arc(toporouter_vertex_t *pathv, toporouter_vertex_t *arcv, gdouble r, gdouble d, gint wind, GList *list)
6144 toporouter_rubberband_arc_t *rba = malloc(sizeof(toporouter_rubberband_arc_t));
6145 rba->pathv = pathv;
6146 rba->arcv = arcv;
6147 rba->r = r;
6148 rba->d = d;
6149 rba->wind = wind;
6150 rba->list = list;
6151 return rba;
6154 gint
6155 compare_rubberband_arcs(toporouter_rubberband_arc_t *a, toporouter_rubberband_arc_t *b)
6156 { return b->d - a->d; }
6158 void
6159 free_list_elements(gpointer data, gpointer user_data)
6160 { free(data); }
6163 /* 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 */
6165 GtsEdge *
6166 vertex_edge_facing_vertex(GtsVertex *v, gdouble x, gdouble y)
6168 GSList *ts = gts_vertex_triangles(GTS_VERTEX(n), NULL);
6169 GSList *i = ts;
6171 while(i) {
6172 GtsTriangle *t = GTS_TRIANGLE(i->data);
6173 GtsEdge *e = gts_triangle_edge_opposite(t, v);
6175 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)) &&
6176 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))
6178 g_slist_free(ts);
6179 return e;
6182 i = i->next;
6185 g_slist_free(ts);
6186 return NULL;
6190 gdouble
6191 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)
6193 GSList *ns = gts_vertex_neighbors(GTS_VERTEX(v), NULL, NULL);
6194 GSList *i = ns;
6195 gdouble maxd = 0.;
6197 while(i) {
6198 toporouter_vertex_t *n = TOPOROUTER_VERTEX(i->data);
6199 gdouble segintx, seginty;
6200 if(vertex_line_normal_intersection(x0, y0, x1, y1, vx(n), vy(n), &segintx, &seginty)) {
6201 toporouter_edge_t *e = tedge(n, v);
6202 gdouble ms = 0., d = coord_distance(segintx, seginty, vx(n), vy(n));
6203 toporouter_vertex_t *a, *b;
6204 GList *closestnet = NULL;
6206 g_assert(e);
6208 if(v == tedge_v1(e)) {
6209 a = tedge_v1(e);
6210 b = tedge_v2(e);
6211 closestnet = edge_routing(e);
6212 }else{
6213 a = tedge_v2(e);
6214 b = tedge_v1(e);
6215 closestnet = g_list_last(edge_routing(e));
6218 if(closestnet) {
6219 ms = edge_min_spacing(closestnet, e, b, 0);
6220 ms += min_oproute_net_spacing(oproute, TOPOROUTER_VERTEX(closestnet->data));
6221 }else{
6222 ms = min_oproute_vertex_spacing(oproute, b);
6225 if(ms - d > maxd) {
6226 *arcr = ms;
6227 *arc = n;
6228 maxd = ms - d;
6229 if(vx(v) == x0 && vy(v) == y0) {
6230 *arcwind = coord_wind(x0, y0, vx(n), vy(n), x1, y1);
6231 }else if(vx(v) == x1 && vy(v) == y1) {
6232 *arcwind = coord_wind(x1, y1, vx(n), vy(n), x0, y0);
6233 }else{
6234 fprintf(stderr, "ERROR: check_adj_pushing_vertex encountered bad vertex v (coordinates don't match)\n");
6239 i = i->next;
6242 g_slist_free(ns);
6243 return maxd;
6247 // path is t1 path
6248 GList *
6249 oproute_rubberband_segment(toporouter_t *r, toporouter_oproute_t *oproute, GList *path, gpointer t1, gpointer t2, guint debug)
6251 gdouble x0, y0, x1, y1;
6252 toporouter_vertex_t *v1, *v2, *av1, *av2; /* v{1,2} are the vertex terminals of the segment, or arc terminal centres */
6253 toporouter_arc_t *arc1 = NULL, *arc2 = NULL, *newarc = NULL; /* arc{1,2} are the arc terminals of the segment, if they exist */
6254 GList *i = path;
6255 GList *list1, *list2;
6257 GList *arcs = NULL;
6258 toporouter_rubberband_arc_t *max = NULL;
6260 gdouble d, arcr;
6261 gint v1wind, v2wind, arcwind;
6263 if(TOPOROUTER_IS_VERTEX(t1)) {
6264 v1 = TOPOROUTER_VERTEX(t1);
6265 x0 = vx(v1); y0 = vy(v1);
6266 }else{
6267 g_assert(TOPOROUTER_IS_ARC(t1));
6268 arc1 = TOPOROUTER_ARC(t1);
6269 v1 = TOPOROUTER_VERTEX(arc1->v1);
6270 x0 = arc1->x1;
6271 y0 = arc1->y1;
6274 if(TOPOROUTER_IS_VERTEX(t2)) {
6275 v2 = TOPOROUTER_VERTEX(t2);
6276 x1 = vx(v2); y1 = vy(v2);
6277 }else{
6278 g_assert(TOPOROUTER_IS_ARC(t2));
6279 arc2 = TOPOROUTER_ARC(t2);
6280 v2 = TOPOROUTER_VERTEX(arc2->v2);
6281 x1 = arc2->x0;
6282 y1 = arc2->y0;
6285 #define TEST_AND_INSERT(z) if(d > EPSILON) arcs = g_list_prepend(arcs, new_rubberband_arc(v, z, arcr, d, arcwind, i));
6286 #define ARC_CHECKS(z) (!(arc1 && arc1->centre == z) && !(arc2 && arc2->centre == z) && \
6287 !(TOPOROUTER_IS_VERTEX(t1) && z == v1) && !(TOPOROUTER_IS_VERTEX(t2) && z == v2))
6289 if(v1 == v2 || !i->next || TOPOROUTER_VERTEX(i->data) == v2) return NULL;
6291 //#ifdef DEBUG_RUBBERBAND
6292 if(debug) {
6293 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));
6294 // if(v1->routingedge) print_edge(v1->routingedge);
6295 // if(v2->routingedge) print_edge(v2->routingedge);
6298 //#endif
6300 /* check the vectices adjacent to the terminal vectices for push against the segment */
6301 //if(TOPOROUTER_IS_VERTEX(t1)) {
6302 // toporouter_vertex_t *arcc = NULL;
6303 // d = check_adj_pushing_vertex(oproute, x0, y0, x1, y1, v1, &arcr, &arcwind, &arcc);
6304 // g_assert(arcc != v1);
6305 // if(ARC_CHECKS(arcc) && d > EPSILON) arcs = g_list_prepend(arcs, new_rubberband_arc(v1, arcc, arcr, d, arcwind, path->next));
6308 //if(TOPOROUTER_IS_VERTEX(t2)) {
6309 // toporouter_vertex_t *arcc = NULL;
6310 // d = check_adj_pushing_vertex(oproute, x0, y0, x1, y1, v2, &arcr, &arcwind, &arcc);
6311 // g_assert(arcc != v2);
6312 // if(ARC_CHECKS(arcc) && d > EPSILON) arcs = g_list_prepend(arcs, new_rubberband_arc(v2, arcc, arcr, d, arcwind, g_list_last(path)->prev));
6315 i = i->next;
6316 while(i) {
6317 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
6319 if(v == v2 || v == v1 || !v->routingedge) break;
6321 #ifdef DEBUG_RUBBERBAND
6322 // if(debug)
6323 // printf("current v %f,%f - edge %f,%f %f,%f\n", vx(v), vy(v),
6324 // vx(tedge_v1(v->routingedge)), vy(tedge_v1(v->routingedge)),
6325 // vx(tedge_v2(v->routingedge)), vy(tedge_v2(v->routingedge))
6326 // );
6327 #endif
6328 g_assert(v->routingedge);
6330 v1wind = coord_wind(x0, y0, x1, y1, vx(tedge_v1(v->routingedge)), vy(tedge_v1(v->routingedge)));
6331 v2wind = coord_wind(x0, y0, x1, y1, vx(tedge_v2(v->routingedge)), vy(tedge_v2(v->routingedge)));
6332 // if(debug) printf("\twinds: %d %d\n", v1wind, v2wind);
6333 if(!v1wind && !v2wind) { i = i->next; continue; }
6336 if(v1wind && v2wind && v1wind != v2wind) { /* edge is cutting through the current segment */
6338 if(ARC_CHECKS(tedge_v1(v->routingedge)) ){ /* edge v1 is not the centre of an arc terminal */
6339 d = check_intersect_vertex(x0, y0, x1, y1, v, tedge_v1(v->routingedge), tedge_v2(v->routingedge), v1wind, &arcwind, &arcr, debug);
6340 TEST_AND_INSERT(tedge_v1(v->routingedge));
6343 if(ARC_CHECKS(tedge_v2(v->routingedge)) ){ /* edge v2 is not the centre of an arc terminal */
6344 d = check_intersect_vertex(x0, y0, x1, y1, v, tedge_v2(v->routingedge), tedge_v1(v->routingedge), v2wind, &arcwind, &arcr, debug);
6345 TEST_AND_INSERT(tedge_v2(v->routingedge));
6347 }else{ /* edge is on one side of the segment */
6349 if(ARC_CHECKS(tedge_v1(v->routingedge)) ){ /* edge v1 is not the centre of an arc terminal */
6350 d = check_non_intersect_vertex(x0, y0, x1, y1, v, tedge_v1(v->routingedge), tedge_v2(v->routingedge), v1wind, &arcwind, &arcr, debug);
6351 TEST_AND_INSERT(tedge_v1(v->routingedge));
6354 if(ARC_CHECKS(tedge_v2(v->routingedge)) ){ /* edge v2 is not the centre of an arc terminal */
6355 d = check_non_intersect_vertex(x0, y0, x1, y1, v, tedge_v2(v->routingedge), tedge_v1(v->routingedge), v2wind, &arcwind, &arcr, debug);
6356 TEST_AND_INSERT(tedge_v2(v->routingedge));
6360 i = i->next;
6363 arcs = g_list_sort(arcs, (GCompareFunc) compare_rubberband_arcs);
6364 //rubberband_insert_maxarc:
6365 if(!arcs) return NULL;
6366 max = TOPOROUTER_RUBBERBAND_ARC(arcs->data);
6368 av2 = max->pathv; i = max->list->next;
6369 while(i) {
6370 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
6371 if(v->routingedge && (tedge_v1(v->routingedge) == max->arcv || tedge_v2(v->routingedge) == max->arcv)) {
6372 av2 = v; i = i->next; continue;
6374 break;
6377 av1 = max->pathv; i = max->list->prev;
6378 while(i) {
6379 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
6380 if(v->routingedge && (tedge_v1(v->routingedge) == max->arcv || tedge_v2(v->routingedge) == max->arcv)) {
6381 av1 = v; i = i->prev; continue;
6383 break;
6385 //#ifdef DEBUG_RUBBERBAND
6386 if(debug)
6387 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);
6388 //#endif
6389 newarc = toporouter_arc_new(oproute, av1, av2, max->arcv, max->r, max->wind);
6391 if(TOPOROUTER_IS_VERTEX(t1))
6392 calculate_term_to_arc(TOPOROUTER_VERTEX(t1), newarc, 0);
6393 else if(calculate_arc_to_arc(r, TOPOROUTER_ARC(t1), newarc)) {
6394 printf("\tERROR: best: r = %f d = %f\n", max->r, max->d);
6395 printf("\tOPROUTE: %s\n", oproute->netlist);
6396 print_vertex(oproute->term1);
6397 print_vertex(oproute->term2);
6398 return NULL;
6401 if(TOPOROUTER_IS_VERTEX(t2))
6402 calculate_term_to_arc(TOPOROUTER_VERTEX(t2), newarc, 1);
6403 else if(calculate_arc_to_arc(r, newarc, TOPOROUTER_ARC(t2))) {
6404 printf("\tERROR: best: r = %f d = %f\n", max->r, max->d);
6405 printf("\tOPROUTE: %s\n", oproute->netlist);
6406 print_vertex(oproute->term1);
6407 print_vertex(oproute->term2);
6408 return NULL;
6411 //if(check_arc_for_loops(t1, newarc, t2)) {
6412 // if(arc1 && arc2) calculate_arc_to_arc(r, arc1, arc2);
6413 // else if(arc1) calculate_term_to_arc(TOPOROUTER_VERTEX(t2), arc1, 1);
6414 // else if(arc2) calculate_term_to_arc(TOPOROUTER_VERTEX(t1), arc2, 0);
6416 //#ifdef DEBUG_RUBBERBAND
6417 // printf("REMOVING NEW ARC @ %f,%f\n", vx(newarc->centre), vy(newarc->centre));
6418 // //TODO: properly remove newarc
6419 //#endif
6421 // arcs = g_list_remove(arcs, max);
6422 // free(max);
6423 // goto rubberband_insert_maxarc;
6427 list1 = oproute_rubberband_segment(r, oproute, path, t1, newarc, debug);
6428 list2 = oproute_rubberband_segment(r, oproute, i->next, newarc, t2, debug);
6430 if(list1) {
6431 GList *list = g_list_last(list1);
6432 toporouter_arc_t *testarc = TOPOROUTER_ARC(list->data);
6433 toporouter_arc_t *parc = list->prev ? TOPOROUTER_ARC(list->prev->data) : arc1;
6434 gdouble px = parc ? parc->x1 : vx(TOPOROUTER_VERTEX(t1)), py = parc ? parc->y1 : vy(TOPOROUTER_VERTEX(t1));
6436 if(coord_intersect_prop(px, py, testarc->x0, testarc->y0, testarc->x1, testarc->y1, newarc->x0, newarc->y0)) {
6437 list1 = g_list_remove(list1, testarc);
6438 if(parc) calculate_arc_to_arc(r, parc, newarc);
6439 else calculate_term_to_arc(TOPOROUTER_VERTEX(t1), newarc, 0);
6440 //#ifdef DEBUG_RUBBERBAND
6441 if(debug)
6442 printf("REMOVING ARC @ %f,%f\n", vx(testarc->centre), vy(testarc->centre));
6443 //#endif
6446 if(list2) {
6447 toporouter_arc_t *testarc = TOPOROUTER_ARC(list2->data);
6448 toporouter_arc_t *narc = list2->next ? TOPOROUTER_ARC(list2->next->data) : arc2;
6449 gdouble nx = narc ? narc->x0 : vx(TOPOROUTER_VERTEX(t2)), ny = narc ? narc->y0 : vy(TOPOROUTER_VERTEX(t2));
6451 if(coord_intersect_prop(newarc->x1, newarc->y1, testarc->x0, testarc->y0, testarc->x1, testarc->y1, nx, ny)) {
6452 list2 = g_list_remove(list2, testarc);
6453 if(narc) calculate_arc_to_arc(r, newarc, narc);
6454 else calculate_term_to_arc(TOPOROUTER_VERTEX(t2), newarc, 1);
6456 //#ifdef DEBUG_RUBBERBAND
6457 if(debug)
6458 printf("REMOVING ARC @ %f,%f\n", vx(testarc->centre), vy(testarc->centre));
6459 //#endif
6463 g_list_foreach(arcs, free_list_elements, NULL);
6464 g_list_free(arcs);
6466 return g_list_concat(list1, g_list_prepend(list2, newarc));
6469 void
6470 oproute_check_all_loops(toporouter_t *r, toporouter_oproute_t *oproute)
6472 GList *i;
6473 gpointer t1;
6475 loopcheck_restart:
6476 t1 = oproute->term1;
6477 i = oproute->arcs;
6478 while(i) {
6479 toporouter_arc_t *arc = TOPOROUTER_ARC(i->data);
6480 gpointer t2 = i->next ? i->next->data : oproute->term2;
6482 if(check_arc_for_loops(t1, arc, t2)) {
6484 if(TOPOROUTER_IS_ARC(t1) && TOPOROUTER_IS_ARC(t2))
6485 calculate_arc_to_arc(r, TOPOROUTER_ARC(t1), TOPOROUTER_ARC(t2));
6486 else if(TOPOROUTER_IS_ARC(t1))
6487 calculate_term_to_arc(TOPOROUTER_VERTEX(t2), TOPOROUTER_ARC(t1), 1);
6488 else if(TOPOROUTER_IS_ARC(t2))
6489 calculate_term_to_arc(TOPOROUTER_VERTEX(t1), TOPOROUTER_ARC(t2), 0);
6491 oproute->arcs = g_list_remove(oproute->arcs, arc);
6492 goto loopcheck_restart;
6495 t1 = arc;
6497 i = i->next;
6502 GtsTriangle *
6503 opposite_triangle(GtsTriangle *t, toporouter_edge_t *e)
6505 GSList *i = GTS_EDGE(e)->triangles;
6507 g_assert(e && t);
6509 while(i) {
6510 if(GTS_TRIANGLE(i->data) != t) return GTS_TRIANGLE(i->data);
6511 i = i->next;
6514 return NULL;
6518 void
6519 speccut_edge_routing_from_edge(GList *i, toporouter_edge_t *e)
6521 g_assert(TOPOROUTER_IS_EDGE(e));
6522 while(i) {
6523 toporouter_vertex_t *curv = TOPOROUTER_VERTEX(i->data);
6525 if(!(curv->flags & VERTEX_FLAG_TEMP)) {
6526 toporouter_vertex_t *newv = tvertex_intersect(curv, curv->parent, tedge_v1(e), tedge_v2(e));
6528 // printf("\nCURV:\n");
6529 // print_vertex(curv);
6531 // printf("CURV child:\n");
6532 // if(curv->child)
6533 // print_vertex(curv->child);
6534 // else
6535 // printf("NULL\n");
6537 // printf("CURV parent:\n");
6538 // if(curv->parent)
6539 // print_vertex(curv->parent);
6540 // else
6541 // printf("NULL\n");
6543 if(newv) {
6544 gint index;
6545 newv->flags |= VERTEX_FLAG_ROUTE;
6546 newv->flags |= VERTEX_FLAG_SPECCUT;
6547 e->routing = g_list_insert_sorted_with_data(e->routing, newv, routing_edge_insert, e);
6548 newv->route = curv->route;
6549 newv->oproute = curv->oproute;
6550 newv->routingedge = e;
6551 GTS_POINT(newv)->z = vz(curv);
6553 newv->parent = curv->parent;
6554 newv->child = curv;
6556 // curv->parent = newv;
6558 index = g_list_index(newv->route->path, curv);
6560 newv->route->path = g_list_insert(newv->route->path, newv, index);
6563 if(newv->oproute) newv->oproute->path = newv->route->path;
6566 if(!(curv->child->routingedge)) {
6567 newv = tvertex_intersect(curv, curv->child, tedge_v1(e), tedge_v2(e));
6569 if(newv) {
6570 gint index;
6571 newv->flags |= VERTEX_FLAG_ROUTE;
6572 newv->flags |= VERTEX_FLAG_SPECCUT;
6573 e->routing = g_list_insert_sorted_with_data(e->routing, newv, routing_edge_insert, e);
6574 newv->route = curv->route;
6575 newv->oproute = curv->oproute;
6576 newv->routingedge = e;
6577 GTS_POINT(newv)->z = vz(curv);
6579 newv->parent = curv;
6580 newv->child = curv->child;
6582 // curv->child = newv;
6584 index = g_list_index(newv->route->path, curv);
6586 newv->route->path = g_list_insert(newv->route->path, newv, index+1);
6589 if(newv->oproute) newv->oproute->path = newv->route->path;
6595 i = i->next;
6600 void
6601 speccut_edge_patch_links(toporouter_edge_t *e)
6603 GList *i = e->routing;
6604 g_assert(TOPOROUTER_IS_EDGE(e));
6605 while(i) {
6606 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
6607 v->parent->child = v;
6608 v->child->parent = v;
6609 i = i->next;
6613 gint
6614 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)
6616 GtsTriangle *t, *opt;
6617 toporouter_vertex_t *opv, *opv2;
6618 toporouter_edge_t *ope1, *ope2;
6619 gdouble cap, flow, line_int_x, line_int_y;
6621 if(TOPOROUTER_IS_CONSTRAINT(e)) return 0;
6623 if(!(t = gts_triangle_use_edges(GTS_EDGE(e), GTS_EDGE(e1), GTS_EDGE(e2)))) {
6624 printf("check_speccut: NULL t\n");
6625 return 0;
6628 if(!(opt = opposite_triangle(t, e))) {
6629 // printf("check_speccut: NULL opt\n");
6630 return 0;
6633 if(!(opv = segment_common_vertex(GTS_SEGMENT(e1), GTS_SEGMENT(e2)))) {
6634 printf("check_speccut: NULL opv\n");
6635 return 0;
6638 if(!(opv2 = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(opt, GTS_EDGE(e))))) {
6639 printf("check_speccut: NULL opv2\n");
6640 return 0;
6643 //TODO: shifting it out of the way would be better
6644 if(e->routing) {
6645 GList *i = e->routing;
6646 while(i) {
6647 toporouter_vertex_t *ev = TOPOROUTER_VERTEX(i->data);
6648 if(!tvertex_wind(opv, ev, opv2)) return 0;
6649 i = i->next;
6654 ope1 = tedge(opv2, tedge_v1(e));
6655 ope2 = tedge(opv2, tedge_v2(e));
6657 //this fixes the weird pad exits in r8c board
6658 // if(TOPOROUTER_IS_CONSTRAINT(ope1)) return 0;
6659 if(TOPOROUTER_IS_CONSTRAINT(ope2)) return 0;
6661 if(!tvertex_wind(opv2, tedge_v1(e), opv)) return 0;
6662 if(!tvertex_wind(opv2, tedge_v2(e), opv)) return 0;
6664 if(!vertex_line_normal_intersection(
6665 vx(tedge_v1(e)), vy(tedge_v1(e)),
6666 vx(tedge_v2(e)), vy(tedge_v2(e)),
6667 vx(opv2), vy(opv2),
6668 &line_int_x, &line_int_y)) return 0;
6671 // return 0;
6672 //if(vertex_line_normal_intersection(tev1x(e), tev1y(e), tev2x(e), tev2y(e), vx(opv), vy(opv), &line_int_x, &line_int_y))
6673 // return 0;
6675 g_assert(opt && opv2);
6677 /* this is just temp, for the purposes of determining flow */
6678 if(tedge_v1(ope1) == opv2) {
6679 if(TOPOROUTER_IS_CONSTRAINT(ope1))
6680 TOPOROUTER_CONSTRAINT(ope1)->routing = g_list_append(TOPOROUTER_CONSTRAINT(ope1)->routing, v1);
6681 else
6682 ope1->routing = g_list_append(ope1->routing, v1);
6683 }else{
6684 if(TOPOROUTER_IS_CONSTRAINT(ope1))
6685 TOPOROUTER_CONSTRAINT(ope1)->routing = g_list_prepend(TOPOROUTER_CONSTRAINT(ope1)->routing, v1);
6686 else
6687 ope1->routing = g_list_prepend(ope1->routing, v1);
6690 cap = triangle_interior_capacity(opt, opv2);
6691 flow = flow_from_edge_to_edge(opt, tedge(opv2, tedge_v1(e)), tedge(opv2, tedge_v2(e)), opv2, v1);
6693 /* temp v1 removed */
6694 if(TOPOROUTER_IS_CONSTRAINT(ope1))
6695 TOPOROUTER_CONSTRAINT(ope1)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(ope1)->routing, v1);
6696 else
6697 ope1->routing = g_list_remove(ope1->routing, v1);
6699 if(flow >= cap) {
6700 toporouter_edge_t *newe = TOPOROUTER_EDGE(gts_edge_new(GTS_EDGE_CLASS(toporouter_edge_class()), GTS_VERTEX(opv), GTS_VERTEX(opv2)));
6702 speccut_edge_routing_from_edge(edge_routing(e1), newe);
6703 speccut_edge_routing_from_edge(edge_routing(e2), newe);
6704 speccut_edge_routing_from_edge(edge_routing(ope1), newe);
6705 speccut_edge_routing_from_edge(edge_routing(ope2), newe);
6707 speccut_edge_patch_links(newe);
6709 printf("SPECCUT WITH v %f,%f for seg %f,%f %f,%f detected\n", vx(opv2), vy(opv2),
6710 vx(v1), vy(v1),
6711 vx(v2), vy(v2));
6712 printf("\tflow %f cap %f\n", flow, cap);
6713 print_edge(newe);
6715 if(newe->routing) return 1;
6719 return 0;
6723 gint
6724 oproute_path_speccut(toporouter_oproute_t *oproute)
6726 GList *i;
6727 toporouter_vertex_t *pv;
6728 path_speccut_restart:
6729 i = oproute->path;
6730 pv = NULL;
6731 while(i) {
6732 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
6735 if(pv && (v->routingedge || pv->routingedge) && !(pv->flags & VERTEX_FLAG_SPECCUT) && !(v->flags & VERTEX_FLAG_SPECCUT)) {
6737 if(!v->routingedge) {
6738 if(check_speccut(oproute, pv, v, tedge(tedge_v1(pv->routingedge), v), pv->routingedge, tedge(tedge_v2(pv->routingedge), v)))
6739 goto path_speccut_restart;
6740 if(check_speccut(oproute, pv, v, tedge(tedge_v2(pv->routingedge), v), pv->routingedge, tedge(tedge_v1(pv->routingedge), v)))
6741 goto path_speccut_restart;
6742 }else if(!pv->routingedge) {
6743 if(check_speccut(oproute, v, pv, tedge(tedge_v1(v->routingedge), pv), v->routingedge, tedge(tedge_v2(v->routingedge), pv)))
6744 goto path_speccut_restart;
6745 if(check_speccut(oproute, v, pv, tedge(tedge_v2(v->routingedge), pv), v->routingedge, tedge(tedge_v1(v->routingedge), pv)))
6746 goto path_speccut_restart;
6747 }else{
6748 toporouter_vertex_t *v1 = NULL, *v2 = NULL;
6749 edges_third_edge(GTS_SEGMENT(v->routingedge), GTS_SEGMENT(pv->routingedge), &v1, &v2);
6750 if(check_speccut(oproute, v, pv, tedge(v1, v2), v->routingedge, pv->routingedge))
6751 goto path_speccut_restart;
6756 pv = v;
6757 i = i->next;
6760 return 0;
6763 toporouter_oproute_t *
6764 oproute_rubberband(toporouter_t *r, GList *path)
6766 toporouter_oproute_t *oproute = malloc(sizeof(toporouter_oproute_t));
6768 g_assert(path);
6770 oproute->term1 = TOPOROUTER_VERTEX(path->data);
6771 oproute->term2 = TOPOROUTER_VERTEX(g_list_last(path)->data);
6772 oproute->arcs = NULL;
6773 oproute->style = vertex_bbox(oproute->term1)->cluster->netlist->style;
6774 oproute->netlist = vertex_bbox(oproute->term1)->cluster->netlist->netlist;
6775 oproute->layergroup = vz(oproute->term1);
6776 oproute->path = path;
6777 oproute->serp = NULL;
6779 oproute->term1->parent = NULL;
6780 oproute->term2->child = NULL;
6782 path_set_oproute(path, oproute);
6784 // if(!strcmp(oproute->netlist, " unnamed_net1"))
6785 oproute_path_speccut(oproute);
6787 #ifdef DEBUG_RUBBERBAND
6788 if(!strcmp(oproute->netlist, " VCC3V3") && vx(oproute->term1) == 95700. && vy(oproute->term1) == 70800. &&
6789 vx(oproute->term2) == 196700. && vy(oproute->term2) == 67300.)
6791 // printf("OPROUTE %s - %f,%f %f,%f\n", oproute->netlist, vx(oproute->term1), vy(oproute->term1), vx(oproute->term2), vy(oproute->term2));
6792 // print_path(path);
6793 oproute->arcs = oproute_rubberband_segment(r, oproute, path, oproute->term1, oproute->term2, 1);
6794 }else
6795 #endif
6796 oproute->arcs = oproute_rubberband_segment(r, oproute, path, oproute->term1, oproute->term2, 0);
6798 oproute_check_all_loops(r, oproute);
6799 return oproute;
6803 void
6804 toporouter_export(toporouter_t *r)
6806 GList *i = r->routednets;
6807 GList *oproutes = NULL;
6809 while(i) {
6810 toporouter_route_t *routedata = TOPOROUTER_ROUTE(i->data);
6811 toporouter_oproute_t *oproute = oproute_rubberband(r, routedata->path);
6812 oproutes = g_list_prepend(oproutes, oproute);
6813 i = i->next;
6816 i = oproutes;
6817 while(i) {
6818 toporouter_oproute_t *oproute = (toporouter_oproute_t *) i->data;
6819 export_oproutes(r, oproute);
6820 oproute_free(oproute);
6821 i = i->next;
6824 Message(_("Reticulating splines... successful\n\n"));
6825 Message(_("Wiring cost: %f inches\n"), r->wiring_score / 1000.);
6826 printf("Wiring cost: %f inches\n", r->wiring_score / 1000.);
6828 g_list_free(oproutes);
6832 toporouter_route_t *
6833 routedata_create(void)
6835 toporouter_route_t *routedata = malloc(sizeof(toporouter_route_t));
6836 routedata->netlist = NULL;
6837 routedata->alltemppoints = NULL;
6838 routedata->path = NULL;
6839 routedata->curpoint = NULL;
6840 routedata->pscore = routedata->score = 0.;
6841 routedata->flags = 0;
6842 routedata->src = routedata->dest = NULL;
6843 routedata->psrc = routedata->pdest = NULL;
6844 routedata->ppath = routedata->topopath = NULL;
6846 routedata->ppathindices = NULL;
6848 routedata->destvertices = routedata->srcvertices = NULL;
6849 return routedata;
6852 void
6853 print_routedata(toporouter_route_t *routedata)
6855 GList *srcvertices = cluster_vertices(routedata->src);
6856 GList *destvertices = cluster_vertices(routedata->dest);
6858 printf("ROUTEDATA:\n");
6859 printf("SRCVERTICES:\n");
6860 print_vertices(srcvertices);
6861 printf("DESTVERTICES:\n");
6862 print_vertices(destvertices);
6864 g_list_free(srcvertices);
6865 g_list_free(destvertices);
6868 toporouter_route_t *
6869 import_route(toporouter_t *r, RatType *line)
6871 toporouter_route_t *routedata = routedata_create();
6873 routedata->src = cluster_find(r, line->Point1.X, line->Point1.Y, line->group1);
6874 routedata->dest = cluster_find(r, line->Point2.X, line->Point2.Y, line->group2);
6876 if(!routedata->src) printf("couldn't locate src\n");
6877 if(!routedata->dest) printf("couldn't locate dest\n");
6879 if(!routedata->src || !routedata->dest) {
6880 printf("PROBLEM: couldn't locate rat src or dest for rat %d,%d,%d -> %d,%d,%d\n",
6881 line->Point1.X, line->Point1.Y, line->group1, line->Point2.X, line->Point2.Y, line->group2);
6882 free(routedata);
6883 return NULL;
6886 routedata->netlist = routedata->src->netlist;
6888 g_assert(routedata->src->netlist == routedata->dest->netlist);
6890 g_ptr_array_add(r->routes, routedata);
6891 g_ptr_array_add(routedata->netlist->routes, routedata);
6893 r->failednets = g_list_prepend(r->failednets, routedata);
6895 return routedata;
6898 void
6899 delete_route(toporouter_route_t *routedata, guint destroy)
6901 GList *i = routedata->path;
6902 toporouter_vertex_t *pv = NULL;
6904 while(i) {
6905 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
6907 g_assert(tv);
6909 if(tv && pv && !(tv->flags & VERTEX_FLAG_ROUTE) && !(pv->flags & VERTEX_FLAG_ROUTE)) {
6910 toporouter_edge_t *e = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(tv), GTS_VERTEX(pv)));
6912 if(e && (e->flags & EDGE_FLAG_DIRECTCONNECTION)) {
6913 e->flags ^= EDGE_FLAG_DIRECTCONNECTION;
6916 pv = tv;
6917 i = i->next;
6920 i = routedata->path;
6921 while(i) {
6922 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
6924 tv->parent = NULL;
6925 tv->child = NULL;
6927 if(tv->routingedge) {
6928 if(TOPOROUTER_IS_CONSTRAINT(tv->routingedge))
6929 TOPOROUTER_CONSTRAINT(tv->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(tv->routingedge)->routing, tv);
6930 else
6931 tv->routingedge->routing = g_list_remove(tv->routingedge->routing, tv);
6932 if(destroy) gts_object_destroy ( GTS_OBJECT(tv) );
6935 i = i->next;
6938 if(routedata->path) g_list_free(routedata->path);
6939 routedata->path = NULL;
6940 routedata->curpoint = NULL;
6941 routedata->score = INFINITY;
6942 routedata->alltemppoints = NULL;
6945 /* remove route can be later reapplied */
6946 void
6947 remove_route(GList *path)
6949 GList *i = path;
6951 while(i) {
6952 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
6954 tv->parent = NULL;
6955 tv->child = NULL;
6957 // if(tv->flags & VERTEX_FLAG_ROUTE) g_assert(tv->route == routedata);
6959 if(tv->routingedge) {
6961 if(TOPOROUTER_IS_CONSTRAINT(tv->routingedge))
6962 TOPOROUTER_CONSTRAINT(tv->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(tv->routingedge)->routing, tv);
6963 else
6964 tv->routingedge->routing = g_list_remove(tv->routingedge->routing, tv);
6966 i = i->next;
6971 gint
6972 apply_route(GList *path, toporouter_route_t *routedata)
6974 GList *i = path;
6975 toporouter_vertex_t *pv = NULL;
6976 gint count = 0;
6978 if(!path) return 0;
6979 // g_assert(path);
6981 while(i) {
6982 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data);
6984 if(tv->routingedge) {
6985 if(TOPOROUTER_IS_CONSTRAINT(tv->routingedge))
6986 TOPOROUTER_CONSTRAINT(tv->routingedge)->routing = g_list_insert_sorted_with_data(
6987 TOPOROUTER_CONSTRAINT(tv->routingedge)->routing,
6988 tv,
6989 routing_edge_insert,
6990 tv->routingedge);
6991 else
6992 tv->routingedge->routing = g_list_insert_sorted_with_data(
6993 tv->routingedge->routing,
6994 tv,
6995 routing_edge_insert,
6996 tv->routingedge);
6998 count++;
7001 if(pv) {
7002 pv->child = tv;
7003 tv->parent = pv;
7006 if(tv->flags & VERTEX_FLAG_ROUTE) g_assert(tv->route == routedata);
7008 pv = tv;
7009 i = i->next;
7012 TOPOROUTER_VERTEX(path->data)->parent = NULL;
7013 pv->child = NULL;
7015 return count;
7019 gint
7020 compare_routedata_ascending(gconstpointer a, gconstpointer b)
7022 toporouter_route_t *ra = (toporouter_route_t *)a;
7023 toporouter_route_t *rb = (toporouter_route_t *)b;
7024 return ra->score - rb->score;
7027 void
7028 print_costmatrix(gdouble *m, guint n)
7030 printf("COST MATRIX:\n");
7031 for(guint i = 0;i<n;i++) {
7032 for(guint j = 0;j<n;j++) {
7033 printf("%f ", m[(i*n)+j]);
7035 printf("\n");
7040 inline void
7041 init_cost_matrix(gdouble *m, guint n)
7043 for(guint i=0;i<n;i++) {
7044 for(guint j=0;j<n;j++) {
7045 m[(i*n)+j] = INFINITY;
7051 toporouter_netscore_t *
7052 netscore_create(toporouter_t *r, toporouter_route_t *routedata, guint n, guint id)
7054 toporouter_netscore_t *netscore = malloc(sizeof(toporouter_netscore_t));
7055 GList *path = route(r, routedata, 0);
7057 netscore->id = id;
7059 netscore->routedata = routedata;
7060 routedata->detourscore = netscore->score = routedata->score;
7062 if(!finite(routedata->detourscore)) {
7063 printf("WARNING: !finite(detourscore)\n");
7064 print_cluster(routedata->src);
7065 print_cluster(routedata->dest);
7066 return NULL;
7069 netscore->pairwise_nodetour = malloc(n * sizeof(guint));
7071 for(guint i=0;i<n;i++) {
7072 netscore->pairwise_nodetour[i] = 0;
7075 netscore->pairwise_detour_sum = 0.;
7076 netscore->pairwise_fails = 0;
7078 netscore->r = r;
7080 if(path) {
7081 routedata->topopath = g_list_copy(routedata->path);
7082 delete_route(routedata, 0);
7085 return netscore;
7088 inline void
7089 netscore_destroy(toporouter_netscore_t *netscore)
7091 free(netscore->pairwise_nodetour);
7092 free(netscore);
7095 void
7096 print_netscores(GPtrArray* netscores)
7098 printf("NETSCORES: \n\n");
7099 printf(" %15s %15s %15s\n----------------------------------------------------\n", "Score", "Detour Sum", "Pairwise Fails");
7101 for(toporouter_netscore_t **i = (toporouter_netscore_t **) netscores->pdata; i < (toporouter_netscore_t **) netscores->pdata + netscores->len; i++) {
7102 #ifdef DEBUG_NETSCORES
7103 printf("%4d %15f %15f %15d %15x\n", (*i)->id, (*i)->score, (*i)->pairwise_detour_sum, (*i)->pairwise_fails, (guint)*i);
7104 #endif
7107 printf("\n");
7110 void
7111 netscore_pairwise_calculation(toporouter_netscore_t *netscore, GPtrArray *netscores)
7113 toporouter_netscore_t **netscores_base = (toporouter_netscore_t **) (netscores->pdata);
7114 toporouter_route_t *temproutedata = routedata_create();
7116 //route(netscore->r, netscore->routedata, 0);
7117 apply_route(netscore->routedata->topopath, netscore->routedata);
7119 for(toporouter_netscore_t **i = netscores_base; i < netscores_base + netscores->len; i++) {
7121 if(!netscore->pairwise_nodetour[i-netscores_base] && *i != netscore && (*i)->routedata->netlist != netscore->routedata->netlist) {
7123 temproutedata->src = (*i)->routedata->src;
7124 temproutedata->dest = (*i)->routedata->dest;
7126 route(netscore->r, temproutedata, 0);
7128 if(temproutedata->score == (*i)->score) {
7129 netscore->pairwise_nodetour[i-netscores_base] = 1;
7130 (*i)->pairwise_nodetour[netscore->id] = 1;
7131 }else
7132 if(!finite(temproutedata->score)) {
7133 netscore->pairwise_fails += 1;
7134 }else{
7135 netscore->pairwise_detour_sum += temproutedata->score - (*i)->score;
7138 delete_route(temproutedata, 1);
7143 // delete_route(netscore->routedata, 1);
7144 remove_route(netscore->routedata->topopath);
7146 free(temproutedata);
7149 gint
7150 netscore_pairwise_size_compare(toporouter_netscore_t **a, toporouter_netscore_t **b)
7152 // infinite scores are last
7153 if(!finite((*a)->score) && !finite((*b)->score)) return 0;
7154 if(finite((*a)->score) && !finite((*b)->score)) return -1;
7155 if(finite((*b)->score) && !finite((*a)->score)) return 1;
7157 // order by pairwise fails
7158 if((*a)->pairwise_fails < (*b)->pairwise_fails) return -1;
7159 if((*b)->pairwise_fails < (*a)->pairwise_fails) return 1;
7161 // order by pairwise detour
7162 if((*a)->pairwise_detour_sum < (*b)->pairwise_detour_sum) return -1;
7163 if((*b)->pairwise_detour_sum < (*a)->pairwise_detour_sum) return 1;
7165 // order by score
7166 if((*a)->score < (*b)->score) return -1;
7167 if((*b)->score < (*a)->score) return 1;
7169 return 0;
7172 gint
7173 netscore_pairwise_compare(toporouter_netscore_t **a, toporouter_netscore_t **b)
7175 // infinite scores are last
7176 if(!finite((*a)->score) && !finite((*b)->score)) return 0;
7177 if(finite((*a)->score) && !finite((*b)->score)) return -1;
7178 if(finite((*b)->score) && !finite((*a)->score)) return 1;
7180 // order by pairwise fails
7181 if((*a)->pairwise_fails < (*b)->pairwise_fails) return -1;
7182 if((*b)->pairwise_fails < (*a)->pairwise_fails) return 1;
7184 // order by pairwise detour
7185 if((*a)->pairwise_detour_sum < (*b)->pairwise_detour_sum) return -1;
7186 if((*b)->pairwise_detour_sum < (*a)->pairwise_detour_sum) return 1;
7188 return 0;
7191 guint
7192 order_nets_preroute_greedy(toporouter_t *r, GList *nets, GList **rnets)
7194 gint len = g_list_length(nets);
7195 GPtrArray* netscores = g_ptr_array_sized_new(len);
7196 guint failcount = 0;
7198 while(nets) {
7199 toporouter_netscore_t *ns = netscore_create(r, TOPOROUTER_ROUTE(nets->data), len, failcount++);
7200 if(ns) g_ptr_array_add(netscores, ns);
7201 nets = nets->next;
7204 failcount = 0;
7206 g_ptr_array_foreach(netscores, (GFunc) netscore_pairwise_calculation, netscores);
7208 g_ptr_array_sort(netscores, (GCompareFunc) r->netsort);
7210 #ifdef DEBUG_ORDERING
7211 print_netscores(netscores);
7212 #endif
7214 *rnets = NULL;
7215 FOREACH_NETSCORE(netscores) {
7216 *rnets = g_list_prepend(*rnets, netscore->routedata);
7217 if(!finite(netscore->score)) failcount++;
7218 netscore_destroy(netscore);
7219 } FOREACH_END;
7221 g_ptr_array_free(netscores, TRUE);
7223 return failcount;
7226 toporouter_vertex_t *
7227 edge_closest_vertex(toporouter_edge_t *e, toporouter_vertex_t *v)
7229 GList *i = v->routingedge ? edge_routing(v->routingedge) : NULL;
7230 gdouble closestd = 0.;
7231 toporouter_vertex_t *closestv = NULL;
7233 while(i) {
7234 toporouter_vertex_t *ev = TOPOROUTER_VERTEX(i->data);
7235 gdouble tempd = gts_point_distance2(GTS_POINT(ev), GTS_POINT(v));
7237 if(!closestv || (tempd < closestd)) {
7238 closestd = tempd;
7239 closestv = ev;
7242 i = i->next;
7245 return closestv;
7248 void
7249 snapshot(toporouter_t *r, char *name, GList *datas)
7251 ///*
7253 int i;
7254 for(i=0;i<groupcount();i++) {
7255 char buffer[256];
7256 sprintf(buffer, "route-%s-%d.png", name, i);
7257 toporouter_draw_surface(r, r->layers[i].surface, buffer, 2048, 2048, 2, datas, i, NULL);
7260 //*/
7264 gdouble
7265 route_conflict(toporouter_t *r, toporouter_route_t *route, guint *n)
7267 GList *i = route->path;
7268 toporouter_vertex_t *pv = NULL;
7269 gdouble cost = 0.;
7271 while(i) {
7272 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
7273 if(pv && vz(v) == vz(pv))
7274 cost += vertices_routing_conflict_cost(r, v, pv, n);
7275 pv = v;
7276 i = i->next;
7279 return cost;
7282 GList *
7283 route_conflicts(toporouter_route_t *route)
7285 GList *conflicts = NULL, *i = route->path;
7286 toporouter_vertex_t *pv = NULL;
7288 while(i) {
7289 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
7291 if(pv && vz(pv) == vz(v)) {
7292 GList *temp = vertices_routing_conflicts(pv, v), *j;
7294 j = temp;
7295 while(j) {
7296 toporouter_route_t *conroute = TOPOROUTER_ROUTE(j->data);
7297 if(!g_list_find(conflicts, conroute))
7298 conflicts = g_list_prepend(conflicts, conroute);
7299 j = j->next;
7302 if(temp) g_list_free(temp);
7305 pv = v;
7306 i = i->next;
7308 return conflicts;
7311 gint
7312 spread_edge(gpointer item, gpointer data)
7314 toporouter_edge_t *e = TOPOROUTER_EDGE(item);
7315 toporouter_vertex_t *v;
7316 gdouble spacing, s;
7317 GList *i;
7319 if(TOPOROUTER_IS_CONSTRAINT(e)) return 0;
7321 i = edge_routing(e);
7323 if(!g_list_length(i)) return 0;
7325 if(g_list_length(i) == 1) {
7326 v = TOPOROUTER_VERTEX(i->data);
7327 GTS_POINT(v)->x = (vx(edge_v1(e)) + vx(edge_v2(e))) / 2.;
7328 GTS_POINT(v)->y = (vy(edge_v1(e)) + vy(edge_v2(e))) / 2.;
7329 return 0;
7332 s = spacing = (gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e))) ) / (g_list_length(i) + 1);
7334 while(i) {
7335 v = TOPOROUTER_VERTEX(i->data);
7336 vertex_move_towards_vertex_values(edge_v1(e), edge_v2(e), s, &(GTS_POINT(v)->x), &(GTS_POINT(v)->y));
7338 s += spacing;
7339 i = i->next;
7342 return 0;
7345 void
7346 route_checkpoint(toporouter_route_t *route, toporouter_route_t *temproute)
7348 GList *i = g_list_last(route->path);
7349 gint n = g_list_length(route->path);
7351 if(route->ppathindices) free(route->ppathindices);
7352 route->ppathindices = malloc(sizeof(gint)*n);
7354 // n = 0;
7355 while(i) {
7356 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
7357 n--;
7359 if(v->routingedge) {
7360 GList *j = g_list_find(edge_routing(v->routingedge), v)->prev;
7361 gint tempindex = g_list_index(edge_routing(v->routingedge), v);
7363 while(j) {
7364 if(TOPOROUTER_VERTEX(j->data)->route == temproute) tempindex--;
7365 j = j->prev;
7368 route->ppathindices[n] = tempindex;
7370 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge))
7371 TOPOROUTER_CONSTRAINT(v->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(v->routingedge)->routing, v);
7372 else
7373 v->routingedge->routing = g_list_remove(v->routingedge->routing, v);
7376 i = i->prev;
7379 route->pscore = route->score;
7380 route->ppath = route->path;
7381 remove_route(route->path);
7382 route->path = NULL;
7383 route->psrc = route->src;
7384 route->pdest = route->dest;
7385 //route->src->pc = route->src->c;
7386 //route->dest->pc = route->dest->c;
7389 void
7390 route_restore(toporouter_route_t *route)
7392 GList *i;
7393 toporouter_vertex_t *pv = NULL;
7394 gint n = 0;
7396 g_assert(route->ppath);
7397 g_assert(route->ppathindices);
7399 route->path = route->ppath;
7400 i = route->ppath;
7401 while(i) {
7402 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data);
7404 if(v->routingedge) {
7405 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge))
7406 TOPOROUTER_CONSTRAINT(v->routingedge)->routing = g_list_insert(TOPOROUTER_CONSTRAINT(v->routingedge)->routing, v, route->ppathindices[n]);
7407 else
7408 v->routingedge->routing = g_list_insert(v->routingedge->routing, v, route->ppathindices[n]);
7410 // space_edge(v->routingedge, NULL);
7413 if(pv) {
7414 pv->child = v;
7415 v->parent = pv;
7418 n++;
7419 pv = v;
7420 i = i->next;
7423 route->score = route->pscore;
7424 route->src = route->psrc;
7425 route->dest = route->pdest;
7426 //route->src->c = route->src->pc;
7427 //route->dest->c = route->dest->pc;
7431 void
7432 cluster_merge(toporouter_route_t *routedata)
7434 gint oldc = routedata->dest->c, newc = routedata->src->c;
7436 FOREACH_CLUSTER(routedata->netlist->clusters) {
7437 if(cluster->c == oldc)
7438 cluster->c = newc;
7439 } FOREACH_END;
7443 void
7444 netlist_recalculate(toporouter_netlist_t *netlist, GList *ignore)
7446 GList *i = g_list_last(netlist->routed);
7447 gint n = netlist->clusters->len-1;
7449 FOREACH_CLUSTER(netlist->clusters) {
7450 cluster->c = n--;
7451 } FOREACH_END;
7453 while(i) {
7454 if(!ignore || !g_list_find(ignore, i->data)) cluster_merge(TOPOROUTER_ROUTE(i->data));
7455 i = i->prev;
7460 void
7461 netlists_recalculate(GList *netlists, GList *ignore)
7463 GList *i = netlists;
7464 while(i) {
7465 netlist_recalculate(TOPOROUTER_NETLIST(i->data), ignore);
7466 i = i->next;
7470 void
7471 netlists_rollback(GList *netlists)
7473 // netlists_recalculate(netlists, NULL);
7474 while(netlists) {
7475 toporouter_netlist_t *netlist = TOPOROUTER_NETLIST(netlists->data);
7477 FOREACH_CLUSTER(netlist->clusters) {
7478 cluster->c = cluster->pc;
7479 } FOREACH_END;
7481 netlists = netlists->next;
7485 void
7486 print_netlist(toporouter_netlist_t *netlist)
7489 printf("NETLIST %s: ", netlist->netlist);
7491 FOREACH_CLUSTER(netlist->clusters) {
7492 printf("%d ", cluster->c);
7494 } FOREACH_END;
7495 printf("\n");
7498 #define REMOVE_ROUTING(x) x->netlist->routed = g_list_remove(x->netlist->routed, x); \
7499 r->routednets = g_list_remove(r->routednets, x); \
7500 r->failednets = g_list_prepend(r->failednets, x)
7502 #define INSERT_ROUTING(x) x->netlist->routed = g_list_prepend(x->netlist->routed, x); \
7503 r->routednets = g_list_prepend(r->routednets, x); \
7504 r->failednets = g_list_remove(r->failednets, x)
7506 gint
7507 roar_route(toporouter_t *r, toporouter_route_t *routedata, gint threshold)
7509 gint intfails = 0;
7510 GList *netlists = NULL, *routed = NULL;
7512 g_assert(!routedata->path);
7514 if(routedata->src->c == routedata->dest->c) {
7515 printf("ERROR: attempt to route already complete route\n");
7516 g_assert(routedata->src->c != routedata->dest->c);
7519 routedata->src->pc = routedata->src->c;
7520 routedata->dest->pc = routedata->dest->c;
7521 routedata->psrc = routedata->src;
7522 routedata->pdest = routedata->dest;
7524 r->flags |= TOPOROUTER_FLAG_LEASTINVALID;
7525 if(route(r, routedata, 0)) {
7526 GList *conflicts, *j;
7528 INSERT_ROUTING(routedata);
7530 conflicts = route_conflicts(routedata);
7531 cluster_merge(routedata);
7533 r->flags &= ~TOPOROUTER_FLAG_LEASTINVALID;
7535 j = conflicts;
7536 while(j) {
7537 toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data);
7538 if(!g_list_find(netlists, conflict->netlist))
7539 netlists = g_list_prepend(netlists, conflict->netlist);
7541 route_checkpoint(conflict, routedata);
7543 REMOVE_ROUTING(conflict);
7544 j = j->next;
7547 netlists = g_list_prepend(netlists, routedata->netlist);
7548 netlists_recalculate(netlists, NULL);
7550 j = conflicts;
7551 while(j) {
7552 toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data);
7553 g_assert(conflict->src->c != conflict->dest->c);
7554 if(route(r, conflict, 0)) {
7555 cluster_merge(conflict);
7557 routed = g_list_prepend(routed, conflict);
7559 INSERT_ROUTING(conflict);
7561 netlist_recalculate(conflict->netlist, NULL);
7563 }else{
7564 if(++intfails >= threshold) {
7565 GList *i = routed;
7566 while(i) {
7567 toporouter_route_t *intconflict = TOPOROUTER_ROUTE(i->data);
7568 REMOVE_ROUTING(intconflict);
7569 delete_route(intconflict, 1);
7570 i = i->next;
7572 delete_route(routedata, 1);
7573 i = g_list_last(conflicts);
7574 while(i) {
7575 toporouter_route_t *intconflict = TOPOROUTER_ROUTE(i->data);
7577 route_restore(intconflict);
7578 INSERT_ROUTING(intconflict);
7580 i = i->prev;
7582 REMOVE_ROUTING(routedata);
7583 intfails = 0;
7584 netlists_recalculate(netlists, NULL);
7585 goto roar_route_end;
7589 j = j->next;
7593 netlists_recalculate(netlists, NULL);
7595 intfails--;
7596 roar_route_end:
7597 g_list_free(conflicts);
7598 g_list_free(netlists);
7600 }else{
7601 r->flags &= ~TOPOROUTER_FLAG_LEASTINVALID;
7604 g_list_free(routed);
7605 return intfails;
7608 gint
7609 roar_router(toporouter_t *r, gint failcount, gint threshold)
7611 gint pfailcount = failcount +1;
7613 Message(_("ROAR router: "));
7614 for(guint j=0;j<6;j++) {
7615 GList *failed = g_list_copy(r->failednets), *k = failed;
7617 k = failed;
7618 while(k) {
7619 failcount += roar_route(r, TOPOROUTER_ROUTE(k->data), threshold);
7620 k = k->next;
7622 g_list_free(failed);
7624 printf("\tROAR pass %d - %d routed - %d failed\n", j, g_list_length(r->routednets), g_list_length(r->failednets));
7626 if(!failcount || failcount >= pfailcount) {
7627 Message(_("%d nets remaining\n"), failcount);
7628 break;
7630 Message(_("%d -> "), failcount);
7631 pfailcount = failcount;
7634 return failcount;
7637 gint
7638 route_detour_compare(toporouter_route_t **a, toporouter_route_t **b)
7639 { return ((*b)->score - (*b)->detourscore) - ((*a)->score - (*a)->detourscore); }
7643 void
7644 roar_detour_route(toporouter_t *r, toporouter_route_t *data)
7646 gdouble pscore = data->score, nscore = 0.;
7647 GList *netlists = NULL;
7649 route_checkpoint(data, NULL);
7651 REMOVE_ROUTING(data);
7653 netlists = g_list_prepend(NULL, data->netlist);
7654 netlists_recalculate(netlists, NULL);
7656 r->flags |= TOPOROUTER_FLAG_LEASTINVALID;
7657 if(route(r, data, 0)) {
7658 GList *conflicts, *j;
7660 nscore = data->score;
7661 conflicts = route_conflicts(data);
7663 INSERT_ROUTING(data);
7665 r->flags &= ~TOPOROUTER_FLAG_LEASTINVALID;
7667 j = conflicts;
7668 while(j) {
7669 toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data);
7671 if(!g_list_find(netlists, conflict->netlist))
7672 netlists = g_list_prepend(netlists, conflict->netlist);
7673 pscore += conflict->score;
7675 route_checkpoint(conflict, NULL);
7676 REMOVE_ROUTING(conflict);
7678 j = j->next;
7680 netlists_recalculate(netlists, NULL);
7682 j = conflicts;
7683 while(j) {
7684 toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data);
7686 if(route(r, conflict, 0)) {
7687 cluster_merge(conflict);
7688 INSERT_ROUTING(conflict);
7689 nscore += conflict->score;
7690 }else{
7691 j = j->prev;
7692 goto roar_detour_route_rollback_int;
7694 j = j->next;
7697 if(nscore > pscore) {
7698 j = g_list_last(conflicts);
7699 roar_detour_route_rollback_int:
7700 REMOVE_ROUTING(data);
7702 while(j) {
7703 toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data);
7704 REMOVE_ROUTING(conflict);
7705 delete_route(conflict, 1);
7706 j = j->prev;
7709 j = g_list_last(conflicts);
7710 while(j) {
7711 toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data);
7712 route_restore(conflict);
7713 INSERT_ROUTING(conflict);
7714 j = j->prev;
7716 delete_route(data, 1);
7718 goto roar_detour_route_rollback_exit;
7722 g_list_free(conflicts);
7723 }else{
7724 r->flags &= ~TOPOROUTER_FLAG_LEASTINVALID;
7725 roar_detour_route_rollback_exit:
7726 route_restore(data);
7727 INSERT_ROUTING(data);
7729 netlists_recalculate(netlists, NULL);
7731 g_list_free(netlists);
7734 void
7735 detour_router(toporouter_t *r)
7737 GList *i = r->routednets;
7738 guint n = g_list_length(r->routednets);
7739 GPtrArray* scores = g_ptr_array_sized_new(n);
7741 while(i) {
7742 toporouter_route_t *curroute = TOPOROUTER_ROUTE(i->data);
7743 curroute->score = path_score(r, curroute->path);
7744 g_ptr_array_add(scores, i->data);
7745 i = i->next;
7748 g_ptr_array_sort(scores, (GCompareFunc) route_detour_compare);
7750 r->flags |= TOPOROUTER_FLAG_DETOUR;
7752 for(toporouter_route_t **i = (toporouter_route_t **) scores->pdata; i < (toporouter_route_t **) scores->pdata + scores->len; i++) {
7753 toporouter_route_t *curroute = (*i);
7755 if(finite(curroute->score) && finite(curroute->detourscore)) {
7756 // printf("%15s %15f \t %8f,%8f - %8f,%8f\n", (*i)->src->netlist + 2, (*i)->score - (*i)->detourscore,
7757 // vx(curroute->mergebox1->point), vy(curroute->mergebox1->point),
7758 // vx(curroute->mergebox2->point), vy(curroute->mergebox2->point));
7760 if(curroute->score - curroute->detourscore > 1000.) {
7761 roar_detour_route(r, curroute);
7762 }else break;
7766 printf("\n");
7768 r->flags ^= TOPOROUTER_FLAG_DETOUR;
7770 g_ptr_array_free(scores, TRUE);
7774 gint
7775 rubix_router(toporouter_t *r, gint failcount)
7777 GList *i, *ordering;
7778 order_nets_preroute_greedy(r, r->failednets, &ordering);
7780 i = ordering;
7781 while(i) {
7782 toporouter_route_t *data = TOPOROUTER_ROUTE(i->data);
7784 if(route(r, data, 0)) {
7785 INSERT_ROUTING(data);
7786 cluster_merge(data);
7787 failcount--;
7790 i = i->next;
7793 g_list_free(ordering);
7795 return failcount;
7798 guint
7799 hybrid_router(toporouter_t *r)
7801 gint failcount = g_list_length(r->failednets);
7802 r->flags |= TOPOROUTER_FLAG_AFTERORDER;
7803 r->flags |= TOPOROUTER_FLAG_AFTERRUBIX;
7804 failcount = rubix_router(r, failcount);
7806 Message(_("RUBIX router: %d nets remaining\n"), failcount);
7807 printf("RUBIX router: %d nets remaining\n", failcount);
7809 r->flags |= TOPOROUTER_FLAG_GOFAR;
7811 for(guint i=0;i<6 && failcount;i++) {
7812 if(i % 2 == 1) {
7813 failcount = roar_router(r, failcount, 5);
7814 // printf("THRESH 5\n");
7815 }else{
7816 failcount = roar_router(r, failcount, 2);
7817 // printf("THRESH 2\n");
7820 detour_router(r);
7823 failcount = roar_router(r, failcount, 2);
7824 detour_router(r);
7826 return failcount;
7829 void
7830 parse_arguments(toporouter_t *r, int argc, char **argv)
7832 int i, tempint;
7833 for(i=0;i<argc;i++) {
7834 if(sscanf(argv[i], "viacost=%d", &tempint)) {
7835 r->viacost = (double)tempint;
7836 }else if(sscanf(argv[i], "l%d", &tempint)) {
7837 gdouble *layer = malloc(sizeof(gdouble));
7838 *layer = (double)tempint;
7839 r->keepoutlayers = g_list_prepend(r->keepoutlayers, layer);
7843 for (guint group = 0; group < max_layer; group++)
7844 for (i = 0; i < PCB->LayerGroups.Number[group]; i++)
7845 if ((PCB->LayerGroups.Entries[group][i] < max_layer) && !(PCB->Data->Layer[PCB->LayerGroups.Entries[group][i]].On)) {
7846 gdouble *layer = malloc(sizeof(gdouble));
7847 *layer = (double)group;
7848 r->keepoutlayers = g_list_prepend(r->keepoutlayers, layer);
7853 toporouter_t *
7854 toporouter_new(void)
7856 toporouter_t *r = calloc(1, sizeof(toporouter_t));
7857 time_t ltime;
7859 gettimeofday(&r->starttime, NULL);
7861 r->netsort = netscore_pairwise_compare;
7863 r->destboxes = NULL;
7864 r->consumeddestboxes = NULL;
7866 r->paths = NULL;
7868 r->layers = NULL;
7869 r->flags = 0;
7870 r->viamax = 3;
7871 r->viacost = 10000.;
7872 r->stublength = 300.;
7873 r->serpintine_half_amplitude = 1500.;
7875 r->wiring_score = 0.;
7877 r->bboxes = NULL;
7878 r->bboxtree = NULL;
7880 r->netlists = g_ptr_array_new();
7881 r->routes = g_ptr_array_new();
7883 r->keepoutlayers = NULL;
7885 r->routednets = NULL;
7886 r->failednets = NULL;
7888 ltime=time(NULL);
7890 gts_predicates_init();
7892 Message(_("Topological Autorouter\n"));
7893 Message(_("Started %s"),asctime(localtime(&ltime)));
7894 Message(_("-------------------------------------\n"));
7895 Message(_("Copyright 2009 Anthony Blake (tonyb33@gmail.com)\n\n"));
7896 return r;
7899 void
7900 acquire_twonets(toporouter_t *r)
7902 RAT_LOOP(PCB->Data);
7903 if( TEST_FLAG(SELECTEDFLAG, line) ) import_route(r, line);
7904 END_LOOP;
7905 // /*
7906 if(!r->routes->len) {
7907 RAT_LOOP(PCB->Data);
7908 import_route(r, line);
7909 END_LOOP;
7911 // */
7915 toporouter_netlist_t *
7916 find_netlist_by_name(toporouter_t *r, char *name)
7918 FOREACH_NETLIST(r->netlists) {
7919 if(!strcmp(netlist->netlist, name)) return netlist;
7920 } FOREACH_END;
7921 return NULL;
7924 gint
7925 toporouter_set_pair(toporouter_t *r, toporouter_netlist_t *n1, toporouter_netlist_t *n2)
7927 if(!n1 || !n2) return 0;
7928 n1->pair = n2;
7929 n2->pair = n1;
7930 return 1;
7933 static int
7934 toporouter (int argc, char **argv, int x, int y)
7936 toporouter_t *r = toporouter_new();
7937 parse_arguments(r, argc, argv);
7938 import_geometry(r);
7939 acquire_twonets(r);
7941 //if(!toporouter_set_pair(r, find_netlist_by_name(r, " DRAM_DQS_N"), find_netlist_by_name(r, " DRAM_DQS"))) {
7942 // printf("Couldn't associate pair\n");
7945 hybrid_router(r);
7947 for(gint i=0;i<groupcount();i++) {
7948 gts_surface_foreach_edge(r->layers[i].surface, space_edge, NULL);
7951 int i;
7952 for(i=0;i<groupcount();i++) {
7953 char buffer[256];
7954 sprintf(buffer, "route%d.png", i);
7955 toporouter_draw_surface(r, r->layers[i].surface, buffer, 1024, 1024, 2, NULL, i, NULL);
7959 toporouter_export(r);
7960 toporouter_free(r);
7962 SaveUndoSerialNumber ();
7963 DeleteRats (false);
7964 RestoreUndoSerialNumber ();
7965 AddAllRats (false, NULL);
7966 RestoreUndoSerialNumber ();
7967 IncrementUndoSerialNumber ();
7968 ClearAndRedrawOutput ();
7970 return 0;
7973 static int
7974 escape (int argc, char **argv, int x, int y)
7976 guint dir, viax, viay;
7977 gdouble pitch, length, dx, dy;
7979 if(argc != 1) return 0;
7981 dir = atoi(argv[0]);
7984 ALLPAD_LOOP(PCB->Data);
7986 if( TEST_FLAG(SELECTEDFLAG, pad) ) {
7987 PinTypePtr via;
7988 LineTypePtr line;
7990 pitch = sqrt( pow(abs(element->Pad[0].Point1.X - element->Pad[1].Point1.X), 2) +
7991 pow(abs(element->Pad[0].Point1.Y - element->Pad[1].Point1.Y), 2) );
7992 length = sqrt(pow(pitch,2) + pow(pitch,2)) / 2.;
7994 dx = length * sin(M_PI/4.);
7995 dy = length * cos(M_PI/4.);
7997 switch(dir) {
7998 case 1:
7999 viax = pad->Point1.X - dx;
8000 viay = pad->Point1.Y + dy;
8001 break;
8002 case 3:
8003 viax = pad->Point1.X + dx;
8004 viay = pad->Point1.Y + dy;
8005 break;
8006 case 9:
8007 viax = pad->Point1.X + dx;
8008 viay = pad->Point1.Y - dy;
8009 break;
8010 case 7:
8011 viax = pad->Point1.X - dx;
8012 viay = pad->Point1.Y - dy;
8013 break;
8014 case 2:
8015 viax = pad->Point1.X;
8016 viay = pad->Point1.Y + (pitch/2);
8017 break;
8018 case 8:
8019 viax = pad->Point1.X;
8020 viay = pad->Point1.Y - (pitch/2);
8021 break;
8022 case 4:
8023 viax = pad->Point1.X - (pitch/2);
8024 viay = pad->Point1.Y;
8025 break;
8026 case 6:
8027 viax = pad->Point1.X + (pitch/2);
8028 viay = pad->Point1.Y;
8029 break;
8030 default:
8031 printf("ERROR: escape() with bad direction (%d)\n", dir);
8032 return 1;
8035 if ((via = CreateNewVia (PCB->Data, viax, viay,
8036 Settings.ViaThickness, 2 * Settings.Keepaway,
8037 0, Settings.ViaDrillingHole, NULL,
8038 NoFlags ())) != NULL)
8040 AddObjectToCreateUndoList (VIA_TYPE, via, via, via);
8041 // if (gui->shift_is_pressed ())
8042 // ChangeObjectThermal (VIA_TYPE, via, via, via, PCB->ThermStyle);
8043 DrawVia (via, 0);
8044 if((line = CreateDrawnLineOnLayer (CURRENT, pad->Point1.X + 1., pad->Point1.Y + 1., viax + 1., viay + 1.,
8045 Settings.LineThickness, 2 * Settings.Keepaway,
8046 NoFlags())))
8049 AddObjectToCreateUndoList (LINE_TYPE, CURRENT, line, line);
8050 DrawLine (CURRENT, line, 0);
8058 END_LOOP;
8059 END_LOOP;
8061 IncrementUndoSerialNumber ();
8062 Draw ();
8063 return 0;
8066 static HID_Action toporouter_action_list[] = {
8067 {"Escape", "Select a set of pads", escape, "Pad escape", "Escape()"},
8068 {"Toporouter", "Select net(s)", toporouter, "Topological autorouter", "Toporouter()"}
8071 REGISTER_ACTIONS (toporouter_action_list)
8073 void hid_toporouter_init()
8075 register_toporouter_action_list();