8 * <h1><b>Copyright.</b></h1>\n
10 * PCB, interactive printed circuit board design
12 * Copyright (C) 2003 DJ Delorie
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.
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.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 * Contact addresses for paper mail and Email:
29 * DJ Delorie, 334 North Road, Deerfield NH 03037-1110, USA
51 #include "pcb-printf.h"
53 #ifdef HAVE_LIBDMALLOC
58 #define rint(x) (ceil((x) - 0.5))
61 #define dprintf if(0)pcb_printf
63 #define selected(x) TEST_FLAG (SELECTEDFLAG, (x))
64 #define autorouted(x) TEST_FLAG (AUTOFLAG, (x))
66 #define SB (PCB->Bloat+1)
78 #define ORIENT(x) ((x) & 0xf0)
79 #define DIRECT(x) ((x) & 0x0f)
81 #define LONGEST_FRECKLE 2 /*!< Manhattan length of the longest "freckle" */
86 typedef struct corner_s
89 struct corner_s
*next
;
97 struct line_s
**lines
;
100 typedef struct line_s
109 typedef struct rect_s
114 #define DELETE(q) (q)->layer = 0xdeadbeef
115 #define DELETED(q) ((q)->layer == 0xdeadbeef)
117 static corner_s
*corners
, *next_corner
= 0;
118 static line_s
*lines
;
120 static int layer_groupings
[MAX_LAYER
];
121 static char layer_type
[MAX_LAYER
];
125 static int autorouted_only
= 1;
127 static const char djopt_sao_syntax
[] = "OptAutoOnly()";
129 static const char djopt_sao_help
[] =
130 "Toggles the optimize-only-autorouted flag.";
132 /* %start-doc actions OptAutoOnly
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.
145 djopt_set_auto_only (int argc
, char **argv
, Coord x
, Coord y
)
147 autorouted_only
= autorouted_only
? 0 : 1;
152 djopt_get_auto_only (void *data
)
154 return autorouted_only
;
157 HID_Flag djopt_flag_list
[] = {
158 {"optautoonly", djopt_get_auto_only
, NULL
}
161 REGISTER_FLAGS (djopt_flag_list
)
164 element_name_for (corner_s
* c
)
166 ELEMENT_LOOP (PCB
->Data
);
171 return element
->Name
[1].TextString
;
177 return element
->Name
[1].TextString
;
186 corner_name (corner_s
* c
)
188 static char buf
[4][100];
194 if (c
->net
== 0xf1eef1ee)
196 sprintf (buf
[bn
], "\033[31m[%p freed corner]\033[0m", (void *) c
);
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
]);
206 pcb_snprintf (bp
, size_left
, "pin %s:%s at %#mD",
207 element_name_for (c
), c
->pin
->Number
, c
->x
, c
->y
);
209 pcb_snprintf (bp
, size_left
, "via at %#mD", c
->x
, c
->y
);
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
);
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
);
223 static int solder_layer
, component_layer
;
226 dj_abort (char *msg
, ...)
239 #define check(c,l) check2(__LINE__,c,l)
241 check2 (int srcline
, corner_s
* c
, line_s
* l
)
243 int saw_c
= 0, saw_l
= 0;
248 for (cc
= corners
; cc
; cc
= cc
->next
)
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
);
263 dj_abort ("check:%d: corner not in corners list\n", srcline
);
264 for (ll
= lines
; ll
; ll
= ll
->next
)
270 for (i
= 0; i
< ll
->s
->n_lines
; i
++)
271 if (ll
->s
->lines
[i
] == ll
)
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
)
278 if (i
== ll
->e
->n_lines
)
279 dj_abort ("check:%d: ll->e has no backref\n", srcline
);
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
))
286 pcb_printf ("line: %#mD to %#mD pcbline: %#mD to %#mD\n",
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
);
295 dj_abort ("check:%d: line not in lines list\n", srcline
);
300 #define SWAP(a,b) { a^=b; b^=a; a^=b; }
307 return n
- n
% (Settings
.Grid
);
310 /* Avoid commonly used names. */
315 return x
> 0 ? x
: -x
;
321 return x
> y
? x
: y
;
327 return x
< y
? x
: y
;
331 * \brief Find distance between 2 points.
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.
338 dist (int x1
, int y1
, int x2
, int y2
)
340 double dx1
, dy1
, dx2
, dy2
, d
;
347 d
= sqrt ((dx1
- dx2
) * (dx1
- dx2
) + (dy1
- dy2
) * (dy1
- dy2
));
354 line_length (line_s
* l
)
356 if (l
->s
->x
== l
->e
->x
)
357 return djabs (l
->s
->y
- l
->e
->y
);
358 if (l
->s
->y
== l
->e
->y
)
359 return djabs (l
->s
->x
- l
->e
->x
);
360 return dist (l
->s
->x
, l
->s
->y
, l
->e
->x
, l
->e
->y
);
364 dist_ltp2 (int dx
, int y
, int y1
, int y2
)
369 return dist (dx
, y
, 0, y1
);
371 return dist (dx
, y
, 0, y2
);
382 intersecting_layers (int l1
, int l2
)
384 if (l1
== -1 || l2
== -1)
388 if (layer_groupings
[l1
] == layer_groupings
[l2
])
394 dist_line_to_point (line_s
* l
, corner_s
* c
)
397 /* We can do this quickly if l is vertical or horizontal. */
398 if (l
->s
->x
== l
->e
->x
)
399 return dist_ltp2 (l
->s
->x
- c
->x
, c
->y
, l
->s
->y
, l
->e
->y
);
400 if (l
->s
->y
== l
->e
->y
)
401 return dist_ltp2 (l
->s
->y
- c
->y
, c
->x
, l
->s
->x
, l
->e
->x
);
403 /* Do it the hard way. See comments for IsPointOnLine() in search.c */
404 len
= sqrt (sqr (l
->s
->x
- l
->e
->x
) + sqr (l
->s
->y
- l
->e
->y
));
406 return dist (l
->s
->x
, l
->s
->y
, c
->x
, c
->y
);
408 (l
->s
->y
- c
->y
) * (l
->s
->y
- l
->e
->y
) + (l
->s
->x
- c
->x
) * (l
->s
->x
-
412 return dist (l
->s
->x
, l
->s
->y
, c
->x
, c
->y
);
414 return dist (l
->e
->x
, l
->e
->y
, c
->x
, c
->y
);
416 (l
->e
->y
- l
->s
->y
) * (c
->x
* l
->s
->x
) + (l
->e
->x
- l
->s
->x
) * (c
->y
-
418 return (int) (d
/ len
);
422 line_orient (line_s
* l
, corner_s
* c
)
457 common_corner (line_s
* l1
, line_s
* l2
)
459 if (l1
->s
== l2
->s
|| l1
->s
== l2
->e
)
461 if (l1
->e
== l2
->s
|| l1
->e
== l2
->e
)
463 dj_abort ("common_corner: no common corner found\n");
469 other_corner (line_s
* l
, corner_s
* c
)
475 dj_abort ("other_corner: neither corner passed\n");
480 find_corner_if (int x
, int y
, int l
)
483 for (c
= corners
; c
; c
= c
->next
)
487 if (c
->x
!= x
|| c
->y
!= y
)
489 if (!(c
->layer
== -1 || intersecting_layers (c
->layer
, l
)))
497 find_corner (int x
, int y
, int l
)
500 for (c
= corners
; c
; c
= c
->next
)
504 if (c
->x
!= x
|| c
->y
!= y
)
506 if (!(c
->layer
== -1 || intersecting_layers (c
->layer
, l
)))
510 c
= (corner_s
*) malloc (sizeof (corner_s
));
521 c
->lines
= (line_s
**) malloc (INC
* sizeof (line_s
*));
526 add_line_to_corner (line_s
* l
, corner_s
* c
)
529 n
= (c
->n_lines
+ 1 + INC
) & ~INC
;
530 c
->lines
= (line_s
**) realloc (c
->lines
, n
* sizeof (line_s
*));
531 c
->lines
[c
->n_lines
] = l
;
533 dprintf ("add_line_to_corner %#mD\n", c
->x
, c
->y
);
537 create_pcb_line (int layer
, int x1
, int y1
, int x2
, int y2
,
538 int thick
, int clear
, FlagType flags
)
542 LayerType
*lyr
= LAYER_PTR (layer
);
544 from
= (char *) lyr
->Line
;
545 nl
= CreateNewLineOnLayer (PCB
->Data
->Layer
+ layer
,
546 x1
, y1
, x2
, y2
, thick
, clear
, flags
);
547 AddObjectToCreateUndoList (LINE_TYPE
, lyr
, nl
, nl
);
549 to
= (char *) lyr
->Line
;
553 for (lp
= lines
; lp
; lp
= lp
->next
)
557 if ((char *) (lp
->line
) >= from
558 && (char *) (lp
->line
) <= from
+ lyr
->LineN
* sizeof (LineType
))
559 lp
->line
= (LineType
*) ((char *) (lp
->line
) + (to
- from
));
566 new_line (corner_s
* s
, corner_s
* e
, int layer
, LineType
* example
)
570 if (layer
>= max_copper_layer
)
571 dj_abort ("layer %d\n", layer
);
574 dj_abort ("NULL example passed to new_line()\n", layer
);
576 if (s
->x
== e
->x
&& s
->y
== e
->y
)
579 ls
= (line_s
*) malloc (sizeof (line_s
));
587 if ((example
->Point1
.X
== s
->x
&& example
->Point1
.Y
== s
->y
588 && example
->Point2
.X
== e
->x
&& example
->Point2
.Y
== e
->y
)
589 || (example
->Point2
.X
== s
->x
&& example
->Point2
.Y
== s
->y
590 && example
->Point1
.X
== e
->x
&& example
->Point1
.Y
== e
->y
))
599 ("New line \033[35m%#mD to %#mD from l%d t%#mS c%#mS f%s\033[0m\n",
600 s
->x
, s
->y
, e
->x
, e
->y
, layer
, example
->Thickness
,
601 example
->Clearance
, flags_to_string (example
->Flags
, LINE_TYPE
));
603 create_pcb_line (layer
, s
->x
, s
->y
, e
->x
, e
->y
, example
->Thickness
,
604 example
->Clearance
, example
->Flags
);
607 dj_abort ("can't create new line!");
610 add_line_to_corner (ls
, s
);
611 add_line_to_corner (ls
, e
);
619 c_orth_to (corner_s
* c
, line_s
* l
, int o
)
623 for (i
= 0; i
< c
->n_lines
; i
++)
625 if (c
->lines
[i
] == l
)
627 o2
= line_orient (c
->lines
[i
], c
);
628 if (ORIENT (o
) == ORIENT (o2
) || o2
== DIAGONAL
)
637 other_line (corner_s
* c
, line_s
* l
)
641 if (c
->pin
|| c
->pad
|| c
->via
)
643 for (i
= 0; i
< c
->n_lines
; i
++)
645 if (c
->lines
[i
] == l
)
655 empty_rect (rect_s
* rect
)
657 rect
->x1
= rect
->y1
= INT_MAX
;
658 rect
->x2
= rect
->y2
= INT_MIN
;
662 add_point_to_rect (rect_s
* rect
, int x
, int y
, int w
)
664 if (rect
->x1
> x
- w
)
666 if (rect
->x2
< x
+ w
)
668 if (rect
->y1
> y
- w
)
670 if (rect
->y2
< y
+ w
)
675 add_line_to_rect (rect_s
* rect
, line_s
* l
)
677 add_point_to_rect (rect
, l
->s
->x
, l
->s
->y
, 0);
678 add_point_to_rect (rect
, l
->e
->x
, l
->e
->y
, 0);
682 pin_in_rect (rect_s
* r
, int x
, int y
, int w
)
684 if (x
< r
->x1
&& x
+ w
< r
->x1
)
686 if (x
> r
->x2
&& x
- w
> r
->x2
)
688 if (y
< r
->y1
&& y
+ w
< r
->y1
)
690 if (y
> r
->y2
&& y
- w
> r
->y2
)
696 line_in_rect (rect_s
* r
, line_s
* l
)
700 add_point_to_rect (&lr
, l
->s
->x
, l
->s
->y
, l
->line
->Thickness
/ 2);
701 add_point_to_rect (&lr
, l
->e
->x
, l
->e
->y
, l
->line
->Thickness
/ 2);
702 dprintf ("line_in_rect %#mD-%#mD vs %#mD-%#mD\n",
703 r
->x1
, r
->y1
, r
->x2
, r
->y2
, lr
.x1
, lr
.y1
, lr
.x2
, lr
.y2
);
704 /* simple intersection of rectangles */
713 if (lr
.x1
< lr
.x2
&& lr
.y1
< lr
.y2
)
719 corner_radius (corner_s
* c
)
724 diam
= djmax (c
->pin
->Thickness
, diam
);
726 diam
= djmax (c
->via
->Thickness
, diam
);
727 for (i
= 0; i
< c
->n_lines
; i
++)
728 if (c
->lines
[i
]->line
)
729 diam
= djmax (c
->lines
[i
]->line
->Thickness
, diam
);
730 diam
= (diam
+ 1) / 2;
737 corner_layer (corner_s
* c
)
739 if (c
->pin
|| c
->via
)
743 return c
->lines
[0]->layer
;
748 add_corner_to_rect_if (rect_s
* rect
, corner_s
* c
, rect_s
* e
)
750 int diam
= corner_radius (c
);
751 if (!pin_in_rect (e
, c
->x
, c
->y
, diam
))
753 if (c
->x
< e
->x1
&& c
->y
< e
->y1
&& dist (c
->x
, c
->y
, e
->x1
, e
->y1
) > diam
)
755 if (c
->x
> e
->x2
&& c
->y
< e
->y1
&& dist (c
->x
, c
->y
, e
->x2
, e
->y1
) > diam
)
757 if (c
->x
< e
->x1
&& c
->y
> e
->y2
&& dist (c
->x
, c
->y
, e
->x1
, e
->y2
) > diam
)
759 if (c
->x
> e
->x2
&& c
->y
> e
->y2
&& dist (c
->x
, c
->y
, e
->x2
, e
->y2
) > diam
)
762 /*pcb_printf("add point %#mD diam %#mS\n", c->x, c->y, diam); */
763 add_point_to_rect (rect
, c
->x
, c
->y
, diam
);
767 remove_line (line_s
* l
)
770 LayerType
*layer
= &(PCB
->Data
->Layer
[l
->layer
]);
775 RemoveLine (layer
, l
->line
);
779 for (i
= 0, j
= 0; i
< l
->s
->n_lines
; i
++)
780 if (l
->s
->lines
[i
] != l
)
781 l
->s
->lines
[j
++] = l
->s
->lines
[i
];
784 for (i
= 0, j
= 0; i
< l
->e
->n_lines
; i
++)
785 if (l
->e
->lines
[i
] != l
)
786 l
->e
->lines
[j
++] = l
->e
->lines
[i
];
792 move_line_to_layer (line_s
* l
, int layer
)
796 ls
= LAYER_PTR (l
->layer
);
797 ld
= LAYER_PTR (layer
);
799 MoveObjectToLayer (LINE_TYPE
, ls
, l
->line
, 0, ld
, 0);
804 remove_via_at (corner_s
* c
)
806 RemoveObject (VIA_TYPE
, c
->via
, 0, 0);
811 remove_corner (corner_s
* c2
)
814 dprintf ("remove corner %s\n", corner_name (c2
));
817 for (c
= corners
; c
; c
= c
->next
)
824 if (next_corner
== c2
)
825 next_corner
= c2
->next
;
832 merge_corners (corner_s
* c1
, corner_s
* c2
)
837 dprintf ("merge corners %s %s\n", corner_name (c1
), corner_name (c2
));
838 for (i
= 0; i
< c2
->n_lines
; i
++)
840 add_line_to_corner (c2
->lines
[i
], c1
);
841 if (c2
->lines
[i
]->s
== c2
)
842 c2
->lines
[i
]->s
= c1
;
843 if (c2
->lines
[i
]->e
== c2
)
844 c2
->lines
[i
]->e
= c1
;
846 if (c1
->via
&& c2
->via
)
854 if (c2
->layer
!= c1
->layer
)
861 move_corner (corner_s
* c
, int x
, int y
)
868 if (c
->pad
|| c
->pin
)
869 dj_abort ("move_corner: has pin or pad\n");
870 dprintf ("move_corner %p from %#mD to %#mD\n", (void *) c
, c
->x
, c
->y
, x
, y
);
871 pad
= find_corner_if (x
, y
, c
->layer
);
877 MoveObject (VIA_TYPE
, via
, via
, via
, x
- via
->X
, y
- via
->Y
);
878 dprintf ("via move %#mD to %#mD\n", via
->X
, via
->Y
, x
, y
);
880 for (i
= 0; i
< c
->n_lines
; i
++)
882 LineType
*tl
= c
->lines
[i
]->line
;
885 if (c
->lines
[i
]->s
== c
)
887 MoveObject (LINEPOINT_TYPE
, LAYER_PTR (c
->lines
[i
]->layer
), tl
,
888 &tl
->Point1
, x
- (tl
->Point1
.X
),
893 MoveObject (LINEPOINT_TYPE
, LAYER_PTR (c
->lines
[i
]->layer
), tl
,
894 &tl
->Point2
, x
- (tl
->Point2
.X
),
897 dprintf ("Line %p moved to %#mD %#mD\n", (void *) tl
,
898 tl
->Point1
.X
, tl
->Point1
.Y
, tl
->Point2
.X
, tl
->Point2
.Y
);
902 merge_corners (c
, pad
);
904 for (i
= 0; i
< c
->n_lines
; i
++)
906 if (c
->lines
[i
]->s
->x
== c
->lines
[i
]->e
->x
907 && c
->lines
[i
]->s
->y
== c
->lines
[i
]->e
->y
)
909 corner_s
*c2
= other_corner (c
->lines
[i
], c
);
910 dprintf ("move_corner: removing line %#mD %#mD %p %p\n",
911 c
->x
, c
->y
, c2
->x
, c2
->y
, (void *) c
, (void *) c2
);
913 remove_line (c
->lines
[i
]);
915 merge_corners (c
, c2
);
921 gui
->progress (0, 0, 0);
929 for (l
= lines
; l
; l
= l
->next
)
933 if (l
->line
&& selected (l
->line
))
940 trim_step (int s
, int l1
, int l2
)
942 dprintf ("trim %d %d %d\n", s
, l1
, l2
);
947 if (s
!= l1
&& s
!= l2
)
952 static int canonicalize_line (line_s
* l
);
955 split_line (line_s
* l
, corner_s
* c
)
961 if (!intersecting_layers (l
->layer
, c
->layer
))
967 dprintf ("split on pad!\n");
968 if (l
->s
->pad
== c
->pad
|| l
->e
->pad
== c
->pad
)
970 dprintf ("splitting...\n");
974 pcbline
= create_pcb_line (l
->layer
,
975 c
->x
, c
->y
, l
->e
->x
, l
->e
->y
,
976 l
->line
->Thickness
, l
->line
->Clearance
,
979 return 0; /* already a line there */
983 dprintf ("split line from %#mD to %#mD at %#mD\n",
984 l
->s
->x
, l
->s
->y
, l
->e
->x
, l
->e
->y
, c
->x
, c
->y
);
985 ls
= (line_s
*) malloc (sizeof (line_s
));
993 ls
->layer
= l
->layer
;
994 for (i
= 0; i
< l
->e
->n_lines
; i
++)
995 if (l
->e
->lines
[i
] == l
)
998 add_line_to_corner (l
, c
);
999 add_line_to_corner (ls
, c
);
1001 MoveObject (LINEPOINT_TYPE
, LAYER_PTR (l
->layer
), l
->line
, &l
->line
->Point2
,
1002 c
->x
- (l
->line
->Point2
.X
), c
->y
- (l
->line
->Point2
.Y
));
1008 canonicalize_line (line_s
* l
)
1010 /* This could be faster */
1012 if (l
->s
->x
== l
->e
->x
)
1016 int x1
= l
->s
->x
- l
->line
->Thickness
/ 2;
1017 int x2
= l
->s
->x
+ l
->line
->Thickness
/ 2;
1024 for (c
= corners
; c
; c
= c
->next
)
1028 if ((y1
< c
->y
&& c
->y
< y2
)
1029 && intersecting_layers (l
->layer
, c
->layer
))
1032 && c
->x
< x2
&& c
->x
> x1
&& !(c
->pad
|| c
->pin
))
1034 move_corner (c
, l
->s
->x
, c
->y
);
1036 if (c
->x
== l
->s
->x
)
1038 /* FIXME: if the line is split, we have to re-canonicalize
1040 return split_line (l
, c
);
1045 else if (l
->s
->y
== l
->e
->y
)
1049 int y1
= l
->s
->y
- l
->line
->Thickness
/ 2;
1050 int y2
= l
->s
->y
+ l
->line
->Thickness
/ 2;
1057 for (c
= corners
; c
; c
= c
->next
)
1061 if ((x1
< c
->x
&& c
->x
< x2
)
1062 && intersecting_layers (l
->layer
, c
->layer
))
1065 && c
->y
< y2
&& c
->y
> y1
&& !(c
->pad
|| c
->pin
))
1067 move_corner (c
, c
->x
, l
->s
->y
);
1069 if (c
->y
== l
->s
->y
)
1071 /* FIXME: Likewise. */
1072 return split_line (l
, c
);
1079 /* diagonal lines. Let's try to split them at pins/vias
1097 for (c
= corners
; c
; c
= c
->next
)
1101 if (!c
->via
&& !c
->pin
)
1103 if ((x1
< c
->x
&& c
->x
< x2
)
1104 && (y1
< c
->y
&& c
->y
< y2
)
1105 && intersecting_layers (l
->layer
, c
->layer
))
1107 int th
= c
->pin
? c
->pin
->Thickness
: c
->via
->Thickness
;
1109 if (dist (l
->s
->x
, l
->s
->y
, c
->x
, c
->y
) > th
1110 && dist (l
->e
->x
, l
->e
->y
, c
->x
, c
->y
) > th
1111 && PinLineIntersect (c
->pin
? c
->pin
: c
->via
, l
->line
))
1113 return split_line (l
, c
);
1122 * \brief Make sure all vias are at line end points.
1125 canonicalize_lines ()
1133 for (l
= lines
; l
; l
= l
->next
)
1137 count
+= canonicalize_line (l
);
1147 simple_optimize_corner (corner_s
* c
)
1155 /* see if no via is needed */
1156 if (selected (c
->via
))
1157 dprintf ("via check: line[0] layer %d at %#mD nl %d\n",
1158 c
->lines
[0]->layer
, c
->x
, c
->y
, c
->n_lines
);
1159 /* We can't delete vias that connect to power planes, or vias
1160 that aren't tented (assume they're test points). */
1161 if (!TEST_ANY_THERMS (c
->via
)
1162 && c
->via
->Mask
== 0)
1164 for (i
= 1; i
< c
->n_lines
; i
++)
1166 if (selected (c
->via
))
1167 dprintf (" line[%d] layer %d %#mD to %#mD\n",
1168 i
, c
->lines
[i
]->layer
,
1169 c
->lines
[i
]->s
->x
, c
->lines
[i
]->s
->y
,
1170 c
->lines
[i
]->e
->x
, c
->lines
[i
]->e
->y
);
1171 if (c
->lines
[i
]->layer
!= c
->lines
[0]->layer
)
1174 if (i
== c
->n_lines
)
1176 if (selected (c
->via
))
1177 dprintf (" remove it\n");
1185 if (c
->n_lines
== 2 && !c
->via
)
1187 /* see if it is an unneeded corner */
1188 int o
= line_orient (c
->lines
[0], c
);
1189 corner_s
*c2
= other_corner (c
->lines
[1], c
);
1190 corner_s
*c0
= other_corner (c
->lines
[0], c
);
1191 if (o
== line_orient (c
->lines
[1], c2
) && o
!= DIAGONAL
)
1193 dprintf ("straight %#mD to %#mD to %#mD\n",
1194 c0
->x
, c0
->y
, c
->x
, c
->y
, c2
->x
, c2
->y
);
1195 if (selected (c
->lines
[0]->line
))
1196 SET_FLAG (SELECTEDFLAG
, c
->lines
[1]->line
);
1197 if (selected (c
->lines
[1]->line
))
1198 SET_FLAG (SELECTEDFLAG
, c
->lines
[0]->line
);
1199 move_corner (c
, c2
->x
, c2
->y
);
1203 if (c
->n_lines
== 1 && !c
->via
)
1205 corner_s
*c0
= other_corner (c
->lines
[0], c
);
1206 if (abs(c
->x
- c0
->x
) + abs(c
->y
- c0
->y
) <= LONGEST_FRECKLE
)
1209 * Remove this line, as it is a "freckle". A freckle is an extremely
1210 * short line (around 0.01 thou) that is unconnected at one end.
1211 * Freckles are almost insignificantly small, but are annoying as
1212 * they prevent the mitering optimiser from working.
1213 * Freckles sometimes arise because of a bug in the autorouter that
1214 * causes it to create small overshoots (typically 0.01 thou) at the
1215 * intersections of vertical and horizontal lines. These overshoots
1216 * are converted to freckles as a side effect of canonicalize_line().
1217 * Note that canonicalize_line() is not at fault, the bug is in the
1218 * autorouter creating overshoots.
1219 * The autorouter bug arose some time between the 20080202 and 20091103
1221 * This code is probably worth keeping even when the autorouter bug is
1222 * fixed, as "freckles" could conceivably arise in other ways.
1224 dprintf ("freckle %#mD to %#mD\n", c
->x
, c
->y
, c0
->x
, c0
->y
);
1225 move_corner (c
, c0
->x
, c0
->y
);
1232 /* We always run these */
1234 simple_optimizations ()
1239 /* Look for corners that aren't */
1240 for (c
= corners
; c
; c
= c
->next
)
1244 if (c
->pad
|| c
->pin
)
1246 rv
+= simple_optimize_corner (c
);
1252 is_hole (corner_s
* c
)
1254 return c
->pin
|| c
->pad
|| c
->via
;
1258 orthopull_1 (corner_s
* c
, int fdir
, int rdir
, int any_sel
)
1260 static corner_s
**cs
= 0;
1262 static line_s
**ls
= 0;
1264 int i
, li
, ln
, cn
, snap
;
1267 int adir
= 0, sdir
= 0, pull
;
1268 int saw_sel
= 0, saw_auto
= 0;
1269 int max
, len
= 0, r1
= 0, r2
;
1275 cs
= (corner_s
**) malloc (10 * sizeof (corner_s
));
1277 ls
= (line_s
**) malloc (10 * sizeof (line_s
));
1281 for (i
= 0; i
< c
->n_lines
; i
++)
1283 int o
= line_orient (c
->lines
[i
], c
);
1299 dj_abort ("fdir not right or down\n");
1308 if (c2
->pad
|| c2
->pin
|| c2
->n_lines
< 2)
1313 cs
= (corner_s
**) realloc (cs
, cm
* sizeof (corner_s
*));
1316 r2
= corner_radius (c2
);
1320 for (i
= 0; i
< c2
->n_lines
; i
++)
1322 int o
= line_orient (c2
->lines
[i
], c2
);
1328 return 0; /* we don't support overlapping lines yet */
1331 if (o
== rdir
&& c2
->lines
[i
] != ls
[ln
- 1])
1332 return 0; /* likewise */
1340 if (selected (l
->line
))
1342 if (autorouted (l
->line
))
1347 ls
= (line_s
**) realloc (ls
, lm
* sizeof (line_s
*));
1350 c2
= other_corner (l
, c2
);
1352 if (cn
< 2 || pull
== 0)
1354 if (any_sel
&& !saw_sel
)
1356 if (!any_sel
&& autorouted_only
&& !saw_auto
)
1359 /* Ok, now look for other blockages. */
1362 add_point_to_rect (&rr
, c
->x
, c
->y
, corner_radius (c
));
1363 add_point_to_rect (&rr
, c2
->x
, c2
->y
, corner_radius (c2
));
1365 if (fdir
== RIGHT
&& pull
< 0)
1367 else if (fdir
== RIGHT
&& pull
> 0)
1369 else if (fdir
== DOWN
&& pull
< 0)
1371 else if (fdir
== DOWN
&& pull
> 0)
1375 for (i
= 0; i
< cn
; i
++)
1376 for (li
= 0; li
< cs
[i
]->n_lines
; li
++)
1378 if (line_orient (cs
[i
]->lines
[li
], cs
[i
]) != edir
)
1380 len
= line_length (cs
[i
]->lines
[li
]);
1381 if (max
> len
|| max
== -1)
1384 dprintf ("c %s %4#mD cn %d pull %3d max %4#mS\n",
1385 fdir
== RIGHT
? "right" : "down ", c
->x
, c
->y
, cn
, pull
, max
);
1390 rr
.y1
= c
->y
- r1
- max
;
1393 rr
.y2
= c
->y
+ r1
+ max
;
1396 rr
.x1
= c
->x
- r1
- max
;
1399 rr
.x2
= c
->x
+ r1
+ max
;
1408 for (cb
= corners
; cb
; cb
= cb
->next
)
1413 r1
= corner_radius (cb
);
1414 if (cb
->net
== c
->net
&& !cb
->pad
)
1416 if (!pin_in_rect (&rr
, cb
->x
, cb
->y
, r1
))
1420 #define ECHK(X,Y,LT) \
1421 for (i=0; i<cn; i++) \
1423 if (!intersecting_layers(cs[i]->layer, cb->layer)) \
1425 r2 = corner_radius(cs[i]); \
1426 if (cb->X + r1 <= cs[i]->X - r2 - SB - 1) \
1428 if (cb->X - r1 >= cs[i]->X + r2 + SB + 1) \
1430 if (cb->Y LT cs[i]->Y) \
1432 sep = djabs(cb->Y - cs[i]->Y) - r1 - r2 - SB - 1; \
1434 { max = sep; snap = 1; }\
1436 for (i=0; i<ln; i++) \
1438 if (!intersecting_layers(ls[i]->layer, cb->layer)) \
1440 if (cb->X <= cs[i]->X || cb->X >= cs[i+1]->X) \
1442 sep = (djabs(cb->Y - cs[i]->Y) - ls[i]->line->Thickness/2 \
1445 { max = sep; snap = 1; }\
1462 /* We must now check every line segment against our corners. */
1463 for (l
= lines
; l
; l
= l
->next
)
1465 int o
, x1
, x2
, y1
, y2
;
1468 dprintf ("check line %#mD to %#mD\n", l
->s
->x
, l
->s
->y
, l
->e
->x
, l
->e
->y
);
1469 if (l
->s
->net
== c
->net
)
1471 dprintf (" same net\n");
1474 o
= line_orient (l
, 0);
1475 /* We don't need to check perpendicular lines, because their
1476 corners already take care of it. */
1477 if ((fdir
== RIGHT
&& (o
== UP
|| o
== DOWN
))
1478 || (fdir
== DOWN
&& (o
== RIGHT
|| o
== LEFT
)))
1480 dprintf (" perpendicular\n");
1484 /* Choose so that x1,y1 is closest to corner C */
1485 if ((fdir
== RIGHT
&& l
->s
->x
< l
->e
->x
)
1486 || (fdir
== DOWN
&& l
->s
->y
< l
->e
->y
))
1501 /* Eliminate all lines outside our range */
1502 if ((fdir
== RIGHT
&& (x2
< c
->x
|| x1
> c2
->x
))
1503 || (fdir
== DOWN
&& (y2
< c
->y
|| y1
> c2
->y
)))
1505 dprintf (" outside our range\n");
1509 /* Eliminate all lines on the wrong side of us */
1510 if ((edir
== UP
&& y1
> c
->y
&& y2
> c
->y
)
1511 || (edir
== DOWN
&& y1
< c
->y
&& y2
< c
->y
)
1512 || (edir
== LEFT
&& x1
> c
->x
&& x2
> c
->x
)
1513 || (edir
== RIGHT
&& x1
< c
->x
&& x2
< c
->x
))
1515 dprintf (" wrong side\n");
1519 /* For now, cheat on diagonals */
1540 /* Ok, now see how far we can get for each of our corners. */
1541 for (i
= 0; i
< cn
; i
++)
1543 int r
= l
->line
->Thickness
+ SB
+ corner_radius (cs
[i
]) + 1;
1545 if ((fdir
== RIGHT
&& (x2
< cs
[i
]->x
|| x1
> cs
[i
]->x
))
1546 || (fdir
== DOWN
&& (y2
< cs
[i
]->y
|| y1
> cs
[i
]->y
)))
1548 if (!intersecting_layers (cs
[i
]->layer
, l
->layer
))
1566 dprintf (" len is %#mS vs corner at %#mD\n", len
, cs
[i
]->x
, cs
[i
]->y
);
1575 /* We must make sure that if a segment isn't being completely
1576 removed, that any vias and/or pads don't overlap. */
1581 for (i
= 0; i
< cn
; i
++)
1582 for (li
= 0; li
< cs
[i
]->n_lines
; li
++)
1584 line_s
*l
= cs
[i
]->lines
[li
];
1585 corner_s
*oc
= other_corner (l
, cs
[i
]);
1586 if (line_orient (l
, cs
[i
]) != edir
)
1588 len
= line_length (l
);
1589 if (!oc
->pad
|| !cs
[i
]->via
)
1591 if (!is_hole (l
->s
) || !is_hole (l
->e
))
1596 len
-= corner_radius (l
->s
);
1597 len
-= corner_radius (l
->e
);
1624 if (snap
&& max
> Settings
.Grid
)
1627 len
+= Settings
.Grid
- 1;
1628 len
= gridsnap (len
);
1630 if ((fdir
== RIGHT
&& len
== cs
[0]->y
) || (fdir
== DOWN
&& len
== cs
[0]->x
))
1632 for (i
= 0; i
< cn
; i
++)
1636 max
= len
- cs
[i
]->y
;
1637 move_corner (cs
[i
], cs
[i
]->x
, len
);
1641 max
= len
- cs
[i
]->x
;
1642 move_corner (cs
[i
], len
, cs
[i
]->y
);
1649 * \brief Look for straight runs which could be moved to reduce total
1655 int any_sel
= any_line_selected ();
1659 for (c
= corners
; c
;)
1663 if (c
->pin
|| c
->pad
)
1669 rv
+= orthopull_1 (c
, RIGHT
, LEFT
, any_sel
);
1670 if (c
!= next_corner
)
1675 rv
+= orthopull_1 (c
, DOWN
, UP
, any_sel
);
1676 if (c
!= next_corner
)
1684 pcb_printf ("orthopull: %ml mils saved\n", rv
);
1689 * \brief Look for "U" shaped traces we can shorten (or eliminate).
1695 int any_selected
= any_line_selected ();
1696 line_s
*l
, *l1
, *l2
;
1697 corner_s
*c
, *c1
, *c2
;
1699 int o
, o1
, o2
, step
, w
;
1700 for (l
= lines
; l
; l
= l
->next
)
1706 if (any_selected
&& !selected (l
->line
))
1708 if (!any_selected
&& autorouted_only
&& !autorouted (l
->line
))
1710 if (l
->s
->pin
|| l
->s
->pad
|| l
->e
->pin
|| l
->e
->pad
)
1712 o
= line_orient (l
, 0);
1715 l1
= other_line (l
->s
, l
);
1718 o1
= line_orient (l1
, l
->s
);
1719 l2
= other_line (l
->e
, l
);
1722 o2
= line_orient (l2
, l
->e
);
1723 if (ORIENT (o
) == ORIENT (o1
) || o1
!= o2
|| o1
== DIAGONAL
)
1726 dprintf ("\nline: %#mD to %#mD\n", l
->s
->x
, l
->s
->y
, l
->e
->x
, l
->e
->y
);
1727 w
= l
->line
->Thickness
/ 2 + SB
+ 1;
1729 add_line_to_rect (&rr
, l1
);
1730 add_line_to_rect (&rr
, l2
);
1731 if (rr
.x1
!= l
->s
->x
&& rr
.x1
!= l
->e
->x
)
1733 if (rr
.x2
!= l
->s
->x
&& rr
.x2
!= l
->e
->x
)
1735 if (rr
.y1
!= l
->s
->y
&& rr
.y1
!= l
->e
->y
)
1737 if (rr
.y2
!= l
->s
->y
&& rr
.y2
!= l
->e
->y
)
1739 dprintf ("range: x %#mS..%#mS y %#mS..%#mS\n", rr
.x1
, rr
.x2
, rr
.y1
, rr
.y2
);
1741 c1
= other_corner (l1
, l
->s
);
1742 c2
= other_corner (l2
, l
->e
);
1745 for (c
= corners
; c
; c
= c
->next
)
1749 if (c
->net
!= l
->s
->net
1750 && intersecting_layers (c
->layer
, l
->s
->layer
))
1751 add_corner_to_rect_if (&rp
, c
, &rr
);
1753 if (rp
.x1
== INT_MAX
)
1760 dprintf ("pin r: x %#mS..%#mS y %#mS..%#mS\n", rp
.x1
, rp
.x2
, rp
.y1
, rp
.y2
);
1765 step
= l
->s
->x
- rp
.x2
- w
;
1766 step
= gridsnap (step
);
1767 if (step
> l
->s
->x
- c1
->x
)
1768 step
= l
->s
->x
- c1
->x
;
1769 if (step
> l
->s
->x
- c2
->x
)
1770 step
= l
->s
->x
- c2
->x
;
1773 dprintf ("left step %#mS at %#mD\n", step
, l
->s
->x
, l
->s
->y
);
1774 move_corner (l
->s
, l
->s
->x
- step
, l
->s
->y
);
1775 move_corner (l
->e
, l
->e
->x
- step
, l
->e
->y
);
1780 step
= rp
.x1
- l
->s
->x
- w
;
1781 step
= gridsnap (step
);
1782 if (step
> c1
->x
- l
->s
->x
)
1783 step
= c1
->x
- l
->s
->x
;
1784 if (step
> c2
->x
- l
->s
->x
)
1785 step
= c2
->x
- l
->s
->x
;
1788 dprintf ("right step %#mS at %#mD\n", step
, l
->s
->x
, l
->s
->y
);
1789 move_corner (l
->s
, l
->s
->x
+ step
, l
->s
->y
);
1790 move_corner (l
->e
, l
->e
->x
+ step
, l
->e
->y
);
1795 if (rp
.y2
== INT_MIN
)
1797 step
= trim_step (l
->s
->y
- rp
.y2
- w
,
1798 l
->s
->y
- c1
->y
, l
->s
->y
- c2
->y
);
1801 dprintf ("up step %#mS at %#mD\n", step
, l
->s
->x
, l
->s
->y
);
1802 move_corner (l
->s
, l
->s
->x
, l
->s
->y
- step
);
1803 move_corner (l
->e
, l
->e
->x
, l
->e
->y
- step
);
1808 step
= rp
.y1
- l
->s
->y
- w
;
1809 step
= gridsnap (step
);
1810 if (step
> c1
->y
- l
->s
->y
)
1811 step
= c1
->y
- l
->s
->y
;
1812 if (step
> c2
->y
- l
->s
->y
)
1813 step
= c2
->y
- l
->s
->y
;
1816 dprintf ("down step %#mS at %#mD\n", step
, l
->s
->x
, l
->s
->y
);
1817 move_corner (l
->s
, l
->s
->x
, l
->s
->y
+ step
);
1818 move_corner (l
->e
, l
->e
->x
, l
->e
->y
+ step
);
1826 rv
+= simple_optimizations ();
1828 pcb_printf ("debumpify: %ml mils saved\n", rv
/ 50);
1833 simple_corner (corner_s
* c
)
1836 if (c
->pad
|| c
->pin
|| c
->via
)
1838 if (c
->n_lines
!= 2)
1840 o1
= line_orient (c
->lines
[0], c
);
1841 o2
= line_orient (c
->lines
[1], c
);
1842 if (ORIENT (o1
) == ORIENT (o2
))
1844 if (ORIENT (o1
) == DIAGONAL
|| ORIENT (o2
) == DIAGONAL
)
1850 * \brief Look for sequences of simple corners we can reduce.
1856 corner_s
*c
, *c0
, *c1
, *cc
;
1857 int l
, w
, sel
= any_line_selected ();
1860 for (c
= corners
; c
; c
= c
->next
)
1864 if (!simple_corner (c
))
1866 if (!c
->lines
[0]->line
|| !c
->lines
[1]->line
)
1868 if (sel
&& !(selected (c
->lines
[0]->line
)
1869 || selected (c
->lines
[1]->line
)))
1871 if (!sel
&& autorouted_only
1872 && !(autorouted (c
->lines
[0]->line
)
1873 || autorouted (c
->lines
[1]->line
)))
1875 dprintf ("simple at %#mD\n", c
->x
, c
->y
);
1877 c0
= other_corner (c
->lines
[0], c
);
1878 o0
= line_orient (c
->lines
[0], c
);
1879 s0
= simple_corner (c0
);
1881 c1
= other_corner (c
->lines
[1], c
);
1882 o1
= line_orient (c
->lines
[1], c
);
1883 s1
= simple_corner (c1
);
1887 dprintf ("simples at %#mD\n", c
->x
, c
->y
);
1890 for (l
= 0; l
< c0
->n_lines
; l
++)
1891 if (c0
->lines
[l
] != c
->lines
[0]
1892 && c0
->lines
[l
]->layer
== c
->lines
[0]->layer
)
1894 int o
= line_orient (c0
->lines
[l
], c0
);
1898 for (l
= 0; l
< c1
->n_lines
; l
++)
1899 if (c1
->lines
[l
] != c
->lines
[0]
1900 && c1
->lines
[l
]->layer
== c
->lines
[0]->layer
)
1902 int o
= line_orient (c1
->lines
[l
], c1
);
1908 dprintf ("orient ok\n");
1910 w
= c
->lines
[0]->line
->Thickness
/ 2 + SB
+ 1;
1912 add_line_to_rect (&rr
, c
->lines
[0]);
1913 add_line_to_rect (&rr
, c
->lines
[1]);
1924 for (cc
= corners
; cc
; cc
= cc
->next
)
1928 if (cc
->net
!= c
->net
&& intersecting_layers (cc
->layer
, c
->layer
))
1929 add_corner_to_rect_if (&rp
, cc
, &rr
);
1931 dprintf ("rp x %#mS..%#mS y %#mS..%#mS\n", rp
.x1
, rp
.x2
, rp
.y1
, rp
.y2
);
1932 if (rp
.x1
<= rp
.x2
) /* something triggered */
1935 dprintf ("unjaggy at %#mD layer %d\n", c
->x
, c
->y
, c
->layer
);
1937 move_corner (c
, c1
->x
, c0
->y
);
1939 move_corner (c
, c0
->x
, c1
->y
);
1943 rv
+= simple_optimizations ();
1952 for (i
= 0; i
< 100; i
++)
1954 j
= unjaggy_once ();
1960 printf ("%d unjagg%s \n", r
, r
== 1 ? "y" : "ies");
1965 * \brief Look for vias with all lines leaving the same way, try to
1966 * nudge via to eliminate one or more of them.
1972 corner_s
*c
, *c2
, *c3
;
1974 unsigned char directions
[MAX_LAYER
];
1975 unsigned char counts
[MAX_LAYER
];
1977 memset (directions
, 0, sizeof (directions
));
1978 memset (counts
, 0, sizeof (counts
));
1980 for (c
= corners
; c
; c
= c
->next
)
1982 int o
, i
, vr
, cr
, oboth
;
1983 int len
= 0, saved
= 0;
1991 memset (directions
, 0, sizeof (directions
));
1992 memset (counts
, 0, sizeof (counts
));
1994 for (i
= 0; i
< c
->n_lines
; i
++)
1996 o
= line_orient (c
->lines
[i
], c
);
1997 counts
[c
->lines
[i
]->layer
]++;
1998 directions
[c
->lines
[i
]->layer
] |= o
;
2000 for (o
= 0, i
= 0; i
< max_copper_layer
; i
++)
2010 oboth
= LEFT
| RIGHT
;
2019 for (i
= 0; i
< max_copper_layer
; i
++)
2020 if (counts
[i
] && directions
[i
] != o
&& directions
[i
] != oboth
)
2021 goto vianudge_continue
;
2024 for (i
= 0; i
< c
->n_lines
; i
++)
2026 int ll
= line_length (c
->lines
[i
]);
2027 if (line_orient (c
->lines
[i
], c
) != o
)
2033 if (c2
== 0 || len
> ll
)
2036 c2
= other_corner (c
->lines
[i
], c
);
2039 if (c2
->pad
|| c2
->pin
|| c2
->via
)
2042 /* Now look for clearance in the new position */
2043 vr
= c
->via
->Thickness
/ 2 + SB
+ 1;
2044 for (c3
= corners
; c3
; c3
= c3
->next
)
2048 if ((c3
->net
!= c
->net
&& (c3
->pin
|| c3
->via
)) || c3
->pad
)
2050 cr
= corner_radius (c3
);
2051 if (dist (c2
->x
, c2
->y
, c3
->x
, c3
->y
) < vr
+ cr
)
2052 goto vianudge_continue
;
2055 for (l
= lines
; l
; l
= l
->next
)
2059 if (l
->s
->net
!= c
->net
)
2061 int ld
= dist_line_to_point (l
, c2
);
2062 if (ld
< l
->line
->Thickness
/ 2 + vr
)
2063 goto vianudge_continue
;
2067 /* at this point, we know we can move it */
2069 dprintf ("vianudge: nudging via at %#mD by %#mS saving %#mS\n",
2070 c
->x
, c
->y
, len
, saved
);
2072 move_corner (c
, c2
->x
, c2
->y
);
2081 pcb_printf ("vianudge: %ml mils saved\n", rv
);
2086 * \brief Look for traces that can be moved to the other side of the
2087 * board, to reduce the number of vias needed.
2089 * For now, we look for simple lines, not multi-segmented lines.
2095 int i
, rv
= 0, vrm
= 0;
2096 int any_sel
= any_line_selected ();
2098 for (l
= lines
; l
; l
= l
->next
)
2101 int my_layer
, other_layer
;
2109 if (any_sel
&& !selected (l
->line
))
2111 if (!any_sel
&& autorouted_only
&& !autorouted (l
->line
))
2114 my_layer
= l
->layer
;
2116 dprintf ("line %p on layer %d from %#mD to %#mD\n", (void *) l
,
2117 l
->layer
, l
->s
->x
, l
->s
->y
, l
->e
->x
, l
->e
->y
);
2118 for (i
= 0; i
< l
->s
->n_lines
; i
++)
2119 if (l
->s
->lines
[i
] != l
)
2121 if (other_layer
== -1)
2123 other_layer
= l
->s
->lines
[i
]->layer
;
2124 dprintf ("noting other line %p on layer %d\n",
2125 (void *) (l
->s
->lines
[i
]), my_layer
);
2127 else if (l
->s
->lines
[i
]->layer
!= other_layer
)
2129 dprintf ("saw other line %p on layer %d (not %d)\n",
2130 (void *) (l
->s
->lines
[i
]), l
->s
->lines
[i
]->layer
,
2133 goto viatrim_other_corner
;
2136 viatrim_other_corner
:
2137 if (other_layer
== -1)
2138 for (i
= 0; i
< l
->e
->n_lines
; i
++)
2139 if (l
->e
->lines
[i
] != l
)
2141 if (other_layer
== -1)
2143 other_layer
= l
->s
->lines
[i
]->layer
;
2144 dprintf ("noting other line %p on layer %d\n",
2145 (void *) (l
->s
->lines
[i
]), my_layer
);
2147 else if (l
->e
->lines
[i
]->layer
!= other_layer
)
2149 dprintf ("saw end line on layer %d (not %d)\n",
2150 l
->e
->lines
[i
]->layer
, other_layer
);
2151 goto viatrim_continue
;
2155 /* Now see if any other line intersects us. We don't need to
2156 check corners, because they'd either be pins/vias and
2157 already conflict, or pads, which we'll check here anyway. */
2159 add_point_to_rect (&r
, l
->s
->x
, l
->s
->y
, l
->line
->Thickness
);
2160 add_point_to_rect (&r
, l
->e
->x
, l
->e
->y
, l
->line
->Thickness
);
2162 for (l2
= lines
; l2
; l2
= l2
->next
)
2166 if (l2
->s
->net
!= l
->s
->net
&& l2
->layer
== other_layer
)
2168 dprintf ("checking other line %#mD to %#mD\n", l2
->s
->x
,
2169 l2
->s
->y
, l2
->e
->x
, l2
->e
->y
);
2170 if (line_in_rect (&r
, l2
))
2172 dprintf ("line from %#mD to %#mD in the way\n",
2173 l2
->s
->x
, l2
->s
->y
, l2
->e
->x
, l2
->e
->y
);
2174 goto viatrim_continue
;
2179 if (l
->layer
== other_layer
)
2181 move_line_to_layer (l
, other_layer
);
2187 vrm
= simple_optimizations ();
2189 printf ("viatrim: %d traces moved, %d vias removed\n", rv
, vrm
);
2196 int more
= 1, oldmore
= 0;
2198 while (more
!= oldmore
&& --toomany
)
2201 more
+= debumpify ();
2203 more
+= orthopull ();
2204 more
+= vianudge ();
2215 int sel
= any_line_selected ();
2218 for (c
= corners
; c
; c
= c
->next
)
2223 if (c
->n_lines
== 2 && !c
->via
&& !c
->pin
&& !c
->via
)
2225 int o1
= line_orient (c
->lines
[0], c
);
2226 int o2
= line_orient (c
->lines
[1], c
);
2227 if (ORIENT (o1
) != ORIENT (o2
)
2228 && o1
!= DIAGONAL
&& o2
!= DIAGONAL
2229 && c
->lines
[0]->line
->Thickness
== c
->lines
[1]->line
->Thickness
)
2236 while (!done
&& progress
)
2240 for (c
= corners
; c
; c
= c
->next
)
2246 int max
= line_length (c
->lines
[0]);
2247 int len
= line_length (c
->lines
[1]);
2250 corner_s
*closest_corner
= 0, *c2
, *oc1
, *oc2
;
2251 int mx
= 0, my
= 0, x
, y
;
2252 int o1
= line_orient (c
->lines
[0], c
);
2253 int o2
= line_orient (c
->lines
[1], c
);
2255 if (c
->pad
|| c
->pin
|| c
->via
)
2262 oc1
= other_corner (c
->lines
[0], c
);
2263 oc2
= other_corner (c
->lines
[1], c
);
2271 if ((sel
&& !(selected (c
->lines
[0]->line
)
2272 || selected (c
->lines
[1]->line
)))
2273 || (!sel
&& autorouted_only
2274 && !(autorouted (c
->lines
[0]->line
)
2275 || autorouted (c
->lines
[1]->line
))))
2314 ref
= c
->x
* mx
+ c
->y
* my
;
2317 bloat
= (c
->lines
[0]->line
->Thickness
/ 2 + SB
+ 1) * 3 / 2;
2319 for (c2
= corners
; c2
; c2
= c2
->next
)
2323 if (c2
!= c
&& c2
!= oc1
&& c2
!= oc2
2324 && c
->x
* mx
<= c2
->x
* mx
2325 && c
->y
* my
<= c2
->y
* my
2326 && c
->net
!= c2
->net
2327 && intersecting_layers (c
->layer
, c2
->layer
))
2329 int cr
= corner_radius (c2
);
2330 len
= c2
->x
* mx
+ c2
->y
* my
- ref
- cr
- bloat
;
2331 if (c
->x
!= c2
->x
&& c
->y
!= c2
->y
)
2333 if (len
< dist
|| (len
== dist
&& c
->miter
!= -1))
2336 closest_corner
= c2
;
2341 if (closest_corner
&& closest_corner
->miter
== -1)
2348 if (dist
< Settings
.Grid
)
2355 dist
-= dist
% Settings
.Grid
;
2381 c2
= find_corner (x
, y
, c
->layer
);
2382 if (c2
!= other_corner (c
->lines
[0], c
))
2383 split_line (c
->lines
[0], c2
);
2401 move_corner (c
, x
, y
);
2413 classify_corner (corner_s
* c
, int this_net
)
2416 if (c
->net
== this_net
)
2419 for (i
= 0; i
< c
->n_lines
; i
++)
2420 classify_corner (other_corner (c
->lines
[i
], c
), this_net
);
2426 static int this_net
= 1;
2429 for (c
= corners
; c
; c
= c
->next
)
2435 classify_corner (c
, this_net
);
2447 for (c
= corners
; c
; c
= c
->next
)
2451 printf ("%p corner %d,%d layer %d net %d\n",
2452 (void *) c
, c
->x
, c
->y
, c
->layer
, c
->net
);
2454 for (l
= lines
; l
; l
= l
->next
)
2458 printf ("%p line %p to %p layer %d\n",
2459 (void *) l
, (void *) (l
->s
), (void *) (l
->e
), l
->layer
);
2466 nudge_corner (corner_s
* c
, int dx
, int dy
, corner_s
* prev_corner
)
2471 if (prev_corner
&& (c
->pin
|| c
->pad
))
2473 move_corner (c
, ox
+ dx
, oy
+ dy
);
2474 for (l
= 0; l
< c
->n_lines
; l
++)
2476 corner_s
*oc
= other_corner (c
->lines
[l
], c
);
2477 if (oc
== prev_corner
)
2479 if (dx
&& oc
->x
== ox
)
2480 nudge_corner (oc
, dx
, 0, c
);
2481 if (dy
&& oc
->y
== oy
)
2482 nudge_corner (oc
, 0, dy
, c
);
2488 choose_example_line (corner_s
* c1
, corner_s
* c2
)
2494 dprintf ("choose_example_line\n");
2495 for (ci
= 0; ci
< 2; ci
++)
2496 for (li
= 0; li
< c
[ci
]->n_lines
; li
++)
2498 dprintf (" try[%d,%d] \033[36m<%#mD-%#mD t%#mS c%#mS f%s>\033[0m\n",
2500 c
[ci
]->lines
[li
]->s
->x
, c
[ci
]->lines
[li
]->s
->y
,
2501 c
[ci
]->lines
[li
]->e
->x
, c
[ci
]->lines
[li
]->e
->y
,
2502 c
[ci
]->lines
[li
]->line
->Thickness
,
2503 c
[ci
]->lines
[li
]->line
->Clearance
,
2504 flags_to_string (c
[ci
]->lines
[li
]->line
->Flags
, LINE_TYPE
));
2505 /* Pads are disqualified, as we want to mimic a trace line. */
2506 if (c
[ci
]->lines
[li
]->line
== (LineType
*) c
[ci
]->pad
)
2508 dprintf (" bad, pad\n");
2511 /* Lines on layers that don't connect to the other pad are bad too. */
2512 if (!intersecting_layers (c
[ci
]->lines
[li
]->layer
, c
[1 - ci
]->layer
))
2514 dprintf (" bad, layers\n");
2517 dprintf (" good\n");
2518 return c
[ci
]->lines
[li
];
2520 dprintf ("choose_example_line: none found!\n");
2525 connect_corners (corner_s
* c1
, corner_s
* c2
)
2528 line_s
*ex
= choose_example_line (c1
, c2
);
2529 LineType
*example
= ex
->line
;
2532 ("connect_corners \033[32m%#mD to %#mD, example line %#mD to %#mD l%d\033[0m\n",
2533 c1
->x
, c1
->y
, c2
->x
, c2
->y
, ex
->s
->x
, ex
->s
->y
, ex
->e
->x
, ex
->e
->y
,
2538 /* Assume c1 is the moveable one. */
2539 if (!(c1
->pin
|| c1
->pad
|| c1
->via
) && c1
->n_lines
== 1)
2542 /* Extend the line */
2543 if (c1
->lines
[0]->s
->x
== c1
->lines
[0]->e
->x
)
2544 nx
= c1
->x
, ny
= c2
->y
;
2546 nx
= c2
->x
, ny
= c1
->y
;
2547 if (nx
!= c2
->x
|| ny
!= c2
->y
)
2549 move_corner (c1
, nx
, ny
);
2550 new_line (c1
, c2
, layer
, example
);
2555 move_corner (c1
, nx
, ny
);
2561 corner_s
*nc
= find_corner (c1
->x
, c2
->y
, layer
);
2562 new_line (c1
, nc
, layer
, example
);
2563 new_line (nc
, c2
, layer
, example
);
2569 * \brief Look for pins that have no connections.
2571 * See if there's a corner close by that should be connected to it.
2572 * This usually happens when the MUCS router needs to route to an
2579 int best_dist
[MAX_LAYER
+ 1];
2580 corner_s
*best_c
[MAX_LAYER
+ 1];
2582 int left
= 0, right
= 0, top
= 0, bottom
= 0;
2592 for (c
= corners
; c
; c
= c
->next
)
2596 if (!(c
->pin
|| c
->via
|| c
->pad
))
2601 dprintf ("\ncorner %s\n", corner_name (c
));
2602 if (c
->pin
|| c
->via
)
2604 pin
= c
->pin
? c
->pin
: c
->via
;
2605 close
= pin
->Thickness
/ 2;
2606 left
= c
->x
- close
;
2607 right
= c
->x
+ close
;
2608 bottom
= c
->y
- close
;
2613 close
= c
->pad
->Thickness
/ 2 + 1;
2614 left
= djmin (c
->pad
->Point1
.X
, c
->pad
->Point2
.X
) - close
;
2615 right
= djmax (c
->pad
->Point1
.X
, c
->pad
->Point2
.X
) + close
;
2616 bottom
= djmin (c
->pad
->Point1
.Y
, c
->pad
->Point2
.Y
) - close
;
2617 top
= djmax (c
->pad
->Point1
.Y
, c
->pad
->Point2
.Y
) + close
;
2618 if (c
->pad
->Point1
.X
== c
->pad
->Point2
.X
)
2620 int hy
= (c
->pad
->Point1
.Y
+ c
->pad
->Point2
.Y
) / 2;
2621 dprintf ("pad y %#mS %#mS hy %#mS c %#mS\n", c
->pad
->Point1
.Y
,
2622 c
->pad
->Point2
.Y
, hy
, c
->y
);
2630 int hx
= (c
->pad
->Point1
.X
+ c
->pad
->Point2
.X
) / 2;
2631 dprintf ("pad x %#mS %#mS hx %#mS c %#mS\n", c
->pad
->Point1
.X
,
2632 c
->pad
->Point2
.X
, hx
, c
->x
);
2640 dprintf ("%s x %#mS-%#mS y %#mS-%#mS\n", corner_name (c
), left
, right
, bottom
, top
);
2641 for (l
= 0; l
<= max_copper_layer
; l
++)
2643 best_dist
[l
] = close
* 2;
2647 for (c2
= corners
; c2
; c2
= c2
->next
)
2653 lt
= corner_radius (c2
);
2656 && !(c2
->pin
|| c2
->pad
|| c2
->via
)
2657 && intersecting_layers (c
->layer
, c2
->layer
)
2658 && c2
->x
>= left
- lt
2659 && c2
->x
<= right
+ lt
2660 && c2
->y
>= bottom
- lt
&& c2
->y
<= top
+ lt
)
2662 int d
= dist (c
->x
, c
->y
, c2
->x
, c2
->y
);
2663 if (pin
&& d
> pin
->Thickness
/ 2 + lt
)
2665 if (c2
->n_lines
== 1)
2668 dprintf ("found orphan %s vs %s\n", corner_name (c2
),
2670 connect_corners (c
, c2
);
2674 if (best_c
[c2
->layer
] == 0
2675 || c2
->n_lines
< best_c
[c2
->layer
]->n_lines
2676 || (d
< best_dist
[c2
->layer
]
2677 && c2
->n_lines
<= best_c
[c2
->layer
]->n_lines
))
2679 best_dist
[c2
->layer
] = d
;
2680 best_c
[c2
->layer
] = c2
;
2681 dprintf ("layer %d best now %s\n", c2
->layer
,
2685 if (!got_one
&& c
->n_lines
== (c
->pad
? 1 : 0))
2687 for (l
= 0; l
<= max_copper_layer
; l
++)
2689 dprintf ("best[%d] = %s\n", l
, corner_name (best_c
[l
]));
2690 for (l
= 0; l
<= max_copper_layer
; l
++)
2693 dprintf ("move %s to %s\n", corner_name (best_c
[l
]),
2695 connect_corners (best_c
[l
], c
);
2704 /* Now look for line ends that don't connect, see if they need to be
2705 extended to intersect another line. */
2706 for (c
= corners
; c
; c
= c
->next
)
2713 if (c
->pin
|| c
->via
|| c
->pad
)
2715 if (c
->n_lines
!= 1)
2719 lo
= line_orient (l
, c
);
2720 dprintf ("line end %#mD orient %d\n", c
->x
, c
->y
, lo
);
2722 for (t
= lines
; t
; t
= t
->next
)
2726 if (t
->layer
!= c
->lines
[0]->layer
)
2728 switch (lo
) /* remember, orient is for the line relative to the corner */
2731 if (t
->s
->x
== t
->e
->x
2734 c
->x
+ (l
->line
->Thickness
+ t
->line
->Thickness
) / 2
2735 && ((t
->s
->y
< c
->y
&& c
->y
< t
->e
->y
)
2736 || (t
->e
->y
< c
->y
&& c
->y
< t
->s
->y
)))
2738 dprintf ("found %#mD - %#mD\n", t
->s
->x
, t
->s
->y
, t
->e
->x
, t
->e
->y
);
2739 move_corner (c
, t
->s
->x
, c
->y
);
2743 if (t
->s
->x
== t
->e
->x
2746 c
->x
- (l
->line
->Thickness
+ t
->line
->Thickness
) / 2
2747 && ((t
->s
->y
< c
->y
&& c
->y
< t
->e
->y
)
2748 || (t
->e
->y
< c
->y
&& c
->y
< t
->s
->y
)))
2750 dprintf ("found %#mD - %#mD\n", t
->s
->x
, t
->s
->y
, t
->e
->x
, t
->e
->y
);
2751 move_corner (c
, t
->s
->x
, c
->y
);
2755 if (t
->s
->y
== t
->e
->y
2758 c
->y
+ (l
->line
->Thickness
+ t
->line
->Thickness
) / 2
2759 && ((t
->s
->x
< c
->x
&& c
->x
< t
->e
->x
)
2760 || (t
->e
->x
< c
->x
&& c
->x
< t
->s
->x
)))
2762 dprintf ("found %#mD - %#mD\n", t
->s
->x
, t
->s
->y
, t
->e
->x
, t
->e
->y
);
2763 move_corner (c
, c
->x
, t
->s
->y
);
2767 if (t
->s
->y
== t
->e
->y
2770 c
->y
- (l
->line
->Thickness
+ t
->line
->Thickness
) / 2
2771 && ((t
->s
->x
< c
->x
&& c
->x
< t
->e
->x
)
2772 || (t
->e
->x
< c
->x
&& c
->x
< t
->s
->x
)))
2774 dprintf ("found %#mD - %#mD\n", t
->s
->x
, t
->s
->y
, t
->e
->x
, t
->e
->y
);
2775 move_corner (c
, c
->x
, t
->s
->y
);
2784 pad_orient (PadType
* p
)
2786 if (p
->Point1
.X
== p
->Point2
.X
)
2788 if (p
->Point1
.Y
== p
->Point2
.Y
)
2800 dprintf ("\ndj: padcleaner\n");
2801 for (l
= lines
; l
; l
= nextl
)
2811 dprintf ("dj: line %p\n", (void *) l
);
2814 if (l
->s
->pad
&& l
->s
->pad
== l
->e
->pad
)
2817 ALLPAD_LOOP (PCB
->Data
);
2820 TEST_FLAG (ONSOLDERFLAG
, element
) ? LT_BOTTOM
: LT_TOP
;
2822 if (layer_type
[l
->layer
] != layerflag
)
2826 close
= pad
->Thickness
/ 2 + 1;
2827 add_point_to_rect (&r
, pad
->Point1
.X
, pad
->Point1
.Y
, close
- SB
/ 2);
2828 add_point_to_rect (&r
, pad
->Point2
.X
, pad
->Point2
.Y
, close
- SB
/ 2);
2829 if (pin_in_rect (&r
, l
->s
->x
, l
->s
->y
, 0)
2830 && pin_in_rect (&r
, l
->e
->x
, l
->e
->y
, 0)
2831 && ORIENT (line_orient (l
, 0)) == pad_orient (pad
))
2834 ("padcleaner %#mD-%#mD %#mS vs line %#mD-%#mD %#mS\n",
2835 pad
->Point1
.X
, pad
->Point1
.Y
, pad
->Point2
.X
, pad
->Point2
.Y
,
2836 pad
->Thickness
, l
->s
->x
, l
->s
->y
, l
->e
->x
, l
->e
->y
,
2837 l
->line
->Thickness
);
2848 grok_layer_groups ()
2851 LayerGroupType
*l
= &(PCB
->LayerGroups
);
2853 solder_layer
= component_layer
= -1;
2854 for (i
= 0; i
< max_copper_layer
; i
++)
2857 layer_groupings
[i
] = 0;
2859 for (i
= 0; i
< max_group
; i
++)
2862 for (j
= 0; j
< l
->Number
[i
]; j
++)
2864 if (l
->Entries
[i
][j
] == bottom_silk_layer
)
2866 if (l
->Entries
[i
][j
] == top_silk_layer
)
2869 for (j
= 0; j
< l
->Number
[i
]; j
++)
2871 if (l
->Entries
[i
][j
] < max_copper_layer
)
2873 layer_type
[l
->Entries
[i
][j
]] |= f
;
2874 layer_groupings
[l
->Entries
[i
][j
]] = i
;
2875 if (solder_layer
== -1 && f
== LT_BOTTOM
)
2876 solder_layer
= l
->Entries
[i
][j
];
2877 if (component_layer
== -1 && f
== LT_TOP
)
2878 component_layer
= l
->Entries
[i
][j
];
2884 static const char djopt_syntax
[] =
2885 "djopt(debumpify|unjaggy|simple|vianudge|viatrim|orthopull|splitlines)\n"
2886 "djopt(auto) - all of the above\n"
2889 static const char djopt_help
[] =
2890 "Perform various optimizations on the current board.";
2892 /* %start-doc actions djopt
2894 The different types of optimizations change your board in order to
2895 reduce the total trace length and via count.
2900 Looks for U-shaped traces that can be shortened or eliminated.
2906 @center @image{debumpify,,,Example pcb before debumpify,png}
2910 @center @image{debumpify.out,,,Example pcb after debumpify,png}
2914 Looks for corners which could be flipped to eliminate one or more
2915 corners (i.e. jaggy lines become simpler).
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.
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
2928 Looks for traces that go from via to via, where moving that trace to a
2929 different layer eliminates one or both vias.
2932 Looks for chains of traces all going in one direction, with more
2933 traces orthogonal on one side than on the other. Moves the chain in
2934 that direction, causing a net reduction in trace length, possibly
2935 eliminating traces and/or corners.
2938 Looks for lines that pass through vias, pins, or pads, and splits them
2939 into separate lines so they can be managed separately.
2942 Performs the above options, repeating until no further optimizations
2946 Replaces 90 degree corners with a pair of 45 degree corners, to reduce
2947 RF losses and trace length.
2954 ActionDJopt (int argc
, char **argv
, Coord x
, Coord y
)
2956 char *arg
= argc
> 0 ? argv
[0] : 0;
2957 int layn
, saved
= 0;
2965 grok_layer_groups ();
2967 ELEMENT_LOOP (PCB
->Data
);
2970 c
= find_corner (pin
->X
, pin
->Y
, -1);
2977 TEST_FLAG (ONSOLDERFLAG
, pad
) ? solder_layer
: component_layer
;
2978 line_s
*ls
= (line_s
*) malloc (sizeof (line_s
));
2982 ls
->s
= find_corner (pad
->Point1
.X
, pad
->Point1
.Y
, layern
);
2984 ls
->e
= find_corner (pad
->Point2
.X
, pad
->Point2
.Y
, layern
);
2987 ls
->line
= (LineType
*) pad
;
2988 add_line_to_corner (ls
, ls
->s
);
2989 add_line_to_corner (ls
, ls
->e
);
2994 VIA_LOOP (PCB
->Data
);
2995 /* hace don't mess with vias that have thermals */
2996 /* but then again don't bump into them
2997 if (!TEST_FLAG(ALLTHERMFLAGS, via))
3000 c
= find_corner (via
->X
, via
->Y
, -1);
3006 if (NSTRCMP (arg
, "splitlines") == 0)
3008 if (canonicalize_lines ())
3009 IncrementUndoSerialNumber ();
3013 for (layn
= 0; layn
< max_copper_layer
; layn
++)
3015 LayerType
*layer
= LAYER_PTR (layn
);
3021 if(autorouted_only
&& !autorouted (line
))
3024 /* don't mess with thermals */
3025 if (TEST_FLAG (USETHERMALFLAG
, line
))
3028 if (line
->Point1
.X
== line
->Point2
.X
&&
3029 line
->Point1
.Y
== line
->Point2
.Y
)
3031 RemoveLine (layer
, line
);
3035 ls
= (line_s
*) malloc (sizeof (line_s
));
3039 ls
->s
= find_corner (line
->Point1
.X
, line
->Point1
.Y
, layn
);
3040 ls
->e
= find_corner (line
->Point2
.X
, line
->Point2
.Y
, layn
);
3042 add_line_to_corner (ls
, ls
->s
);
3043 add_line_to_corner (ls
, ls
->e
);
3051 canonicalize_lines ();
3057 if (NSTRCMP (arg
, "debumpify") == 0)
3058 saved
+= debumpify ();
3059 else if (NSTRCMP (arg
, "unjaggy") == 0)
3060 saved
+= unjaggy ();
3061 else if (NSTRCMP (arg
, "simple") == 0)
3062 saved
+= simple_optimizations ();
3063 else if (NSTRCMP (arg
, "vianudge") == 0)
3064 saved
+= vianudge ();
3065 else if (NSTRCMP (arg
, "viatrim") == 0)
3066 saved
+= viatrim ();
3067 else if (NSTRCMP (arg
, "orthopull") == 0)
3068 saved
+= orthopull ();
3069 else if (NSTRCMP (arg
, "auto") == 0)
3070 saved
+= automagic ();
3071 else if (NSTRCMP (arg
, "miter") == 0)
3075 printf ("unknown command: %s\n", arg
);
3083 IncrementUndoSerialNumber ();
3087 HID_Action djopt_action_list
[] = {
3088 {"djopt", 0, ActionDJopt
,
3089 djopt_help
, djopt_syntax
}
3091 {"OptAutoOnly", 0, djopt_set_auto_only
,
3092 djopt_sao_help
, djopt_sao_syntax
}
3095 REGISTER_ACTIONS (djopt_action_list
)