1 /*!
2  * \file src/djopt.c
3  *
4  * \brief .
5  *
6  * <hr>
7  *
8  * <h1><b>Copyright.</b></h1>\n
9  *
10  * PCB, interactive printed circuit board design
11  *
12  * Copyright (C) 2003 DJ Delorie
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with this program; if not, write to the Free Software Foundation, Inc.,
26  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27  *
28  * Contact addresses for paper mail and Email:
29  * DJ Delorie, 334 North Road, Deerfield NH 03037-1110, USA
30  * dj@delorie.com
31  */
32 
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 
37 #include "global.h"
38 
39 #include <memory.h>
40 #include <limits.h>
41 
42 
43 #include "data.h"
44 #include "create.h"
45 #include "remove.h"
46 #include "move.h"
47 #include "draw.h"
48 #include "undo.h"
49 #include "strflags.h"
50 #include "find.h"
51 #include "pcb-printf.h"
52 
53 #ifdef HAVE_LIBDMALLOC
54 #include <dmalloc.h>
55 #endif
56 
57 #ifndef HAVE_RINT
58 #define rint(x)  (ceil((x) - 0.5))
59 #endif
60 
61 #define dprintf if(0)pcb_printf
62 
63 #define selected(x) TEST_FLAG (SELECTEDFLAG, (x))
64 #define autorouted(x) TEST_FLAG (AUTOFLAG, (x))
65 
66 #define SB (PCB->Bloat+1)
67 
68 /* must be 2^N-1 */
69 #define INC 7
70 
71 #define O_HORIZ		0x10
72 #define O_VERT		0x20
73 #define LEFT		0x11
74 #define RIGHT		0x12
75 #define UP		0x24
76 #define DOWN		0x28
77 #define DIAGONAL	0xf0
78 #define ORIENT(x) ((x) & 0xf0)
79 #define DIRECT(x) ((x) & 0x0f)
80 
81 #define LONGEST_FRECKLE	2 /*!< Manhattan length of the longest "freckle" */
82 
83 
84 struct line_s;
85 
86 typedef struct corner_s
87 {
88   int layer;
89   struct corner_s *next;
90   int x, y;
91   int net;
92   PinType *via;
93   PadType *pad;
94   PinType *pin;
95   int miter;
96   int n_lines;
97   struct line_s **lines;
98 } corner_s;
99 
100 typedef struct line_s
101 {
102   int layer;
103   struct line_s *next;
104   corner_s *s, *e;
105   LineType *line;
106   char is_pad;
107 } line_s;
108 
109 typedef struct rect_s
110 {
111   int x1, y1, x2, y2;
112 } rect_s;
113 
114 #define DELETE(q) (q)->layer = 0xdeadbeef
115 #define DELETED(q) ((q)->layer == 0xdeadbeef)
116 
117 static corner_s *corners, *next_corner = 0;
118 static line_s *lines;
119 
120 static int layer_groupings[MAX_LAYER];
121 static char layer_type[MAX_LAYER];
122 #define LT_TOP 1
123 #define LT_BOTTOM 2
124 
125 static int autorouted_only = 1;
126 
127 static const char djopt_sao_syntax[] = "OptAutoOnly()";
128 
129 static const char djopt_sao_help[] =
130   "Toggles the optimize-only-autorouted flag.";
131 
132 /* %start-doc actions OptAutoOnly
133 
134 The original purpose of the trace optimizer was to clean up the traces
135 created by the various autorouters that have been used with PCB.  When
136 a board has a mix of autorouted and carefully hand-routed traces, you
137 don't normally want the optimizer to move your hand-routed traces.
138 But, sometimes you do.  By default, the optimizer only optimizes
139 autorouted traces.  This action toggles that setting, so that you can
140 optimize hand-routed traces also.
141 
142 %end-doc */
143 
144 int
djopt_set_auto_only(int argc,char ** argv,Coord x,Coord y)145 djopt_set_auto_only (int argc, char **argv, Coord x, Coord y)
146 {
147   autorouted_only = autorouted_only ? 0 : 1;
148   return 0;
149 }
150 
151 static int
djopt_get_auto_only(void * data)152 djopt_get_auto_only (void *data)
153 {
154   return autorouted_only;
155 }
156 
157 HID_Flag djopt_flag_list[] = {
158   {"optautoonly", djopt_get_auto_only, NULL}
159 };
160 
REGISTER_FLAGS(djopt_flag_list)161 REGISTER_FLAGS (djopt_flag_list)
162 
163 static char *
164 element_name_for (corner_s * c)
165 {
166   ELEMENT_LOOP (PCB->Data);
167   {
168     PIN_LOOP (element);
169     {
170       if (pin == c->pin)
171         return element->Name[1].TextString;
172     }
173     END_LOOP;
174     PAD_LOOP (element);
175     {
176       if (pad == c->pad)
177         return element->Name[1].TextString;
178     }
179     END_LOOP;
180   }
181   END_LOOP;
182   return "unknown";
183 }
184 
185 static char *
corner_name(corner_s * c)186 corner_name (corner_s * c)
187 {
188   static char buf[4][100];
189   static int bn = 0;
190   char *bp;
191   size_t size_left;
192   bn = (bn + 1) % 4;
193 
194   if (c->net == 0xf1eef1ee)
195     {
196       sprintf (buf[bn], "\033[31m[%p freed corner]\033[0m", (void *) c);
197       return buf[bn];
198     }
199 
200   sprintf (buf[bn], "\033[%dm[%p ",
201 	   (c->pin || c->pad || c->via) ? 33 : 34, (void *) c);
202   bp = buf[bn] + strlen (buf[bn]);
203   size_left = sizeof (buf[bn]) - strlen (buf[bn]);
204 
205   if (c->pin)
206     pcb_snprintf (bp, size_left, "pin %s:%s at %#mD",
207 		  element_name_for (c), c->pin->Number, c->x, c->y);
208   else if (c->via)
209     pcb_snprintf (bp, size_left, "via at %#mD", c->x, c->y);
210   else if (c->pad)
211     {
212       pcb_snprintf (bp, size_left, "pad %s:%s at %#mD %#mD-%#mD",
213 	       element_name_for (c), c->pad->Number, c->x, c->y,
214 	       c->pad->Point1.X, c->pad->Point1.Y,
215 	       c->pad->Point2.X, c->pad->Point2.Y);
216     }
217   else
218     pcb_snprintf (bp, size_left, "at %#mD", c->x, c->y);
219   sprintf (bp + strlen (bp), " n%d l%d]\033[0m", c->n_lines, c->layer);
220   return buf[bn];
221 }
222 
223 static int solder_layer, component_layer;
224 
225 static void
dj_abort(char * msg,...)226 dj_abort (char *msg, ...)
227 {
228   va_list a;
229   va_start (a, msg);
230   vprintf (msg, a);
231   va_end (a);
232   fflush (stdout);
233   abort ();
234 }
235 
236 #if 1
237 #define check(c,l)
238 #else
239 #define check(c,l) check2(__LINE__,c,l)
240 static void
check2(int srcline,corner_s * c,line_s * l)241 check2 (int srcline, corner_s * c, line_s * l)
242 {
243   int saw_c = 0, saw_l = 0;
244   corner_s *cc;
245   line_s *ll;
246   int i;
247 
248   for (cc = corners; cc; cc = cc->next)
249     {
250       if (DELETED (cc))
251 	continue;
252       if (cc == c)
253 	saw_c = 1;
254       for (i = 0; i < cc->n_lines; i++)
255 	if (cc->lines[i]->s != cc && cc->lines[i]->e != cc)
256 	  dj_abort ("check:%d: cc has line without backref\n", srcline);
257       if (cc->via && (cc->x != cc->via->X || cc->y != cc->via->Y))
258 	dj_abort ("check:%d: via not at corner\n", srcline);
259       if (cc->pin && (cc->x != cc->pin->X || cc->y != cc->pin->Y))
260 	dj_abort ("check:%d: pin not at corner\n", srcline);
261     }
262   if (c && !saw_c)
263     dj_abort ("check:%d: corner not in corners list\n", srcline);
264   for (ll = lines; ll; ll = ll->next)
265     {
266       if (DELETED (ll))
267 	continue;
268       if (ll == l)
269 	saw_l = 1;
270       for (i = 0; i < ll->s->n_lines; i++)
271 	if (ll->s->lines[i] == ll)
272 	  break;
273       if (i == ll->s->n_lines)
274 	dj_abort ("check:%d: ll->s has no backref\n", srcline);
275       for (i = 0; i < ll->e->n_lines; i++)
276 	if (ll->e->lines[i] == ll)
277 	  break;
278       if (i == ll->e->n_lines)
279 	dj_abort ("check:%d: ll->e has no backref\n", srcline);
280       if (!ll->is_pad
281 	  && (ll->s->x != ll->line->Point1.X
282 	      || ll->s->y != ll->line->Point1.Y
283 	      || ll->e->x != ll->line->Point2.X
284 	      || ll->e->y != ll->line->Point2.Y))
285 	{
286 	  pcb_printf ("line: %#mD to %#mD  pcbline: %#mD to %#mD\n",
287 		  ll->s->x, ll->s->y,
288 		  ll->e->x, ll->e->y,
289 		  ll->line->Point1.X,
290 		  ll->line->Point1.Y, ll->line->Point2.X, ll->line->Point2.Y);
291 	  dj_abort ("check:%d: line doesn't match pcbline\n", srcline);
292 	}
293     }
294   if (l && !saw_l)
295     dj_abort ("check:%d: line not in lines list\n", srcline);
296 }
297 
298 #endif
299 
300 #define SWAP(a,b) { a^=b; b^=a; a^=b; }
301 
302 static int
gridsnap(Coord n)303 gridsnap (Coord n)
304 {
305   if (n <= 0)
306     return 0;
307   return n - n % (Settings.Grid);
308 }
309 
310 /* Avoid commonly used names. */
311 
312 static int
djabs(int x)313 djabs (int x)
314 {
315   return x > 0 ? x : -x;
316 }
317 
318 static int
djmax(int x,int y)319 djmax (int x, int y)
320 {
321   return x > y ? x : y;
322 }
323 
324 static int
djmin(int x,int y)325 djmin (int x, int y)
326 {
327   return x < y ? x : y;
328 }
329 
330 /*!
331  * \brief Find distance between 2 points.
332  *
333  * We use floating point math here because we can fairly easily overflow
334  * a 32 bit integer here.
335  * In fact it only takes 0.46" to do so.
336  */
337 static int
dist(int x1,int y1,int x2,int y2)338 dist (int x1, int y1, int x2, int y2)
339 {
340   double d;
341 
342   d = hypot ((double) x1 - (double) x2, (double) y1 - (double) y2);
343   d = rint (d);
344 
345   return (int) d;
346 }
347 
348 static int
line_length(line_s * l)349 line_length (line_s * l)
350 {
351   if (l->s->x == l->e->x)
352     return djabs (l->s->y - l->e->y);
353   if (l->s->y == l->e->y)
354     return djabs (l->s->x - l->e->x);
355   return dist (l->s->x, l->s->y, l->e->x, l->e->y);
356 }
357 
358 static int
dist_ltp2(int dx,int y,int y1,int y2)359 dist_ltp2 (int dx, int y, int y1, int y2)
360 {
361   if (y1 > y2)
362     SWAP (y1, y2);
363   if (y < y1)
364     return dist (dx, y, 0, y1);
365   if (y > y2)
366     return dist (dx, y, 0, y2);
367   return djabs (dx);
368 }
369 
370 static int
intersecting_layers(int l1,int l2)371 intersecting_layers (int l1, int l2)
372 {
373   if (l1 == -1 || l2 == -1)
374     return 1;
375   if (l1 == l2)
376     return 1;
377   if (layer_groupings[l1] == layer_groupings[l2])
378     return 1;
379   return 0;
380 }
381 
382 static int
dist_line_to_point(line_s * l,corner_s * c)383 dist_line_to_point (line_s * l, corner_s * c)
384 {
385   double len, r, d;
386   /* We can do this quickly if l is vertical or horizontal.  */
387   if (l->s->x == l->e->x)
388     return dist_ltp2 (l->s->x - c->x, c->y, l->s->y, l->e->y);
389   if (l->s->y == l->e->y)
390     return dist_ltp2 (l->s->y - c->y, c->x, l->s->x, l->e->x);
391 
392   /* Do it the hard way.  See comments for IsPointOnLine() in search.c */
393   len = hypot (l->s->x - l->e->x, l->s->y - l->e->y);
394   if (len == 0)
395     return dist (l->s->x, l->s->y, c->x, c->y);
396   r =
397     (l->s->y - c->y) * (l->s->y - l->e->y) + (l->s->x - c->x) * (l->s->x -
398 								 l->e->x);
399   r /= len * len;
400   if (r < 0)
401     return dist (l->s->x, l->s->y, c->x, c->y);
402   if (r > 1)
403     return dist (l->e->x, l->e->y, c->x, c->y);
404   d =
405     (l->e->y - l->s->y) * (c->x * l->s->x) + (l->e->x - l->s->x) * (c->y -
406 								    l->s->y);
407   return (int) (d / len);
408 }
409 
410 static int
line_orient(line_s * l,corner_s * c)411 line_orient (line_s * l, corner_s * c)
412 {
413   int x1, y1, x2, y2;
414   if (c == l->s)
415     {
416       x1 = l->s->x;
417       y1 = l->s->y;
418       x2 = l->e->x;
419       y2 = l->e->y;
420     }
421   else
422     {
423       x1 = l->e->x;
424       y1 = l->e->y;
425       x2 = l->s->x;
426       y2 = l->s->y;
427     }
428   if (x1 == x2)
429     {
430       if (y1 < y2)
431 	return DOWN;
432       return UP;
433     }
434   else if (y1 == y2)
435     {
436       if (x1 < x2)
437 	return RIGHT;
438       return LEFT;
439     }
440   return DIAGONAL;
441 }
442 
443 #if 0
444 /* Not used */
445 static corner_s *
446 common_corner (line_s * l1, line_s * l2)
447 {
448   if (l1->s == l2->s || l1->s == l2->e)
449     return l1->s;
450   if (l1->e == l2->s || l1->e == l2->e)
451     return l1->e;
452   dj_abort ("common_corner: no common corner found\n");
453   return NULL;
454 }
455 #endif
456 
457 static corner_s *
other_corner(line_s * l,corner_s * c)458 other_corner (line_s * l, corner_s * c)
459 {
460   if (l->s == c)
461     return l->e;
462   if (l->e == c)
463     return l->s;
464   dj_abort ("other_corner: neither corner passed\n");
465   return NULL;
466 }
467 
468 static corner_s *
find_corner_if(int x,int y,int l)469 find_corner_if (int x, int y, int l)
470 {
471   corner_s *c;
472   for (c = corners; c; c = c->next)
473     {
474       if (DELETED (c))
475 	continue;
476       if (c->x != x || c->y != y)
477 	continue;
478       if (!(c->layer == -1 || intersecting_layers (c->layer, l)))
479 	continue;
480       return c;
481     }
482   return 0;
483 }
484 
485 static corner_s *
find_corner(int x,int y,int l)486 find_corner (int x, int y, int l)
487 {
488   corner_s *c;
489   for (c = corners; c; c = c->next)
490     {
491       if (DELETED (c))
492 	continue;
493       if (c->x != x || c->y != y)
494 	continue;
495       if (!(c->layer == -1 || intersecting_layers (c->layer, l)))
496 	continue;
497       return c;
498     }
499   c = (corner_s *) malloc (sizeof (corner_s));
500   c->next = corners;
501   corners = c;
502   c->x = x;
503   c->y = y;
504   c->net = 0;
505   c->via = 0;
506   c->pad = 0;
507   c->pin = 0;
508   c->layer = l;
509   c->n_lines = 0;
510   c->lines = (line_s **) malloc (INC * sizeof (line_s *));
511   return c;
512 }
513 
514 static void
add_line_to_corner(line_s * l,corner_s * c)515 add_line_to_corner (line_s * l, corner_s * c)
516 {
517   int n;
518   n = (c->n_lines + 1 + INC) & ~INC;
519   c->lines = (line_s **) realloc (c->lines, n * sizeof (line_s *));
520   c->lines[c->n_lines] = l;
521   c->n_lines++;
522   dprintf ("add_line_to_corner %#mD\n", c->x, c->y);
523 }
524 
525 static LineType *
create_pcb_line(int layer,int x1,int y1,int x2,int y2,int thick,int clear,FlagType flags)526 create_pcb_line (int layer, int x1, int y1, int x2, int y2,
527 		 int thick, int clear, FlagType flags)
528 {
529   char *from, *to;
530   LineType *nl;
531   LayerType *lyr = LAYER_PTR (layer);
532 
533   from = (char *) lyr->Line;
534   nl = CreateNewLineOnLayer (PCB->Data->Layer + layer,
535 			     x1, y1, x2, y2, thick, clear, flags);
536   AddObjectToCreateUndoList (LINE_TYPE, lyr, nl, nl);
537 
538   to = (char *) lyr->Line;
539   if (from != to)
540     {
541       line_s *lp;
542       for (lp = lines; lp; lp = lp->next)
543 	{
544 	  if (DELETED (lp))
545 	    continue;
546 	  if ((char *) (lp->line) >= from
547 	      && (char *) (lp->line) <= from + lyr->LineN * sizeof (LineType))
548 	    lp->line = (LineType *) ((char *) (lp->line) + (to - from));
549 	}
550     }
551   return nl;
552 }
553 
554 static void
new_line(corner_s * s,corner_s * e,int layer,LineType * example)555 new_line (corner_s * s, corner_s * e, int layer, LineType * example)
556 {
557   line_s *ls;
558 
559   if (layer >= max_copper_layer)
560     dj_abort ("layer %d\n", layer);
561 
562   if (example == NULL)
563     dj_abort ("NULL example passed to new_line()\n", layer);
564 
565   if (s->x == e->x && s->y == e->y)
566     return;
567 
568   ls = (line_s *) malloc (sizeof (line_s));
569   ls->next = lines;
570   lines = ls;
571   ls->is_pad = 0;
572   ls->s = s;
573   ls->e = e;
574   ls->layer = layer;
575 #if 0
576   if ((example->Point1.X == s->x && example->Point1.Y == s->y
577        && example->Point2.X == e->x && example->Point2.Y == e->y)
578       || (example->Point2.X == s->x && example->Point2.Y == s->y
579 	  && example->Point1.X == e->x && example->Point1.Y == e->y))
580     {
581       ls->line = example;
582     }
583   else
584 #endif
585     {
586       LineType *nl;
587       dprintf
588 	("New line \033[35m%#mD to %#mD from l%d t%#mS c%#mS f%s\033[0m\n",
589 	 s->x, s->y, e->x, e->y, layer, example->Thickness,
590 	 example->Clearance, flags_to_string (example->Flags, LINE_TYPE));
591       nl =
592 	create_pcb_line (layer, s->x, s->y, e->x, e->y, example->Thickness,
593 			 example->Clearance, example->Flags);
594 
595       if (!nl)
596 	dj_abort ("can't create new line!");
597       ls->line = nl;
598     }
599   add_line_to_corner (ls, s);
600   add_line_to_corner (ls, e);
601   check (s, ls);
602   check (e, ls);
603 }
604 
605 #if 0
606 /* Not used */
607 static int
608 c_orth_to (corner_s * c, line_s * l, int o)
609 {
610   int i, o2;
611   int rv = 0;
612   for (i = 0; i < c->n_lines; i++)
613     {
614       if (c->lines[i] == l)
615 	continue;
616       o2 = line_orient (c->lines[i], c);
617       if (ORIENT (o) == ORIENT (o2) || o2 == DIAGONAL)
618 	return 0;
619       rv++;
620     }
621   return rv;
622 }
623 #endif
624 
625 static line_s *
other_line(corner_s * c,line_s * l)626 other_line (corner_s * c, line_s * l)
627 {
628   int i;
629   line_s *rv = 0;
630   if (c->pin || c->pad || c->via)
631     return 0;
632   for (i = 0; i < c->n_lines; i++)
633     {
634       if (c->lines[i] == l)
635 	continue;
636       if (rv)
637 	return 0;
638       rv = c->lines[i];
639     }
640   return rv;
641 }
642 
643 static void
empty_rect(rect_s * rect)644 empty_rect (rect_s * rect)
645 {
646   rect->x1 = rect->y1 = INT_MAX;
647   rect->x2 = rect->y2 = INT_MIN;
648 }
649 
650 static void
add_point_to_rect(rect_s * rect,int x,int y,int w)651 add_point_to_rect (rect_s * rect, int x, int y, int w)
652 {
653   if (rect->x1 > x - w)
654     rect->x1 = x - w;
655   if (rect->x2 < x + w)
656     rect->x2 = x + w;
657   if (rect->y1 > y - w)
658     rect->y1 = y - w;
659   if (rect->y2 < y + w)
660     rect->y2 = y + w;
661 }
662 
663 static void
add_line_to_rect(rect_s * rect,line_s * l)664 add_line_to_rect (rect_s * rect, line_s * l)
665 {
666   add_point_to_rect (rect, l->s->x, l->s->y, 0);
667   add_point_to_rect (rect, l->e->x, l->e->y, 0);
668 }
669 
670 static int
pin_in_rect(rect_s * r,int x,int y,int w)671 pin_in_rect (rect_s * r, int x, int y, int w)
672 {
673   if (x < r->x1 && x + w < r->x1)
674     return 0;
675   if (x > r->x2 && x - w > r->x2)
676     return 0;
677   if (y < r->y1 && y + w < r->y1)
678     return 0;
679   if (y > r->y2 && y - w > r->y2)
680     return 0;
681   return 1;
682 }
683 
684 static int
line_in_rect(rect_s * r,line_s * l)685 line_in_rect (rect_s * r, line_s * l)
686 {
687   rect_s lr;
688   empty_rect (&lr);
689   add_point_to_rect (&lr, l->s->x, l->s->y, l->line->Thickness / 2);
690   add_point_to_rect (&lr, l->e->x, l->e->y, l->line->Thickness / 2);
691   dprintf ("line_in_rect %#mD-%#mD vs %#mD-%#mD\n",
692 	   r->x1, r->y1, r->x2, r->y2, lr.x1, lr.y1, lr.x2, lr.y2);
693   /* simple intersection of rectangles */
694   if (lr.x1 < r->x1)
695     lr.x1 = r->x1;
696   if (lr.x2 > r->x2)
697     lr.x2 = r->x2;
698   if (lr.y1 < r->y1)
699     lr.y1 = r->y1;
700   if (lr.y2 > r->y2)
701     lr.y2 = r->y2;
702   if (lr.x1 < lr.x2 && lr.y1 < lr.y2)
703     return 1;
704   return 0;
705 }
706 
707 static int
corner_radius(corner_s * c)708 corner_radius (corner_s * c)
709 {
710   int diam = 0;
711   int i;
712   if (c->pin)
713     diam = djmax (c->pin->Thickness, diam);
714   if (c->via)
715     diam = djmax (c->via->Thickness, diam);
716   for (i = 0; i < c->n_lines; i++)
717     if (c->lines[i]->line)
718       diam = djmax (c->lines[i]->line->Thickness, diam);
719   diam = (diam + 1) / 2;
720   return diam;
721 }
722 
723 #if 0
724 /* Not used */
725 static int
726 corner_layer (corner_s * c)
727 {
728   if (c->pin || c->via)
729     return -1;
730   if (c->n_lines < 1)
731     return -1;
732   return c->lines[0]->layer;
733 }
734 #endif
735 
736 static void
add_corner_to_rect_if(rect_s * rect,corner_s * c,rect_s * e)737 add_corner_to_rect_if (rect_s * rect, corner_s * c, rect_s * e)
738 {
739   int diam = corner_radius (c);
740   if (!pin_in_rect (e, c->x, c->y, diam))
741     return;
742   if (c->x < e->x1 && c->y < e->y1 && dist (c->x, c->y, e->x1, e->y1) > diam)
743     return;
744   if (c->x > e->x2 && c->y < e->y1 && dist (c->x, c->y, e->x2, e->y1) > diam)
745     return;
746   if (c->x < e->x1 && c->y > e->y2 && dist (c->x, c->y, e->x1, e->y2) > diam)
747     return;
748   if (c->x > e->x2 && c->y > e->y2 && dist (c->x, c->y, e->x2, e->y2) > diam)
749     return;
750 
751   /*pcb_printf("add point %#mD diam %#mS\n", c->x, c->y, diam); */
752   add_point_to_rect (rect, c->x, c->y, diam);
753 }
754 
755 static void
remove_line(line_s * l)756 remove_line (line_s * l)
757 {
758   int i, j;
759   LayerType *layer = &(PCB->Data->Layer[l->layer]);
760 
761   check (0, 0);
762 
763   if (l->line)
764     RemoveLine (layer, l->line);
765 
766   DELETE (l);
767 
768   for (i = 0, j = 0; i < l->s->n_lines; i++)
769     if (l->s->lines[i] != l)
770       l->s->lines[j++] = l->s->lines[i];
771   l->s->n_lines = j;
772 
773   for (i = 0, j = 0; i < l->e->n_lines; i++)
774     if (l->e->lines[i] != l)
775       l->e->lines[j++] = l->e->lines[i];
776   l->e->n_lines = j;
777   check (0, 0);
778 }
779 
780 static void
move_line_to_layer(line_s * l,int layer)781 move_line_to_layer (line_s * l, int layer)
782 {
783   LayerType *ls, *ld;
784 
785   ls = LAYER_PTR (l->layer);
786   ld = LAYER_PTR (layer);
787 
788   MoveObjectToLayer (LINE_TYPE, ls, l->line, 0, ld, 0);
789   l->layer = layer;
790 }
791 
792 static void
remove_via_at(corner_s * c)793 remove_via_at (corner_s * c)
794 {
795   RemoveObject (VIA_TYPE, c->via, 0, 0);
796   c->via = 0;
797 }
798 
799 static void
remove_corner(corner_s * c2)800 remove_corner (corner_s * c2)
801 {
802   corner_s *c;
803   dprintf ("remove corner %s\n", corner_name (c2));
804   if (corners == c2)
805     corners = c2->next;
806   for (c = corners; c; c = c->next)
807     {
808       if (DELETED (c))
809 	continue;
810       if (c->next == c2)
811 	c->next = c2->next;
812     }
813   if (next_corner == c2)
814     next_corner = c2->next;
815   free (c2->lines);
816   c2->lines = 0;
817   DELETE (c2);
818 }
819 
820 static void
merge_corners(corner_s * c1,corner_s * c2)821 merge_corners (corner_s * c1, corner_s * c2)
822 {
823   int i;
824   if (c1 == c2)
825     abort ();
826   dprintf ("merge corners %s %s\n", corner_name (c1), corner_name (c2));
827   for (i = 0; i < c2->n_lines; i++)
828     {
829       add_line_to_corner (c2->lines[i], c1);
830       if (c2->lines[i]->s == c2)
831 	c2->lines[i]->s = c1;
832       if (c2->lines[i]->e == c2)
833 	c2->lines[i]->e = c1;
834     }
835   if (c1->via && c2->via)
836     remove_via_at (c2);
837   else if (c2->via)
838     c1->via = c2->via;
839   if (c2->pad)
840     c1->pad = c2->pad;
841   if (c2->pin)
842     c1->pin = c2->pin;
843   if (c2->layer != c1->layer)
844     c1->layer = -1;
845 
846   remove_corner (c2);
847 }
848 
849 static void
move_corner(corner_s * c,int x,int y)850 move_corner (corner_s * c, int x, int y)
851 {
852   PinType *via;
853   int i;
854   corner_s *pad;
855 
856   check (c, 0);
857   if (c->pad || c->pin)
858     dj_abort ("move_corner: has pin or pad\n");
859   dprintf ("move_corner %p from %#mD to %#mD\n", (void *) c, c->x, c->y, x, y);
860   pad = find_corner_if (x, y, c->layer);
861   c->x = x;
862   c->y = y;
863   via = c->via;
864   if (via)
865     {
866       MoveObject (VIA_TYPE, via, via, via, x - via->X, y - via->Y);
867       dprintf ("via move %#mD to %#mD\n", via->X, via->Y, x, y);
868     }
869   for (i = 0; i < c->n_lines; i++)
870     {
871       LineType *tl = c->lines[i]->line;
872       if (tl)
873 	{
874 	  if (c->lines[i]->s == c)
875 	    {
876 	      MoveObject (LINEPOINT_TYPE, LAYER_PTR (c->lines[i]->layer), tl,
877 			  &tl->Point1, x - (tl->Point1.X),
878 			  y - (tl->Point1.Y));
879 	    }
880 	  else
881 	    {
882 	      MoveObject (LINEPOINT_TYPE, LAYER_PTR (c->lines[i]->layer), tl,
883 			  &tl->Point2, x - (tl->Point2.X),
884 			  y - (tl->Point2.Y));
885 	    }
886 	  dprintf ("Line %p moved to %#mD %#mD\n", (void *) tl,
887 		   tl->Point1.X, tl->Point1.Y, tl->Point2.X, tl->Point2.Y);
888 	}
889     }
890   if (pad && pad != c)
891     merge_corners (c, pad);
892   else
893     for (i = 0; i < c->n_lines; i++)
894       {
895 	if (c->lines[i]->s->x == c->lines[i]->e->x
896 	    && c->lines[i]->s->y == c->lines[i]->e->y)
897 	  {
898 	    corner_s *c2 = other_corner (c->lines[i], c);
899 	    dprintf ("move_corner: removing line %#mD %#mD %p %p\n",
900 		     c->x, c->y, c2->x, c2->y, (void *) c, (void *) c2);
901 
902 	    remove_line (c->lines[i]);
903 	    if (c != c2)
904 	      merge_corners (c, c2);
905 	    check (c, 0);
906 	    i--;
907 	    break;
908 	  }
909       }
910   gui->progress (0, 0, 0);
911   check (c, 0);
912 }
913 
914 static int
any_line_selected()915 any_line_selected ()
916 {
917   line_s *l;
918   for (l = lines; l; l = l->next)
919     {
920       if (DELETED (l))
921 	continue;
922       if (l->line && selected (l->line))
923 	return 1;
924     }
925   return 0;
926 }
927 
928 static int
trim_step(int s,int l1,int l2)929 trim_step (int s, int l1, int l2)
930 {
931   dprintf ("trim %d %d %d\n", s, l1, l2);
932   if (s > l1)
933     s = l1;
934   if (s > l2)
935     s = l2;
936   if (s != l1 && s != l2)
937     s = gridsnap (s);
938   return s;
939 }
940 
941 static int canonicalize_line (line_s * l);
942 
943 static int
split_line(line_s * l,corner_s * c)944 split_line (line_s * l, corner_s * c)
945 {
946   int i;
947   LineType *pcbline;
948   line_s *ls;
949 
950   if (!intersecting_layers (l->layer, c->layer))
951     return 0;
952   if (l->is_pad)
953     return 0;
954   if (c->pad)
955     {
956       dprintf ("split on pad!\n");
957       if (l->s->pad == c->pad || l->e->pad == c->pad)
958 	return 0;
959       dprintf ("splitting...\n");
960     }
961 
962   check (c, l);
963   pcbline = create_pcb_line (l->layer,
964 			     c->x, c->y, l->e->x, l->e->y,
965 			     l->line->Thickness, l->line->Clearance,
966 			     l->line->Flags);
967   if (pcbline == 0)
968     return 0;			/* already a line there */
969 
970   check (c, l);
971 
972   dprintf ("split line from %#mD to %#mD at %#mD\n",
973 	   l->s->x, l->s->y, l->e->x, l->e->y, c->x, c->y);
974   ls = (line_s *) malloc (sizeof (line_s));
975 
976   ls->next = lines;
977   lines = ls;
978   ls->is_pad = 0;
979   ls->s = c;
980   ls->e = l->e;
981   ls->line = pcbline;
982   ls->layer = l->layer;
983   for (i = 0; i < l->e->n_lines; i++)
984     if (l->e->lines[i] == l)
985       l->e->lines[i] = ls;
986   l->e = c;
987   add_line_to_corner (l, c);
988   add_line_to_corner (ls, c);
989 
990   MoveObject (LINEPOINT_TYPE, LAYER_PTR (l->layer), l->line, &l->line->Point2,
991 	      c->x - (l->line->Point2.X), c->y - (l->line->Point2.Y));
992 
993   return 1;
994 }
995 
996 static int
canonicalize_line(line_s * l)997 canonicalize_line (line_s * l)
998 {
999   /* This could be faster */
1000   corner_s *c;
1001   if (l->s->x == l->e->x)
1002     {
1003       int y1 = l->s->y;
1004       int y2 = l->e->y;
1005       int x1 = l->s->x - l->line->Thickness / 2;
1006       int x2 = l->s->x + l->line->Thickness / 2;
1007       if (y1 > y2)
1008 	{
1009 	  int t = y1;
1010 	  y1 = y2;
1011 	  y2 = t;
1012 	}
1013       for (c = corners; c; c = c->next)
1014 	{
1015 	  if (DELETED (c))
1016 	    continue;
1017 	  if ((y1 < c->y && c->y < y2)
1018 	      && intersecting_layers (l->layer, c->layer))
1019 	    {
1020 	      if (c->x != l->s->x
1021 		  && c->x < x2 && c->x > x1 && !(c->pad || c->pin))
1022 		{
1023 		  move_corner (c, l->s->x, c->y);
1024 		}
1025 	      if (c->x == l->s->x)
1026 		{
1027 		  /* FIXME: if the line is split, we have to re-canonicalize
1028 		     both segments. */
1029 		  return split_line (l, c);
1030 		}
1031 	    }
1032 	}
1033     }
1034   else if (l->s->y == l->e->y)
1035     {
1036       int x1 = l->s->x;
1037       int x2 = l->e->x;
1038       int y1 = l->s->y - l->line->Thickness / 2;
1039       int y2 = l->s->y + l->line->Thickness / 2;
1040       if (x1 > x2)
1041 	{
1042 	  int t = x1;
1043 	  x1 = x2;
1044 	  x2 = t;
1045 	}
1046       for (c = corners; c; c = c->next)
1047 	{
1048 	  if (DELETED (c))
1049 	    continue;
1050 	  if ((x1 < c->x && c->x < x2)
1051 	      && intersecting_layers (l->layer, c->layer))
1052 	    {
1053 	      if (c->y != l->s->y
1054 		  && c->y < y2 && c->y > y1 && !(c->pad || c->pin))
1055 		{
1056 		  move_corner (c, c->x, l->s->y);
1057 		}
1058 	      if (c->y == l->s->y)
1059 		{
1060 		  /* FIXME: Likewise.  */
1061 		  return split_line (l, c);
1062 		}
1063 	    }
1064 	}
1065     }
1066   else
1067     {
1068       /* diagonal lines.  Let's try to split them at pins/vias
1069          anyway.  */
1070       int x1 = l->s->x;
1071       int x2 = l->e->x;
1072       int y1 = l->s->y;
1073       int y2 = l->e->y;
1074       if (x1 > x2)
1075 	{
1076 	  int t = x1;
1077 	  x1 = x2;
1078 	  x2 = t;
1079 	}
1080       if (y1 > y2)
1081 	{
1082 	  int t = y1;
1083 	  y1 = y2;
1084 	  y2 = t;
1085 	}
1086       for (c = corners; c; c = c->next)
1087 	{
1088 	  if (DELETED (c))
1089 	    continue;
1090 	  if (!c->via && !c->pin)
1091 	    continue;
1092 	  if ((x1 < c->x && c->x < x2)
1093 	      && (y1 < c->y && c->y < y2)
1094 	      && intersecting_layers (l->layer, c->layer))
1095 	    {
1096 	      int th = c->pin ? c->pin->Thickness : c->via->Thickness;
1097 	      th /= 2;
1098 	      if (dist (l->s->x, l->s->y, c->x, c->y) > th
1099 		  && dist (l->e->x, l->e->y, c->x, c->y) > th
1100 		  && PinLineIntersect (c->pin ? c->pin : c->via, l->line))
1101 		{
1102 		  return split_line (l, c);
1103 		}
1104 	    }
1105 	}
1106     }
1107   return 0;
1108 }
1109 
1110 /*!
1111  * \brief Make sure all vias are at line end points.
1112  */
1113 static int
canonicalize_lines()1114 canonicalize_lines ()
1115 {
1116   int changes = 0;
1117   int count;
1118   line_s *l;
1119   while (1)
1120     {
1121       count = 0;
1122       for (l = lines; l; l = l->next)
1123 	{
1124 	  if (DELETED (l))
1125 	    continue;
1126 	  count += canonicalize_line (l);
1127 	}
1128       changes += count;
1129       if (count == 0)
1130 	break;
1131     }
1132   return changes;
1133 }
1134 
1135 static int
simple_optimize_corner(corner_s * c)1136 simple_optimize_corner (corner_s * c)
1137 {
1138   int i;
1139   int rv = 0;
1140 
1141   check (c, 0);
1142   if (c->via)
1143     {
1144       /* see if no via is needed */
1145       if (selected (c->via))
1146 	dprintf ("via check: line[0] layer %d at %#mD nl %d\n",
1147 		 c->lines[0]->layer, c->x, c->y, c->n_lines);
1148       /* We can't delete vias that connect to power planes, or vias
1149 	 that aren't tented (assume they're test points).  */
1150       if (!TEST_ANY_THERMS (c->via)
1151 	  && c->via->Mask == 0)
1152 	{
1153 	  for (i = 1; i < c->n_lines; i++)
1154 	    {
1155 	      if (selected (c->via))
1156 		dprintf ("           line[%d] layer %d %#mD to %#mD\n",
1157 			 i, c->lines[i]->layer,
1158 			 c->lines[i]->s->x, c->lines[i]->s->y,
1159 			 c->lines[i]->e->x, c->lines[i]->e->y);
1160 	      if (c->lines[i]->layer != c->lines[0]->layer)
1161 		break;
1162 	    }
1163 	  if (i == c->n_lines)
1164 	    {
1165 	      if (selected (c->via))
1166 		dprintf ("           remove it\n");
1167 	      remove_via_at (c);
1168 	      rv++;
1169 	    }
1170 	}
1171     }
1172 
1173   check (c, 0);
1174   if (c->n_lines == 2 && !c->via)
1175     {
1176       /* see if it is an unneeded corner */
1177       int o = line_orient (c->lines[0], c);
1178       corner_s *c2 = other_corner (c->lines[1], c);
1179       corner_s *c0 = other_corner (c->lines[0], c);
1180       if (o == line_orient (c->lines[1], c2) && o != DIAGONAL)
1181 	{
1182 	  dprintf ("straight %#mD to %#mD to %#mD\n",
1183 		   c0->x, c0->y, c->x, c->y, c2->x, c2->y);
1184 	  if (selected (c->lines[0]->line))
1185 	    SET_FLAG (SELECTEDFLAG, c->lines[1]->line);
1186 	  if (selected (c->lines[1]->line))
1187 	    SET_FLAG (SELECTEDFLAG, c->lines[0]->line);
1188 	  move_corner (c, c2->x, c2->y);
1189 	}
1190     }
1191   check (c, 0);
1192   if (c->n_lines == 1 && !c->via)
1193     {
1194       corner_s *c0 = other_corner (c->lines[0], c);
1195       if (abs(c->x - c0->x) + abs(c->y - c0->y) <= LONGEST_FRECKLE)
1196 	{
1197           /*
1198            * Remove this line, as it is a "freckle".  A freckle is an extremely
1199            * short line (around 0.01 thou) that is unconnected at one end.
1200            * Freckles are almost insignificantly small, but are annoying as
1201            * they prevent the mitering optimiser from working.
1202            * Freckles sometimes arise because of a bug in the autorouter that
1203            * causes it to create small overshoots (typically 0.01 thou) at the
1204            * intersections of vertical and horizontal lines. These overshoots
1205            * are converted to freckles as a side effect of canonicalize_line().
1206            * Note that canonicalize_line() is not at fault, the bug is in the
1207            * autorouter creating overshoots.
1208            * The autorouter bug arose some time between the 20080202 and 20091103
1209            * releases.
1210            * This code is probably worth keeping even when the autorouter bug is
1211            * fixed, as "freckles" could conceivably arise in other ways.
1212            */
1213 	  dprintf ("freckle %#mD to %#mD\n", c->x, c->y, c0->x, c0->y);
1214 	  move_corner (c, c0->x, c0->y);
1215 	}
1216     }
1217   check (c, 0);
1218   return rv;
1219 }
1220 
1221 /* We always run these */
1222 static int
simple_optimizations()1223 simple_optimizations ()
1224 {
1225   corner_s *c;
1226   int rv = 0;
1227 
1228   /* Look for corners that aren't */
1229   for (c = corners; c; c = c->next)
1230     {
1231       if (DELETED (c))
1232 	continue;
1233       if (c->pad || c->pin)
1234 	continue;
1235       rv += simple_optimize_corner (c);
1236     }
1237   return rv;
1238 }
1239 
1240 static int
is_hole(corner_s * c)1241 is_hole (corner_s * c)
1242 {
1243   return c->pin || c->pad || c->via;
1244 }
1245 
1246 static int
orthopull_1(corner_s * c,int fdir,int rdir,int any_sel)1247 orthopull_1 (corner_s * c, int fdir, int rdir, int any_sel)
1248 {
1249   static corner_s **cs = 0;
1250   static int cm = 0;
1251   static line_s **ls = 0;
1252   static int lm = 0;
1253   int i, li, ln, cn, snap;
1254   line_s *l = 0;
1255   corner_s *c2, *cb;
1256   int adir = 0, sdir = 0, pull;
1257   int saw_sel = 0, saw_auto = 0;
1258   int max, len = 0, r1 = 0, r2;
1259   rect_s rr;
1260   int edir = 0, done;
1261 
1262   if (cs == 0)
1263     {
1264       cs = (corner_s **) malloc (10 * sizeof (corner_s));
1265       cm = 10;
1266       ls = (line_s **) malloc (10 * sizeof (line_s));
1267       lm = 10;
1268     }
1269 
1270   for (i = 0; i < c->n_lines; i++)
1271     {
1272       int o = line_orient (c->lines[i], c);
1273       if (o == rdir)
1274 	return 0;
1275     }
1276 
1277   switch (fdir)
1278     {
1279     case RIGHT:
1280       adir = DOWN;
1281       sdir = UP;
1282       break;
1283     case DOWN:
1284       adir = RIGHT;
1285       sdir = LEFT;
1286       break;
1287     default:
1288       dj_abort ("fdir not right or down\n");
1289     }
1290 
1291   c2 = c;
1292   cn = 0;
1293   ln = 0;
1294   pull = 0;
1295   while (c2)
1296     {
1297       if (c2->pad || c2->pin || c2->n_lines < 2)
1298 	return 0;
1299       if (cn >= cm)
1300 	{
1301 	  cm = cn + 10;
1302 	  cs = (corner_s **) realloc (cs, cm * sizeof (corner_s *));
1303 	}
1304       cs[cn++] = c2;
1305       r2 = corner_radius (c2);
1306       if (r1 < r2)
1307 	r1 = r2;
1308       l = 0;
1309       for (i = 0; i < c2->n_lines; i++)
1310 	{
1311 	  int o = line_orient (c2->lines[i], c2);
1312 	  if (o == DIAGONAL)
1313 	    return 0;
1314 	  if (o == fdir)
1315 	    {
1316 	      if (l)
1317 		return 0;	/* we don't support overlapping lines yet */
1318 	      l = c2->lines[i];
1319 	    }
1320 	  if (o == rdir && c2->lines[i] != ls[ln - 1])
1321 	    return 0;		/* likewise */
1322 	  if (o == adir)
1323 	    pull++;
1324 	  if (o == sdir)
1325 	    pull--;
1326 	}
1327       if (!l)
1328 	break;
1329       if (selected (l->line))
1330 	saw_sel = 1;
1331       if (autorouted (l->line))
1332 	saw_auto = 1;
1333       if (ln >= lm)
1334 	{
1335 	  lm = ln + 10;
1336 	  ls = (line_s **) realloc (ls, lm * sizeof (line_s *));
1337 	}
1338       ls[ln++] = l;
1339       c2 = other_corner (l, c2);
1340     }
1341   if (cn < 2 || pull == 0)
1342     return 0;
1343   if (any_sel && !saw_sel)
1344     return 0;
1345   if (!any_sel && autorouted_only && !saw_auto)
1346     return 0;
1347 
1348   /* Ok, now look for other blockages. */
1349 
1350   empty_rect (&rr);
1351   add_point_to_rect (&rr, c->x, c->y, corner_radius (c));
1352   add_point_to_rect (&rr, c2->x, c2->y, corner_radius (c2));
1353 
1354   if (fdir == RIGHT && pull < 0)
1355     edir = UP;
1356   else if (fdir == RIGHT && pull > 0)
1357     edir = DOWN;
1358   else if (fdir == DOWN && pull < 0)
1359     edir = LEFT;
1360   else if (fdir == DOWN && pull > 0)
1361     edir = RIGHT;
1362 
1363   max = -1;
1364   for (i = 0; i < cn; i++)
1365     for (li = 0; li < cs[i]->n_lines; li++)
1366       {
1367 	if (line_orient (cs[i]->lines[li], cs[i]) != edir)
1368 	  continue;
1369 	len = line_length (cs[i]->lines[li]);
1370 	if (max > len || max == -1)
1371 	  max = len;
1372       }
1373   dprintf ("c %s %4#mD  cn %d pull %3d  max %4#mS\n",
1374 	   fdir == RIGHT ? "right" : "down ", c->x, c->y, cn, pull, max);
1375 
1376   switch (edir)
1377     {
1378     case UP:
1379       rr.y1 = c->y - r1 - max;
1380       break;
1381     case DOWN:
1382       rr.y2 = c->y + r1 + max;
1383       break;
1384     case LEFT:
1385       rr.x1 = c->x - r1 - max;
1386       break;
1387     case RIGHT:
1388       rr.x2 = c->x + r1 + max;
1389       break;
1390     }
1391   rr.x1 -= SB + 1;
1392   rr.x2 += SB + 1;
1393   rr.y1 -= SB + 1;
1394   rr.y2 += SB + 1;
1395 
1396   snap = 0;
1397   for (cb = corners; cb; cb = cb->next)
1398     {
1399       int sep;
1400       if (DELETED (cb))
1401 	continue;
1402       r1 = corner_radius (cb);
1403       if (cb->net == c->net && !cb->pad)
1404 	continue;
1405       if (!pin_in_rect (&rr, cb->x, cb->y, r1))
1406 	continue;
1407       switch (edir)
1408 	{
1409 #define ECHK(X,Y,LT) \
1410 	  for (i=0; i<cn; i++) \
1411 	    { \
1412 	      if (!intersecting_layers(cs[i]->layer, cb->layer)) \
1413 		continue; \
1414 	      r2 = corner_radius(cs[i]); \
1415 	      if (cb->X + r1 <= cs[i]->X - r2 - SB - 1) \
1416 		continue; \
1417 	      if (cb->X - r1 >= cs[i]->X + r2 + SB + 1) \
1418 		continue; \
1419 	      if (cb->Y LT cs[i]->Y) \
1420 		continue; \
1421 	      sep = djabs(cb->Y - cs[i]->Y) - r1 - r2 - SB - 1; \
1422 	      if (max > sep) \
1423 		{ max = sep; snap = 1; }\
1424 	    } \
1425 	  for (i=0; i<ln; i++) \
1426 	    { \
1427 	      if (!intersecting_layers(ls[i]->layer, cb->layer)) \
1428 		continue; \
1429 	      if (cb->X <= cs[i]->X || cb->X >= cs[i+1]->X) \
1430 		continue; \
1431 	      sep = (djabs(cb->Y - cs[i]->Y) - ls[i]->line->Thickness/2 \
1432 		     - r1 - SB - 1); \
1433 	      if (max > sep) \
1434 		{ max = sep; snap = 1; }\
1435 	    }
1436 	case UP:
1437 	  ECHK (x, y, >=);
1438 	  break;
1439 	case DOWN:
1440 	  ECHK (x, y, <=);
1441 	  break;
1442 	case LEFT:
1443 	  ECHK (y, x, >=);
1444 	  break;
1445 	case RIGHT:
1446 	  ECHK (y, x, <=);
1447 	  break;
1448 	}
1449     }
1450 
1451   /* We must now check every line segment against our corners.  */
1452   for (l = lines; l; l = l->next)
1453     {
1454       int o, x1, x2, y1, y2;
1455       if (DELETED (l))
1456 	continue;
1457       dprintf ("check line %#mD to %#mD\n", l->s->x, l->s->y, l->e->x, l->e->y);
1458       if (l->s->net == c->net)
1459 	{
1460 	  dprintf ("  same net\n");
1461 	  continue;
1462 	}
1463       o = line_orient (l, 0);
1464       /* We don't need to check perpendicular lines, because their
1465          corners already take care of it.  */
1466       if ((fdir == RIGHT && (o == UP || o == DOWN))
1467 	  || (fdir == DOWN && (o == RIGHT || o == LEFT)))
1468 	{
1469 	  dprintf ("  perpendicular\n");
1470 	  continue;
1471 	}
1472 
1473       /* Choose so that x1,y1 is closest to corner C */
1474       if ((fdir == RIGHT && l->s->x < l->e->x)
1475 	  || (fdir == DOWN && l->s->y < l->e->y))
1476 	{
1477 	  x1 = l->s->x;
1478 	  y1 = l->s->y;
1479 	  x2 = l->e->x;
1480 	  y2 = l->e->y;
1481 	}
1482       else
1483 	{
1484 	  x1 = l->e->x;
1485 	  y1 = l->e->y;
1486 	  x2 = l->s->x;
1487 	  y2 = l->s->y;
1488 	}
1489 
1490       /* Eliminate all lines outside our range */
1491       if ((fdir == RIGHT && (x2 < c->x || x1 > c2->x))
1492 	  || (fdir == DOWN && (y2 < c->y || y1 > c2->y)))
1493 	{
1494 	  dprintf ("  outside our range\n");
1495 	  continue;
1496 	}
1497 
1498       /* Eliminate all lines on the wrong side of us */
1499       if ((edir == UP && y1 > c->y && y2 > c->y)
1500 	  || (edir == DOWN && y1 < c->y && y2 < c->y)
1501 	  || (edir == LEFT && x1 > c->x && x2 > c->x)
1502 	  || (edir == RIGHT && x1 < c->x && x2 < c->x))
1503 	{
1504 	  dprintf ("  wrong side\n");
1505 	  continue;
1506 	}
1507 
1508       /* For now, cheat on diagonals */
1509       switch (edir)
1510 	{
1511 	case RIGHT:
1512 	  if (x1 > x2)
1513 	    x1 = x2;
1514 	  break;
1515 	case LEFT:
1516 	  if (x1 < x2)
1517 	    x1 = x2;
1518 	  break;
1519 	case DOWN:
1520 	  if (y1 > y2)
1521 	    y1 = y2;
1522 	  break;
1523 	case UP:
1524 	  if (y1 < y2)
1525 	    y1 = y2;
1526 	  break;
1527 	}
1528 
1529       /* Ok, now see how far we can get for each of our corners. */
1530       for (i = 0; i < cn; i++)
1531 	{
1532 	  int r = l->line->Thickness + SB + corner_radius (cs[i]) + 1;
1533 	  int len = 0;
1534 	  if ((fdir == RIGHT && (x2 < cs[i]->x || x1 > cs[i]->x))
1535 	      || (fdir == DOWN && (y2 < cs[i]->y || y1 > cs[i]->y)))
1536 	    continue;
1537 	  if (!intersecting_layers (cs[i]->layer, l->layer))
1538 	    continue;
1539 	  switch (edir)
1540 	    {
1541 	    case RIGHT:
1542 	      len = x1 - c->x;
1543 	      break;
1544 	    case LEFT:
1545 	      len = c->x - x1;
1546 	      break;
1547 	    case DOWN:
1548 	      len = y1 - c->y;
1549 	      break;
1550 	    case UP:
1551 	      len = c->y - y1;
1552 	      break;
1553 	    }
1554 	  len -= r;
1555 	  dprintf ("  len is %#mS vs corner at %#mD\n", len, cs[i]->x, cs[i]->y);
1556 	  if (len <= 0)
1557 	    return 0;
1558 	  if (max > len)
1559 	    max = len;
1560 	}
1561 
1562     }
1563 
1564   /* We must make sure that if a segment isn't being completely
1565      removed, that any vias and/or pads don't overlap.  */
1566   done = 0;
1567   while (!done)
1568     {
1569       done = 1;
1570       for (i = 0; i < cn; i++)
1571 	for (li = 0; li < cs[i]->n_lines; li++)
1572 	  {
1573 	    line_s *l = cs[i]->lines[li];
1574 	    corner_s *oc = other_corner (l, cs[i]);
1575 	    if (line_orient (l, cs[i]) != edir)
1576 	      continue;
1577 	    len = line_length (l);
1578 	    if (!oc->pad || !cs[i]->via)
1579 	      {
1580 		if (!is_hole (l->s) || !is_hole (l->e))
1581 		  continue;
1582 		if (len == max)
1583 		  continue;
1584 	      }
1585 	    len -= corner_radius (l->s);
1586 	    len -= corner_radius (l->e);
1587 	    len -= SB + 1;
1588 	    if (max > len)
1589 	      {
1590 		max = len;
1591 		done = 0;
1592 	      }
1593 	  }
1594     }
1595 
1596   if (max <= 0)
1597     return 0;
1598   switch (edir)
1599     {
1600     case UP:
1601       len = c->y - max;
1602       break;
1603     case DOWN:
1604       len = c->y + max;
1605       break;
1606     case LEFT:
1607       len = c->x - max;
1608       break;
1609     case RIGHT:
1610       len = c->x + max;
1611       break;
1612     }
1613   if (snap && max > Settings.Grid)
1614     {
1615       if (pull < 0)
1616 	len += Settings.Grid - 1;
1617       len = gridsnap (len);
1618     }
1619   if ((fdir == RIGHT && len == cs[0]->y) || (fdir == DOWN && len == cs[0]->x))
1620     return 0;
1621   for (i = 0; i < cn; i++)
1622     {
1623       if (fdir == RIGHT)
1624 	{
1625 	  max = len - cs[i]->y;
1626 	  move_corner (cs[i], cs[i]->x, len);
1627 	}
1628       else
1629 	{
1630 	  max = len - cs[i]->x;
1631 	  move_corner (cs[i], len, cs[i]->y);
1632 	}
1633     }
1634   return max * pull;
1635 }
1636 
1637 /*!
1638  * \brief Look for straight runs which could be moved to reduce total
1639  * trace length.
1640  */
1641 static int
orthopull()1642 orthopull ()
1643 {
1644   int any_sel = any_line_selected ();
1645   corner_s *c;
1646   int rv = 0;
1647 
1648   for (c = corners; c;)
1649     {
1650       if (DELETED (c))
1651 	continue;
1652       if (c->pin || c->pad)
1653 	{
1654 	  c = c->next;
1655 	  continue;
1656 	}
1657       next_corner = c;
1658       rv += orthopull_1 (c, RIGHT, LEFT, any_sel);
1659       if (c != next_corner)
1660 	{
1661 	  c = next_corner;
1662 	  continue;
1663 	}
1664       rv += orthopull_1 (c, DOWN, UP, any_sel);
1665       if (c != next_corner)
1666 	{
1667 	  c = next_corner;
1668 	  continue;
1669 	}
1670       c = c->next;
1671     }
1672   if (rv)
1673     pcb_printf ("orthopull: %ml mils saved\n", rv);
1674   return rv;
1675 }
1676 
1677 /*!
1678  * \brief Look for "U" shaped traces we can shorten (or eliminate).
1679  */
1680 static int
debumpify()1681 debumpify ()
1682 {
1683   int rv = 0;
1684   int any_selected = any_line_selected ();
1685   line_s *l, *l1, *l2;
1686   corner_s *c, *c1, *c2;
1687   rect_s rr, rp;
1688   int o, o1, o2, step, w;
1689   for (l = lines; l; l = l->next)
1690     {
1691       if (DELETED (l))
1692 	continue;
1693       if (!l->line)
1694 	continue;
1695       if (any_selected && !selected (l->line))
1696 	continue;
1697       if (!any_selected && autorouted_only && !autorouted (l->line))
1698 	continue;
1699       if (l->s->pin || l->s->pad || l->e->pin || l->e->pad)
1700 	continue;
1701       o = line_orient (l, 0);
1702       if (o == DIAGONAL)
1703 	continue;
1704       l1 = other_line (l->s, l);
1705       if (!l1)
1706 	continue;
1707       o1 = line_orient (l1, l->s);
1708       l2 = other_line (l->e, l);
1709       if (!l2)
1710 	continue;
1711       o2 = line_orient (l2, l->e);
1712       if (ORIENT (o) == ORIENT (o1) || o1 != o2 || o1 == DIAGONAL)
1713 	continue;
1714 
1715       dprintf ("\nline: %#mD to %#mD\n", l->s->x, l->s->y, l->e->x, l->e->y);
1716       w = l->line->Thickness / 2 + SB + 1;
1717       empty_rect (&rr);
1718       add_line_to_rect (&rr, l1);
1719       add_line_to_rect (&rr, l2);
1720       if (rr.x1 != l->s->x && rr.x1 != l->e->x)
1721 	rr.x1 -= w;
1722       if (rr.x2 != l->s->x && rr.x2 != l->e->x)
1723 	rr.x2 += w;
1724       if (rr.y1 != l->s->y && rr.y1 != l->e->y)
1725 	rr.y1 -= w;
1726       if (rr.y2 != l->s->y && rr.y2 != l->e->y)
1727 	rr.y2 += w;
1728       dprintf ("range: x %#mS..%#mS y %#mS..%#mS\n", rr.x1, rr.x2, rr.y1, rr.y2);
1729 
1730       c1 = other_corner (l1, l->s);
1731       c2 = other_corner (l2, l->e);
1732 
1733       empty_rect (&rp);
1734       for (c = corners; c; c = c->next)
1735 	{
1736 	  if (DELETED (c))
1737 	    continue;
1738 	  if (c->net != l->s->net
1739 	      && intersecting_layers (c->layer, l->s->layer))
1740 	    add_corner_to_rect_if (&rp, c, &rr);
1741 	}
1742       if (rp.x1 == INT_MAX)
1743 	{
1744 	  rp.x1 = rr.x2;
1745 	  rp.x2 = rr.x1;
1746 	  rp.y1 = rr.y2;
1747 	  rp.y2 = rr.y1;
1748 	}
1749       dprintf ("pin r: x %#mS..%#mS y %#mS..%#mS\n", rp.x1, rp.x2, rp.y1, rp.y2);
1750 
1751       switch (o1)
1752 	{
1753 	case LEFT:
1754 	  step = l->s->x - rp.x2 - w;
1755 	  step = gridsnap (step);
1756 	  if (step > l->s->x - c1->x)
1757 	    step = l->s->x - c1->x;
1758 	  if (step > l->s->x - c2->x)
1759 	    step = l->s->x - c2->x;
1760 	  if (step > 0)
1761 	    {
1762 	      dprintf ("left step %#mS at %#mD\n", step, l->s->x, l->s->y);
1763 	      move_corner (l->s, l->s->x - step, l->s->y);
1764 	      move_corner (l->e, l->e->x - step, l->e->y);
1765 	      rv += step;
1766 	    }
1767 	  break;
1768 	case RIGHT:
1769 	  step = rp.x1 - l->s->x - w;
1770 	  step = gridsnap (step);
1771 	  if (step > c1->x - l->s->x)
1772 	    step = c1->x - l->s->x;
1773 	  if (step > c2->x - l->s->x)
1774 	    step = c2->x - l->s->x;
1775 	  if (step > 0)
1776 	    {
1777 	      dprintf ("right step %#mS at %#mD\n", step, l->s->x, l->s->y);
1778 	      move_corner (l->s, l->s->x + step, l->s->y);
1779 	      move_corner (l->e, l->e->x + step, l->e->y);
1780 	      rv += step;
1781 	    }
1782 	  break;
1783 	case UP:
1784 	  if (rp.y2 == INT_MIN)
1785 	    rp.y2 = rr.y1;
1786 	  step = trim_step (l->s->y - rp.y2 - w,
1787 			    l->s->y - c1->y, l->s->y - c2->y);
1788 	  if (step > 0)
1789 	    {
1790 	      dprintf ("up step %#mS at %#mD\n", step, l->s->x, l->s->y);
1791 	      move_corner (l->s, l->s->x, l->s->y - step);
1792 	      move_corner (l->e, l->e->x, l->e->y - step);
1793 	      rv += step;
1794 	    }
1795 	  break;
1796 	case DOWN:
1797 	  step = rp.y1 - l->s->y - w;
1798 	  step = gridsnap (step);
1799 	  if (step > c1->y - l->s->y)
1800 	    step = c1->y - l->s->y;
1801 	  if (step > c2->y - l->s->y)
1802 	    step = c2->y - l->s->y;
1803 	  if (step > 0)
1804 	    {
1805 	      dprintf ("down step %#mS at %#mD\n", step, l->s->x, l->s->y);
1806 	      move_corner (l->s, l->s->x, l->s->y + step);
1807 	      move_corner (l->e, l->e->x, l->e->y + step);
1808 	      rv += step;
1809 	    }
1810 	  break;
1811 	}
1812       check (0, l);
1813     }
1814 
1815   rv += simple_optimizations ();
1816   if (rv)
1817     pcb_printf ("debumpify: %ml mils saved\n", rv / 50);
1818   return rv;
1819 }
1820 
1821 static int
simple_corner(corner_s * c)1822 simple_corner (corner_s * c)
1823 {
1824   int o1, o2;
1825   if (c->pad || c->pin || c->via)
1826     return 0;
1827   if (c->n_lines != 2)
1828     return 0;
1829   o1 = line_orient (c->lines[0], c);
1830   o2 = line_orient (c->lines[1], c);
1831   if (ORIENT (o1) == ORIENT (o2))
1832     return 0;
1833   if (ORIENT (o1) == DIAGONAL || ORIENT (o2) == DIAGONAL)
1834     return 0;
1835   return 1;
1836 }
1837 
1838 /*!
1839  * \brief Look for sequences of simple corners we can reduce.
1840  */
1841 static int
unjaggy_once()1842 unjaggy_once ()
1843 {
1844   int rv = 0;
1845   corner_s *c, *c0, *c1, *cc;
1846   int l, w, sel = any_line_selected ();
1847   int o0, o1, s0, s1;
1848   rect_s rr, rp;
1849   for (c = corners; c; c = c->next)
1850     {
1851       if (DELETED (c))
1852 	continue;
1853       if (!simple_corner (c))
1854 	continue;
1855       if (!c->lines[0]->line || !c->lines[1]->line)
1856 	continue;
1857       if (sel && !(selected (c->lines[0]->line)
1858 		   || selected (c->lines[1]->line)))
1859 	continue;
1860       if (!sel && autorouted_only
1861 	  && !(autorouted (c->lines[0]->line)
1862 	       || autorouted (c->lines[1]->line)))
1863 	continue;
1864       dprintf ("simple at %#mD\n", c->x, c->y);
1865 
1866       c0 = other_corner (c->lines[0], c);
1867       o0 = line_orient (c->lines[0], c);
1868       s0 = simple_corner (c0);
1869 
1870       c1 = other_corner (c->lines[1], c);
1871       o1 = line_orient (c->lines[1], c);
1872       s1 = simple_corner (c1);
1873 
1874       if (!s0 && !s1)
1875 	continue;
1876       dprintf ("simples at %#mD\n", c->x, c->y);
1877 
1878       w = 1;
1879       for (l = 0; l < c0->n_lines; l++)
1880 	if (c0->lines[l] != c->lines[0]
1881 	    && c0->lines[l]->layer == c->lines[0]->layer)
1882 	  {
1883 	    int o = line_orient (c0->lines[l], c0);
1884 	    if (o == o1)
1885 	      w = 0;
1886 	  }
1887       for (l = 0; l < c1->n_lines; l++)
1888 	if (c1->lines[l] != c->lines[0]
1889 	    && c1->lines[l]->layer == c->lines[0]->layer)
1890 	  {
1891 	    int o = line_orient (c1->lines[l], c1);
1892 	    if (o == o0)
1893 	      w = 0;
1894 	  }
1895       if (!w)
1896 	continue;
1897       dprintf ("orient ok\n");
1898 
1899       w = c->lines[0]->line->Thickness / 2 + SB + 1;
1900       empty_rect (&rr);
1901       add_line_to_rect (&rr, c->lines[0]);
1902       add_line_to_rect (&rr, c->lines[1]);
1903       if (c->x != rr.x1)
1904 	rr.x1 -= w;
1905       else
1906 	rr.x2 += w;
1907       if (c->y != rr.y1)
1908 	rr.y1 -= w;
1909       else
1910 	rr.y2 += w;
1911 
1912       empty_rect (&rp);
1913       for (cc = corners; cc; cc = cc->next)
1914 	{
1915 	  if (DELETED (cc))
1916 	    continue;
1917 	  if (cc->net != c->net && intersecting_layers (cc->layer, c->layer))
1918 	    add_corner_to_rect_if (&rp, cc, &rr);
1919 	}
1920       dprintf ("rp x %#mS..%#mS  y %#mS..%#mS\n", rp.x1, rp.x2, rp.y1, rp.y2);
1921       if (rp.x1 <= rp.x2)	/* something triggered */
1922 	continue;
1923 
1924       dprintf ("unjaggy at %#mD layer %d\n", c->x, c->y, c->layer);
1925       if (c->x == c0->x)
1926 	move_corner (c, c1->x, c0->y);
1927       else
1928 	move_corner (c, c0->x, c1->y);
1929       rv++;
1930       check (c, 0);
1931     }
1932   rv += simple_optimizations ();
1933   check (c, 0);
1934   return rv;
1935 }
1936 
1937 static int
unjaggy()1938 unjaggy ()
1939 {
1940   int i, r = 0, j;
1941   for (i = 0; i < 100; i++)
1942     {
1943       j = unjaggy_once ();
1944       if (j == 0)
1945 	break;
1946       r += j;
1947     }
1948   if (r)
1949     printf ("%d unjagg%s    \n", r, r == 1 ? "y" : "ies");
1950   return r;
1951 }
1952 
1953 /*!
1954  * \brief Look for vias with all lines leaving the same way, try to
1955  * nudge via to eliminate one or more of them.
1956  */
1957 static int
vianudge()1958 vianudge ()
1959 {
1960   int rv = 0;
1961   corner_s *c, *c2, *c3;
1962   line_s *l;
1963   unsigned char directions[MAX_LAYER];
1964   unsigned char counts[MAX_LAYER];
1965 
1966   memset (directions, 0, sizeof (directions));
1967   memset (counts, 0, sizeof (counts));
1968 
1969   for (c = corners; c; c = c->next)
1970     {
1971       int o, i, vr, cr, oboth;
1972       int len = 0, saved = 0;
1973 
1974       if (DELETED (c))
1975 	continue;
1976 
1977       if (!c->via)
1978 	continue;
1979 
1980       memset (directions, 0, sizeof (directions));
1981       memset (counts, 0, sizeof (counts));
1982 
1983       for (i = 0; i < c->n_lines; i++)
1984 	{
1985 	  o = line_orient (c->lines[i], c);
1986 	  counts[c->lines[i]->layer]++;
1987 	  directions[c->lines[i]->layer] |= o;
1988 	}
1989       for (o = 0, i = 0; i < max_copper_layer; i++)
1990 	if (counts[i] == 1)
1991 	  {
1992 	    o = directions[i];
1993 	    break;
1994 	  }
1995       switch (o)
1996 	{
1997 	case LEFT:
1998 	case RIGHT:
1999 	  oboth = LEFT | RIGHT;
2000 	  break;
2001 	case UP:
2002 	case DOWN:
2003 	  oboth = UP | DOWN;
2004 	  break;
2005 	default:
2006 	  continue;
2007 	}
2008       for (i = 0; i < max_copper_layer; i++)
2009 	if (counts[i] && directions[i] != o && directions[i] != oboth)
2010 	  goto vianudge_continue;
2011 
2012       c2 = 0;
2013       for (i = 0; i < c->n_lines; i++)
2014 	{
2015 	  int ll = line_length (c->lines[i]);
2016 	  if (line_orient (c->lines[i], c) != o)
2017 	    {
2018 	      saved--;
2019 	      continue;
2020 	    }
2021 	  saved++;
2022 	  if (c2 == 0 || len > ll)
2023 	    {
2024 	      len = ll;
2025 	      c2 = other_corner (c->lines[i], c);
2026 	    }
2027 	}
2028       if (c2->pad || c2->pin || c2->via)
2029 	continue;
2030 
2031       /* Now look for clearance in the new position */
2032       vr = c->via->Thickness / 2 + SB + 1;
2033       for (c3 = corners; c3; c3 = c3->next)
2034 	{
2035 	  if (DELETED (c3))
2036 	    continue;
2037 	  if ((c3->net != c->net && (c3->pin || c3->via)) || c3->pad)
2038 	    {
2039 	      cr = corner_radius (c3);
2040 	      if (dist (c2->x, c2->y, c3->x, c3->y) < vr + cr)
2041 		goto vianudge_continue;
2042 	    }
2043 	}
2044       for (l = lines; l; l = l->next)
2045 	{
2046 	  if (DELETED (l))
2047 	    continue;
2048 	  if (l->s->net != c->net)
2049 	    {
2050 	      int ld = dist_line_to_point (l, c2);
2051 	      if (ld < l->line->Thickness / 2 + vr)
2052 		goto vianudge_continue;
2053 	    }
2054 	}
2055 
2056       /* at this point, we know we can move it */
2057 
2058       dprintf ("vianudge: nudging via at %#mD by %#mS saving %#mS\n",
2059 	       c->x, c->y, len, saved);
2060       rv += len * saved;
2061       move_corner (c, c2->x, c2->y);
2062 
2063       check (c, 0);
2064 
2065     vianudge_continue:
2066       continue;
2067     }
2068 
2069   if (rv)
2070     pcb_printf ("vianudge: %ml mils saved\n", rv);
2071   return rv;
2072 }
2073 
2074 /*!
2075  * \brief Look for traces that can be moved to the other side of the
2076  * board, to reduce the number of vias needed.
2077  *
2078  * For now, we look for simple lines, not multi-segmented lines.
2079  */
2080 static int
viatrim()2081 viatrim ()
2082 {
2083   line_s *l, *l2;
2084   int i, rv = 0, vrm = 0;
2085   int any_sel = any_line_selected ();
2086 
2087   for (l = lines; l; l = l->next)
2088     {
2089       rect_s r;
2090       int my_layer, other_layer;
2091 
2092       if (DELETED (l))
2093 	continue;
2094       if (!l->s->via)
2095 	continue;
2096       if (!l->e->via)
2097 	continue;
2098       if (any_sel && !selected (l->line))
2099 	continue;
2100       if (!any_sel && autorouted_only && !autorouted (l->line))
2101 	continue;
2102 
2103       my_layer = l->layer;
2104       other_layer = -1;
2105       dprintf ("line %p on layer %d from %#mD to %#mD\n", (void *) l,
2106 	       l->layer, l->s->x, l->s->y, l->e->x, l->e->y);
2107       for (i = 0; i < l->s->n_lines; i++)
2108 	if (l->s->lines[i] != l)
2109 	  {
2110 	    if (other_layer == -1)
2111 	      {
2112 		other_layer = l->s->lines[i]->layer;
2113 		dprintf ("noting other line %p on layer %d\n",
2114 			 (void *) (l->s->lines[i]), my_layer);
2115 	      }
2116 	    else if (l->s->lines[i]->layer != other_layer)
2117 	      {
2118 		dprintf ("saw other line %p on layer %d (not %d)\n",
2119 			 (void *) (l->s->lines[i]), l->s->lines[i]->layer,
2120 			 my_layer);
2121 		other_layer = -1;
2122 		goto viatrim_other_corner;
2123 	      }
2124 	  }
2125     viatrim_other_corner:
2126       if (other_layer == -1)
2127 	for (i = 0; i < l->e->n_lines; i++)
2128 	  if (l->e->lines[i] != l)
2129 	    {
2130 	      if (other_layer == -1)
2131 		{
2132 		  other_layer = l->s->lines[i]->layer;
2133 		  dprintf ("noting other line %p on layer %d\n",
2134 			   (void *) (l->s->lines[i]), my_layer);
2135 		}
2136 	      else if (l->e->lines[i]->layer != other_layer)
2137 		{
2138 		  dprintf ("saw end line on layer %d (not %d)\n",
2139 			   l->e->lines[i]->layer, other_layer);
2140 		  goto viatrim_continue;
2141 		}
2142 	    }
2143 
2144       /* Now see if any other line intersects us.  We don't need to
2145          check corners, because they'd either be pins/vias and
2146          already conflict, or pads, which we'll check here anyway.  */
2147       empty_rect (&r);
2148       add_point_to_rect (&r, l->s->x, l->s->y, l->line->Thickness);
2149       add_point_to_rect (&r, l->e->x, l->e->y, l->line->Thickness);
2150 
2151       for (l2 = lines; l2; l2 = l2->next)
2152 	{
2153 	  if (DELETED (l2))
2154 	    continue;
2155 	  if (l2->s->net != l->s->net && l2->layer == other_layer)
2156 	    {
2157 	      dprintf ("checking other line %#mD to %#mD\n", l2->s->x,
2158 		       l2->s->y, l2->e->x, l2->e->y);
2159 	      if (line_in_rect (&r, l2))
2160 		{
2161 		  dprintf ("line from %#mD to %#mD in the way\n",
2162 			   l2->s->x, l2->s->y, l2->e->x, l2->e->y);
2163 		  goto viatrim_continue;
2164 		}
2165 	    }
2166 	}
2167 
2168       if (l->layer == other_layer)
2169 	continue;
2170       move_line_to_layer (l, other_layer);
2171       rv++;
2172 
2173     viatrim_continue:
2174       continue;
2175     }
2176   vrm = simple_optimizations ();
2177   if (rv > 0)
2178     printf ("viatrim: %d traces moved, %d vias removed\n", rv, vrm);
2179   return rv + vrm;
2180 }
2181 
2182 static int
automagic()2183 automagic ()
2184 {
2185   int more = 1, oldmore = 0;
2186   int toomany = 100;
2187   while (more != oldmore && --toomany)
2188     {
2189       oldmore = more;
2190       more += debumpify ();
2191       more += unjaggy ();
2192       more += orthopull ();
2193       more += vianudge ();
2194       more += viatrim ();
2195     }
2196   return more - 1;
2197 }
2198 
2199 static int
miter()2200 miter ()
2201 {
2202   corner_s *c;
2203   int done, progress;
2204   int sel = any_line_selected ();
2205   int saved = 0;
2206 
2207   for (c = corners; c; c = c->next)
2208     {
2209       if (DELETED (c))
2210 	continue;
2211       c->miter = 0;
2212       if (c->n_lines == 2 && !c->via && !c->pin && !c->via)
2213 	{
2214 	  int o1 = line_orient (c->lines[0], c);
2215 	  int o2 = line_orient (c->lines[1], c);
2216 	  if (ORIENT (o1) != ORIENT (o2)
2217 	      && o1 != DIAGONAL && o2 != DIAGONAL
2218 	      && c->lines[0]->line->Thickness == c->lines[1]->line->Thickness)
2219 	    c->miter = -1;
2220 	}
2221     }
2222 
2223   done = 0;
2224   progress = 1;
2225   while (!done && progress)
2226     {
2227       done = 1;
2228       progress = 0;
2229       for (c = corners; c; c = c->next)
2230 	{
2231 	  if (DELETED (c))
2232 	    continue;
2233 	  if (c->miter == -1)
2234 	    {
2235 	      int max = line_length (c->lines[0]);
2236 	      int len = line_length (c->lines[1]);
2237 	      int bloat;
2238 	      int ref, dist;
2239 	      corner_s *closest_corner = 0, *c2, *oc1, *oc2;
2240 	      int mx = 0, my = 0, x, y;
2241 	      int o1 = line_orient (c->lines[0], c);
2242 	      int o2 = line_orient (c->lines[1], c);
2243 
2244 	      if (c->pad || c->pin || c->via)
2245 		{
2246 		  c->miter = 0;
2247 		  progress = 1;
2248 		  continue;
2249 		}
2250 
2251 	      oc1 = other_corner (c->lines[0], c);
2252 	      oc2 = other_corner (c->lines[1], c);
2253 #if 0
2254 	      if (oc1->pad)
2255 		oc1 = 0;
2256 	      if (oc2->pad)
2257 		oc2 = 0;
2258 #endif
2259 
2260 	      if ((sel && !(selected (c->lines[0]->line)
2261 			    || selected (c->lines[1]->line)))
2262 		  || (!sel && autorouted_only
2263 		      && !(autorouted (c->lines[0]->line)
2264 			   || autorouted (c->lines[1]->line))))
2265 		{
2266 		  c->miter = 0;
2267 		  progress = 1;
2268 		  continue;
2269 		}
2270 
2271 	      if (max > len)
2272 		max = len;
2273 	      switch (o1)
2274 		{
2275 		case LEFT:
2276 		  mx = -1;
2277 		  break;
2278 		case RIGHT:
2279 		  mx = 1;
2280 		  break;
2281 		case UP:
2282 		  my = -1;
2283 		  break;
2284 		case DOWN:
2285 		  my = 1;
2286 		  break;
2287 		}
2288 	      switch (o2)
2289 		{
2290 		case LEFT:
2291 		  mx = -1;
2292 		  break;
2293 		case RIGHT:
2294 		  mx = 1;
2295 		  break;
2296 		case UP:
2297 		  my = -1;
2298 		  break;
2299 		case DOWN:
2300 		  my = 1;
2301 		  break;
2302 		}
2303 	      ref = c->x * mx + c->y * my;
2304 	      dist = max;
2305 
2306 	      bloat = (c->lines[0]->line->Thickness / 2 + SB + 1) * 3 / 2;
2307 
2308 	      for (c2 = corners; c2; c2 = c2->next)
2309 		{
2310 		  if (DELETED (c2))
2311 		    continue;
2312 		  if (c2 != c && c2 != oc1 && c2 != oc2
2313 		      && c->x * mx <= c2->x * mx
2314 		      && c->y * my <= c2->y * my
2315 		      && c->net != c2->net
2316 		      && intersecting_layers (c->layer, c2->layer))
2317 		    {
2318 		      int cr = corner_radius (c2);
2319 		      len = c2->x * mx + c2->y * my - ref - cr - bloat;
2320 		      if (c->x != c2->x && c->y != c2->y)
2321 			len -= cr;
2322 		      if (len < dist || (len == dist && c->miter != -1))
2323 			{
2324 			  dist = len;
2325 			  closest_corner = c2;
2326 			}
2327 		    }
2328 		}
2329 
2330 	      if (closest_corner && closest_corner->miter == -1)
2331 		{
2332 		  done = 0;
2333 		  continue;
2334 		}
2335 
2336 #if 0
2337 	      if (dist < Settings.Grid)
2338 		{
2339 		  c->miter = 0;
2340 		  progress = 1;
2341 		  continue;
2342 		}
2343 
2344 	      dist -= dist % Settings.Grid;
2345 #endif
2346 	      if (dist <= 0)
2347 		{
2348 		  c->miter = 0;
2349 		  progress = 1;
2350 		  continue;
2351 		}
2352 
2353 	      x = c->x;
2354 	      y = c->y;
2355 	      switch (o1)
2356 		{
2357 		case LEFT:
2358 		  x -= dist;
2359 		  break;
2360 		case RIGHT:
2361 		  x += dist;
2362 		  break;
2363 		case UP:
2364 		  y -= dist;
2365 		  break;
2366 		case DOWN:
2367 		  y += dist;
2368 		  break;
2369 		}
2370 	      c2 = find_corner (x, y, c->layer);
2371 	      if (c2 != other_corner (c->lines[0], c))
2372 		split_line (c->lines[0], c2);
2373 	      x = c->x;
2374 	      y = c->y;
2375 	      switch (o2)
2376 		{
2377 		case LEFT:
2378 		  x -= dist;
2379 		  break;
2380 		case RIGHT:
2381 		  x += dist;
2382 		  break;
2383 		case UP:
2384 		  y -= dist;
2385 		  break;
2386 		case DOWN:
2387 		  y += dist;
2388 		  break;
2389 		}
2390 	      move_corner (c, x, y);
2391 	      c->miter = 0;
2392 	      c2->miter = 0;
2393 	      progress = 1;
2394 	      saved++;
2395 	    }
2396 	}
2397     }
2398   return saved;
2399 }
2400 
2401 static void
classify_corner(corner_s * c,int this_net)2402 classify_corner (corner_s * c, int this_net)
2403 {
2404   int i;
2405   if (c->net == this_net)
2406     return;
2407   c->net = this_net;
2408   for (i = 0; i < c->n_lines; i++)
2409     classify_corner (other_corner (c->lines[i], c), this_net);
2410 }
2411 
2412 static void
classify_nets()2413 classify_nets ()
2414 {
2415   static int this_net = 1;
2416   corner_s *c;
2417 
2418   for (c = corners; c; c = c->next)
2419     {
2420       if (DELETED (c))
2421 	continue;
2422       if (c->net)
2423 	continue;
2424       classify_corner (c, this_net);
2425       this_net++;
2426     }
2427 }
2428 
2429 #if 0
2430 /* Not used */
2431 static void
2432 dump_all ()
2433 {
2434   corner_s *c;
2435   line_s *l;
2436   for (c = corners; c; c = c->next)
2437     {
2438       if (DELETED (c))
2439 	continue;
2440       printf ("%p corner %d,%d layer %d net %d\n",
2441 	      (void *) c, c->x, c->y, c->layer, c->net);
2442     }
2443   for (l = lines; l; l = l->next)
2444     {
2445       if (DELETED (l))
2446 	continue;
2447       printf ("%p line %p to %p layer %d\n",
2448 	      (void *) l, (void *) (l->s), (void *) (l->e), l->layer);
2449     }
2450 }
2451 #endif
2452 
2453 #if 0
2454 static void
2455 nudge_corner (corner_s * c, int dx, int dy, corner_s * prev_corner)
2456 {
2457   int ox = c->x;
2458   int oy = c->y;
2459   int l;
2460   if (prev_corner && (c->pin || c->pad))
2461     return;
2462   move_corner (c, ox + dx, oy + dy);
2463   for (l = 0; l < c->n_lines; l++)
2464     {
2465       corner_s *oc = other_corner (c->lines[l], c);
2466       if (oc == prev_corner)
2467 	continue;
2468       if (dx && oc->x == ox)
2469 	nudge_corner (oc, dx, 0, c);
2470       if (dy && oc->y == oy)
2471 	nudge_corner (oc, 0, dy, c);
2472     }
2473 }
2474 #endif
2475 
2476 static line_s *
choose_example_line(corner_s * c1,corner_s * c2)2477 choose_example_line (corner_s * c1, corner_s * c2)
2478 {
2479   int ci, li;
2480   corner_s *c[2];
2481   c[0] = c1;
2482   c[1] = c2;
2483   dprintf ("choose_example_line\n");
2484   for (ci = 0; ci < 2; ci++)
2485     for (li = 0; li < c[ci]->n_lines; li++)
2486       {
2487 	dprintf ("  try[%d,%d] \033[36m<%#mD-%#mD t%#mS c%#mS f%s>\033[0m\n",
2488 		 ci, li,
2489 		 c[ci]->lines[li]->s->x, c[ci]->lines[li]->s->y,
2490 		 c[ci]->lines[li]->e->x, c[ci]->lines[li]->e->y,
2491 		 c[ci]->lines[li]->line->Thickness,
2492 		 c[ci]->lines[li]->line->Clearance,
2493 		 flags_to_string (c[ci]->lines[li]->line->Flags, LINE_TYPE));
2494 	/* Pads are disqualified, as we want to mimic a trace line. */
2495 	if (c[ci]->lines[li]->line == (LineType *) c[ci]->pad)
2496 	  {
2497 	    dprintf ("  bad, pad\n");
2498 	    continue;
2499 	  }
2500 	/* Lines on layers that don't connect to the other pad are bad too.  */
2501 	if (!intersecting_layers (c[ci]->lines[li]->layer, c[1 - ci]->layer))
2502 	  {
2503 	    dprintf ("  bad, layers\n");
2504 	    continue;
2505 	  }
2506 	dprintf ("  good\n");
2507 	return c[ci]->lines[li];
2508       }
2509   dprintf ("choose_example_line: none found!\n");
2510   return 0;
2511 }
2512 
2513 static int
connect_corners(corner_s * c1,corner_s * c2)2514 connect_corners (corner_s * c1, corner_s * c2)
2515 {
2516   int layer;
2517   line_s *ex = choose_example_line (c1, c2);
2518   LineType *example = ex->line;
2519 
2520   dprintf
2521     ("connect_corners \033[32m%#mD to %#mD, example line %#mD to %#mD l%d\033[0m\n",
2522      c1->x, c1->y, c2->x, c2->y, ex->s->x, ex->s->y, ex->e->x, ex->e->y,
2523      ex->layer);
2524 
2525   layer = ex->layer;
2526 
2527   /* Assume c1 is the moveable one.  */
2528   if (!(c1->pin || c1->pad || c1->via) && c1->n_lines == 1)
2529     {
2530       int nx, ny;
2531       /* Extend the line */
2532       if (c1->lines[0]->s->x == c1->lines[0]->e->x)
2533 	nx = c1->x, ny = c2->y;
2534       else
2535 	nx = c2->x, ny = c1->y;
2536       if (nx != c2->x || ny != c2->y)
2537 	{
2538 	  move_corner (c1, nx, ny);
2539 	  new_line (c1, c2, layer, example);
2540 	  return 1;
2541 	}
2542       else
2543 	{
2544 	  move_corner (c1, nx, ny);
2545 	  return 1;
2546 	}
2547     }
2548   else
2549     {
2550       corner_s *nc = find_corner (c1->x, c2->y, layer);
2551       new_line (c1, nc, layer, example);
2552       new_line (nc, c2, layer, example);
2553       return 0;
2554     }
2555 }
2556 
2557 /*!
2558  * \brief Look for pins that have no connections.
2559  *
2560  * See if there's a corner close by that should be connected to it.
2561  * This usually happens when the MUCS router needs to route to an
2562  * off-grid pin.
2563  */
2564 static void
pinsnap()2565 pinsnap ()
2566 {
2567   corner_s *c;
2568   int best_dist[MAX_LAYER + 1];
2569   corner_s *best_c[MAX_LAYER + 1];
2570   int l, got_one;
2571   int left = 0, right = 0, top = 0, bottom = 0;
2572   PinType *pin;
2573   int again = 1;
2574 
2575   int close = 0;
2576   corner_s *c2;
2577 
2578   while (again)
2579     {
2580       again = 0;
2581       for (c = corners; c; c = c->next)
2582 	{
2583 	  if (DELETED (c))
2584 	    continue;
2585 	  if (!(c->pin || c->via || c->pad))
2586 	    continue;
2587 
2588 	  pin = 0;
2589 
2590 	  dprintf ("\ncorner %s\n", corner_name (c));
2591 	  if (c->pin || c->via)
2592 	    {
2593 	      pin = c->pin ? c->pin : c->via;
2594 	      close = pin->Thickness / 2;
2595 	      left = c->x - close;
2596 	      right = c->x + close;
2597 	      bottom = c->y - close;
2598 	      top = c->y + close;
2599 	    }
2600 	  else if (c->pad)
2601 	    {
2602 	      close = c->pad->Thickness / 2 + 1;
2603 	      left = djmin (c->pad->Point1.X, c->pad->Point2.X) - close;
2604 	      right = djmax (c->pad->Point1.X, c->pad->Point2.X) + close;
2605 	      bottom = djmin (c->pad->Point1.Y, c->pad->Point2.Y) - close;
2606 	      top = djmax (c->pad->Point1.Y, c->pad->Point2.Y) + close;
2607 	      if (c->pad->Point1.X == c->pad->Point2.X)
2608 		{
2609 		  int hy = (c->pad->Point1.Y + c->pad->Point2.Y) / 2;
2610 		  dprintf ("pad y %#mS %#mS hy %#mS c %#mS\n", c->pad->Point1.Y,
2611 			   c->pad->Point2.Y, hy, c->y);
2612 		  if (c->y < hy)
2613 		    top = hy;
2614 		  else
2615 		    bottom = hy + 1;
2616 		}
2617 	      else
2618 		{
2619 		  int hx = (c->pad->Point1.X + c->pad->Point2.X) / 2;
2620 		  dprintf ("pad x %#mS %#mS hx %#mS c %#mS\n", c->pad->Point1.X,
2621 			   c->pad->Point2.X, hx, c->x);
2622 		  if (c->x < hx)
2623 		    right = hx;
2624 		  else
2625 		    left = hx + 1;
2626 		}
2627 	    }
2628 
2629 	  dprintf ("%s x %#mS-%#mS y %#mS-%#mS\n", corner_name (c), left, right, bottom, top);
2630 	  for (l = 0; l <= max_copper_layer; l++)
2631 	    {
2632 	      best_dist[l] = close * 2;
2633 	      best_c[l] = 0;
2634 	    }
2635 	  got_one = 0;
2636 	  for (c2 = corners; c2; c2 = c2->next)
2637 	    {
2638 	      int lt;
2639 
2640 	      if (DELETED (c2))
2641 		continue;
2642 	      lt = corner_radius (c2);
2643 	      if (c2->n_lines
2644 		  && c2 != c
2645 		  && !(c2->pin || c2->pad || c2->via)
2646 		  && intersecting_layers (c->layer, c2->layer)
2647 		  && c2->x >= left - lt
2648 		  && c2->x <= right + lt
2649 		  && c2->y >= bottom - lt && c2->y <= top + lt)
2650 		{
2651 		  int d = dist (c->x, c->y, c2->x, c2->y);
2652 		  if (pin && d > pin->Thickness / 2 + lt)
2653 		    continue;
2654 		  if (c2->n_lines == 1)
2655 		    {
2656 		      got_one++;
2657 		      dprintf ("found orphan %s vs %s\n", corner_name (c2),
2658 			       corner_name (c));
2659 		      connect_corners (c, c2);
2660 		      again = 1;
2661 		      continue;
2662 		    }
2663 		  if (best_c[c2->layer] == 0
2664 		      || c2->n_lines < best_c[c2->layer]->n_lines
2665 		      || (d < best_dist[c2->layer]
2666 			  && c2->n_lines <= best_c[c2->layer]->n_lines))
2667 		    {
2668 		      best_dist[c2->layer] = d;
2669 		      best_c[c2->layer] = c2;
2670 		      dprintf ("layer %d best now %s\n", c2->layer,
2671 			       corner_name (c2));
2672 		    }
2673 		}
2674 	      if (!got_one && c->n_lines == (c->pad ? 1 : 0))
2675 		{
2676 		  for (l = 0; l <= max_copper_layer; l++)
2677 		    if (best_c[l])
2678 		      dprintf ("best[%d] = %s\n", l, corner_name (best_c[l]));
2679 		  for (l = 0; l <= max_copper_layer; l++)
2680 		    if (best_c[l])
2681 		      {
2682 			dprintf ("move %s to %s\n", corner_name (best_c[l]),
2683 				 corner_name (c));
2684 			connect_corners (best_c[l], c);
2685 			again = 1;
2686 			continue;
2687 		      }
2688 		}
2689 	    }
2690 	}
2691     }
2692 
2693   /* Now look for line ends that don't connect, see if they need to be
2694      extended to intersect another line.  */
2695   for (c = corners; c; c = c->next)
2696     {
2697       line_s *l, *t;
2698       int lo;
2699 
2700       if (DELETED (c))
2701 	continue;
2702       if (c->pin || c->via || c->pad)
2703 	continue;
2704       if (c->n_lines != 1)
2705 	continue;
2706 
2707       l = c->lines[0];
2708       lo = line_orient (l, c);
2709       dprintf ("line end %#mD orient %d\n", c->x, c->y, lo);
2710 
2711       for (t = lines; t; t = t->next)
2712 	{
2713 	  if (DELETED (t))
2714 	    continue;
2715 	  if (t->layer != c->lines[0]->layer)
2716 	    continue;
2717 	  switch (lo)		/* remember, orient is for the line relative to the corner */
2718 	    {
2719 	    case LEFT:
2720 	      if (t->s->x == t->e->x
2721 		  && c->x < t->s->x
2722 		  && t->s->x <
2723 		  c->x + (l->line->Thickness + t->line->Thickness) / 2
2724 		  && ((t->s->y < c->y && c->y < t->e->y)
2725 		      || (t->e->y < c->y && c->y < t->s->y)))
2726 		{
2727 		  dprintf ("found %#mD - %#mD\n", t->s->x, t->s->y, t->e->x, t->e->y);
2728 		  move_corner (c, t->s->x, c->y);
2729 		}
2730 	      break;
2731 	    case RIGHT:
2732 	      if (t->s->x == t->e->x
2733 		  && c->x > t->s->x
2734 		  && t->s->x >
2735 		  c->x - (l->line->Thickness + t->line->Thickness) / 2
2736 		  && ((t->s->y < c->y && c->y < t->e->y)
2737 		      || (t->e->y < c->y && c->y < t->s->y)))
2738 		{
2739 		  dprintf ("found %#mD - %#mD\n", t->s->x, t->s->y, t->e->x, t->e->y);
2740 		  move_corner (c, t->s->x, c->y);
2741 		}
2742 	      break;
2743 	    case UP:
2744 	      if (t->s->y == t->e->y
2745 		  && c->y < t->s->y
2746 		  && t->s->y <
2747 		  c->y + (l->line->Thickness + t->line->Thickness) / 2
2748 		  && ((t->s->x < c->x && c->x < t->e->x)
2749 		      || (t->e->x < c->x && c->x < t->s->x)))
2750 		{
2751 		  dprintf ("found %#mD - %#mD\n", t->s->x, t->s->y, t->e->x, t->e->y);
2752 		  move_corner (c, c->x, t->s->y);
2753 		}
2754 	      break;
2755 	    case DOWN:
2756 	      if (t->s->y == t->e->y
2757 		  && c->y > t->s->y
2758 		  && t->s->y >
2759 		  c->y - (l->line->Thickness + t->line->Thickness) / 2
2760 		  && ((t->s->x < c->x && c->x < t->e->x)
2761 		      || (t->e->x < c->x && c->x < t->s->x)))
2762 		{
2763 		  dprintf ("found %#mD - %#mD\n", t->s->x, t->s->y, t->e->x, t->e->y);
2764 		  move_corner (c, c->x, t->s->y);
2765 		}
2766 	      break;
2767 	    }
2768 	}
2769     }
2770 }
2771 
2772 static int
pad_orient(PadType * p)2773 pad_orient (PadType * p)
2774 {
2775   if (p->Point1.X == p->Point2.X)
2776     return O_VERT;
2777   if (p->Point1.Y == p->Point2.Y)
2778     return O_HORIZ;
2779   return DIAGONAL;
2780 }
2781 
2782 static void
padcleaner()2783 padcleaner ()
2784 {
2785   line_s *l, *nextl;
2786   int close;
2787   rect_s r;
2788 
2789   dprintf ("\ndj: padcleaner\n");
2790   for (l = lines; l; l = nextl)
2791     {
2792       nextl = l->next;
2793 
2794       if (l->is_pad)
2795 	continue;
2796 
2797       if (DELETED (l))
2798 	continue;
2799 
2800       dprintf ("dj: line %p\n", (void *) l);
2801       check (0, l);
2802 
2803       if (l->s->pad && l->s->pad == l->e->pad)
2804 	continue;
2805 
2806       ALLPAD_LOOP (PCB->Data);
2807 	{
2808 	  int layerflag =
2809 	    TEST_FLAG (ONSOLDERFLAG, element) ? LT_BOTTOM : LT_TOP;
2810 
2811 	  if (layer_type[l->layer] != layerflag)
2812 	    continue;
2813 
2814 	  empty_rect (&r);
2815 	  close = pad->Thickness / 2 + 1;
2816 	  add_point_to_rect (&r, pad->Point1.X, pad->Point1.Y, close - SB / 2);
2817 	  add_point_to_rect (&r, pad->Point2.X, pad->Point2.Y, close - SB / 2);
2818 	  if (pin_in_rect (&r, l->s->x, l->s->y, 0)
2819 	      && pin_in_rect (&r, l->e->x, l->e->y, 0)
2820 	      && ORIENT (line_orient (l, 0)) == pad_orient (pad))
2821 	    {
2822 	      dprintf
2823 		("padcleaner %#mD-%#mD %#mS vs line %#mD-%#mD %#mS\n",
2824 		 pad->Point1.X, pad->Point1.Y, pad->Point2.X, pad->Point2.Y,
2825 		 pad->Thickness, l->s->x, l->s->y, l->e->x, l->e->y,
2826 		 l->line->Thickness);
2827 	      remove_line (l);
2828 	      goto next_line;
2829 	    }
2830 	}
2831       ENDALL_LOOP;
2832     next_line:;
2833     }
2834 }
2835 
2836 static void
grok_layer_groups()2837 grok_layer_groups ()
2838 {
2839   int i, j, f;
2840   LayerGroupType *l = &(PCB->LayerGroups);
2841 
2842   solder_layer = component_layer = -1;
2843   for (i = 0; i < max_copper_layer; i++)
2844     {
2845       layer_type[i] = 0;
2846       layer_groupings[i] = 0;
2847     }
2848   for (i = 0; i < max_group; i++)
2849     {
2850       f = 0;
2851       for (j = 0; j < l->Number[i]; j++)
2852 	{
2853 	  if (l->Entries[i][j] == bottom_silk_layer)
2854 	    f |= LT_BOTTOM;
2855 	  if (l->Entries[i][j] == top_silk_layer)
2856 	    f |= LT_TOP;
2857 	}
2858       for (j = 0; j < l->Number[i]; j++)
2859 	{
2860 	  if (l->Entries[i][j] < max_copper_layer)
2861 	    {
2862 	      layer_type[l->Entries[i][j]] |= f;
2863 	      layer_groupings[l->Entries[i][j]] = i;
2864 	      if (solder_layer == -1 && f == LT_BOTTOM)
2865 		solder_layer = l->Entries[i][j];
2866 	      if (component_layer == -1 && f == LT_TOP)
2867 		component_layer = l->Entries[i][j];
2868 	    }
2869 	}
2870     }
2871 }
2872 
2873 static const char djopt_syntax[] =
2874   "djopt(debumpify|unjaggy|simple|vianudge|viatrim|orthopull|splitlines)\n"
2875   "djopt(auto) - all of the above\n"
2876   "djopt(miter)";
2877 
2878 static const char djopt_help[] =
2879   "Perform various optimizations on the current board.";
2880 
2881 /* %start-doc actions djopt
2882 
2883 The different types of optimizations change your board in order to
2884 reduce the total trace length and via count.
2885 
2886 @table @code
2887 
2888 @item debumpify
2889 Looks for U-shaped traces that can be shortened or eliminated.
2890 
2891 Example:
2892 
2893 Before debumpify:
2894 
2895 @center @image{debumpify,,,Example pcb before debumpify,png}
2896 
2897 After debumpify:
2898 
2899 @center @image{debumpify.out,,,Example pcb after debumpify,png}
2900 
2901 
2902 @item unjaggy
2903 Looks for corners which could be flipped to eliminate one or more
2904 corners (i.e. jaggy lines become simpler).
2905 
2906 Example:
2907 
2908 Before unjaggy:
2909 
2910 @center @image{unjaggy,,,Example pcb before unjaggy,png}
2911 
2912 After unjaggy:
2913 
2914 @center @image{unjaggy.out,,,Example pcb after unjaggy,png}
2915 
2916 
2917 @item simple
2918 Removing uneeded vias, replacing two or more trace segments in a row
2919 with a single segment.  This is usually performed automatically after
2920 other optimizations.
2921 
2922 @item vianudge
2923 Looks for vias where all traces leave in the same direction.  Tries to
2924 move via in that direction to eliminate one of the traces (and thus a
2925 corner).
2926 
2927 Example:
2928 
2929 Before vianudge:
2930 
2931 @center @image{vianudge,,,Example pcb before vianudge,png}
2932 
2933 After vianudge:
2934 
2935 @center @image{vianudge.out,,,Example pcb after vianudge,png}
2936 
2937 
2938 @item viatrim
2939 Looks for traces that go from via to via, where moving that trace to a
2940 different layer eliminates one or both vias.
2941 
2942 Example:
2943 
2944 Before viatrim:
2945 
2946 @center @image{viatrim,,,Example pcb before viatrim,png}
2947 
2948 After viatrim:
2949 
2950 @center @image{viatrim.out,,,Example pcb after viatrim,png}
2951 
2952 
2953 @item orthopull
2954 Looks for chains of traces all going in one direction, with more
2955 traces orthogonal on one side than on the other.  Moves the chain in
2956 that direction, causing a net reduction in trace length, possibly
2957 eliminating traces and/or corners.
2958 
2959 Example:
2960 
2961 Before orthopull:
2962 
2963 @center @image{orthopull,,,Example pcb before orthopull,png}
2964 
2965 After orthopull:
2966 
2967 @center @image{orthopull.out,,,Example pcb after orthopull,png}
2968 
2969 
2970 @item splitlines
2971 Looks for lines that pass through vias, pins, or pads, and splits them
2972 into separate lines so they can be managed separately.
2973 
2974 @item auto
2975 Performs the above options, repeating until no further optimizations
2976 can be made.
2977 
2978 @item miter
2979 Replaces 90 degree corners with a pair of 45 degree corners, to reduce
2980 RF losses and trace length.
2981 
2982 Example:
2983 
2984 Before miter:
2985 
2986 @center @image{miter,,,Example pcb before miter,png}
2987 
2988 After miter:
2989 
2990 @center @image{miter.out,,,Example pcb after miter,png}
2991 
2992 
2993 @end table
2994 
2995 %end-doc */
2996 
2997 static int
ActionDJopt(int argc,char ** argv,Coord x,Coord y)2998 ActionDJopt (int argc, char **argv, Coord x, Coord y)
2999 {
3000   char *arg = argc > 0 ? argv[0] : 0;
3001   int layn, saved = 0;
3002   corner_s *c;
3003 
3004   hid_action("Busy");
3005 
3006   lines = 0;
3007   corners = 0;
3008 
3009   grok_layer_groups ();
3010 
3011   ELEMENT_LOOP (PCB->Data);
3012   PIN_LOOP (element);
3013   {
3014     c = find_corner (pin->X, pin->Y, -1);
3015     c->pin = pin;
3016   }
3017   END_LOOP;
3018   PAD_LOOP (element);
3019   {
3020     int layern =
3021       TEST_FLAG (ONSOLDERFLAG, pad) ? solder_layer : component_layer;
3022     line_s *ls = (line_s *) malloc (sizeof (line_s));
3023     ls->next = lines;
3024     lines = ls;
3025     ls->is_pad = 1;
3026     ls->s = find_corner (pad->Point1.X, pad->Point1.Y, layern);
3027     ls->s->pad = pad;
3028     ls->e = find_corner (pad->Point2.X, pad->Point2.Y, layern);
3029     ls->e->pad = pad;
3030     ls->layer = layern;
3031     ls->line = (LineType *) pad;
3032     add_line_to_corner (ls, ls->s);
3033     add_line_to_corner (ls, ls->e);
3034 
3035   }
3036   END_LOOP;
3037   END_LOOP;
3038   VIA_LOOP (PCB->Data);
3039   /* hace don't mess with vias that have thermals */
3040   /* but then again don't bump into them
3041      if (!TEST_FLAG(ALLTHERMFLAGS, via))
3042    */
3043   {
3044     c = find_corner (via->X, via->Y, -1);
3045     c->via = via;
3046   }
3047   END_LOOP;
3048   check (0, 0);
3049 
3050   for (layn = 0; layn < max_copper_layer; layn++)
3051     {
3052       LayerType *layer = LAYER_PTR (layn);
3053       if (layer->Type != LT_COPPER)
3054 	continue;
3055 
3056       LINE_LOOP (layer);
3057 	{
3058 	  line_s *ls;
3059 
3060           if(autorouted_only && !autorouted (line))
3061             continue;
3062 
3063 	  /* don't mess with thermals */
3064 	  if (TEST_FLAG (USETHERMALFLAG, line))
3065 	    continue;
3066 
3067 	  if (line->Point1.X == line->Point2.X &&
3068               line->Point1.Y == line->Point2.Y)
3069 	    {
3070 	      RemoveLine (layer, line);
3071 	      continue;
3072 	    }
3073 
3074 	  ls = (line_s *) malloc (sizeof (line_s));
3075 	  ls->next = lines;
3076 	  lines = ls;
3077 	  ls->is_pad = 0;
3078 	  ls->s = find_corner (line->Point1.X, line->Point1.Y, layn);
3079 	  ls->e = find_corner (line->Point2.X, line->Point2.Y, layn);
3080 	  ls->line = line;
3081 	  add_line_to_corner (ls, ls->s);
3082 	  add_line_to_corner (ls, ls->e);
3083 	  ls->layer = layn;
3084 	}
3085       END_LOOP;
3086     }
3087 
3088   check (0, 0);
3089   if (NSTRCMP (arg, "splitlines") != 0)
3090     pinsnap ();
3091   saved += canonicalize_lines ();
3092   check (0, 0);
3093   classify_nets ();
3094   /*dump_all(); */
3095   check (0, 0);
3096 
3097   if (NSTRCMP (arg, "debumpify") == 0)
3098     saved += debumpify ();
3099   else if (NSTRCMP (arg, "unjaggy") == 0)
3100     saved += unjaggy ();
3101   else if (NSTRCMP (arg, "simple") == 0)
3102     saved += simple_optimizations ();
3103   else if (NSTRCMP (arg, "vianudge") == 0)
3104     saved += vianudge ();
3105   else if (NSTRCMP (arg, "viatrim") == 0)
3106     saved += viatrim ();
3107   else if (NSTRCMP (arg, "orthopull") == 0)
3108     saved += orthopull ();
3109   else if (NSTRCMP (arg, "auto") == 0)
3110     saved += automagic ();
3111   else if (NSTRCMP (arg, "miter") == 0)
3112     saved += miter ();
3113   else if (NSTRCMP (arg, "splitlines") == 0)
3114     /* Just to call canonicalize_lines() above.  */ ;
3115   else
3116     {
3117       printf ("unknown command: %s\n", arg);
3118       return 1;
3119     }
3120 
3121   padcleaner ();
3122 
3123   check (0, 0);
3124   if (saved)
3125     IncrementUndoSerialNumber ();
3126   return 0;
3127 }
3128 
3129 HID_Action djopt_action_list[] = {
3130   {"djopt", 0, ActionDJopt,
3131    djopt_help, djopt_syntax}
3132   ,
3133   {"OptAutoOnly", 0, djopt_set_auto_only,
3134    djopt_sao_help, djopt_sao_syntax}
3135 };
3136 
3137 REGISTER_ACTIONS (djopt_action_list)
3138