4 * PCB, interactive printed circuit board design
5 * Copyright (C) 2003 DJ Delorie
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Contact addresses for paper mail and Email:
22 * DJ Delorie, 334 North Road, Deerfield NH 03037-1110, USA
45 #include "pcb-printf.h"
47 #ifdef HAVE_LIBDMALLOC
52 #define rint(x) (ceil((x) - 0.5))
55 #define dprintf if(0)pcb_printf
57 #define selected(x) TEST_FLAG (SELECTEDFLAG, (x))
58 #define autorouted(x) TEST_FLAG (AUTOFLAG, (x))
60 #define SB (PCB->Bloat+1)
72 #define ORIENT(x) ((x) & 0xf0)
73 #define DIRECT(x) ((x) & 0x0f)
75 /* Manhattan length of the longest "freckle" */
76 #define LONGEST_FRECKLE 2
80 typedef struct corner_s
83 struct corner_s
*next
;
91 struct line_s
**lines
;
103 typedef struct rect_s
108 #define DELETE(q) (q)->layer = 0xdeadbeef
109 #define DELETED(q) ((q)->layer == 0xdeadbeef)
111 static corner_s
*corners
, *next_corner
= 0;
112 static line_s
*lines
;
114 static int layer_groupings
[MAX_LAYER
];
115 static char layer_type
[MAX_LAYER
];
116 #define LT_COMPONENT 1
119 static int autorouted_only
= 1;
121 static const char djopt_sao_syntax
[] = "OptAutoOnly()";
123 static const char djopt_sao_help
[] =
124 "Toggles the optimize-only-autorouted flag.";
126 /* %start-doc actions OptAutoOnly
128 The original purpose of the trace optimizer was to clean up the traces
129 created by the various autorouters that have been used with PCB. When
130 a board has a mix of autorouted and carefully hand-routed traces, you
131 don't normally want the optimizer to move your hand-routed traces.
132 But, sometimes you do. By default, the optimizer only optimizes
133 autorouted traces. This action toggles that setting, so that you can
134 optimize hand-routed traces also.
139 djopt_set_auto_only (int argc
, char **argv
, Coord x
, Coord y
)
141 autorouted_only
= autorouted_only
? 0 : 1;
146 djopt_get_auto_only (void *data
)
148 return autorouted_only
;
151 HID_Flag djopt_flag_list
[] = {
152 {"optautoonly", djopt_get_auto_only
, NULL
}
155 REGISTER_FLAGS (djopt_flag_list
)
158 element_name_for (corner_s
* c
)
160 ELEMENT_LOOP (PCB
->Data
);
165 return element
->Name
[1].TextString
;
171 return element
->Name
[1].TextString
;
180 corner_name (corner_s
* c
)
182 static char buf
[4][100];
187 if (c
->net
== 0xf1eef1ee)
189 sprintf (buf
[bn
], "\033[31m[%p freed corner]\033[0m", (void *) c
);
193 sprintf (buf
[bn
], "\033[%dm[%p ",
194 (c
->pin
|| c
->pad
|| c
->via
) ? 33 : 34, (void *) c
);
195 bp
= buf
[bn
] + strlen (buf
[bn
]);
198 pcb_sprintf (bp
, "pin %s:%s at %#mD", element_name_for (c
), c
->pin
->Number
, c
->x
, c
->y
);
200 pcb_sprintf (bp
, "via at %#mD", c
->x
, c
->y
);
203 pcb_sprintf (bp
, "pad %s:%s at %#mD %#mD-%#mD",
204 element_name_for (c
), c
->pad
->Number
, c
->x
, c
->y
,
205 c
->pad
->Point1
.X
, c
->pad
->Point1
.Y
,
206 c
->pad
->Point2
.X
, c
->pad
->Point2
.Y
);
209 pcb_sprintf (bp
, "at %#mD", c
->x
, c
->y
);
210 sprintf (bp
+ strlen (bp
), " n%d l%d]\033[0m", c
->n_lines
, c
->layer
);
214 static int solder_layer
, component_layer
;
217 dj_abort (char *msg
, ...)
230 #define check(c,l) check2(__LINE__,c,l)
232 check2 (int srcline
, corner_s
* c
, line_s
* l
)
234 int saw_c
= 0, saw_l
= 0;
239 for (cc
= corners
; cc
; cc
= cc
->next
)
245 for (i
= 0; i
< cc
->n_lines
; i
++)
246 if (cc
->lines
[i
]->s
!= cc
&& cc
->lines
[i
]->e
!= cc
)
247 dj_abort ("check:%d: cc has line without backref\n", srcline
);
248 if (cc
->via
&& (cc
->x
!= cc
->via
->X
|| cc
->y
!= cc
->via
->Y
))
249 dj_abort ("check:%d: via not at corner\n", srcline
);
250 if (cc
->pin
&& (cc
->x
!= cc
->pin
->X
|| cc
->y
!= cc
->pin
->Y
))
251 dj_abort ("check:%d: pin not at corner\n", srcline
);
254 dj_abort ("check:%d: corner not in corners list\n", srcline
);
255 for (ll
= lines
; ll
; ll
= ll
->next
)
261 for (i
= 0; i
< ll
->s
->n_lines
; i
++)
262 if (ll
->s
->lines
[i
] == ll
)
264 if (i
== ll
->s
->n_lines
)
265 dj_abort ("check:%d: ll->s has no backref\n", srcline
);
266 for (i
= 0; i
< ll
->e
->n_lines
; i
++)
267 if (ll
->e
->lines
[i
] == ll
)
269 if (i
== ll
->e
->n_lines
)
270 dj_abort ("check:%d: ll->e has no backref\n", srcline
);
272 && (ll
->s
->x
!= ll
->line
->Point1
.X
273 || ll
->s
->y
!= ll
->line
->Point1
.Y
274 || ll
->e
->x
!= ll
->line
->Point2
.X
275 || ll
->e
->y
!= ll
->line
->Point2
.Y
))
277 pcb_printf ("line: %#mD to %#mD pcbline: %#mD to %#mD\n",
281 ll
->line
->Point1
.Y
, ll
->line
->Point2
.X
, ll
->line
->Point2
.Y
);
282 dj_abort ("check:%d: line doesn't match pcbline\n", srcline
);
286 dj_abort ("check:%d: line not in lines list\n", srcline
);
291 #define SWAP(a,b) { a^=b; b^=a; a^=b; }
298 return n
- n
% (Settings
.Grid
);
301 /* Avoid commonly used names. */
306 return x
> 0 ? x
: -x
;
312 return x
> y
? x
: y
;
318 return x
< y
? x
: y
;
322 * Find distance between 2 points. We use floating point math here
323 * because we can fairly easily overflow a 32 bit integer here. In
324 * fact it only takes 0.46" to do so.
327 dist (int x1
, int y1
, int x2
, int y2
)
329 double dx1
, dy1
, dx2
, dy2
, d
;
336 d
= sqrt ((dx1
- dx2
) * (dx1
- dx2
) + (dy1
- dy2
) * (dy1
- dy2
));
343 line_length (line_s
* l
)
345 if (l
->s
->x
== l
->e
->x
)
346 return djabs (l
->s
->y
- l
->e
->y
);
347 if (l
->s
->y
== l
->e
->y
)
348 return djabs (l
->s
->x
- l
->e
->x
);
349 return dist (l
->s
->x
, l
->s
->y
, l
->e
->x
, l
->e
->y
);
353 dist_ltp2 (int dx
, int y
, int y1
, int y2
)
358 return dist (dx
, y
, 0, y1
);
360 return dist (dx
, y
, 0, y2
);
371 intersecting_layers (int l1
, int l2
)
373 if (l1
== -1 || l2
== -1)
377 if (layer_groupings
[l1
] == layer_groupings
[l2
])
383 dist_line_to_point (line_s
* l
, corner_s
* c
)
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
);
392 /* Do it the hard way. See comments for IsPointOnLine() in search.c */
393 len
= sqrt (sqr (l
->s
->x
- l
->e
->x
) + sqr (l
->s
->y
- l
->e
->y
));
395 return dist (l
->s
->x
, l
->s
->y
, c
->x
, c
->y
);
397 (l
->s
->y
- c
->y
) * (l
->s
->y
- l
->e
->y
) + (l
->s
->x
- c
->x
) * (l
->s
->x
-
401 return dist (l
->s
->x
, l
->s
->y
, c
->x
, c
->y
);
403 return dist (l
->e
->x
, l
->e
->y
, c
->x
, c
->y
);
405 (l
->e
->y
- l
->s
->y
) * (c
->x
* l
->s
->x
) + (l
->e
->x
- l
->s
->x
) * (c
->y
-
407 return (int) (d
/ len
);
411 line_orient (line_s
* l
, corner_s
* c
)
446 common_corner (line_s
* l1
, line_s
* l2
)
448 if (l1
->s
== l2
->s
|| l1
->s
== l2
->e
)
450 if (l1
->e
== l2
->s
|| l1
->e
== l2
->e
)
452 dj_abort ("common_corner: no common corner found\n");
458 other_corner (line_s
* l
, corner_s
* c
)
464 dj_abort ("other_corner: neither corner passed\n");
469 find_corner_if (int x
, int y
, int l
)
472 for (c
= corners
; c
; c
= c
->next
)
476 if (c
->x
!= x
|| c
->y
!= y
)
478 if (!(c
->layer
== -1 || intersecting_layers (c
->layer
, l
)))
486 find_corner (int x
, int y
, int l
)
489 for (c
= corners
; c
; c
= c
->next
)
493 if (c
->x
!= x
|| c
->y
!= y
)
495 if (!(c
->layer
== -1 || intersecting_layers (c
->layer
, l
)))
499 c
= (corner_s
*) malloc (sizeof (corner_s
));
510 c
->lines
= (line_s
**) malloc (INC
* sizeof (line_s
*));
515 add_line_to_corner (line_s
* l
, corner_s
* c
)
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
;
522 dprintf ("add_line_to_corner %#mD\n", c
->x
, c
->y
);
526 create_pcb_line (int layer
, int x1
, int y1
, int x2
, int y2
,
527 int thick
, int clear
, FlagType flags
)
531 LayerType
*lyr
= LAYER_PTR (layer
);
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
);
538 to
= (char *) lyr
->Line
;
542 for (lp
= lines
; lp
; lp
= lp
->next
)
546 if ((char *) (lp
->line
) >= from
547 && (char *) (lp
->line
) <= from
+ lyr
->LineN
* sizeof (LineType
))
548 lp
->line
= (LineType
*) ((char *) (lp
->line
) + (to
- from
));
555 new_line (corner_s
* s
, corner_s
* e
, int layer
, LineType
* example
)
559 if (layer
>= max_copper_layer
)
560 dj_abort ("layer %d\n", layer
);
563 dj_abort ("NULL example passed to new_line()\n", layer
);
565 if (s
->x
== e
->x
&& s
->y
== e
->y
)
568 ls
= (line_s
*) malloc (sizeof (line_s
));
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
))
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
));
592 create_pcb_line (layer
, s
->x
, s
->y
, e
->x
, e
->y
, example
->Thickness
,
593 example
->Clearance
, example
->Flags
);
596 dj_abort ("can't create new line!");
599 add_line_to_corner (ls
, s
);
600 add_line_to_corner (ls
, e
);
608 c_orth_to (corner_s
* c
, line_s
* l
, int o
)
612 for (i
= 0; i
< c
->n_lines
; i
++)
614 if (c
->lines
[i
] == l
)
616 o2
= line_orient (c
->lines
[i
], c
);
617 if (ORIENT (o
) == ORIENT (o2
) || o2
== DIAGONAL
)
626 other_line (corner_s
* c
, line_s
* l
)
630 if (c
->pin
|| c
->pad
|| c
->via
)
632 for (i
= 0; i
< c
->n_lines
; i
++)
634 if (c
->lines
[i
] == l
)
644 empty_rect (rect_s
* rect
)
646 rect
->x1
= rect
->y1
= INT_MAX
;
647 rect
->x2
= rect
->y2
= INT_MIN
;
651 add_point_to_rect (rect_s
* rect
, int x
, int y
, int w
)
653 if (rect
->x1
> x
- w
)
655 if (rect
->x2
< x
+ w
)
657 if (rect
->y1
> y
- w
)
659 if (rect
->y2
< y
+ w
)
664 add_line_to_rect (rect_s
* rect
, line_s
* l
)
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);
671 pin_in_rect (rect_s
* r
, int x
, int y
, int w
)
673 if (x
< r
->x1
&& x
+ w
< r
->x1
)
675 if (x
> r
->x2
&& x
- w
> r
->x2
)
677 if (y
< r
->y1
&& y
+ w
< r
->y1
)
679 if (y
> r
->y2
&& y
- w
> r
->y2
)
685 line_in_rect (rect_s
* r
, line_s
* l
)
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 */
702 if (lr
.x1
< lr
.x2
&& lr
.y1
< lr
.y2
)
708 corner_radius (corner_s
* c
)
713 diam
= djmax (c
->pin
->Thickness
, diam
);
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;
726 corner_layer (corner_s
* c
)
728 if (c
->pin
|| c
->via
)
732 return c
->lines
[0]->layer
;
737 add_corner_to_rect_if (rect_s
* rect
, corner_s
* c
, rect_s
* e
)
739 int diam
= corner_radius (c
);
740 if (!pin_in_rect (e
, c
->x
, c
->y
, diam
))
742 if (c
->x
< e
->x1
&& c
->y
< e
->y1
&& dist (c
->x
, c
->y
, e
->x1
, e
->y1
) > diam
)
744 if (c
->x
> e
->x2
&& c
->y
< e
->y1
&& dist (c
->x
, c
->y
, e
->x2
, e
->y1
) > diam
)
746 if (c
->x
< e
->x1
&& c
->y
> e
->y2
&& dist (c
->x
, c
->y
, e
->x1
, e
->y2
) > diam
)
748 if (c
->x
> e
->x2
&& c
->y
> e
->y2
&& dist (c
->x
, c
->y
, e
->x2
, e
->y2
) > diam
)
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
);
756 remove_line (line_s
* l
)
759 LayerType
*layer
= &(PCB
->Data
->Layer
[l
->layer
]);
764 RemoveLine (layer
, l
->line
);
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
];
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
];
781 move_line_to_layer (line_s
* l
, int layer
)
785 ls
= LAYER_PTR (l
->layer
);
786 ld
= LAYER_PTR (layer
);
788 MoveObjectToLayer (LINE_TYPE
, ls
, l
->line
, 0, ld
, 0);
793 remove_via_at (corner_s
* c
)
795 RemoveObject (VIA_TYPE
, c
->via
, 0, 0);
800 remove_corner (corner_s
* c2
)
803 dprintf ("remove corner %s\n", corner_name (c2
));
806 for (c
= corners
; c
; c
= c
->next
)
813 if (next_corner
== c2
)
814 next_corner
= c2
->next
;
821 merge_corners (corner_s
* c1
, corner_s
* c2
)
826 dprintf ("merge corners %s %s\n", corner_name (c1
), corner_name (c2
));
827 for (i
= 0; i
< c2
->n_lines
; i
++)
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
;
835 if (c1
->via
&& c2
->via
)
843 if (c2
->layer
!= c1
->layer
)
850 move_corner (corner_s
* c
, int x
, int y
)
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
);
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
);
869 for (i
= 0; i
< c
->n_lines
; i
++)
871 LineType
*tl
= c
->lines
[i
]->line
;
874 if (c
->lines
[i
]->s
== c
)
876 MoveObject (LINEPOINT_TYPE
, LAYER_PTR (c
->lines
[i
]->layer
), tl
,
877 &tl
->Point1
, x
- (tl
->Point1
.X
),
882 MoveObject (LINEPOINT_TYPE
, LAYER_PTR (c
->lines
[i
]->layer
), tl
,
883 &tl
->Point2
, x
- (tl
->Point2
.X
),
886 dprintf ("Line %p moved to %#mD %#mD\n", (void *) tl
,
887 tl
->Point1
.X
, tl
->Point1
.Y
, tl
->Point2
.X
, tl
->Point2
.Y
);
891 merge_corners (c
, pad
);
893 for (i
= 0; i
< c
->n_lines
; i
++)
895 if (c
->lines
[i
]->s
->x
== c
->lines
[i
]->e
->x
896 && c
->lines
[i
]->s
->y
== c
->lines
[i
]->e
->y
)
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
);
902 remove_line (c
->lines
[i
]);
904 merge_corners (c
, c2
);
910 gui
->progress (0, 0, 0);
918 for (l
= lines
; l
; l
= l
->next
)
922 if (l
->line
&& selected (l
->line
))
929 trim_step (int s
, int l1
, int l2
)
931 dprintf ("trim %d %d %d\n", s
, l1
, l2
);
936 if (s
!= l1
&& s
!= l2
)
941 static int canonicalize_line (line_s
* l
);
944 split_line (line_s
* l
, corner_s
* c
)
950 if (!intersecting_layers (l
->layer
, c
->layer
))
956 dprintf ("split on pad!\n");
957 if (l
->s
->pad
== c
->pad
|| l
->e
->pad
== c
->pad
)
959 dprintf ("splitting...\n");
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
,
968 return 0; /* already a line there */
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
));
982 ls
->layer
= l
->layer
;
983 for (i
= 0; i
< l
->e
->n_lines
; i
++)
984 if (l
->e
->lines
[i
] == l
)
987 add_line_to_corner (l
, c
);
988 add_line_to_corner (ls
, c
);
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
));
997 canonicalize_line (line_s
* l
)
999 /* This could be faster */
1001 if (l
->s
->x
== l
->e
->x
)
1005 int x1
= l
->s
->x
- l
->line
->Thickness
/ 2;
1006 int x2
= l
->s
->x
+ l
->line
->Thickness
/ 2;
1013 for (c
= corners
; c
; c
= c
->next
)
1017 if ((y1
< c
->y
&& c
->y
< y2
)
1018 && intersecting_layers (l
->layer
, c
->layer
))
1021 && c
->x
< x2
&& c
->x
> x1
&& !(c
->pad
|| c
->pin
))
1023 move_corner (c
, l
->s
->x
, c
->y
);
1025 if (c
->x
== l
->s
->x
)
1027 /* FIXME: if the line is split, we have to re-canonicalize
1029 return split_line (l
, c
);
1034 else if (l
->s
->y
== l
->e
->y
)
1038 int y1
= l
->s
->y
- l
->line
->Thickness
/ 2;
1039 int y2
= l
->s
->y
+ l
->line
->Thickness
/ 2;
1046 for (c
= corners
; c
; c
= c
->next
)
1050 if ((x1
< c
->x
&& c
->x
< x2
)
1051 && intersecting_layers (l
->layer
, c
->layer
))
1054 && c
->y
< y2
&& c
->y
> y1
&& !(c
->pad
|| c
->pin
))
1056 move_corner (c
, c
->x
, l
->s
->y
);
1058 if (c
->y
== l
->s
->y
)
1060 /* FIXME: Likewise. */
1061 return split_line (l
, c
);
1068 /* diagonal lines. Let's try to split them at pins/vias
1086 for (c
= corners
; c
; c
= c
->next
)
1090 if (!c
->via
&& !c
->pin
)
1092 if ((x1
< c
->x
&& c
->x
< x2
)
1093 && (y1
< c
->y
&& c
->y
< y2
)
1094 && intersecting_layers (l
->layer
, c
->layer
))
1096 int th
= c
->pin
? c
->pin
->Thickness
: c
->via
->Thickness
;
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
))
1102 return split_line (l
, c
);
1110 /* Make sure all vias are at line end points */
1112 canonicalize_lines ()
1120 for (l
= lines
; l
; l
= l
->next
)
1124 count
+= canonicalize_line (l
);
1134 simple_optimize_corner (corner_s
* c
)
1142 /* see if no via is needed */
1143 if (selected (c
->via
))
1144 dprintf ("via check: line[0] layer %d at %#mD nl %d\n",
1145 c
->lines
[0]->layer
, c
->x
, c
->y
, c
->n_lines
);
1146 /* We can't delete vias that connect to power planes, or vias
1147 that aren't tented (assume they're test points). */
1148 if (!TEST_ANY_THERMS (c
->via
)
1149 && c
->via
->Mask
== 0)
1151 for (i
= 1; i
< c
->n_lines
; i
++)
1153 if (selected (c
->via
))
1154 dprintf (" line[%d] layer %d %#mD to %#mD\n",
1155 i
, c
->lines
[i
]->layer
,
1156 c
->lines
[i
]->s
->x
, c
->lines
[i
]->s
->y
,
1157 c
->lines
[i
]->e
->x
, c
->lines
[i
]->e
->y
);
1158 if (c
->lines
[i
]->layer
!= c
->lines
[0]->layer
)
1161 if (i
== c
->n_lines
)
1163 if (selected (c
->via
))
1164 dprintf (" remove it\n");
1172 if (c
->n_lines
== 2 && !c
->via
)
1174 /* see if it is an unneeded corner */
1175 int o
= line_orient (c
->lines
[0], c
);
1176 corner_s
*c2
= other_corner (c
->lines
[1], c
);
1177 corner_s
*c0
= other_corner (c
->lines
[0], c
);
1178 if (o
== line_orient (c
->lines
[1], c2
) && o
!= DIAGONAL
)
1180 dprintf ("straight %#mD to %#mD to %#mD\n",
1181 c0
->x
, c0
->y
, c
->x
, c
->y
, c2
->x
, c2
->y
);
1182 if (selected (c
->lines
[0]->line
))
1183 SET_FLAG (SELECTEDFLAG
, c
->lines
[1]->line
);
1184 if (selected (c
->lines
[1]->line
))
1185 SET_FLAG (SELECTEDFLAG
, c
->lines
[0]->line
);
1186 move_corner (c
, c2
->x
, c2
->y
);
1190 if (c
->n_lines
== 1 && !c
->via
)
1192 corner_s
*c0
= other_corner (c
->lines
[0], c
);
1193 if (abs(c
->x
- c0
->x
) + abs(c
->y
- c0
->y
) <= LONGEST_FRECKLE
)
1196 * Remove this line, as it is a "freckle". A freckle is an extremely
1197 * short line (around 0.01 thou) that is unconnected at one end.
1198 * Freckles are almost insignificantly small, but are annoying as
1199 * they prevent the mitering optimiser from working.
1200 * Freckles sometimes arise because of a bug in the autorouter that
1201 * causes it to create small overshoots (typically 0.01 thou) at the
1202 * intersections of vertical and horizontal lines. These overshoots
1203 * are converted to freckles as a side effect of canonicalize_line().
1204 * Note that canonicalize_line() is not at fault, the bug is in the
1205 * autorouter creating overshoots.
1206 * The autorouter bug arose some time between the 20080202 and 20091103
1208 * This code is probably worth keeping even when the autorouter bug is
1209 * fixed, as "freckles" could conceivably arise in other ways.
1211 dprintf ("freckle %#mD to %#mD\n", c
->x
, c
->y
, c0
->x
, c0
->y
);
1212 move_corner (c
, c0
->x
, c0
->y
);
1219 /* We always run these */
1221 simple_optimizations ()
1226 /* Look for corners that aren't */
1227 for (c
= corners
; c
; c
= c
->next
)
1231 if (c
->pad
|| c
->pin
)
1233 rv
+= simple_optimize_corner (c
);
1239 is_hole (corner_s
* c
)
1241 return c
->pin
|| c
->pad
|| c
->via
;
1245 orthopull_1 (corner_s
* c
, int fdir
, int rdir
, int any_sel
)
1247 static corner_s
**cs
= 0;
1249 static line_s
**ls
= 0;
1251 int i
, li
, ln
, cn
, snap
;
1254 int adir
= 0, sdir
= 0, pull
;
1255 int saw_sel
= 0, saw_auto
= 0;
1256 int max
, len
= 0, r1
= 0, r2
;
1262 cs
= (corner_s
**) malloc (10 * sizeof (corner_s
));
1264 ls
= (line_s
**) malloc (10 * sizeof (line_s
));
1268 for (i
= 0; i
< c
->n_lines
; i
++)
1270 int o
= line_orient (c
->lines
[i
], c
);
1286 dj_abort ("fdir not right or down\n");
1295 if (c2
->pad
|| c2
->pin
|| c2
->n_lines
< 2)
1300 cs
= (corner_s
**) realloc (cs
, cm
* sizeof (corner_s
*));
1303 r2
= corner_radius (c2
);
1307 for (i
= 0; i
< c2
->n_lines
; i
++)
1309 int o
= line_orient (c2
->lines
[i
], c2
);
1315 return 0; /* we don't support overlapping lines yet */
1318 if (o
== rdir
&& c2
->lines
[i
] != ls
[ln
- 1])
1319 return 0; /* likewise */
1327 if (selected (l
->line
))
1329 if (autorouted (l
->line
))
1334 ls
= (line_s
**) realloc (ls
, lm
* sizeof (line_s
*));
1337 c2
= other_corner (l
, c2
);
1339 if (cn
< 2 || pull
== 0)
1341 if (any_sel
&& !saw_sel
)
1343 if (!any_sel
&& autorouted_only
&& !saw_auto
)
1346 /* Ok, now look for other blockages. */
1349 add_point_to_rect (&rr
, c
->x
, c
->y
, corner_radius (c
));
1350 add_point_to_rect (&rr
, c2
->x
, c2
->y
, corner_radius (c2
));
1352 if (fdir
== RIGHT
&& pull
< 0)
1354 else if (fdir
== RIGHT
&& pull
> 0)
1356 else if (fdir
== DOWN
&& pull
< 0)
1358 else if (fdir
== DOWN
&& pull
> 0)
1362 for (i
= 0; i
< cn
; i
++)
1363 for (li
= 0; li
< cs
[i
]->n_lines
; li
++)
1365 if (line_orient (cs
[i
]->lines
[li
], cs
[i
]) != edir
)
1367 len
= line_length (cs
[i
]->lines
[li
]);
1368 if (max
> len
|| max
== -1)
1371 dprintf ("c %s %4#mD cn %d pull %3d max %4#mS\n",
1372 fdir
== RIGHT
? "right" : "down ", c
->x
, c
->y
, cn
, pull
, max
);
1377 rr
.y1
= c
->y
- r1
- max
;
1380 rr
.y2
= c
->y
+ r1
+ max
;
1383 rr
.x1
= c
->x
- r1
- max
;
1386 rr
.x2
= c
->x
+ r1
+ max
;
1395 for (cb
= corners
; cb
; cb
= cb
->next
)
1400 r1
= corner_radius (cb
);
1401 if (cb
->net
== c
->net
&& !cb
->pad
)
1403 if (!pin_in_rect (&rr
, cb
->x
, cb
->y
, r1
))
1407 #define ECHK(X,Y,LT) \
1408 for (i=0; i<cn; i++) \
1410 if (!intersecting_layers(cs[i]->layer, cb->layer)) \
1412 r2 = corner_radius(cs[i]); \
1413 if (cb->X + r1 <= cs[i]->X - r2 - SB - 1) \
1415 if (cb->X - r1 >= cs[i]->X + r2 + SB + 1) \
1417 if (cb->Y LT cs[i]->Y) \
1419 sep = djabs(cb->Y - cs[i]->Y) - r1 - r2 - SB - 1; \
1421 { max = sep; snap = 1; }\
1423 for (i=0; i<ln; i++) \
1425 if (!intersecting_layers(ls[i]->layer, cb->layer)) \
1427 if (cb->X <= cs[i]->X || cb->X >= cs[i+1]->X) \
1429 sep = (djabs(cb->Y - cs[i]->Y) - ls[i]->line->Thickness/2 \
1432 { max = sep; snap = 1; }\
1449 /* We must now check every line segment against our corners. */
1450 for (l
= lines
; l
; l
= l
->next
)
1452 int o
, x1
, x2
, y1
, y2
;
1455 dprintf ("check line %#mD to %#mD\n", l
->s
->x
, l
->s
->y
, l
->e
->x
, l
->e
->y
);
1456 if (l
->s
->net
== c
->net
)
1458 dprintf (" same net\n");
1461 o
= line_orient (l
, 0);
1462 /* We don't need to check perpendicular lines, because their
1463 corners already take care of it. */
1464 if ((fdir
== RIGHT
&& (o
== UP
|| o
== DOWN
))
1465 || (fdir
== DOWN
&& (o
== RIGHT
|| o
== LEFT
)))
1467 dprintf (" perpendicular\n");
1471 /* Choose so that x1,y1 is closest to corner C */
1472 if ((fdir
== RIGHT
&& l
->s
->x
< l
->e
->x
)
1473 || (fdir
== DOWN
&& l
->s
->y
< l
->e
->y
))
1488 /* Eliminate all lines outside our range */
1489 if ((fdir
== RIGHT
&& (x2
< c
->x
|| x1
> c2
->x
))
1490 || (fdir
== DOWN
&& (y2
< c
->y
|| y1
> c2
->y
)))
1492 dprintf (" outside our range\n");
1496 /* Eliminate all lines on the wrong side of us */
1497 if ((edir
== UP
&& y1
> c
->y
&& y2
> c
->y
)
1498 || (edir
== DOWN
&& y1
< c
->y
&& y2
< c
->y
)
1499 || (edir
== LEFT
&& x1
> c
->x
&& x2
> c
->x
)
1500 || (edir
== RIGHT
&& x1
< c
->x
&& x2
< c
->x
))
1502 dprintf (" wrong side\n");
1506 /* For now, cheat on diagonals */
1527 /* Ok, now see how far we can get for each of our corners. */
1528 for (i
= 0; i
< cn
; i
++)
1530 int r
= l
->line
->Thickness
+ SB
+ corner_radius (cs
[i
]) + 1;
1532 if ((fdir
== RIGHT
&& (x2
< cs
[i
]->x
|| x1
> cs
[i
]->x
))
1533 || (fdir
== DOWN
&& (y2
< cs
[i
]->y
|| y1
> cs
[i
]->y
)))
1535 if (!intersecting_layers (cs
[i
]->layer
, l
->layer
))
1553 dprintf (" len is %#mS vs corner at %#mD\n", len
, cs
[i
]->x
, cs
[i
]->y
);
1562 /* We must make sure that if a segment isn't being completely
1563 removed, that any vias and/or pads don't overlap. */
1568 for (i
= 0; i
< cn
; i
++)
1569 for (li
= 0; li
< cs
[i
]->n_lines
; li
++)
1571 line_s
*l
= cs
[i
]->lines
[li
];
1572 corner_s
*oc
= other_corner (l
, cs
[i
]);
1573 if (line_orient (l
, cs
[i
]) != edir
)
1575 len
= line_length (l
);
1576 if (!oc
->pad
|| !cs
[i
]->via
)
1578 if (!is_hole (l
->s
) || !is_hole (l
->e
))
1583 len
-= corner_radius (l
->s
);
1584 len
-= corner_radius (l
->e
);
1611 if (snap
&& max
> Settings
.Grid
)
1614 len
+= Settings
.Grid
- 1;
1615 len
= gridsnap (len
);
1617 if ((fdir
== RIGHT
&& len
== cs
[0]->y
) || (fdir
== DOWN
&& len
== cs
[0]->x
))
1619 for (i
= 0; i
< cn
; i
++)
1623 max
= len
- cs
[i
]->y
;
1624 move_corner (cs
[i
], cs
[i
]->x
, len
);
1628 max
= len
- cs
[i
]->x
;
1629 move_corner (cs
[i
], len
, cs
[i
]->y
);
1638 /* Look for straight runs which could be moved to reduce total trace
1640 int any_sel
= any_line_selected ();
1644 for (c
= corners
; c
;)
1648 if (c
->pin
|| c
->pad
)
1654 rv
+= orthopull_1 (c
, RIGHT
, LEFT
, any_sel
);
1655 if (c
!= next_corner
)
1660 rv
+= orthopull_1 (c
, DOWN
, UP
, any_sel
);
1661 if (c
!= next_corner
)
1669 pcb_printf ("orthopull: %ml mils saved\n", rv
);
1676 /* Look for "U" shaped traces we can shorten (or eliminate) */
1678 int any_selected
= any_line_selected ();
1679 line_s
*l
, *l1
, *l2
;
1680 corner_s
*c
, *c1
, *c2
;
1682 int o
, o1
, o2
, step
, w
;
1683 for (l
= lines
; l
; l
= l
->next
)
1689 if (any_selected
&& !selected (l
->line
))
1691 if (!any_selected
&& autorouted_only
&& !autorouted (l
->line
))
1693 if (l
->s
->pin
|| l
->s
->pad
|| l
->e
->pin
|| l
->e
->pad
)
1695 o
= line_orient (l
, 0);
1698 l1
= other_line (l
->s
, l
);
1701 o1
= line_orient (l1
, l
->s
);
1702 l2
= other_line (l
->e
, l
);
1705 o2
= line_orient (l2
, l
->e
);
1706 if (ORIENT (o
) == ORIENT (o1
) || o1
!= o2
|| o1
== DIAGONAL
)
1709 dprintf ("\nline: %#mD to %#mD\n", l
->s
->x
, l
->s
->y
, l
->e
->x
, l
->e
->y
);
1710 w
= l
->line
->Thickness
/ 2 + SB
+ 1;
1712 add_line_to_rect (&rr
, l1
);
1713 add_line_to_rect (&rr
, l2
);
1714 if (rr
.x1
!= l
->s
->x
&& rr
.x1
!= l
->e
->x
)
1716 if (rr
.x2
!= l
->s
->x
&& rr
.x2
!= l
->e
->x
)
1718 if (rr
.y1
!= l
->s
->y
&& rr
.y1
!= l
->e
->y
)
1720 if (rr
.y2
!= l
->s
->y
&& rr
.y2
!= l
->e
->y
)
1722 dprintf ("range: x %#mS..%#mS y %#mS..%#mS\n", rr
.x1
, rr
.x2
, rr
.y1
, rr
.y2
);
1724 c1
= other_corner (l1
, l
->s
);
1725 c2
= other_corner (l2
, l
->e
);
1728 for (c
= corners
; c
; c
= c
->next
)
1732 if (c
->net
!= l
->s
->net
1733 && intersecting_layers (c
->layer
, l
->s
->layer
))
1734 add_corner_to_rect_if (&rp
, c
, &rr
);
1736 if (rp
.x1
== INT_MAX
)
1743 dprintf ("pin r: x %#mS..%#mS y %#mS..%#mS\n", rp
.x1
, rp
.x2
, rp
.y1
, rp
.y2
);
1748 step
= l
->s
->x
- rp
.x2
- w
;
1749 step
= gridsnap (step
);
1750 if (step
> l
->s
->x
- c1
->x
)
1751 step
= l
->s
->x
- c1
->x
;
1752 if (step
> l
->s
->x
- c2
->x
)
1753 step
= l
->s
->x
- c2
->x
;
1756 dprintf ("left step %#mS at %#mD\n", step
, l
->s
->x
, l
->s
->y
);
1757 move_corner (l
->s
, l
->s
->x
- step
, l
->s
->y
);
1758 move_corner (l
->e
, l
->e
->x
- step
, l
->e
->y
);
1763 step
= rp
.x1
- l
->s
->x
- w
;
1764 step
= gridsnap (step
);
1765 if (step
> c1
->x
- l
->s
->x
)
1766 step
= c1
->x
- l
->s
->x
;
1767 if (step
> c2
->x
- l
->s
->x
)
1768 step
= c2
->x
- l
->s
->x
;
1771 dprintf ("right step %#mS at %#mD\n", step
, l
->s
->x
, l
->s
->y
);
1772 move_corner (l
->s
, l
->s
->x
+ step
, l
->s
->y
);
1773 move_corner (l
->e
, l
->e
->x
+ step
, l
->e
->y
);
1778 if (rp
.y2
== INT_MIN
)
1780 step
= trim_step (l
->s
->y
- rp
.y2
- w
,
1781 l
->s
->y
- c1
->y
, l
->s
->y
- c2
->y
);
1784 dprintf ("up step %#mS at %#mD\n", step
, l
->s
->x
, l
->s
->y
);
1785 move_corner (l
->s
, l
->s
->x
, l
->s
->y
- step
);
1786 move_corner (l
->e
, l
->e
->x
, l
->e
->y
- step
);
1791 step
= rp
.y1
- l
->s
->y
- w
;
1792 step
= gridsnap (step
);
1793 if (step
> c1
->y
- l
->s
->y
)
1794 step
= c1
->y
- l
->s
->y
;
1795 if (step
> c2
->y
- l
->s
->y
)
1796 step
= c2
->y
- l
->s
->y
;
1799 dprintf ("down step %#mS at %#mD\n", step
, l
->s
->x
, l
->s
->y
);
1800 move_corner (l
->s
, l
->s
->x
, l
->s
->y
+ step
);
1801 move_corner (l
->e
, l
->e
->x
, l
->e
->y
+ step
);
1809 rv
+= simple_optimizations ();
1811 pcb_printf ("debumpify: %ml mils saved\n", rv
/ 50);
1816 simple_corner (corner_s
* c
)
1819 if (c
->pad
|| c
->pin
|| c
->via
)
1821 if (c
->n_lines
!= 2)
1823 o1
= line_orient (c
->lines
[0], c
);
1824 o2
= line_orient (c
->lines
[1], c
);
1825 if (ORIENT (o1
) == ORIENT (o2
))
1827 if (ORIENT (o1
) == DIAGONAL
|| ORIENT (o2
) == DIAGONAL
)
1835 /* Look for sequences of simple corners we can reduce. */
1837 corner_s
*c
, *c0
, *c1
, *cc
;
1838 int l
, w
, sel
= any_line_selected ();
1841 for (c
= corners
; c
; c
= c
->next
)
1845 if (!simple_corner (c
))
1847 if (!c
->lines
[0]->line
|| !c
->lines
[1]->line
)
1849 if (sel
&& !(selected (c
->lines
[0]->line
)
1850 || selected (c
->lines
[1]->line
)))
1852 if (!sel
&& autorouted_only
1853 && !(autorouted (c
->lines
[0]->line
)
1854 || autorouted (c
->lines
[1]->line
)))
1856 dprintf ("simple at %#mD\n", c
->x
, c
->y
);
1858 c0
= other_corner (c
->lines
[0], c
);
1859 o0
= line_orient (c
->lines
[0], c
);
1860 s0
= simple_corner (c0
);
1862 c1
= other_corner (c
->lines
[1], c
);
1863 o1
= line_orient (c
->lines
[1], c
);
1864 s1
= simple_corner (c1
);
1868 dprintf ("simples at %#mD\n", c
->x
, c
->y
);
1871 for (l
= 0; l
< c0
->n_lines
; l
++)
1872 if (c0
->lines
[l
] != c
->lines
[0]
1873 && c0
->lines
[l
]->layer
== c
->lines
[0]->layer
)
1875 int o
= line_orient (c0
->lines
[l
], c0
);
1879 for (l
= 0; l
< c1
->n_lines
; l
++)
1880 if (c1
->lines
[l
] != c
->lines
[0]
1881 && c1
->lines
[l
]->layer
== c
->lines
[0]->layer
)
1883 int o
= line_orient (c1
->lines
[l
], c1
);
1889 dprintf ("orient ok\n");
1891 w
= c
->lines
[0]->line
->Thickness
/ 2 + SB
+ 1;
1893 add_line_to_rect (&rr
, c
->lines
[0]);
1894 add_line_to_rect (&rr
, c
->lines
[1]);
1905 for (cc
= corners
; cc
; cc
= cc
->next
)
1909 if (cc
->net
!= c
->net
&& intersecting_layers (cc
->layer
, c
->layer
))
1910 add_corner_to_rect_if (&rp
, cc
, &rr
);
1912 dprintf ("rp x %#mS..%#mS y %#mS..%#mS\n", rp
.x1
, rp
.x2
, rp
.y1
, rp
.y2
);
1913 if (rp
.x1
<= rp
.x2
) /* something triggered */
1916 dprintf ("unjaggy at %#mD layer %d\n", c
->x
, c
->y
, c
->layer
);
1918 move_corner (c
, c1
->x
, c0
->y
);
1920 move_corner (c
, c0
->x
, c1
->y
);
1924 rv
+= simple_optimizations ();
1933 for (i
= 0; i
< 100; i
++)
1935 j
= unjaggy_once ();
1941 printf ("%d unjagg%s \n", r
, r
== 1 ? "y" : "ies");
1948 /* Look for vias with all lines leaving the same way, try to nudge
1949 via to eliminate one or more of them. */
1951 corner_s
*c
, *c2
, *c3
;
1953 unsigned char directions
[MAX_LAYER
];
1954 unsigned char counts
[MAX_LAYER
];
1956 memset (directions
, 0, sizeof (directions
));
1957 memset (counts
, 0, sizeof (counts
));
1959 for (c
= corners
; c
; c
= c
->next
)
1961 int o
, i
, vr
, cr
, oboth
;
1962 int len
= 0, saved
= 0;
1970 memset (directions
, 0, sizeof (directions
));
1971 memset (counts
, 0, sizeof (counts
));
1973 for (i
= 0; i
< c
->n_lines
; i
++)
1975 o
= line_orient (c
->lines
[i
], c
);
1976 counts
[c
->lines
[i
]->layer
]++;
1977 directions
[c
->lines
[i
]->layer
] |= o
;
1979 for (o
= 0, i
= 0; i
< max_copper_layer
; i
++)
1989 oboth
= LEFT
| RIGHT
;
1998 for (i
= 0; i
< max_copper_layer
; i
++)
1999 if (counts
[i
] && directions
[i
] != o
&& directions
[i
] != oboth
)
2000 goto vianudge_continue
;
2003 for (i
= 0; i
< c
->n_lines
; i
++)
2005 int ll
= line_length (c
->lines
[i
]);
2006 if (line_orient (c
->lines
[i
], c
) != o
)
2012 if (c2
== 0 || len
> ll
)
2015 c2
= other_corner (c
->lines
[i
], c
);
2018 if (c2
->pad
|| c2
->pin
|| c2
->via
)
2021 /* Now look for clearance in the new position */
2022 vr
= c
->via
->Thickness
/ 2 + SB
+ 1;
2023 for (c3
= corners
; c3
; c3
= c3
->next
)
2027 if ((c3
->net
!= c
->net
&& (c3
->pin
|| c3
->via
)) || c3
->pad
)
2029 cr
= corner_radius (c3
);
2030 if (dist (c2
->x
, c2
->y
, c3
->x
, c3
->y
) < vr
+ cr
)
2031 goto vianudge_continue
;
2034 for (l
= lines
; l
; l
= l
->next
)
2038 if (l
->s
->net
!= c
->net
)
2040 int ld
= dist_line_to_point (l
, c2
);
2041 if (ld
< l
->line
->Thickness
/ 2 + vr
)
2042 goto vianudge_continue
;
2046 /* at this point, we know we can move it */
2048 dprintf ("vianudge: nudging via at %#mD by %#mS saving %#mS\n",
2049 c
->x
, c
->y
, len
, saved
);
2051 move_corner (c
, c2
->x
, c2
->y
);
2060 pcb_printf ("vianudge: %ml mils saved\n", rv
);
2067 /* Look for traces that can be moved to the other side of the board,
2068 to reduce the number of vias needed. For now, we look for simple
2069 lines, not multi-segmented lines. */
2071 int i
, rv
= 0, vrm
= 0;
2072 int any_sel
= any_line_selected ();
2074 for (l
= lines
; l
; l
= l
->next
)
2077 int my_layer
, other_layer
;
2085 if (any_sel
&& !selected (l
->line
))
2087 if (!any_sel
&& autorouted_only
&& !autorouted (l
->line
))
2090 my_layer
= l
->layer
;
2092 dprintf ("line %p on layer %d from %#mD to %#mD\n", (void *) l
,
2093 l
->layer
, l
->s
->x
, l
->s
->y
, l
->e
->x
, l
->e
->y
);
2094 for (i
= 0; i
< l
->s
->n_lines
; i
++)
2095 if (l
->s
->lines
[i
] != l
)
2097 if (other_layer
== -1)
2099 other_layer
= l
->s
->lines
[i
]->layer
;
2100 dprintf ("noting other line %p on layer %d\n",
2101 (void *) (l
->s
->lines
[i
]), my_layer
);
2103 else if (l
->s
->lines
[i
]->layer
!= other_layer
)
2105 dprintf ("saw other line %p on layer %d (not %d)\n",
2106 (void *) (l
->s
->lines
[i
]), l
->s
->lines
[i
]->layer
,
2109 goto viatrim_other_corner
;
2112 viatrim_other_corner
:
2113 if (other_layer
== -1)
2114 for (i
= 0; i
< l
->e
->n_lines
; i
++)
2115 if (l
->e
->lines
[i
] != l
)
2117 if (other_layer
== -1)
2119 other_layer
= l
->s
->lines
[i
]->layer
;
2120 dprintf ("noting other line %p on layer %d\n",
2121 (void *) (l
->s
->lines
[i
]), my_layer
);
2123 else if (l
->e
->lines
[i
]->layer
!= other_layer
)
2125 dprintf ("saw end line on layer %d (not %d)\n",
2126 l
->e
->lines
[i
]->layer
, other_layer
);
2127 goto viatrim_continue
;
2131 /* Now see if any other line intersects us. We don't need to
2132 check corners, because they'd either be pins/vias and
2133 already conflict, or pads, which we'll check here anyway. */
2135 add_point_to_rect (&r
, l
->s
->x
, l
->s
->y
, l
->line
->Thickness
);
2136 add_point_to_rect (&r
, l
->e
->x
, l
->e
->y
, l
->line
->Thickness
);
2138 for (l2
= lines
; l2
; l2
= l2
->next
)
2142 if (l2
->s
->net
!= l
->s
->net
&& l2
->layer
== other_layer
)
2144 dprintf ("checking other line %#mD to %#mD\n", l2
->s
->x
,
2145 l2
->s
->y
, l2
->e
->x
, l2
->e
->y
);
2146 if (line_in_rect (&r
, l2
))
2148 dprintf ("line from %#mD to %#mD in the way\n",
2149 l2
->s
->x
, l2
->s
->y
, l2
->e
->x
, l2
->e
->y
);
2150 goto viatrim_continue
;
2155 if (l
->layer
== other_layer
)
2157 move_line_to_layer (l
, other_layer
);
2163 vrm
= simple_optimizations ();
2165 printf ("viatrim: %d traces moved, %d vias removed\n", rv
, vrm
);
2172 int more
= 1, oldmore
= 0;
2174 while (more
!= oldmore
&& --toomany
)
2177 more
+= debumpify ();
2179 more
+= orthopull ();
2180 more
+= vianudge ();
2191 int sel
= any_line_selected ();
2194 for (c
= corners
; c
; c
= c
->next
)
2199 if (c
->n_lines
== 2 && !c
->via
&& !c
->pin
&& !c
->via
)
2201 int o1
= line_orient (c
->lines
[0], c
);
2202 int o2
= line_orient (c
->lines
[1], c
);
2203 if (ORIENT (o1
) != ORIENT (o2
)
2204 && o1
!= DIAGONAL
&& o2
!= DIAGONAL
2205 && c
->lines
[0]->line
->Thickness
== c
->lines
[1]->line
->Thickness
)
2212 while (!done
&& progress
)
2216 for (c
= corners
; c
; c
= c
->next
)
2222 int max
= line_length (c
->lines
[0]);
2223 int len
= line_length (c
->lines
[1]);
2226 corner_s
*closest_corner
= 0, *c2
, *oc1
, *oc2
;
2227 int mx
= 0, my
= 0, x
, y
;
2228 int o1
= line_orient (c
->lines
[0], c
);
2229 int o2
= line_orient (c
->lines
[1], c
);
2231 if (c
->pad
|| c
->pin
|| c
->via
)
2238 oc1
= other_corner (c
->lines
[0], c
);
2239 oc2
= other_corner (c
->lines
[1], c
);
2247 if ((sel
&& !(selected (c
->lines
[0]->line
)
2248 || selected (c
->lines
[1]->line
)))
2249 || (!sel
&& autorouted_only
2250 && !(autorouted (c
->lines
[0]->line
)
2251 || autorouted (c
->lines
[1]->line
))))
2290 ref
= c
->x
* mx
+ c
->y
* my
;
2293 bloat
= (c
->lines
[0]->line
->Thickness
/ 2 + SB
+ 1) * 3 / 2;
2295 for (c2
= corners
; c2
; c2
= c2
->next
)
2299 if (c2
!= c
&& c2
!= oc1
&& c2
!= oc2
2300 && c
->x
* mx
<= c2
->x
* mx
2301 && c
->y
* my
<= c2
->y
* my
2302 && c
->net
!= c2
->net
2303 && intersecting_layers (c
->layer
, c2
->layer
))
2305 int cr
= corner_radius (c2
);
2306 len
= c2
->x
* mx
+ c2
->y
* my
- ref
- cr
- bloat
;
2307 if (c
->x
!= c2
->x
&& c
->y
!= c2
->y
)
2309 if (len
< dist
|| (len
== dist
&& c
->miter
!= -1))
2312 closest_corner
= c2
;
2317 if (closest_corner
&& closest_corner
->miter
== -1)
2324 if (dist
< Settings
.Grid
)
2331 dist
-= dist
% Settings
.Grid
;
2357 c2
= find_corner (x
, y
, c
->layer
);
2358 if (c2
!= other_corner (c
->lines
[0], c
))
2359 split_line (c
->lines
[0], c2
);
2377 move_corner (c
, x
, y
);
2389 classify_corner (corner_s
* c
, int this_net
)
2392 if (c
->net
== this_net
)
2395 for (i
= 0; i
< c
->n_lines
; i
++)
2396 classify_corner (other_corner (c
->lines
[i
], c
), this_net
);
2402 static int this_net
= 1;
2405 for (c
= corners
; c
; c
= c
->next
)
2411 classify_corner (c
, this_net
);
2423 for (c
= corners
; c
; c
= c
->next
)
2427 printf ("%p corner %d,%d layer %d net %d\n",
2428 (void *) c
, c
->x
, c
->y
, c
->layer
, c
->net
);
2430 for (l
= lines
; l
; l
= l
->next
)
2434 printf ("%p line %p to %p layer %d\n",
2435 (void *) l
, (void *) (l
->s
), (void *) (l
->e
), l
->layer
);
2442 nudge_corner (corner_s
* c
, int dx
, int dy
, corner_s
* prev_corner
)
2447 if (prev_corner
&& (c
->pin
|| c
->pad
))
2449 move_corner (c
, ox
+ dx
, oy
+ dy
);
2450 for (l
= 0; l
< c
->n_lines
; l
++)
2452 corner_s
*oc
= other_corner (c
->lines
[l
], c
);
2453 if (oc
== prev_corner
)
2455 if (dx
&& oc
->x
== ox
)
2456 nudge_corner (oc
, dx
, 0, c
);
2457 if (dy
&& oc
->y
== oy
)
2458 nudge_corner (oc
, 0, dy
, c
);
2464 choose_example_line (corner_s
* c1
, corner_s
* c2
)
2470 dprintf ("choose_example_line\n");
2471 for (ci
= 0; ci
< 2; ci
++)
2472 for (li
= 0; li
< c
[ci
]->n_lines
; li
++)
2474 dprintf (" try[%d,%d] \033[36m<%#mD-%#mD t%#mS c%#mS f%s>\033[0m\n",
2476 c
[ci
]->lines
[li
]->s
->x
, c
[ci
]->lines
[li
]->s
->y
,
2477 c
[ci
]->lines
[li
]->e
->x
, c
[ci
]->lines
[li
]->e
->y
,
2478 c
[ci
]->lines
[li
]->line
->Thickness
,
2479 c
[ci
]->lines
[li
]->line
->Clearance
,
2480 flags_to_string (c
[ci
]->lines
[li
]->line
->Flags
, LINE_TYPE
));
2481 /* Pads are disqualified, as we want to mimic a trace line. */
2482 if (c
[ci
]->lines
[li
]->line
== (LineType
*) c
[ci
]->pad
)
2484 dprintf (" bad, pad\n");
2487 /* Lines on layers that don't connect to the other pad are bad too. */
2488 if (!intersecting_layers (c
[ci
]->lines
[li
]->layer
, c
[1 - ci
]->layer
))
2490 dprintf (" bad, layers\n");
2493 dprintf (" good\n");
2494 return c
[ci
]->lines
[li
];
2496 dprintf ("choose_example_line: none found!\n");
2501 connect_corners (corner_s
* c1
, corner_s
* c2
)
2504 line_s
*ex
= choose_example_line (c1
, c2
);
2505 LineType
*example
= ex
->line
;
2508 ("connect_corners \033[32m%#mD to %#mD, example line %#mD to %#mD l%d\033[0m\n",
2509 c1
->x
, c1
->y
, c2
->x
, c2
->y
, ex
->s
->x
, ex
->s
->y
, ex
->e
->x
, ex
->e
->y
,
2514 /* Assume c1 is the moveable one. */
2515 if (!(c1
->pin
|| c1
->pad
|| c1
->via
) && c1
->n_lines
== 1)
2518 /* Extend the line */
2519 if (c1
->lines
[0]->s
->x
== c1
->lines
[0]->e
->x
)
2520 nx
= c1
->x
, ny
= c2
->y
;
2522 nx
= c2
->x
, ny
= c1
->y
;
2523 if (nx
!= c2
->x
|| ny
!= c2
->y
)
2525 move_corner (c1
, nx
, ny
);
2526 new_line (c1
, c2
, layer
, example
);
2531 move_corner (c1
, nx
, ny
);
2537 corner_s
*nc
= find_corner (c1
->x
, c2
->y
, layer
);
2538 new_line (c1
, nc
, layer
, example
);
2539 new_line (nc
, c2
, layer
, example
);
2548 int best_dist
[MAX_LAYER
+ 1];
2549 corner_s
*best_c
[MAX_LAYER
+ 1];
2551 int left
= 0, right
= 0, top
= 0, bottom
= 0;
2558 /* Look for pins that have no connections. See if there's a corner
2559 close by that should be connected to it. This usually happens
2560 when the MUCS router needs to route to an off-grid pin. */
2564 for (c
= corners
; c
; c
= c
->next
)
2568 if (!(c
->pin
|| c
->via
|| c
->pad
))
2573 dprintf ("\ncorner %s\n", corner_name (c
));
2574 if (c
->pin
|| c
->via
)
2576 pin
= c
->pin
? c
->pin
: c
->via
;
2577 close
= pin
->Thickness
/ 2;
2578 left
= c
->x
- close
;
2579 right
= c
->x
+ close
;
2580 bottom
= c
->y
- close
;
2585 close
= c
->pad
->Thickness
/ 2 + 1;
2586 left
= djmin (c
->pad
->Point1
.X
, c
->pad
->Point2
.X
) - close
;
2587 right
= djmax (c
->pad
->Point1
.X
, c
->pad
->Point2
.X
) + close
;
2588 bottom
= djmin (c
->pad
->Point1
.Y
, c
->pad
->Point2
.Y
) - close
;
2589 top
= djmax (c
->pad
->Point1
.Y
, c
->pad
->Point2
.Y
) + close
;
2590 if (c
->pad
->Point1
.X
== c
->pad
->Point2
.X
)
2592 int hy
= (c
->pad
->Point1
.Y
+ c
->pad
->Point2
.Y
) / 2;
2593 dprintf ("pad y %#mS %#mS hy %#mS c %#mS\n", c
->pad
->Point1
.Y
,
2594 c
->pad
->Point2
.Y
, hy
, c
->y
);
2602 int hx
= (c
->pad
->Point1
.X
+ c
->pad
->Point2
.X
) / 2;
2603 dprintf ("pad x %#mS %#mS hx %#mS c %#mS\n", c
->pad
->Point1
.X
,
2604 c
->pad
->Point2
.X
, hx
, c
->x
);
2612 dprintf ("%s x %#mS-%#mS y %#mS-%#mS\n", corner_name (c
), left
, right
, bottom
, top
);
2613 for (l
= 0; l
<= max_copper_layer
; l
++)
2615 best_dist
[l
] = close
* 2;
2619 for (c2
= corners
; c2
; c2
= c2
->next
)
2625 lt
= corner_radius (c2
);
2628 && !(c2
->pin
|| c2
->pad
|| c2
->via
)
2629 && intersecting_layers (c
->layer
, c2
->layer
)
2630 && c2
->x
>= left
- lt
2631 && c2
->x
<= right
+ lt
2632 && c2
->y
>= bottom
- lt
&& c2
->y
<= top
+ lt
)
2634 int d
= dist (c
->x
, c
->y
, c2
->x
, c2
->y
);
2635 if (pin
&& d
> pin
->Thickness
/ 2 + lt
)
2637 if (c2
->n_lines
== 1)
2640 dprintf ("found orphan %s vs %s\n", corner_name (c2
),
2642 connect_corners (c
, c2
);
2646 if (best_c
[c2
->layer
] == 0
2647 || c2
->n_lines
< best_c
[c2
->layer
]->n_lines
2648 || (d
< best_dist
[c2
->layer
]
2649 && c2
->n_lines
<= best_c
[c2
->layer
]->n_lines
))
2651 best_dist
[c2
->layer
] = d
;
2652 best_c
[c2
->layer
] = c2
;
2653 dprintf ("layer %d best now %s\n", c2
->layer
,
2657 if (!got_one
&& c
->n_lines
== (c
->pad
? 1 : 0))
2659 for (l
= 0; l
<= max_copper_layer
; l
++)
2661 dprintf ("best[%d] = %s\n", l
, corner_name (best_c
[l
]));
2662 for (l
= 0; l
<= max_copper_layer
; l
++)
2665 dprintf ("move %s to %s\n", corner_name (best_c
[l
]),
2667 connect_corners (best_c
[l
], c
);
2676 /* Now look for line ends that don't connect, see if they need to be
2677 extended to intersect another line. */
2678 for (c
= corners
; c
; c
= c
->next
)
2685 if (c
->pin
|| c
->via
|| c
->pad
)
2687 if (c
->n_lines
!= 1)
2691 lo
= line_orient (l
, c
);
2692 dprintf ("line end %#mD orient %d\n", c
->x
, c
->y
, lo
);
2694 for (t
= lines
; t
; t
= t
->next
)
2698 if (t
->layer
!= c
->lines
[0]->layer
)
2700 switch (lo
) /* remember, orient is for the line relative to the corner */
2703 if (t
->s
->x
== t
->e
->x
2706 c
->x
+ (l
->line
->Thickness
+ t
->line
->Thickness
) / 2
2707 && ((t
->s
->y
< c
->y
&& c
->y
< t
->e
->y
)
2708 || (t
->e
->y
< c
->y
&& c
->y
< t
->s
->y
)))
2710 dprintf ("found %#mD - %#mD\n", t
->s
->x
, t
->s
->y
, t
->e
->x
, t
->e
->y
);
2711 move_corner (c
, t
->s
->x
, c
->y
);
2715 if (t
->s
->x
== t
->e
->x
2718 c
->x
- (l
->line
->Thickness
+ t
->line
->Thickness
) / 2
2719 && ((t
->s
->y
< c
->y
&& c
->y
< t
->e
->y
)
2720 || (t
->e
->y
< c
->y
&& c
->y
< t
->s
->y
)))
2722 dprintf ("found %#mD - %#mD\n", t
->s
->x
, t
->s
->y
, t
->e
->x
, t
->e
->y
);
2723 move_corner (c
, t
->s
->x
, c
->y
);
2727 if (t
->s
->y
== t
->e
->y
2730 c
->y
+ (l
->line
->Thickness
+ t
->line
->Thickness
) / 2
2731 && ((t
->s
->x
< c
->x
&& c
->x
< t
->e
->x
)
2732 || (t
->e
->x
< c
->x
&& c
->x
< t
->s
->x
)))
2734 dprintf ("found %#mD - %#mD\n", t
->s
->x
, t
->s
->y
, t
->e
->x
, t
->e
->y
);
2735 move_corner (c
, c
->x
, t
->s
->y
);
2739 if (t
->s
->y
== t
->e
->y
2742 c
->y
- (l
->line
->Thickness
+ t
->line
->Thickness
) / 2
2743 && ((t
->s
->x
< c
->x
&& c
->x
< t
->e
->x
)
2744 || (t
->e
->x
< c
->x
&& c
->x
< t
->s
->x
)))
2746 dprintf ("found %#mD - %#mD\n", t
->s
->x
, t
->s
->y
, t
->e
->x
, t
->e
->y
);
2747 move_corner (c
, c
->x
, t
->s
->y
);
2756 pad_orient (PadType
* p
)
2758 if (p
->Point1
.X
== p
->Point2
.X
)
2760 if (p
->Point1
.Y
== p
->Point2
.Y
)
2772 dprintf ("\ndj: padcleaner\n");
2773 for (l
= lines
; l
; l
= nextl
)
2783 dprintf ("dj: line %p\n", (void *) l
);
2786 if (l
->s
->pad
&& l
->s
->pad
== l
->e
->pad
)
2789 ALLPAD_LOOP (PCB
->Data
);
2792 TEST_FLAG (ONSOLDERFLAG
, element
) ? LT_SOLDER
: LT_COMPONENT
;
2794 if (layer_type
[l
->layer
] != layerflag
)
2798 close
= pad
->Thickness
/ 2 + 1;
2799 add_point_to_rect (&r
, pad
->Point1
.X
, pad
->Point1
.Y
, close
- SB
/ 2);
2800 add_point_to_rect (&r
, pad
->Point2
.X
, pad
->Point2
.Y
, close
- SB
/ 2);
2801 if (pin_in_rect (&r
, l
->s
->x
, l
->s
->y
, 0)
2802 && pin_in_rect (&r
, l
->e
->x
, l
->e
->y
, 0)
2803 && ORIENT (line_orient (l
, 0)) == pad_orient (pad
))
2806 ("padcleaner %#mD-%#mD %#mS vs line %#mD-%#mD %#mS\n",
2807 pad
->Point1
.X
, pad
->Point1
.Y
, pad
->Point2
.X
, pad
->Point2
.Y
,
2808 pad
->Thickness
, l
->s
->x
, l
->s
->y
, l
->e
->x
, l
->e
->y
,
2809 l
->line
->Thickness
);
2820 grok_layer_groups ()
2823 LayerGroupType
*l
= &(PCB
->LayerGroups
);
2825 solder_layer
= component_layer
= -1;
2826 for (i
= 0; i
< max_copper_layer
; i
++)
2829 layer_groupings
[i
] = 0;
2831 for (i
= 0; i
< max_group
; i
++)
2834 for (j
= 0; j
< l
->Number
[i
]; j
++)
2836 if (l
->Entries
[i
][j
] == solder_silk_layer
)
2838 if (l
->Entries
[i
][j
] == component_silk_layer
)
2841 for (j
= 0; j
< l
->Number
[i
]; j
++)
2843 if (l
->Entries
[i
][j
] < max_copper_layer
)
2845 layer_type
[l
->Entries
[i
][j
]] |= f
;
2846 layer_groupings
[l
->Entries
[i
][j
]] = i
;
2847 if (solder_layer
== -1 && f
== LT_SOLDER
)
2848 solder_layer
= l
->Entries
[i
][j
];
2849 if (component_layer
== -1 && f
== LT_COMPONENT
)
2850 component_layer
= l
->Entries
[i
][j
];
2856 static const char djopt_syntax
[] =
2857 "djopt(debumpify|unjaggy|simple|vianudge|viatrim|orthopull)\n"
2858 "djopt(auto) - all of the above\n"
2861 static const char djopt_help
[] =
2862 "Perform various optimizations on the current board.";
2864 /* %start-doc actions djopt
2866 The different types of optimizations change your board in order to
2867 reduce the total trace length and via count.
2872 Looks for U-shaped traces that can be shortened or eliminated.
2875 Looks for corners which could be flipped to eliminate one or more
2876 corners (i.e. jaggy lines become simpler).
2879 Removing uneeded vias, replacing two or more trace segments in a row
2880 with a single segment. This is usually performed automatically after
2881 other optimizations.
2884 Looks for vias where all traces leave in the same direction. Tries to
2885 move via in that direction to eliminate one of the traces (and thus a
2889 Looks for traces that go from via to via, where moving that trace to a
2890 different layer eliminates one or both vias.
2893 Looks for chains of traces all going in one direction, with more
2894 traces orthogonal on one side than on the other. Moves the chain in
2895 that direction, causing a net reduction in trace length, possibly
2896 eliminating traces and/or corners.
2899 Looks for lines that pass through vias, pins, or pads, and splits them
2900 into separate lines so they can be managed separately.
2903 Performs the above options, repeating until no further optimizations
2907 Replaces 90 degree corners with a pair of 45 degree corners, to reduce
2908 RF losses and trace length.
2915 ActionDJopt (int argc
, char **argv
, Coord x
, Coord y
)
2917 char *arg
= argc
> 0 ? argv
[0] : 0;
2918 int layn
, saved
= 0;
2926 grok_layer_groups ();
2928 ELEMENT_LOOP (PCB
->Data
);
2931 c
= find_corner (pin
->X
, pin
->Y
, -1);
2938 TEST_FLAG (ONSOLDERFLAG
, pad
) ? solder_layer
: component_layer
;
2939 line_s
*ls
= (line_s
*) malloc (sizeof (line_s
));
2943 ls
->s
= find_corner (pad
->Point1
.X
, pad
->Point1
.Y
, layern
);
2945 ls
->e
= find_corner (pad
->Point2
.X
, pad
->Point2
.Y
, layern
);
2948 ls
->line
= (LineType
*) pad
;
2949 add_line_to_corner (ls
, ls
->s
);
2950 add_line_to_corner (ls
, ls
->e
);
2955 VIA_LOOP (PCB
->Data
);
2956 /* hace don't mess with vias that have thermals */
2957 /* but then again don't bump into them
2958 if (!TEST_FLAG(ALLTHERMFLAGS, via))
2961 c
= find_corner (via
->X
, via
->Y
, -1);
2967 if (NSTRCMP (arg
, "splitlines") == 0)
2969 if (canonicalize_lines ())
2970 IncrementUndoSerialNumber ();
2974 for (layn
= 0; layn
< max_copper_layer
; layn
++)
2976 LayerType
*layer
= LAYER_PTR (layn
);
2982 if(autorouted_only
&& !autorouted (line
))
2985 /* don't mess with thermals */
2986 if (TEST_FLAG (USETHERMALFLAG
, line
))
2989 if (line
->Point1
.X
== line
->Point2
.X
&&
2990 line
->Point1
.Y
== line
->Point2
.Y
)
2992 RemoveLine (layer
, line
);
2996 ls
= (line_s
*) malloc (sizeof (line_s
));
3000 ls
->s
= find_corner (line
->Point1
.X
, line
->Point1
.Y
, layn
);
3001 ls
->e
= find_corner (line
->Point2
.X
, line
->Point2
.Y
, layn
);
3003 add_line_to_corner (ls
, ls
->s
);
3004 add_line_to_corner (ls
, ls
->e
);
3012 canonicalize_lines ();
3018 if (NSTRCMP (arg
, "debumpify") == 0)
3019 saved
+= debumpify ();
3020 else if (NSTRCMP (arg
, "unjaggy") == 0)
3021 saved
+= unjaggy ();
3022 else if (NSTRCMP (arg
, "simple") == 0)
3023 saved
+= simple_optimizations ();
3024 else if (NSTRCMP (arg
, "vianudge") == 0)
3025 saved
+= vianudge ();
3026 else if (NSTRCMP (arg
, "viatrim") == 0)
3027 saved
+= viatrim ();
3028 else if (NSTRCMP (arg
, "orthopull") == 0)
3029 saved
+= orthopull ();
3030 else if (NSTRCMP (arg
, "auto") == 0)
3031 saved
+= automagic ();
3032 else if (NSTRCMP (arg
, "miter") == 0)
3036 printf ("unknown command: %s\n", arg
);
3044 IncrementUndoSerialNumber ();
3048 HID_Action djopt_action_list
[] = {
3049 {"djopt", 0, ActionDJopt
,
3050 djopt_help
, djopt_syntax
}
3052 {"OptAutoOnly", 0, djopt_set_auto_only
,
3053 djopt_sao_help
, djopt_sao_syntax
}
3056 REGISTER_ACTIONS (djopt_action_list
)