5 * PCB, interactive printed circuit board design
6 * Copyright (C) 1994,1995,1996, 2005 Thomas Nau
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * Contact addresses for paper mail and Email:
23 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
24 * Thomas.Nau@rz.uni-ulm.de
31 * - lists for pins and vias, lines, arcs, pads and for polygons are created.
32 * Every object that has to be checked is added to its list.
33 * Coarse searching is accomplished with the data rtrees.
34 * - there's no 'speed-up' mechanism for polygons because they are not used
35 * as often as other objects
36 * - the maximum distance between line and pin ... would depend on the angle
37 * between them. To speed up computation the limit is set to one half
38 * of the thickness of the objects (cause of square pins).
40 * PV: means pin or via (objects that connect layers)
41 * LO: all non PV objects (layer objects like lines, arcs, polygons, pads)
43 * 1. first, the LO or PV at the given coordinates is looked up
44 * 2. all LO connections to that PV are looked up next
45 * 3. lookup of all LOs connected to LOs from (2).
46 * This step is repeated until no more new connections are found.
47 * 4. lookup all PVs connected to the LOs from (2) and (3)
48 * 5. start again with (1) for all new PVs from (4)
50 * Intersection of line <--> circle:
51 * - calculate the signed distance from the line to the center,
52 * return false if abs(distance) > R
53 * - get the distance from the line <--> distancevector intersection to
54 * (X1,Y1) in range [0,1], return true if 0 <= distance <= 1
55 * - depending on (r > 1.0 or r < 0.0) check the distance of X2,Y2 or X1,Y1
58 * Intersection of line <--> line:
59 * - see the description of 'LineLineIntersect()'
62 /* routines to find connections between pins, vias, lines...
76 #ifdef HAVE_SYS_TIMES_H
77 #include <sys/times.h>
82 #include "crosshair.h"
91 #include "pcb-printf.h"
97 #ifdef HAVE_LIBDMALLOC
103 /* ---------------------------------------------------------------------------
107 #define SEPARATE(FP) \
111 for (i = Settings.CharPerLine; i; i--) \
116 #define LIST_ENTRY(list,I) (((AnyObjectType **)list->Data)[(I)])
117 #define PADLIST_ENTRY(L,I) (((PadType **)PadList[(L)].Data)[(I)])
118 #define LINELIST_ENTRY(L,I) (((LineType **)LineList[(L)].Data)[(I)])
119 #define ARCLIST_ENTRY(L,I) (((ArcType **)ArcList[(L)].Data)[(I)])
120 #define RATLIST_ENTRY(I) (((RatType **)RatList.Data)[(I)])
121 #define POLYGONLIST_ENTRY(L,I) (((PolygonType **)PolygonList[(L)].Data)[(I)])
122 #define PVLIST_ENTRY(I) (((PinType **)PVList.Data)[(I)])
124 #define IS_PV_ON_RAT(PV, Rat) \
125 (IsPointOnLineEnd((PV)->X,(PV)->Y, (Rat)))
127 #define IS_PV_ON_ARC(PV, Arc) \
128 (TEST_FLAG(SQUAREFLAG, (PV)) ? \
130 (PV)->X -MAX(((PV)->Thickness+1)/2 +Bloat,0), (PV)->Y -MAX(((PV)->Thickness+1)/2 +Bloat,0), \
131 (PV)->X +MAX(((PV)->Thickness+1)/2 +Bloat,0), (PV)->Y +MAX(((PV)->Thickness+1)/2 +Bloat,0), \
133 IsPointOnArc((PV)->X,(PV)->Y,MAX((PV)->Thickness/2.0 + Bloat,0.0), (Arc)))
135 #define IS_PV_ON_PAD(PV,Pad) \
136 ( IsPointInPad((PV)->X, (PV)->Y, MAX((PV)->Thickness/2 +Bloat,0), (Pad)))
138 static DrcViolationType
139 *pcb_drc_violation_new (const char *title
,
140 const char *explanation
,
144 Coord measured_value
,
145 Coord required_value
,
147 long int *object_id_list
,
148 int *object_type_list
)
150 DrcViolationType
*violation
= (DrcViolationType
*)malloc (sizeof (DrcViolationType
));
152 violation
->title
= strdup (title
);
153 violation
->explanation
= strdup (explanation
);
156 violation
->angle
= angle
;
157 violation
->have_measured
= have_measured
;
158 violation
->measured_value
= measured_value
;
159 violation
->required_value
= required_value
;
160 violation
->object_count
= object_count
;
161 violation
->object_id_list
= object_id_list
;
162 violation
->object_type_list
= object_type_list
;
168 pcb_drc_violation_free (DrcViolationType
*violation
)
170 free (violation
->title
);
171 free (violation
->explanation
);
175 static GString
*drc_dialog_message
;
177 reset_drc_dialog_message(void)
179 if (drc_dialog_message
)
180 g_string_free (drc_dialog_message
, FALSE
);
181 drc_dialog_message
= g_string_new ("");
182 if (gui
->drc_gui
!= NULL
)
184 gui
->drc_gui
->reset_drc_dialog_message ();
188 append_drc_dialog_message(const char *fmt
, ...)
193 new_str
= pcb_vprintf (fmt
, ap
);
194 g_string_append (drc_dialog_message
, new_str
);
199 static void GotoError (void);
202 append_drc_violation (DrcViolationType
*violation
)
204 if (gui
->drc_gui
!= NULL
)
206 gui
->drc_gui
->append_drc_violation (violation
);
210 /* Fallback to formatting the violation message as text */
211 append_drc_dialog_message ("%s\n", violation
->title
);
212 append_drc_dialog_message (_("%m+near %$mD\n"),
213 Settings
.grid_unit
->allow
,
214 violation
->x
, violation
->y
);
218 if (gui
->drc_gui
== NULL
|| gui
->drc_gui
->log_drc_violations
)
220 Message (_("WARNING! Design Rule error - %s\n"), violation
->title
);
221 Message (_("%m+near location %$mD\n"),
222 Settings
.grid_unit
->allow
,
223 violation
->x
, violation
->y
);
227 * message when asked about continuing DRC checks after next
228 * violation is found.
230 #define DRC_CONTINUE _("Press Next to continue DRC checking")
231 #define DRC_NEXT _("Next")
232 #define DRC_CANCEL _("Cancel")
235 throw_drc_dialog(void)
239 if (gui
->drc_gui
!= NULL
)
241 r
= gui
->drc_gui
->throw_drc_dialog ();
245 /* Fallback to formatting the violation message as text */
246 append_drc_dialog_message (DRC_CONTINUE
);
247 r
= gui
->confirm_dialog (drc_dialog_message
->str
, DRC_CANCEL
, DRC_NEXT
);
248 reset_drc_dialog_message();
253 /* ---------------------------------------------------------------------------
256 * the two 'dummy' structs for PVs and Pads are necessary for creating
257 * connection lists which include the element's name
261 void **Data
; /* pointer to index data */
262 Cardinal Location
, /* currently used position */
263 DrawLocation
, Number
, /* number of objects in list */
267 /* ---------------------------------------------------------------------------
268 * some local identifiers
270 static Coord Bloat
= 0;
271 static int TheFlag
= FOUNDFLAG
;
272 static void *thing_ptr1
, *thing_ptr2
, *thing_ptr3
;
273 static int thing_type
;
274 static bool User
= false; /* user action causing this */
275 static bool drc
= false; /* whether to stop if finding something not found */
276 static Cardinal drcerr_count
; /* count of drc errors */
277 static Cardinal TotalP
, TotalV
, NumberOfPads
[2];
278 static ListType LineList
[MAX_LAYER
], /* list of objects to */
279 PolygonList
[MAX_LAYER
], ArcList
[MAX_LAYER
], PadList
[2], RatList
, PVList
;
281 /* ---------------------------------------------------------------------------
282 * some local prototypes
284 static bool LookupLOConnectionsToPVList (bool);
285 static bool LookupLOConnectionsToLOList (bool);
286 static bool LookupPVConnectionsToLOList (bool);
287 static bool LookupPVConnectionsToPVList (void);
288 static bool LookupLOConnectionsToLine (LineType
*, Cardinal
, bool);
289 static bool LookupLOConnectionsToPad (PadType
*, Cardinal
);
290 static bool LookupLOConnectionsToPolygon (PolygonType
*, Cardinal
);
291 static bool LookupLOConnectionsToArc (ArcType
*, Cardinal
);
292 static bool LookupLOConnectionsToRatEnd (PointType
*, Cardinal
);
293 static bool IsRatPointOnLineEnd (PointType
*, LineType
*);
294 static bool ArcArcIntersect (ArcType
*, ArcType
*);
295 static bool PrepareNextLoop (FILE *);
296 static bool PrintElementConnections (ElementType
*, FILE *, bool);
297 static bool ListsEmpty (bool);
298 static bool DoIt (bool, bool);
299 static void PrintElementNameList (ElementType
*, FILE *);
300 static void PrintConnectionElementName (ElementType
*, FILE *);
301 static void PrintConnectionListEntry (char *, ElementType
*,
303 static void PrintPadConnections (Cardinal
, FILE *, bool);
304 static void PrintPinConnections (FILE *, bool);
305 static bool PrintAndSelectUnusedPinsAndPadsOfElement (ElementType
*,
307 static void DrawNewConnections (void);
308 static void DumpList (void);
309 static void LocateError (Coord
*, Coord
*);
310 static void BuildObjectList (int *, long int **, int **);
311 static void GotoError (void);
312 static bool DRCFind (int, void *, void *, void *);
313 static bool ListStart (int, void *, void *, void *);
314 static bool SetThing (int, void *, void *, void *);
315 static bool IsArcInPolygon (ArcType
*, PolygonType
*);
316 static bool IsLineInPolygon (LineType
*, PolygonType
*);
317 static bool IsPadInPolygon (PadType
*, PolygonType
*);
318 static bool IsPolygonInPolygon (PolygonType
*, PolygonType
*);
320 /* ---------------------------------------------------------------------------
321 * some of the 'pad' routines are the same as for lines because the 'pad'
322 * struct starts with a line struct. See global.h for details
325 LinePadIntersect (LineType
*Line
, PadType
*Pad
)
327 return LineLineIntersect ((Line
), (LineType
*)Pad
);
331 ArcPadIntersect (ArcType
*Arc
, PadType
*Pad
)
333 return LineArcIntersect ((LineType
*) (Pad
), (Arc
));
337 add_object_to_list (ListType
*list
, int type
, void *ptr1
, void *ptr2
, void *ptr3
)
339 AnyObjectType
*object
= (AnyObjectType
*)ptr2
;
342 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr3
);
344 SET_FLAG (TheFlag
, object
);
345 LIST_ENTRY (list
, list
->Number
) = object
;
349 if (list
.Number
> list
.Size
)
350 printf ("add_object_to_list overflow! type=%i num=%d size=%d\n", type
, list
.Number
, list
.Size
);
353 if (drc
&& !TEST_FLAG (SELECTEDFLAG
, object
))
354 return (SetThing (type
, ptr1
, ptr2
, ptr3
));
359 ADD_PV_TO_LIST (PinType
*Pin
)
361 return add_object_to_list (&PVList
, Pin
->Element
? PIN_TYPE
: VIA_TYPE
,
362 Pin
->Element
? Pin
->Element
: Pin
, Pin
, Pin
);
366 ADD_PAD_TO_LIST (Cardinal L
, PadType
*Pad
)
368 return add_object_to_list (&PadList
[L
], PAD_TYPE
, Pad
->Element
, Pad
, Pad
);
372 ADD_LINE_TO_LIST (Cardinal L
, LineType
*Ptr
)
374 return add_object_to_list (&LineList
[L
], LINE_TYPE
, LAYER_PTR (L
), Ptr
, Ptr
);
378 ADD_ARC_TO_LIST (Cardinal L
, ArcType
*Ptr
)
380 return add_object_to_list (&ArcList
[L
], ARC_TYPE
, LAYER_PTR (L
), Ptr
, Ptr
);
384 ADD_RAT_TO_LIST (RatType
*Ptr
)
386 return add_object_to_list (&RatList
, RATLINE_TYPE
, Ptr
, Ptr
, Ptr
);
390 ADD_POLYGON_TO_LIST (Cardinal L
, PolygonType
*Ptr
)
392 return add_object_to_list (&PolygonList
[L
], POLYGON_TYPE
, LAYER_PTR (L
), Ptr
, Ptr
);
396 expand_bounds (BoxType
*box_in
)
398 BoxType box_out
= *box_in
;
412 PinLineIntersect (PinType
*PV
, LineType
*Line
)
414 /* IsLineInRectangle already has Bloat factor */
415 return TEST_FLAG (SQUAREFLAG
,
416 PV
) ? IsLineInRectangle (PV
->X
- (PIN_SIZE (PV
) + 1) / 2,
417 PV
->Y
- (PIN_SIZE (PV
) + 1) / 2,
418 PV
->X
+ (PIN_SIZE (PV
) + 1) / 2,
419 PV
->Y
+ (PIN_SIZE (PV
) + 1) / 2,
420 Line
) : IsPointInPad (PV
->X
,
432 SetThing (int type
, void *ptr1
, void *ptr2
, void *ptr3
)
438 if (type
== PIN_TYPE
&& ptr1
== NULL
)
441 thing_type
= VIA_TYPE
;
447 BoxBoxIntersection (BoxType
*b1
, BoxType
*b2
)
449 if (b2
->X2
< b1
->X1
|| b2
->X1
> b1
->X2
)
451 if (b2
->Y2
< b1
->Y1
|| b2
->Y1
> b1
->Y2
)
457 PadPadIntersect (PadType
*p1
, PadType
*p2
)
459 return LinePadIntersect ((LineType
*) p1
, p2
);
463 PV_TOUCH_PV (PinType
*PV1
, PinType
*PV2
)
468 t1
= MAX (PV1
->Thickness
/ 2.0 + Bloat
, 0);
469 t2
= MAX (PV2
->Thickness
/ 2.0 + Bloat
, 0);
470 if (IsPointOnPin (PV1
->X
, PV1
->Y
, t1
, PV2
)
471 || IsPointOnPin (PV2
->X
, PV2
->Y
, t2
, PV1
))
473 if (!TEST_FLAG (SQUAREFLAG
, PV1
) || !TEST_FLAG (SQUAREFLAG
, PV2
))
475 /* check for square/square overlap */
480 t2
= PV2
->Thickness
/ 2.0;
485 return BoxBoxIntersection (&b1
, &b2
);
488 /* ---------------------------------------------------------------------------
489 * releases all allocated memory
492 FreeLayoutLookupMemory (void)
496 for (i
= 0; i
< max_copper_layer
; i
++)
498 free (LineList
[i
].Data
);
499 LineList
[i
].Data
= NULL
;
500 free (ArcList
[i
].Data
);
501 ArcList
[i
].Data
= NULL
;
502 free (PolygonList
[i
].Data
);
503 PolygonList
[i
].Data
= NULL
;
512 FreeComponentLookupMemory (void)
514 free (PadList
[0].Data
);
515 PadList
[0].Data
= NULL
;
516 free (PadList
[1].Data
);
517 PadList
[1].Data
= NULL
;
520 /* ---------------------------------------------------------------------------
521 * allocates memory for component related stacks ...
522 * initializes index and sorts it by X1 and X2
525 InitComponentLookup (void)
529 /* initialize pad data; start by counting the total number
530 * on each of the two possible layers
532 NumberOfPads
[COMPONENT_LAYER
] = NumberOfPads
[SOLDER_LAYER
] = 0;
533 ALLPAD_LOOP (PCB
->Data
);
535 if (TEST_FLAG (ONSOLDERFLAG
, pad
))
536 NumberOfPads
[SOLDER_LAYER
]++;
538 NumberOfPads
[COMPONENT_LAYER
]++;
541 for (i
= 0; i
< 2; i
++)
543 /* allocate memory for working list */
544 PadList
[i
].Data
= (void **)calloc (NumberOfPads
[i
], sizeof (PadType
*));
546 /* clear some struct members */
547 PadList
[i
].Location
= 0;
548 PadList
[i
].DrawLocation
= 0;
549 PadList
[i
].Number
= 0;
550 PadList
[i
].Size
= NumberOfPads
[i
];
554 /* ---------------------------------------------------------------------------
555 * allocates memory for component related stacks ...
556 * initializes index and sorts it by X1 and X2
559 InitLayoutLookup (void)
563 /* initialize line arc and polygon data */
564 for (i
= 0; i
< max_copper_layer
; i
++)
566 LayerType
*layer
= LAYER_PTR (i
);
570 /* allocate memory for line pointer lists */
571 LineList
[i
].Data
= (void **)calloc (layer
->LineN
, sizeof (LineType
*));
572 LineList
[i
].Size
= layer
->LineN
;
576 ArcList
[i
].Data
= (void **)calloc (layer
->ArcN
, sizeof (ArcType
*));
577 ArcList
[i
].Size
= layer
->ArcN
;
581 /* allocate memory for polygon list */
584 PolygonList
[i
].Data
= (void **)calloc (layer
->PolygonN
, sizeof (PolygonType
*));
585 PolygonList
[i
].Size
= layer
->PolygonN
;
588 /* clear some struct members */
589 LineList
[i
].Location
= 0;
590 LineList
[i
].DrawLocation
= 0;
591 LineList
[i
].Number
= 0;
592 ArcList
[i
].Location
= 0;
593 ArcList
[i
].DrawLocation
= 0;
594 ArcList
[i
].Number
= 0;
595 PolygonList
[i
].Location
= 0;
596 PolygonList
[i
].DrawLocation
= 0;
597 PolygonList
[i
].Number
= 0;
600 if (PCB
->Data
->pin_tree
)
601 TotalP
= PCB
->Data
->pin_tree
->size
;
604 if (PCB
->Data
->via_tree
)
605 TotalV
= PCB
->Data
->via_tree
->size
;
608 /* allocate memory for 'new PV to check' list and clear struct */
609 PVList
.Data
= (void **)calloc (TotalP
+ TotalV
, sizeof (PinType
*));
610 PVList
.Size
= TotalP
+ TotalV
;
612 PVList
.DrawLocation
= 0;
614 /* Initialize ratline data */
615 RatList
.Data
= (void **)calloc (PCB
->Data
->RatN
, sizeof (RatType
*));
616 RatList
.Size
= PCB
->Data
->RatN
;
617 RatList
.Location
= 0;
618 RatList
.DrawLocation
= 0;
630 LOCtoPVline_callback (const BoxType
* b
, void *cl
)
632 LineType
*line
= (LineType
*) b
;
633 struct pv_info
*i
= (struct pv_info
*) cl
;
635 if (!TEST_FLAG (TheFlag
, line
) && PinLineIntersect (&i
->pv
, line
) &&
636 !TEST_FLAG (HOLEFLAG
, &i
->pv
))
638 if (ADD_LINE_TO_LIST (i
->layer
, line
))
645 LOCtoPVarc_callback (const BoxType
* b
, void *cl
)
647 ArcType
*arc
= (ArcType
*) b
;
648 struct pv_info
*i
= (struct pv_info
*) cl
;
650 if (!TEST_FLAG (TheFlag
, arc
) && IS_PV_ON_ARC (&i
->pv
, arc
) &&
651 !TEST_FLAG (HOLEFLAG
, &i
->pv
))
653 if (ADD_ARC_TO_LIST (i
->layer
, arc
))
660 LOCtoPVpad_callback (const BoxType
* b
, void *cl
)
662 PadType
*pad
= (PadType
*) b
;
663 struct pv_info
*i
= (struct pv_info
*) cl
;
665 if (!TEST_FLAG (TheFlag
, pad
) && IS_PV_ON_PAD (&i
->pv
, pad
) &&
666 !TEST_FLAG (HOLEFLAG
, &i
->pv
) &&
667 ADD_PAD_TO_LIST (TEST_FLAG (ONSOLDERFLAG
, pad
) ? SOLDER_LAYER
:
668 COMPONENT_LAYER
, pad
))
674 LOCtoPVrat_callback (const BoxType
* b
, void *cl
)
676 RatType
*rat
= (RatType
*) b
;
677 struct pv_info
*i
= (struct pv_info
*) cl
;
679 if (!TEST_FLAG (TheFlag
, rat
) && IS_PV_ON_RAT (&i
->pv
, rat
) &&
680 ADD_RAT_TO_LIST (rat
))
685 LOCtoPVpoly_callback (const BoxType
* b
, void *cl
)
687 PolygonType
*polygon
= (PolygonType
*) b
;
688 struct pv_info
*i
= (struct pv_info
*) cl
;
690 /* if the pin doesn't have a therm and polygon is clearing
691 * then it can't touch due to clearance, so skip the expensive
692 * test. If it does have a therm, you still need to test
693 * because it might not be inside the polygon, or it could
694 * be on an edge such that it doesn't actually touch.
696 if (!TEST_FLAG (TheFlag
, polygon
) && !TEST_FLAG (HOLEFLAG
, &i
->pv
) &&
697 (TEST_THERM (i
->layer
, &i
->pv
) ||
698 !TEST_FLAG (CLEARPOLYFLAG
,
700 || !i
->pv
.Clearance
))
702 double wide
= MAX (0.5 * i
->pv
.Thickness
+ Bloat
, 0);
703 if (TEST_FLAG (SQUAREFLAG
, &i
->pv
))
705 Coord x1
= i
->pv
.X
- (i
->pv
.Thickness
+ 1 + Bloat
) / 2;
706 Coord x2
= i
->pv
.X
+ (i
->pv
.Thickness
+ 1 + Bloat
) / 2;
707 Coord y1
= i
->pv
.Y
- (i
->pv
.Thickness
+ 1 + Bloat
) / 2;
708 Coord y2
= i
->pv
.Y
+ (i
->pv
.Thickness
+ 1 + Bloat
) / 2;
709 if (IsRectangleInPolygon (x1
, y1
, x2
, y2
, polygon
)
710 && ADD_POLYGON_TO_LIST (i
->layer
, polygon
))
713 else if (TEST_FLAG (OCTAGONFLAG
, &i
->pv
))
715 POLYAREA
*oct
= OctagonPoly (i
->pv
.X
, i
->pv
.Y
, i
->pv
.Thickness
/ 2);
716 if (isects (oct
, polygon
, true)
717 && ADD_POLYGON_TO_LIST (i
->layer
, polygon
))
720 else if (IsPointInPolygon (i
->pv
.X
, i
->pv
.Y
, wide
,
722 && ADD_POLYGON_TO_LIST (i
->layer
, polygon
))
728 /* ---------------------------------------------------------------------------
729 * checks if a PV is connected to LOs, if it is, the LO is added to
730 * the appropriate list and the 'used' flag is set
733 LookupLOConnectionsToPVList (bool AndRats
)
738 /* loop over all PVs currently on list */
739 while (PVList
.Location
< PVList
.Number
)
743 /* get pointer to data */
744 info
.pv
= *(PVLIST_ENTRY (PVList
.Location
));
745 search_box
= expand_bounds (&info
.pv
.BoundingBox
);
748 if (setjmp (info
.env
) == 0)
749 r_search (PCB
->Data
->pad_tree
, &search_box
, NULL
,
750 LOCtoPVpad_callback
, &info
);
754 /* now all lines, arcs and polygons of the several layers */
755 for (layer_no
= 0; layer_no
< max_copper_layer
; layer_no
++)
757 LayerType
*layer
= LAYER_PTR (layer_no
);
762 info
.layer
= layer_no
;
764 /* add touching lines */
765 if (setjmp (info
.env
) == 0)
766 r_search (layer
->line_tree
, &search_box
,
767 NULL
, LOCtoPVline_callback
, &info
);
770 /* add touching arcs */
771 if (setjmp (info
.env
) == 0)
772 r_search (layer
->arc_tree
, &search_box
,
773 NULL
, LOCtoPVarc_callback
, &info
);
776 /* check all polygons */
777 if (setjmp (info
.env
) == 0)
778 r_search (layer
->polygon_tree
, &search_box
,
779 NULL
, LOCtoPVpoly_callback
, &info
);
783 /* Check for rat-lines that may intersect the PV */
786 if (setjmp (info
.env
) == 0)
787 r_search (PCB
->Data
->rat_tree
, &search_box
, NULL
,
788 LOCtoPVrat_callback
, &info
);
797 /* ---------------------------------------------------------------------------
798 * find all connections between LO at the current list position and new LOs
801 LookupLOConnectionsToLOList (bool AndRats
)
804 Cardinal i
, group
, layer
, ratposition
,
805 lineposition
[MAX_LAYER
],
806 polyposition
[MAX_LAYER
], arcposition
[MAX_LAYER
], padposition
[2];
808 /* copy the current LO list positions; the original data is changed
809 * by 'LookupPVConnectionsToLOList()' which has to check the same
810 * list entries plus the new ones
812 for (i
= 0; i
< max_copper_layer
; i
++)
814 lineposition
[i
] = LineList
[i
].Location
;
815 polyposition
[i
] = PolygonList
[i
].Location
;
816 arcposition
[i
] = ArcList
[i
].Location
;
818 for (i
= 0; i
< 2; i
++)
819 padposition
[i
] = PadList
[i
].Location
;
820 ratposition
= RatList
.Location
;
822 /* loop over all new LOs in the list; recurse until no
823 * more new connections in the layergroup were found
831 position
= &ratposition
;
832 for (; *position
< RatList
.Number
; (*position
)++)
834 group
= RATLIST_ENTRY (*position
)->group1
;
835 if (LookupLOConnectionsToRatEnd
836 (&(RATLIST_ENTRY (*position
)->Point1
), group
))
838 group
= RATLIST_ENTRY (*position
)->group2
;
839 if (LookupLOConnectionsToRatEnd
840 (&(RATLIST_ENTRY (*position
)->Point2
), group
))
844 /* loop over all layergroups */
845 for (group
= 0; group
< max_group
; group
++)
849 for (entry
= 0; entry
< PCB
->LayerGroups
.Number
[group
]; entry
++)
851 layer
= PCB
->LayerGroups
.Entries
[group
][entry
];
853 /* be aware that the layer number equal max_copper_layer
854 * and max_copper_layer+1 have a special meaning for pads
856 if (layer
< max_copper_layer
)
858 /* try all new lines */
859 position
= &lineposition
[layer
];
860 for (; *position
< LineList
[layer
].Number
; (*position
)++)
861 if (LookupLOConnectionsToLine
862 (LINELIST_ENTRY (layer
, *position
), group
, true))
865 /* try all new arcs */
866 position
= &arcposition
[layer
];
867 for (; *position
< ArcList
[layer
].Number
; (*position
)++)
868 if (LookupLOConnectionsToArc
869 (ARCLIST_ENTRY (layer
, *position
), group
))
872 /* try all new polygons */
873 position
= &polyposition
[layer
];
874 for (; *position
< PolygonList
[layer
].Number
; (*position
)++)
875 if (LookupLOConnectionsToPolygon
876 (POLYGONLIST_ENTRY (layer
, *position
), group
))
881 /* try all new pads */
882 layer
-= max_copper_layer
;
885 Message (_("bad layer number %d max_copper_layer=%d in find.c\n"),
886 layer
, max_copper_layer
);
889 position
= &padposition
[layer
];
890 for (; *position
< PadList
[layer
].Number
; (*position
)++)
891 if (LookupLOConnectionsToPad
892 (PADLIST_ENTRY (layer
, *position
), group
))
898 /* check if all lists are done; Later for-loops
899 * may have changed the prior lists
901 done
= !AndRats
|| ratposition
>= RatList
.Number
;
902 done
= done
&& padposition
[0] >= PadList
[0].Number
&&
903 padposition
[1] >= PadList
[1].Number
;
904 for (layer
= 0; layer
< max_copper_layer
; layer
++)
906 lineposition
[layer
] >= LineList
[layer
].Number
&&
907 arcposition
[layer
] >= ArcList
[layer
].Number
&&
908 polyposition
[layer
] >= PolygonList
[layer
].Number
;
915 pv_pv_callback (const BoxType
* b
, void *cl
)
917 PinType
*pin
= (PinType
*) b
;
918 struct pv_info
*i
= (struct pv_info
*) cl
;
920 if (!TEST_FLAG (TheFlag
, pin
) && PV_TOUCH_PV (&i
->pv
, pin
))
922 if (TEST_FLAG (HOLEFLAG
, pin
) || TEST_FLAG (HOLEFLAG
, &i
->pv
))
924 SET_FLAG (WARNFLAG
, pin
);
925 Settings
.RatWarn
= true;
927 Message (_("WARNING: Hole too close to pin.\n"));
929 Message (_("WARNING: Hole too close to via.\n"));
931 else if (ADD_PV_TO_LIST (pin
))
937 /* ---------------------------------------------------------------------------
938 * searches for new PVs that are connected to PVs on the list
941 LookupPVConnectionsToPVList (void)
947 /* loop over all PVs on list */
948 save_place
= PVList
.Location
;
949 while (PVList
.Location
< PVList
.Number
)
953 /* get pointer to data */
954 info
.pv
= *(PVLIST_ENTRY (PVList
.Location
));
955 search_box
= expand_bounds ((BoxType
*)&info
.pv
);
957 if (setjmp (info
.env
) == 0)
958 r_search (PCB
->Data
->via_tree
, &search_box
, NULL
,
959 pv_pv_callback
, &info
);
962 if (setjmp (info
.env
) == 0)
963 r_search (PCB
->Data
->pin_tree
, &search_box
, NULL
,
964 pv_pv_callback
, &info
);
969 PVList
.Location
= save_place
;
985 pv_line_callback (const BoxType
* b
, void *cl
)
987 PinType
*pv
= (PinType
*) b
;
988 struct lo_info
*i
= (struct lo_info
*) cl
;
990 if (!TEST_FLAG (TheFlag
, pv
) && PinLineIntersect (pv
, &i
->line
))
992 if (TEST_FLAG (HOLEFLAG
, pv
))
994 SET_FLAG (WARNFLAG
, pv
);
995 Settings
.RatWarn
= true;
996 Message (_("WARNING: Hole too close to line.\n"));
998 else if (ADD_PV_TO_LIST (pv
))
1005 pv_pad_callback (const BoxType
* b
, void *cl
)
1007 PinType
*pv
= (PinType
*) b
;
1008 struct lo_info
*i
= (struct lo_info
*) cl
;
1010 if (!TEST_FLAG (TheFlag
, pv
) && IS_PV_ON_PAD (pv
, &i
->pad
))
1012 if (TEST_FLAG (HOLEFLAG
, pv
))
1014 SET_FLAG (WARNFLAG
, pv
);
1015 Settings
.RatWarn
= true;
1016 Message (_("WARNING: Hole too close to pad.\n"));
1018 else if (ADD_PV_TO_LIST (pv
))
1019 longjmp (i
->env
, 1);
1025 pv_arc_callback (const BoxType
* b
, void *cl
)
1027 PinType
*pv
= (PinType
*) b
;
1028 struct lo_info
*i
= (struct lo_info
*) cl
;
1030 if (!TEST_FLAG (TheFlag
, pv
) && IS_PV_ON_ARC (pv
, &i
->arc
))
1032 if (TEST_FLAG (HOLEFLAG
, pv
))
1034 SET_FLAG (WARNFLAG
, pv
);
1035 Settings
.RatWarn
= true;
1036 Message (_("WARNING: Hole touches arc.\n"));
1038 else if (ADD_PV_TO_LIST (pv
))
1039 longjmp (i
->env
, 1);
1045 pv_poly_callback (const BoxType
* b
, void *cl
)
1047 PinType
*pv
= (PinType
*) b
;
1048 struct lo_info
*i
= (struct lo_info
*) cl
;
1050 /* note that holes in polygons are ok, so they don't generate warnings. */
1051 if (!TEST_FLAG (TheFlag
, pv
) && !TEST_FLAG (HOLEFLAG
, pv
) &&
1052 (TEST_THERM (i
->layer
, pv
) ||
1053 !TEST_FLAG (CLEARPOLYFLAG
, &i
->polygon
) ||
1056 if (TEST_FLAG (SQUAREFLAG
, pv
))
1058 Coord x1
, x2
, y1
, y2
;
1059 x1
= pv
->X
- (PIN_SIZE (pv
) + 1 + Bloat
) / 2;
1060 x2
= pv
->X
+ (PIN_SIZE (pv
) + 1 + Bloat
) / 2;
1061 y1
= pv
->Y
- (PIN_SIZE (pv
) + 1 + Bloat
) / 2;
1062 y2
= pv
->Y
+ (PIN_SIZE (pv
) + 1 + Bloat
) / 2;
1063 if (IsRectangleInPolygon (x1
, y1
, x2
, y2
, &i
->polygon
)
1064 && ADD_PV_TO_LIST (pv
))
1065 longjmp (i
->env
, 1);
1067 else if (TEST_FLAG (OCTAGONFLAG
, pv
))
1069 POLYAREA
*oct
= OctagonPoly (pv
->X
, pv
->Y
, PIN_SIZE (pv
) / 2);
1070 if (isects (oct
, &i
->polygon
, true) && ADD_PV_TO_LIST (pv
))
1071 longjmp (i
->env
, 1);
1075 if (IsPointInPolygon
1076 (pv
->X
, pv
->Y
, PIN_SIZE (pv
) * 0.5 + Bloat
, &i
->polygon
)
1077 && ADD_PV_TO_LIST (pv
))
1078 longjmp (i
->env
, 1);
1085 pv_rat_callback (const BoxType
* b
, void *cl
)
1087 PinType
*pv
= (PinType
*) b
;
1088 struct lo_info
*i
= (struct lo_info
*) cl
;
1090 /* rats can't cause DRC so there is no early exit */
1091 if (!TEST_FLAG (TheFlag
, pv
) && IS_PV_ON_RAT (pv
, &i
->rat
))
1092 ADD_PV_TO_LIST (pv
);
1096 /* ---------------------------------------------------------------------------
1097 * searches for new PVs that are connected to NEW LOs on the list
1098 * This routine updates the position counter of the lists too.
1101 LookupPVConnectionsToLOList (bool AndRats
)
1104 struct lo_info info
;
1106 /* loop over all layers */
1107 for (layer_no
= 0; layer_no
< max_copper_layer
; layer_no
++)
1109 LayerType
*layer
= LAYER_PTR (layer_no
);
1113 /* do nothing if there are no PV's */
1114 if (TotalP
+ TotalV
== 0)
1116 LineList
[layer_no
].Location
= LineList
[layer_no
].Number
;
1117 ArcList
[layer_no
].Location
= ArcList
[layer_no
].Number
;
1118 PolygonList
[layer_no
].Location
= PolygonList
[layer_no
].Number
;
1122 /* check all lines */
1123 while (LineList
[layer_no
].Location
< LineList
[layer_no
].Number
)
1127 info
.line
= *(LINELIST_ENTRY (layer_no
, LineList
[layer_no
].Location
));
1128 search_box
= expand_bounds ((BoxType
*)&info
.line
);
1130 if (setjmp (info
.env
) == 0)
1131 r_search (PCB
->Data
->via_tree
, &search_box
, NULL
,
1132 pv_line_callback
, &info
);
1135 if (setjmp (info
.env
) == 0)
1136 r_search (PCB
->Data
->pin_tree
, &search_box
, NULL
,
1137 pv_line_callback
, &info
);
1140 LineList
[layer_no
].Location
++;
1143 /* check all arcs */
1144 while (ArcList
[layer_no
].Location
< ArcList
[layer_no
].Number
)
1148 info
.arc
= *(ARCLIST_ENTRY (layer_no
, ArcList
[layer_no
].Location
));
1149 search_box
= expand_bounds ((BoxType
*)&info
.arc
);
1151 if (setjmp (info
.env
) == 0)
1152 r_search (PCB
->Data
->via_tree
, &search_box
, NULL
,
1153 pv_arc_callback
, &info
);
1156 if (setjmp (info
.env
) == 0)
1157 r_search (PCB
->Data
->pin_tree
, &search_box
, NULL
,
1158 pv_arc_callback
, &info
);
1161 ArcList
[layer_no
].Location
++;
1164 /* now all polygons */
1165 info
.layer
= layer_no
;
1166 while (PolygonList
[layer_no
].Location
< PolygonList
[layer_no
].Number
)
1170 info
.polygon
= *(POLYGONLIST_ENTRY (layer_no
, PolygonList
[layer_no
].Location
));
1171 search_box
= expand_bounds ((BoxType
*)&info
.polygon
);
1173 if (setjmp (info
.env
) == 0)
1174 r_search (PCB
->Data
->via_tree
, &search_box
, NULL
,
1175 pv_poly_callback
, &info
);
1178 if (setjmp (info
.env
) == 0)
1179 r_search (PCB
->Data
->pin_tree
, &search_box
, NULL
,
1180 pv_poly_callback
, &info
);
1183 PolygonList
[layer_no
].Location
++;
1187 /* loop over all pad-layers */
1188 for (layer_no
= 0; layer_no
< 2; layer_no
++)
1190 /* do nothing if there are no PV's */
1191 if (TotalP
+ TotalV
== 0)
1193 PadList
[layer_no
].Location
= PadList
[layer_no
].Number
;
1197 /* check all pads; for a detailed description see
1198 * the handling of lines in this subroutine
1200 while (PadList
[layer_no
].Location
< PadList
[layer_no
].Number
)
1204 info
.pad
= *(PADLIST_ENTRY (layer_no
, PadList
[layer_no
].Location
));
1205 search_box
= expand_bounds ((BoxType
*)&info
.pad
);
1207 if (setjmp (info
.env
) == 0)
1208 r_search (PCB
->Data
->via_tree
, &search_box
, NULL
,
1209 pv_pad_callback
, &info
);
1212 if (setjmp (info
.env
) == 0)
1213 r_search (PCB
->Data
->pin_tree
, &search_box
, NULL
,
1214 pv_pad_callback
, &info
);
1217 PadList
[layer_no
].Location
++;
1221 /* do nothing if there are no PV's */
1222 if (TotalP
+ TotalV
== 0)
1223 RatList
.Location
= RatList
.Number
;
1225 /* check all rat-lines */
1228 while (RatList
.Location
< RatList
.Number
)
1230 info
.rat
= *(RATLIST_ENTRY (RatList
.Location
));
1231 r_search_pt (PCB
->Data
->via_tree
, & info
.rat
.Point1
, 1, NULL
,
1232 pv_rat_callback
, &info
);
1233 r_search_pt (PCB
->Data
->via_tree
, & info
.rat
.Point2
, 1, NULL
,
1234 pv_rat_callback
, &info
);
1235 r_search_pt (PCB
->Data
->pin_tree
, & info
.rat
.Point1
, 1, NULL
,
1236 pv_rat_callback
, &info
);
1237 r_search_pt (PCB
->Data
->pin_tree
, & info
.rat
.Point2
, 1, NULL
,
1238 pv_rat_callback
, &info
);
1246 /* reduce arc start angle and delta to 0..360 */
1248 normalize_angles (Angle
*sa
, Angle
*d
)
1255 if (*d
> 360) /* full circle */
1257 *sa
= NormalizeAngle (*sa
);
1261 radius_crosses_arc (double x
, double y
, ArcType
*arc
)
1263 double alpha
= atan2 (y
- arc
->Y
, -x
+ arc
->X
) * RAD_TO_DEG
;
1264 Angle sa
= arc
->StartAngle
, d
= arc
->Delta
;
1266 normalize_angles (&sa
, &d
);
1270 return (sa
+ d
) >= alpha
;
1271 return (sa
+ d
- 360) >= alpha
;
1275 get_arc_ends (Coord
*box
, ArcType
*arc
)
1277 box
[0] = arc
->X
- arc
->Width
* cos (M180
* arc
->StartAngle
);
1278 box
[1] = arc
->Y
+ arc
->Height
* sin (M180
* arc
->StartAngle
);
1279 box
[2] = arc
->X
- arc
->Width
* cos (M180
* (arc
->StartAngle
+ arc
->Delta
));
1280 box
[3] = arc
->Y
+ arc
->Height
* sin (M180
* (arc
->StartAngle
+ arc
->Delta
));
1282 /* ---------------------------------------------------------------------------
1283 * check if two arcs intersect
1284 * first we check for circle intersections,
1285 * then find the actual points of intersection
1286 * and test them to see if they are on arcs
1288 * consider a, the distance from the center of arc 1
1289 * to the point perpendicular to the intersecting points.
1291 * a = (r1^2 - r2^2 + l^2)/(2l)
1293 * the perpendicular distance to the point of intersection
1296 * d = sqrt(r1^2 - a^2)
1298 * the points of intersection would then be
1300 * x = X1 + a/l dx +- d/l dy
1301 * y = Y1 + a/l dy -+ d/l dx
1303 * where dx = X2 - X1 and dy = Y2 - Y1
1308 ArcArcIntersect (ArcType
*Arc1
, ArcType
*Arc2
)
1310 double x
, y
, dx
, dy
, r1
, r2
, a
, d
, l
, t
, t1
, t2
, dl
;
1314 t
= 0.5 * Arc1
->Thickness
+ Bloat
;
1315 t2
= 0.5 * Arc2
->Thickness
;
1319 if (t
< 0 || t1
< 0)
1322 /* try the end points first */
1323 get_arc_ends (&box
[0], Arc1
);
1324 get_arc_ends (&box
[4], Arc2
);
1325 if (IsPointOnArc (box
[0], box
[1], t
, Arc2
)
1326 || IsPointOnArc (box
[2], box
[3], t
, Arc2
)
1327 || IsPointOnArc (box
[4], box
[5], t
, Arc1
)
1328 || IsPointOnArc (box
[6], box
[7], t
, Arc1
))
1331 pdx
= Arc2
->X
- Arc1
->X
;
1332 pdy
= Arc2
->Y
- Arc1
->Y
;
1333 dl
= Distance (Arc1
->X
, Arc1
->Y
, Arc2
->X
, Arc2
->Y
);
1334 /* concentric arcs, simpler intersection conditions */
1337 if ((Arc1
->Width
- t
>= Arc2
->Width
- t2
1338 && Arc1
->Width
- t
<= Arc2
->Width
+ t2
)
1339 || (Arc1
->Width
+ t
>= Arc2
->Width
- t2
1340 && Arc1
->Width
+ t
<= Arc2
->Width
+ t2
))
1342 Angle sa1
= Arc1
->StartAngle
, d1
= Arc1
->Delta
;
1343 Angle sa2
= Arc2
->StartAngle
, d2
= Arc2
->Delta
;
1344 /* NB the endpoints have already been checked,
1345 so we just compare the angles */
1347 normalize_angles (&sa1
, &d1
);
1348 normalize_angles (&sa2
, &d2
);
1349 /* sa1 == sa2 was caught when checking endpoints */
1351 if (sa1
< sa2
+ d2
|| sa1
+ d1
- 360 > sa2
)
1354 if (sa2
< sa1
+ d1
|| sa2
+ d2
- 360 > sa1
)
1361 /* arcs centerlines are too far or too near */
1362 if (dl
> r1
+ r2
|| dl
+ r1
< r2
|| dl
+ r2
< r1
)
1364 /* check the nearest to the other arc's center point */
1367 if (dl
+ r1
< r2
) /* Arc1 inside Arc2 */
1373 if (radius_crosses_arc (Arc1
->X
+ dx
, Arc1
->Y
+ dy
, Arc1
)
1374 && IsPointOnArc (Arc1
->X
+ dx
, Arc1
->Y
+ dy
, t
, Arc2
))
1377 dx
= - pdx
* r2
/ dl
;
1378 dy
= - pdy
* r2
/ dl
;
1379 if (dl
+ r2
< r1
) /* Arc2 inside Arc1 */
1385 if (radius_crosses_arc (Arc2
->X
+ dx
, Arc2
->Y
+ dy
, Arc2
)
1386 && IsPointOnArc (Arc2
->X
+ dx
, Arc2
->Y
+ dy
, t1
, Arc1
))
1394 a
= 0.5 * (r1
- r2
+ l
) / l
;
1397 /* the circles are too far apart to touch or probably just touch:
1398 check the nearest point */
1403 x
= Arc1
->X
+ a
* pdx
;
1404 y
= Arc1
->Y
+ a
* pdy
;
1407 if (radius_crosses_arc (x
+ dy
, y
- dx
, Arc1
)
1408 && IsPointOnArc (x
+ dy
, y
- dx
, t
, Arc2
))
1410 if (radius_crosses_arc (x
+ dy
, y
- dx
, Arc2
)
1411 && IsPointOnArc (x
+ dy
, y
- dx
, t1
, Arc1
))
1414 if (radius_crosses_arc (x
- dy
, y
+ dx
, Arc1
)
1415 && IsPointOnArc (x
- dy
, y
+ dx
, t
, Arc2
))
1417 if (radius_crosses_arc (x
- dy
, y
+ dx
, Arc2
)
1418 && IsPointOnArc (x
- dy
, y
+ dx
, t1
, Arc1
))
1423 /* ---------------------------------------------------------------------------
1424 * Tests if point is same as line end point
1427 IsRatPointOnLineEnd (PointType
*Point
, LineType
*Line
)
1429 if ((Point
->X
== Line
->Point1
.X
1430 && Point
->Y
== Line
->Point1
.Y
)
1431 || (Point
->X
== Line
->Point2
.X
&& Point
->Y
== Line
->Point2
.Y
))
1437 form_slanted_rectangle (PointType p
[4], LineType
*l
)
1438 /* writes vertices of a squared line */
1440 double dwx
= 0, dwy
= 0;
1441 if (l
->Point1
.Y
== l
->Point2
.Y
)
1442 dwx
= l
->Thickness
/ 2.0;
1443 else if (l
->Point1
.X
== l
->Point2
.X
)
1444 dwy
= l
->Thickness
/ 2.0;
1447 Coord dX
= l
->Point2
.X
- l
->Point1
.X
;
1448 Coord dY
= l
->Point2
.Y
- l
->Point1
.Y
;
1449 double r
= Distance (l
->Point1
.X
, l
->Point1
.Y
, l
->Point2
.X
, l
->Point2
.Y
);
1450 dwx
= l
->Thickness
/ 2.0 / r
* dX
;
1451 dwy
= l
->Thickness
/ 2.0 / r
* dY
;
1453 p
[0].X
= l
->Point1
.X
- dwx
+ dwy
; p
[0].Y
= l
->Point1
.Y
- dwy
- dwx
;
1454 p
[1].X
= l
->Point1
.X
- dwx
- dwy
; p
[1].Y
= l
->Point1
.Y
- dwy
+ dwx
;
1455 p
[2].X
= l
->Point2
.X
+ dwx
- dwy
; p
[2].Y
= l
->Point2
.Y
+ dwy
+ dwx
;
1456 p
[3].X
= l
->Point2
.X
+ dwx
+ dwy
; p
[3].Y
= l
->Point2
.Y
+ dwy
- dwx
;
1458 /* ---------------------------------------------------------------------------
1459 * checks if two lines intersect
1462 * Let A,B,C,D be 2-space position vectors. Then the directed line
1463 * segments AB & CD are given by:
1465 * AB=A+r(B-A), r in [0,1]
1466 * CD=C+s(D-C), s in [0,1]
1468 * If AB & CD intersect, then
1470 * A+r(B-A)=C+s(D-C), or
1472 * XA+r(XB-XA)=XC+s(XD-XC)
1473 * YA+r(YB-YA)=YC+s(YD-YC) for some r,s in [0,1]
1475 * Solving the above for r and s yields
1477 * (YA-YC)(XD-XC)-(XA-XC)(YD-YC)
1478 * r = ----------------------------- (eqn 1)
1479 * (XB-XA)(YD-YC)-(YB-YA)(XD-XC)
1481 * (YA-YC)(XB-XA)-(XA-XC)(YB-YA)
1482 * s = ----------------------------- (eqn 2)
1483 * (XB-XA)(YD-YC)-(YB-YA)(XD-XC)
1485 * Let I be the position vector of the intersection point, then
1492 * By examining the values of r & s, you can also determine some
1493 * other limiting conditions:
1495 * If 0<=r<=1 & 0<=s<=1, intersection exists
1496 * r<0 or r>1 or s<0 or s>1 line segments do not intersect
1498 * If the denominator in eqn 1 is zero, AB & CD are parallel
1499 * If the numerator in eqn 1 is also zero, AB & CD are coincident
1501 * If the intersection point of the 2 lines are needed (lines in this
1502 * context mean infinite lines) regardless whether the two line
1503 * segments intersect, then
1505 * If r>1, I is located on extension of AB
1506 * If r<0, I is located on extension of BA
1507 * If s>1, I is located on extension of CD
1508 * If s<0, I is located on extension of DC
1510 * Also note that the denominators of eqn 1 & 2 are identical.
1514 LineLineIntersect (LineType
*Line1
, LineType
*Line2
)
1517 double line1_dx
, line1_dy
, line2_dx
, line2_dy
,
1518 point1_dx
, point1_dy
;
1519 if (TEST_FLAG (SQUAREFLAG
, Line1
))/* pretty reckless recursion */
1522 form_slanted_rectangle (p
, Line1
);
1523 return IsLineInQuadrangle (p
, Line2
);
1525 /* here come only round Line1 because IsLineInQuadrangle()
1526 calls LineLineIntersect() with first argument rounded*/
1527 if (TEST_FLAG (SQUAREFLAG
, Line2
))
1530 form_slanted_rectangle (p
, Line2
);
1531 return IsLineInQuadrangle (p
, Line1
);
1533 /* now all lines are round */
1535 /* Check endpoints: this provides a quick exit, catches
1536 * cases where the "real" lines don't intersect but the
1537 * thick lines touch, and ensures that the dx/dy business
1538 * below does not cause a divide-by-zero. */
1539 if (IsPointInPad (Line2
->Point1
.X
, Line2
->Point1
.Y
,
1540 MAX (Line2
->Thickness
/ 2 + Bloat
, 0),
1542 || IsPointInPad (Line2
->Point2
.X
, Line2
->Point2
.Y
,
1543 MAX (Line2
->Thickness
/ 2 + Bloat
, 0),
1545 || IsPointInPad (Line1
->Point1
.X
, Line1
->Point1
.Y
,
1546 MAX (Line1
->Thickness
/ 2 + Bloat
, 0),
1548 || IsPointInPad (Line1
->Point2
.X
, Line1
->Point2
.Y
,
1549 MAX (Line1
->Thickness
/ 2 + Bloat
, 0),
1553 /* setup some constants */
1554 line1_dx
= Line1
->Point2
.X
- Line1
->Point1
.X
;
1555 line1_dy
= Line1
->Point2
.Y
- Line1
->Point1
.Y
;
1556 line2_dx
= Line2
->Point2
.X
- Line2
->Point1
.X
;
1557 line2_dy
= Line2
->Point2
.Y
- Line2
->Point1
.Y
;
1558 point1_dx
= Line1
->Point1
.X
- Line2
->Point1
.X
;
1559 point1_dy
= Line1
->Point1
.Y
- Line2
->Point1
.Y
;
1561 /* If either line is a point, we have failed already, since the
1562 * endpoint check above will have caught an "intersection". */
1563 if ((line1_dx
== 0 && line1_dy
== 0)
1564 || (line2_dx
== 0 && line2_dy
== 0))
1567 /* set s to cross product of Line1 and the line
1568 * Line1.Point1--Line2.Point1 (as vectors) */
1569 s
= point1_dy
* line1_dx
- point1_dx
* line1_dy
;
1571 /* set r to cross product of both lines (as vectors) */
1572 r
= line1_dx
* line2_dy
- line1_dy
* line2_dx
;
1574 /* No cross product means parallel lines, or maybe Line2 is
1575 * zero-length. In either case, since we did a bounding-box
1576 * check before getting here, the above IsPointInPad() checks
1577 * will have caught any intersections. */
1582 r
= (point1_dy
* line2_dx
- point1_dx
* line2_dy
) / r
;
1584 /* intersection is at least on AB */
1585 if (r
>= 0.0 && r
<= 1.0)
1586 return (s
>= 0.0 && s
<= 1.0);
1588 /* intersection is at least on CD */
1589 /* [removed this case since it always returns false --asp] */
1593 /*---------------------------------------------------
1595 * Check for line intersection with an arc
1597 * Mostly this is like the circle/line intersection
1598 * found in IsPointOnLine (search.c) see the detailed
1599 * discussion for the basics there.
1601 * Since this is only an arc, not a full circle we need
1602 * to find the actual points of intersection with the
1603 * circle, and see if they are on the arc.
1605 * To do this, we translate along the line from the point Q
1606 * plus or minus a distance delta = sqrt(Radius^2 - d^2)
1607 * but it's handy to normalize with respect to l, the line
1608 * length so a single projection is done (e.g. we don't first
1611 * The projection is now of the form
1613 * Px = X1 + (r +- r2)(X2 - X1)
1614 * Py = Y1 + (r +- r2)(Y2 - Y1)
1616 * Where r2 sqrt(Radius^2 l^2 - d^2)/l^2
1617 * note that this is the variable d, not the symbol d described in IsPointOnLine
1618 * (variable d = symbol d * l)
1620 * The end points are hell so they are checked individually
1623 LineArcIntersect (LineType
*Line
, ArcType
*Arc
)
1625 double dx
, dy
, dx1
, dy1
, l
, d
, r
, r2
, Radius
;
1628 dx
= Line
->Point2
.X
- Line
->Point1
.X
;
1629 dy
= Line
->Point2
.Y
- Line
->Point1
.Y
;
1630 dx1
= Line
->Point1
.X
- Arc
->X
;
1631 dy1
= Line
->Point1
.Y
- Arc
->Y
;
1632 l
= dx
* dx
+ dy
* dy
;
1633 d
= dx
* dy1
- dy
* dx1
;
1636 /* use the larger diameter circle first */
1638 Arc
->Width
+ MAX (0.5 * (Arc
->Thickness
+ Line
->Thickness
) + Bloat
, 0.0);
1640 r2
= Radius
* l
- d
;
1641 /* projection doesn't even intersect circle when r2 < 0 */
1644 /* check the ends of the line in case the projected point */
1645 /* of intersection is beyond the line end */
1647 (Line
->Point1
.X
, Line
->Point1
.Y
,
1648 MAX (0.5 * Line
->Thickness
+ Bloat
, 0.0), Arc
))
1651 (Line
->Point2
.X
, Line
->Point2
.Y
,
1652 MAX (0.5 * Line
->Thickness
+ Bloat
, 0.0), Arc
))
1657 Radius
= -(dx
* dx1
+ dy
* dy1
);
1658 r
= (Radius
+ r2
) / l
;
1659 if (r
>= 0 && r
<= 1
1660 && IsPointOnArc (Line
->Point1
.X
+ r
* dx
,
1661 Line
->Point1
.Y
+ r
* dy
,
1662 MAX (0.5 * Line
->Thickness
+ Bloat
, 0.0), Arc
))
1664 r
= (Radius
- r2
) / l
;
1665 if (r
>= 0 && r
<= 1
1666 && IsPointOnArc (Line
->Point1
.X
+ r
* dx
,
1667 Line
->Point1
.Y
+ r
* dy
,
1668 MAX (0.5 * Line
->Thickness
+ Bloat
, 0.0), Arc
))
1670 /* check arc end points */
1671 box
= GetArcEnds (Arc
);
1672 if (IsPointInPad (box
->X1
, box
->Y1
, Arc
->Thickness
* 0.5 + Bloat
, (PadType
*)Line
))
1674 if (IsPointInPad (box
->X2
, box
->Y2
, Arc
->Thickness
* 0.5 + Bloat
, (PadType
*)Line
))
1680 LOCtoArcLine_callback (const BoxType
* b
, void *cl
)
1682 LineType
*line
= (LineType
*) b
;
1683 struct lo_info
*i
= (struct lo_info
*) cl
;
1685 if (!TEST_FLAG (TheFlag
, line
) && LineArcIntersect (line
, &i
->arc
))
1687 if (ADD_LINE_TO_LIST (i
->layer
, line
))
1688 longjmp (i
->env
, 1);
1694 LOCtoArcArc_callback (const BoxType
* b
, void *cl
)
1696 ArcType
*arc
= (ArcType
*) b
;
1697 struct lo_info
*i
= (struct lo_info
*) cl
;
1699 if (!arc
->Thickness
)
1701 if (!TEST_FLAG (TheFlag
, arc
) && ArcArcIntersect (&i
->arc
, arc
))
1703 if (ADD_ARC_TO_LIST (i
->layer
, arc
))
1704 longjmp (i
->env
, 1);
1710 LOCtoArcPad_callback (const BoxType
* b
, void *cl
)
1712 PadType
*pad
= (PadType
*) b
;
1713 struct lo_info
*i
= (struct lo_info
*) cl
;
1715 if (!TEST_FLAG (TheFlag
, pad
) && i
->layer
==
1716 (TEST_FLAG (ONSOLDERFLAG
, pad
) ? SOLDER_LAYER
: COMPONENT_LAYER
)
1717 && ArcPadIntersect (&i
->arc
, pad
) && ADD_PAD_TO_LIST (i
->layer
, pad
))
1718 longjmp (i
->env
, 1);
1722 /* ---------------------------------------------------------------------------
1723 * searches all LOs that are connected to the given arc on the given
1724 * layergroup. All found connections are added to the list
1726 * the notation that is used is:
1727 * Xij means Xj at arc i
1730 LookupLOConnectionsToArc (ArcType
*Arc
, Cardinal LayerGroup
)
1733 struct lo_info info
;
1737 search_box
= expand_bounds ((BoxType
*)&info
.arc
);
1739 /* loop over all layers of the group */
1740 for (entry
= 0; entry
< PCB
->LayerGroups
.Number
[LayerGroup
]; entry
++)
1746 layer_no
= PCB
->LayerGroups
.Entries
[LayerGroup
][entry
];
1747 layer
= LAYER_PTR (layer_no
);
1749 /* handle normal layers */
1750 if (layer_no
< max_copper_layer
)
1752 info
.layer
= layer_no
;
1754 if (setjmp (info
.env
) == 0)
1755 r_search (layer
->line_tree
, &search_box
,
1756 NULL
, LOCtoArcLine_callback
, &info
);
1760 if (setjmp (info
.env
) == 0)
1761 r_search (layer
->arc_tree
, &search_box
,
1762 NULL
, LOCtoArcArc_callback
, &info
);
1766 /* now check all polygons */
1767 for (i
= layer
->Polygon
; i
!= NULL
; i
= g_list_next (i
))
1769 PolygonType
*polygon
= i
->data
;
1770 if (!TEST_FLAG (TheFlag
, polygon
) && IsArcInPolygon (Arc
, polygon
)
1771 && ADD_POLYGON_TO_LIST (layer_no
, polygon
))
1777 info
.layer
= layer_no
- max_copper_layer
;
1778 if (setjmp (info
.env
) == 0)
1779 r_search (PCB
->Data
->pad_tree
, &search_box
, NULL
,
1780 LOCtoArcPad_callback
, &info
);
1789 LOCtoLineLine_callback (const BoxType
* b
, void *cl
)
1791 LineType
*line
= (LineType
*) b
;
1792 struct lo_info
*i
= (struct lo_info
*) cl
;
1794 if (!TEST_FLAG (TheFlag
, line
) && LineLineIntersect (&i
->line
, line
))
1796 if (ADD_LINE_TO_LIST (i
->layer
, line
))
1797 longjmp (i
->env
, 1);
1803 LOCtoLineArc_callback (const BoxType
* b
, void *cl
)
1805 ArcType
*arc
= (ArcType
*) b
;
1806 struct lo_info
*i
= (struct lo_info
*) cl
;
1808 if (!arc
->Thickness
)
1810 if (!TEST_FLAG (TheFlag
, arc
) && LineArcIntersect (&i
->line
, arc
))
1812 if (ADD_ARC_TO_LIST (i
->layer
, arc
))
1813 longjmp (i
->env
, 1);
1819 LOCtoLineRat_callback (const BoxType
* b
, void *cl
)
1821 RatType
*rat
= (RatType
*) b
;
1822 struct lo_info
*i
= (struct lo_info
*) cl
;
1824 if (!TEST_FLAG (TheFlag
, rat
))
1826 if ((rat
->group1
== i
->layer
)
1827 && IsRatPointOnLineEnd (&rat
->Point1
, &i
->line
))
1829 if (ADD_RAT_TO_LIST (rat
))
1830 longjmp (i
->env
, 1);
1832 else if ((rat
->group2
== i
->layer
)
1833 && IsRatPointOnLineEnd (&rat
->Point2
, &i
->line
))
1835 if (ADD_RAT_TO_LIST (rat
))
1836 longjmp (i
->env
, 1);
1843 LOCtoLinePad_callback (const BoxType
* b
, void *cl
)
1845 PadType
*pad
= (PadType
*) b
;
1846 struct lo_info
*i
= (struct lo_info
*) cl
;
1848 if (!TEST_FLAG (TheFlag
, pad
) && i
->layer
==
1849 (TEST_FLAG (ONSOLDERFLAG
, pad
) ? SOLDER_LAYER
: COMPONENT_LAYER
)
1850 && LinePadIntersect (&i
->line
, pad
) && ADD_PAD_TO_LIST (i
->layer
, pad
))
1851 longjmp (i
->env
, 1);
1855 /* ---------------------------------------------------------------------------
1856 * searches all LOs that are connected to the given line on the given
1857 * layergroup. All found connections are added to the list
1859 * the notation that is used is:
1860 * Xij means Xj at line i
1863 LookupLOConnectionsToLine (LineType
*Line
, Cardinal LayerGroup
,
1867 struct lo_info info
;
1870 info
.layer
= LayerGroup
;
1872 search_box
= expand_bounds ((BoxType
*)&info
.line
);
1874 /* add the new rat lines */
1875 if (setjmp (info
.env
) == 0)
1876 r_search (PCB
->Data
->rat_tree
, &search_box
, NULL
,
1877 LOCtoLineRat_callback
, &info
);
1881 /* loop over all layers of the group */
1882 for (entry
= 0; entry
< PCB
->LayerGroups
.Number
[LayerGroup
]; entry
++)
1887 layer_no
= PCB
->LayerGroups
.Entries
[LayerGroup
][entry
];
1888 layer
= LAYER_PTR (layer_no
);
1890 /* handle normal layers */
1891 if (layer_no
< max_copper_layer
)
1893 info
.layer
= layer_no
;
1895 if (setjmp (info
.env
) == 0)
1896 r_search (layer
->line_tree
, &search_box
,
1897 NULL
, LOCtoLineLine_callback
, &info
);
1901 if (setjmp (info
.env
) == 0)
1902 r_search (layer
->arc_tree
, &search_box
,
1903 NULL
, LOCtoLineArc_callback
, &info
);
1906 /* now check all polygons */
1910 for (i
= layer
->Polygon
; i
!= NULL
; i
= g_list_next (i
))
1912 PolygonType
*polygon
= i
->data
;
1914 (TheFlag
, polygon
) && IsLineInPolygon (Line
, polygon
)
1915 && ADD_POLYGON_TO_LIST (layer_no
, polygon
))
1922 /* handle special 'pad' layers */
1923 info
.layer
= layer_no
- max_copper_layer
;
1924 if (setjmp (info
.env
) == 0)
1925 r_search (PCB
->Data
->pad_tree
, &search_box
, NULL
,
1926 LOCtoLinePad_callback
, &info
);
1942 LOCtoRat_callback (const BoxType
* b
, void *cl
)
1944 LineType
*line
= (LineType
*) b
;
1945 struct rat_info
*i
= (struct rat_info
*) cl
;
1947 if (!TEST_FLAG (TheFlag
, line
) &&
1948 ((line
->Point1
.X
== i
->Point
->X
&&
1949 line
->Point1
.Y
== i
->Point
->Y
) ||
1950 (line
->Point2
.X
== i
->Point
->X
&& line
->Point2
.Y
== i
->Point
->Y
)))
1952 if (ADD_LINE_TO_LIST (i
->layer
, line
))
1953 longjmp (i
->env
, 1);
1958 PolygonToRat_callback (const BoxType
* b
, void *cl
)
1960 PolygonType
*polygon
= (PolygonType
*) b
;
1961 struct rat_info
*i
= (struct rat_info
*) cl
;
1963 if (!TEST_FLAG (TheFlag
, polygon
) && polygon
->Clipped
&&
1964 (i
->Point
->X
== polygon
->Clipped
->contours
->head
.point
[0]) &&
1965 (i
->Point
->Y
== polygon
->Clipped
->contours
->head
.point
[1]))
1967 if (ADD_POLYGON_TO_LIST (i
->layer
, polygon
))
1968 longjmp (i
->env
, 1);
1974 LOCtoPad_callback (const BoxType
* b
, void *cl
)
1976 PadType
*pad
= (PadType
*) b
;
1977 struct rat_info
*i
= (struct rat_info
*) cl
;
1979 if (!TEST_FLAG (TheFlag
, pad
) && i
->layer
==
1980 (TEST_FLAG (ONSOLDERFLAG
, pad
) ? SOLDER_LAYER
: COMPONENT_LAYER
) &&
1981 ((pad
->Point1
.X
== i
->Point
->X
&& pad
->Point1
.Y
== i
->Point
->Y
) ||
1982 (pad
->Point2
.X
== i
->Point
->X
&& pad
->Point2
.Y
== i
->Point
->Y
) ||
1983 ((pad
->Point1
.X
+ pad
->Point2
.X
) / 2 == i
->Point
->X
&&
1984 (pad
->Point1
.Y
+ pad
->Point2
.Y
) / 2 == i
->Point
->Y
)) &&
1985 ADD_PAD_TO_LIST (i
->layer
, pad
))
1986 longjmp (i
->env
, 1);
1990 /* ---------------------------------------------------------------------------
1991 * searches all LOs that are connected to the given rat-line on the given
1992 * layergroup. All found connections are added to the list
1994 * the notation that is used is:
1995 * Xij means Xj at line i
1998 LookupLOConnectionsToRatEnd (PointType
*Point
, Cardinal LayerGroup
)
2001 struct rat_info info
;
2004 /* loop over all layers of this group */
2005 for (entry
= 0; entry
< PCB
->LayerGroups
.Number
[LayerGroup
]; entry
++)
2010 layer_no
= PCB
->LayerGroups
.Entries
[LayerGroup
][entry
];
2011 layer
= LAYER_PTR (layer_no
);
2012 /* handle normal layers
2013 rats don't ever touch
2017 if (layer_no
< max_copper_layer
)
2019 info
.layer
= layer_no
;
2020 if (setjmp (info
.env
) == 0)
2021 r_search_pt (layer
->line_tree
, Point
, 1, NULL
,
2022 LOCtoRat_callback
, &info
);
2025 if (setjmp (info
.env
) == 0)
2026 r_search_pt (layer
->polygon_tree
, Point
, 1,
2027 NULL
, PolygonToRat_callback
, &info
);
2031 /* handle special 'pad' layers */
2032 info
.layer
= layer_no
- max_copper_layer
;
2033 if (setjmp (info
.env
) == 0)
2034 r_search_pt (PCB
->Data
->pad_tree
, Point
, 1, NULL
,
2035 LOCtoPad_callback
, &info
);
2044 LOCtoPadLine_callback (const BoxType
* b
, void *cl
)
2046 LineType
*line
= (LineType
*) b
;
2047 struct lo_info
*i
= (struct lo_info
*) cl
;
2049 if (!TEST_FLAG (TheFlag
, line
) && LinePadIntersect (line
, &i
->pad
))
2051 if (ADD_LINE_TO_LIST (i
->layer
, line
))
2052 longjmp (i
->env
, 1);
2058 LOCtoPadArc_callback (const BoxType
* b
, void *cl
)
2060 ArcType
*arc
= (ArcType
*) b
;
2061 struct lo_info
*i
= (struct lo_info
*) cl
;
2063 if (!arc
->Thickness
)
2065 if (!TEST_FLAG (TheFlag
, arc
) && ArcPadIntersect (arc
, &i
->pad
))
2067 if (ADD_ARC_TO_LIST (i
->layer
, arc
))
2068 longjmp (i
->env
, 1);
2074 LOCtoPadPoly_callback (const BoxType
* b
, void *cl
)
2076 PolygonType
*polygon
= (PolygonType
*) b
;
2077 struct lo_info
*i
= (struct lo_info
*) cl
;
2080 if (!TEST_FLAG (TheFlag
, polygon
) &&
2081 (!TEST_FLAG (CLEARPOLYFLAG
, polygon
) || !i
->pad
.Clearance
))
2083 if (IsPadInPolygon (&i
->pad
, polygon
) &&
2084 ADD_POLYGON_TO_LIST (i
->layer
, polygon
))
2085 longjmp (i
->env
, 1);
2091 LOCtoPadRat_callback (const BoxType
* b
, void *cl
)
2093 RatType
*rat
= (RatType
*) b
;
2094 struct lo_info
*i
= (struct lo_info
*) cl
;
2096 if (!TEST_FLAG (TheFlag
, rat
))
2098 if (rat
->group1
== i
->layer
&&
2099 ((rat
->Point1
.X
== i
->pad
.Point1
.X
&& rat
->Point1
.Y
== i
->pad
.Point1
.Y
) ||
2100 (rat
->Point1
.X
== i
->pad
.Point2
.X
&& rat
->Point1
.Y
== i
->pad
.Point2
.Y
) ||
2101 (rat
->Point1
.X
== (i
->pad
.Point1
.X
+ i
->pad
.Point2
.X
) / 2 &&
2102 rat
->Point1
.Y
== (i
->pad
.Point1
.Y
+ i
->pad
.Point2
.Y
) / 2)))
2104 if (ADD_RAT_TO_LIST (rat
))
2105 longjmp (i
->env
, 1);
2107 else if (rat
->group2
== i
->layer
&&
2108 ((rat
->Point2
.X
== i
->pad
.Point1
.X
&& rat
->Point2
.Y
== i
->pad
.Point1
.Y
) ||
2109 (rat
->Point2
.X
== i
->pad
.Point2
.X
&& rat
->Point2
.Y
== i
->pad
.Point2
.Y
) ||
2110 (rat
->Point2
.X
== (i
->pad
.Point1
.X
+ i
->pad
.Point2
.X
) / 2 &&
2111 rat
->Point2
.Y
== (i
->pad
.Point1
.Y
+ i
->pad
.Point2
.Y
) / 2)))
2113 if (ADD_RAT_TO_LIST (rat
))
2114 longjmp (i
->env
, 1);
2121 LOCtoPadPad_callback (const BoxType
* b
, void *cl
)
2123 PadType
*pad
= (PadType
*) b
;
2124 struct lo_info
*i
= (struct lo_info
*) cl
;
2126 if (!TEST_FLAG (TheFlag
, pad
) && i
->layer
==
2127 (TEST_FLAG (ONSOLDERFLAG
, pad
) ? SOLDER_LAYER
: COMPONENT_LAYER
)
2128 && PadPadIntersect (pad
, &i
->pad
) && ADD_PAD_TO_LIST (i
->layer
, pad
))
2129 longjmp (i
->env
, 1);
2133 /* ---------------------------------------------------------------------------
2134 * searches all LOs that are connected to the given pad on the given
2135 * layergroup. All found connections are added to the list
2138 LookupLOConnectionsToPad (PadType
*Pad
, Cardinal LayerGroup
)
2141 struct lo_info info
;
2144 if (!TEST_FLAG (SQUAREFLAG
, Pad
))
2145 return (LookupLOConnectionsToLine ((LineType
*) Pad
, LayerGroup
, false));
2148 search_box
= expand_bounds ((BoxType
*)&info
.pad
);
2150 /* add the new rat lines */
2151 info
.layer
= LayerGroup
;
2153 if (setjmp (info
.env
) == 0)
2154 r_search (PCB
->Data
->rat_tree
, &search_box
, NULL
,
2155 LOCtoPadRat_callback
, &info
);
2159 /* loop over all layers of the group */
2160 for (entry
= 0; entry
< PCB
->LayerGroups
.Number
[LayerGroup
]; entry
++)
2165 layer_no
= PCB
->LayerGroups
.Entries
[LayerGroup
][entry
];
2166 layer
= LAYER_PTR (layer_no
);
2167 /* handle normal layers */
2168 if (layer_no
< max_copper_layer
)
2170 info
.layer
= layer_no
;
2172 if (setjmp (info
.env
) == 0)
2173 r_search (layer
->line_tree
, &search_box
,
2174 NULL
, LOCtoPadLine_callback
, &info
);
2178 if (setjmp (info
.env
) == 0)
2179 r_search (layer
->arc_tree
, &search_box
,
2180 NULL
, LOCtoPadArc_callback
, &info
);
2184 if (setjmp (info
.env
) == 0)
2185 r_search (layer
->polygon_tree
, &search_box
,
2186 NULL
, LOCtoPadPoly_callback
, &info
);
2192 /* handle special 'pad' layers */
2193 info
.layer
= layer_no
- max_copper_layer
;
2194 if (setjmp (info
.env
) == 0)
2195 r_search (PCB
->Data
->pad_tree
, &search_box
, NULL
,
2196 LOCtoPadPad_callback
, &info
);
2206 LOCtoPolyLine_callback (const BoxType
* b
, void *cl
)
2208 LineType
*line
= (LineType
*) b
;
2209 struct lo_info
*i
= (struct lo_info
*) cl
;
2211 if (!TEST_FLAG (TheFlag
, line
) && IsLineInPolygon (line
, &i
->polygon
))
2213 if (ADD_LINE_TO_LIST (i
->layer
, line
))
2214 longjmp (i
->env
, 1);
2220 LOCtoPolyArc_callback (const BoxType
* b
, void *cl
)
2222 ArcType
*arc
= (ArcType
*) b
;
2223 struct lo_info
*i
= (struct lo_info
*) cl
;
2225 if (!arc
->Thickness
)
2227 if (!TEST_FLAG (TheFlag
, arc
) && IsArcInPolygon (arc
, &i
->polygon
))
2229 if (ADD_ARC_TO_LIST (i
->layer
, arc
))
2230 longjmp (i
->env
, 1);
2236 LOCtoPolyPad_callback (const BoxType
* b
, void *cl
)
2238 PadType
*pad
= (PadType
*) b
;
2239 struct lo_info
*i
= (struct lo_info
*) cl
;
2241 if (!TEST_FLAG (TheFlag
, pad
) && i
->layer
==
2242 (TEST_FLAG (ONSOLDERFLAG
, pad
) ? SOLDER_LAYER
: COMPONENT_LAYER
)
2243 && IsPadInPolygon (pad
, &i
->polygon
))
2245 if (ADD_PAD_TO_LIST (i
->layer
, pad
))
2246 longjmp (i
->env
, 1);
2252 LOCtoPolyRat_callback (const BoxType
* b
, void *cl
)
2254 RatType
*rat
= (RatType
*) b
;
2255 struct lo_info
*i
= (struct lo_info
*) cl
;
2257 if (!TEST_FLAG (TheFlag
, rat
))
2259 if ((rat
->Point1
.X
== (i
->polygon
.Clipped
->contours
->head
.point
[0]) &&
2260 rat
->Point1
.Y
== (i
->polygon
.Clipped
->contours
->head
.point
[1]) &&
2261 rat
->group1
== i
->layer
) ||
2262 (rat
->Point2
.X
== (i
->polygon
.Clipped
->contours
->head
.point
[0]) &&
2263 rat
->Point2
.Y
== (i
->polygon
.Clipped
->contours
->head
.point
[1]) &&
2264 rat
->group2
== i
->layer
))
2265 if (ADD_RAT_TO_LIST (rat
))
2266 longjmp (i
->env
, 1);
2272 /* ---------------------------------------------------------------------------
2273 * looks up LOs that are connected to the given polygon
2274 * on the given layergroup. All found connections are added to the list
2277 LookupLOConnectionsToPolygon (PolygonType
*Polygon
, Cardinal LayerGroup
)
2280 struct lo_info info
;
2283 if (!Polygon
->Clipped
)
2285 info
.polygon
= *Polygon
;
2286 search_box
= expand_bounds ((BoxType
*)&info
.polygon
);
2288 info
.layer
= LayerGroup
;
2290 if (setjmp (info
.env
) == 0)
2291 r_search (PCB
->Data
->rat_tree
, &search_box
, NULL
,
2292 LOCtoPolyRat_callback
, &info
);
2296 /* loop over all layers of the group */
2297 for (entry
= 0; entry
< PCB
->LayerGroups
.Number
[LayerGroup
]; entry
++)
2302 layer_no
= PCB
->LayerGroups
.Entries
[LayerGroup
][entry
];
2303 layer
= LAYER_PTR (layer_no
);
2305 /* handle normal layers */
2306 if (layer_no
< max_copper_layer
)
2310 /* check all polygons */
2311 for (i
= layer
->Polygon
; i
!= NULL
; i
= g_list_next (i
))
2313 PolygonType
*polygon
= i
->data
;
2314 if (!TEST_FLAG (TheFlag
, polygon
)
2315 && IsPolygonInPolygon (polygon
, Polygon
)
2316 && ADD_POLYGON_TO_LIST (layer_no
, polygon
))
2320 info
.layer
= layer_no
;
2321 /* check all lines */
2322 if (setjmp (info
.env
) == 0)
2323 r_search (layer
->line_tree
, &search_box
,
2324 NULL
, LOCtoPolyLine_callback
, &info
);
2327 /* check all arcs */
2328 if (setjmp (info
.env
) == 0)
2329 r_search (layer
->arc_tree
, &search_box
,
2330 NULL
, LOCtoPolyArc_callback
, &info
);
2336 info
.layer
= layer_no
- max_copper_layer
;
2337 if (setjmp (info
.env
) == 0)
2338 r_search (PCB
->Data
->pad_tree
, &search_box
,
2339 NULL
, LOCtoPolyPad_callback
, &info
);
2347 /* ---------------------------------------------------------------------------
2348 * checks if an arc has a connection to a polygon
2350 * - first check if the arc can intersect with the polygon by
2351 * evaluating the bounding boxes
2352 * - check the two end points of the arc. If none of them matches
2353 * - check all segments of the polygon against the arc.
2356 IsArcInPolygon (ArcType
*Arc
, PolygonType
*Polygon
)
2358 BoxType
*Box
= (BoxType
*) Arc
;
2360 /* arcs with clearance never touch polys */
2361 if (TEST_FLAG (CLEARPOLYFLAG
, Polygon
) && TEST_FLAG (CLEARLINEFLAG
, Arc
))
2363 if (!Polygon
->Clipped
)
2365 if (Box
->X1
<= Polygon
->Clipped
->contours
->xmax
+ Bloat
2366 && Box
->X2
>= Polygon
->Clipped
->contours
->xmin
- Bloat
2367 && Box
->Y1
<= Polygon
->Clipped
->contours
->ymax
+ Bloat
2368 && Box
->Y2
>= Polygon
->Clipped
->contours
->ymin
- Bloat
)
2372 if (!(ap
= ArcPoly (Arc
, Arc
->Thickness
+ Bloat
)))
2373 return false; /* error */
2374 return isects (ap
, Polygon
, true);
2379 /* ---------------------------------------------------------------------------
2380 * checks if a line has a connection to a polygon
2382 * - first check if the line can intersect with the polygon by
2383 * evaluating the bounding boxes
2384 * - check the two end points of the line. If none of them matches
2385 * - check all segments of the polygon against the line.
2388 IsLineInPolygon (LineType
*Line
, PolygonType
*Polygon
)
2390 BoxType
*Box
= (BoxType
*) Line
;
2393 /* lines with clearance never touch polygons */
2394 if (TEST_FLAG (CLEARPOLYFLAG
, Polygon
) && TEST_FLAG (CLEARLINEFLAG
, Line
))
2396 if (!Polygon
->Clipped
)
2398 if (TEST_FLAG(SQUAREFLAG
,Line
)&&(Line
->Point1
.X
==Line
->Point2
.X
||Line
->Point1
.Y
==Line
->Point2
.Y
))
2400 Coord wid
= (Line
->Thickness
+ Bloat
+ 1) / 2;
2401 Coord x1
, x2
, y1
, y2
;
2403 x1
= MIN (Line
->Point1
.X
, Line
->Point2
.X
) - wid
;
2404 y1
= MIN (Line
->Point1
.Y
, Line
->Point2
.Y
) - wid
;
2405 x2
= MAX (Line
->Point1
.X
, Line
->Point2
.X
) + wid
;
2406 y2
= MAX (Line
->Point1
.Y
, Line
->Point2
.Y
) + wid
;
2407 return IsRectangleInPolygon (x1
, y1
, x2
, y2
, Polygon
);
2409 if (Box
->X1
<= Polygon
->Clipped
->contours
->xmax
+ Bloat
2410 && Box
->X2
>= Polygon
->Clipped
->contours
->xmin
- Bloat
2411 && Box
->Y1
<= Polygon
->Clipped
->contours
->ymax
+ Bloat
2412 && Box
->Y2
>= Polygon
->Clipped
->contours
->ymin
- Bloat
)
2414 if (!(lp
= LinePoly (Line
, Line
->Thickness
+ Bloat
)))
2415 return FALSE
; /* error */
2416 return isects (lp
, Polygon
, true);
2421 /* ---------------------------------------------------------------------------
2422 * checks if a pad connects to a non-clearing polygon
2424 * The polygon is assumed to already have been proven non-clearing
2427 IsPadInPolygon (PadType
*pad
, PolygonType
*polygon
)
2429 return IsLineInPolygon ((LineType
*) pad
, polygon
);
2432 /* ---------------------------------------------------------------------------
2433 * checks if a polygon has a connection to a second one
2435 * First check all points out of P1 against P2 and vice versa.
2436 * If both fail check all lines of P1 against the ones of P2
2439 IsPolygonInPolygon (PolygonType
*P1
, PolygonType
*P2
)
2441 if (!P1
->Clipped
|| !P2
->Clipped
)
2443 assert (P1
->Clipped
->contours
);
2444 assert (P2
->Clipped
->contours
);
2446 /* first check if both bounding boxes intersect. If not, return quickly */
2447 if (P1
->Clipped
->contours
->xmin
- Bloat
> P2
->Clipped
->contours
->xmax
||
2448 P1
->Clipped
->contours
->xmax
+ Bloat
< P2
->Clipped
->contours
->xmin
||
2449 P1
->Clipped
->contours
->ymin
- Bloat
> P2
->Clipped
->contours
->ymax
||
2450 P1
->Clipped
->contours
->ymax
+ Bloat
< P2
->Clipped
->contours
->ymin
)
2453 /* first check un-bloated case */
2454 if (isects (P1
->Clipped
, P2
, false))
2457 /* now the difficult case of bloated */
2461 for (c
= P1
->Clipped
->contours
; c
; c
= c
->next
)
2464 VNODE
*v
= &c
->head
;
2465 if (c
->xmin
- Bloat
<= P2
->Clipped
->contours
->xmax
&&
2466 c
->xmax
+ Bloat
>= P2
->Clipped
->contours
->xmin
&&
2467 c
->ymin
- Bloat
<= P2
->Clipped
->contours
->ymax
&&
2468 c
->ymax
+ Bloat
>= P2
->Clipped
->contours
->ymin
)
2471 line
.Point1
.X
= v
->point
[0];
2472 line
.Point1
.Y
= v
->point
[1];
2473 line
.Thickness
= 2 * Bloat
;
2475 line
.Flags
= NoFlags ();
2476 for (v
= v
->next
; v
!= &c
->head
; v
= v
->next
)
2478 line
.Point2
.X
= v
->point
[0];
2479 line
.Point2
.Y
= v
->point
[1];
2480 SetLineBoundingBox (&line
);
2481 if (IsLineInPolygon (&line
, P2
))
2483 line
.Point1
.X
= line
.Point2
.X
;
2484 line
.Point1
.Y
= line
.Point2
.Y
;
2493 /* ---------------------------------------------------------------------------
2494 * writes the several names of an element to a file
2497 PrintElementNameList (ElementType
*Element
, FILE * FP
)
2499 static DynamicStringType cname
, pname
, vname
;
2501 CreateQuotedString (&cname
, (char *)EMPTY (DESCRIPTION_NAME (Element
)));
2502 CreateQuotedString (&pname
, (char *)EMPTY (NAMEONPCB_NAME (Element
)));
2503 CreateQuotedString (&vname
, (char *)EMPTY (VALUE_NAME (Element
)));
2504 fprintf (FP
, "(%s %s %s)\n", cname
.Data
, pname
.Data
, vname
.Data
);
2507 /* ---------------------------------------------------------------------------
2508 * writes the several names of an element to a file
2511 PrintConnectionElementName (ElementType
*Element
, FILE * FP
)
2513 fputs ("Element", FP
);
2514 PrintElementNameList (Element
, FP
);
2518 /* ---------------------------------------------------------------------------
2519 * prints one {pin,pad,via}/element entry of connection lists
2522 PrintConnectionListEntry (char *ObjName
, ElementType
*Element
,
2523 bool FirstOne
, FILE * FP
)
2525 static DynamicStringType oname
;
2527 CreateQuotedString (&oname
, ObjName
);
2529 fprintf (FP
, "\t%s\n\t{\n", oname
.Data
);
2532 fprintf (FP
, "\t\t%s ", oname
.Data
);
2534 PrintElementNameList (Element
, FP
);
2536 fputs ("(__VIA__)\n", FP
);
2540 /* ---------------------------------------------------------------------------
2541 * prints all found connections of a pads to file FP
2542 * the connections are stacked in 'PadList'
2545 PrintPadConnections (Cardinal Layer
, FILE * FP
, bool IsFirst
)
2550 if (!PadList
[Layer
].Number
)
2553 /* the starting pad */
2556 ptr
= PADLIST_ENTRY (Layer
, 0);
2558 PrintConnectionListEntry ((char *)UNKNOWN (ptr
->Name
), NULL
, true, FP
);
2560 printf ("Skipping NULL ptr in 1st part of PrintPadConnections\n");
2563 /* we maybe have to start with i=1 if we are handling the
2564 * starting-pad itself
2566 for (i
= IsFirst
? 1 : 0; i
< PadList
[Layer
].Number
; i
++)
2568 ptr
= PADLIST_ENTRY (Layer
, i
);
2570 PrintConnectionListEntry ((char *)EMPTY (ptr
->Name
), (ElementType
*)ptr
->Element
, false, FP
);
2572 printf ("Skipping NULL ptr in 2nd part of PrintPadConnections\n");
2576 /* ---------------------------------------------------------------------------
2577 * prints all found connections of a pin to file FP
2578 * the connections are stacked in 'PVList'
2581 PrintPinConnections (FILE * FP
, bool IsFirst
)
2591 /* the starting pin */
2592 pv
= PVLIST_ENTRY (0);
2593 PrintConnectionListEntry ((char *)EMPTY (pv
->Name
), NULL
, true, FP
);
2596 /* we maybe have to start with i=1 if we are handling the
2597 * starting-pin itself
2599 for (i
= IsFirst
? 1 : 0; i
< PVList
.Number
; i
++)
2601 /* get the elements name or assume that its a via */
2602 pv
= PVLIST_ENTRY (i
);
2603 PrintConnectionListEntry ((char *)EMPTY (pv
->Name
), (ElementType
*)pv
->Element
, false, FP
);
2607 /* ---------------------------------------------------------------------------
2608 * checks if all lists of new objects are handled
2611 ListsEmpty (bool AndRats
)
2616 empty
= (PVList
.Location
>= PVList
.Number
);
2618 empty
= empty
&& (RatList
.Location
>= RatList
.Number
);
2619 for (i
= 0; i
< max_copper_layer
&& empty
; i
++)
2620 if (!LAYER_PTR (i
)->no_drc
)
2621 empty
= empty
&& LineList
[i
].Location
>= LineList
[i
].Number
2622 && ArcList
[i
].Location
>= ArcList
[i
].Number
2623 && PolygonList
[i
].Location
>= PolygonList
[i
].Number
;
2628 reassign_no_drc_flags (void)
2632 for (layer
= 0; layer
< max_copper_layer
; layer
++)
2634 LayerType
*l
= LAYER_PTR (layer
);
2635 l
->no_drc
= AttributeGet (l
, "PCB::skip-drc") != NULL
;
2642 /* ---------------------------------------------------------------------------
2643 * loops till no more connections are found
2646 DoIt (bool AndRats
, bool AndDraw
)
2648 bool newone
= false;
2649 reassign_no_drc_flags ();
2652 /* lookup connections; these are the steps (2) to (4)
2653 * from the description
2655 newone
= LookupPVConnectionsToPVList () ||
2656 LookupLOConnectionsToPVList (AndRats
) ||
2657 LookupLOConnectionsToLOList (AndRats
) ||
2658 LookupPVConnectionsToLOList (AndRats
);
2660 DrawNewConnections ();
2662 while (!newone
&& !ListsEmpty (AndRats
));
2668 /* ---------------------------------------------------------------------------
2669 * prints all unused pins of an element to file FP
2672 PrintAndSelectUnusedPinsAndPadsOfElement (ElementType
*Element
, FILE * FP
)
2676 static DynamicStringType oname
;
2678 /* check all pins in element */
2682 if (!TEST_FLAG (HOLEFLAG
, pin
))
2684 /* pin might have bee checked before, add to list if not */
2685 if (!TEST_FLAG (TheFlag
, pin
) && FP
)
2688 if (ADD_PV_TO_LIST (pin
))
2691 number
= PadList
[COMPONENT_LAYER
].Number
2692 + PadList
[SOLDER_LAYER
].Number
+ PVList
.Number
;
2693 /* the pin has no connection if it's the only
2694 * list entry; don't count vias
2696 for (i
= 0; i
< PVList
.Number
; i
++)
2697 if (!PVLIST_ENTRY (i
)->Element
)
2701 /* output of element name if not already done */
2704 PrintConnectionElementName (Element
, FP
);
2708 /* write name to list and draw selected object */
2709 CreateQuotedString (&oname
, (char *)EMPTY (pin
->Name
));
2710 fprintf (FP
, "\t%s\n", oname
.Data
);
2711 SET_FLAG (SELECTEDFLAG
, pin
);
2715 /* reset found objects for the next pin */
2716 if (PrepareNextLoop (FP
))
2723 /* check all pads in element */
2726 /* lookup pad in list */
2727 /* pad might has bee checked before, add to list if not */
2728 if (!TEST_FLAG (TheFlag
, pad
) && FP
)
2731 if (ADD_PAD_TO_LIST (TEST_FLAG (ONSOLDERFLAG
, pad
)
2732 ? SOLDER_LAYER
: COMPONENT_LAYER
, pad
))
2735 number
= PadList
[COMPONENT_LAYER
].Number
2736 + PadList
[SOLDER_LAYER
].Number
+ PVList
.Number
;
2737 /* the pin has no connection if it's the only
2738 * list entry; don't count vias
2740 for (i
= 0; i
< PVList
.Number
; i
++)
2741 if (!PVLIST_ENTRY (i
)->Element
)
2745 /* output of element name if not already done */
2748 PrintConnectionElementName (Element
, FP
);
2752 /* write name to list and draw selected object */
2753 CreateQuotedString (&oname
, (char *)EMPTY (pad
->Name
));
2754 fprintf (FP
, "\t%s\n", oname
.Data
);
2755 SET_FLAG (SELECTEDFLAG
, pad
);
2759 /* reset found objects for the next pin */
2760 if (PrepareNextLoop (FP
))
2766 /* print separator if element has unused pins or pads */
2769 fputs ("}\n\n", FP
);
2775 /* ---------------------------------------------------------------------------
2776 * resets some flags for looking up the next pin/pad
2779 PrepareNextLoop (FILE * FP
)
2783 /* reset found LOs for the next pin */
2784 for (layer
= 0; layer
< max_copper_layer
; layer
++)
2786 LineList
[layer
].Location
= LineList
[layer
].Number
= 0;
2787 ArcList
[layer
].Location
= ArcList
[layer
].Number
= 0;
2788 PolygonList
[layer
].Location
= PolygonList
[layer
].Number
= 0;
2791 /* reset found pads */
2792 for (layer
= 0; layer
< 2; layer
++)
2793 PadList
[layer
].Location
= PadList
[layer
].Number
= 0;
2796 PVList
.Number
= PVList
.Location
= 0;
2797 RatList
.Number
= RatList
.Location
= 0;
2802 /* ---------------------------------------------------------------------------
2803 * finds all connections to the pins of the passed element.
2804 * The result is written to file FP
2805 * Returns true if operation was aborted
2808 PrintElementConnections (ElementType
*Element
, FILE * FP
, bool AndDraw
)
2810 PrintConnectionElementName (Element
, FP
);
2812 /* check all pins in element */
2815 /* pin might have been checked before, add to list if not */
2816 if (TEST_FLAG (TheFlag
, pin
))
2818 PrintConnectionListEntry ((char *)EMPTY (pin
->Name
), NULL
, true, FP
);
2819 fputs ("\t\t__CHECKED_BEFORE__\n\t}\n", FP
);
2822 if (ADD_PV_TO_LIST (pin
))
2824 DoIt (true, AndDraw
);
2825 /* printout all found connections */
2826 PrintPinConnections (FP
, true);
2827 PrintPadConnections (COMPONENT_LAYER
, FP
, false);
2828 PrintPadConnections (SOLDER_LAYER
, FP
, false);
2829 fputs ("\t}\n", FP
);
2830 if (PrepareNextLoop (FP
))
2835 /* check all pads in element */
2839 /* pad might have been checked before, add to list if not */
2840 if (TEST_FLAG (TheFlag
, pad
))
2842 PrintConnectionListEntry ((char *)EMPTY (pad
->Name
), NULL
, true, FP
);
2843 fputs ("\t\t__CHECKED_BEFORE__\n\t}\n", FP
);
2846 layer
= TEST_FLAG (ONSOLDERFLAG
, pad
) ? SOLDER_LAYER
: COMPONENT_LAYER
;
2847 if (ADD_PAD_TO_LIST (layer
, pad
))
2849 DoIt (true, AndDraw
);
2850 /* print all found connections */
2851 PrintPadConnections (layer
, FP
, true);
2852 PrintPadConnections (layer
==
2853 (COMPONENT_LAYER
? SOLDER_LAYER
: COMPONENT_LAYER
),
2855 PrintPinConnections (FP
, false);
2856 fputs ("\t}\n", FP
);
2857 if (PrepareNextLoop (FP
))
2861 fputs ("}\n\n", FP
);
2865 /* ---------------------------------------------------------------------------
2866 * draws all new connections which have been found since the
2867 * routine was called the last time
2870 DrawNewConnections (void)
2875 /* decrement 'i' to keep layerstack order */
2876 for (i
= max_copper_layer
- 1; i
!= -1; i
--)
2878 Cardinal layer
= LayerStack
[i
];
2880 if (PCB
->Data
->Layer
[layer
].On
)
2882 /* draw all new lines */
2883 position
= LineList
[layer
].DrawLocation
;
2884 for (; position
< LineList
[layer
].Number
; position
++)
2885 DrawLine (LAYER_PTR (layer
), LINELIST_ENTRY (layer
, position
));
2886 LineList
[layer
].DrawLocation
= LineList
[layer
].Number
;
2888 /* draw all new arcs */
2889 position
= ArcList
[layer
].DrawLocation
;
2890 for (; position
< ArcList
[layer
].Number
; position
++)
2891 DrawArc (LAYER_PTR (layer
), ARCLIST_ENTRY (layer
, position
));
2892 ArcList
[layer
].DrawLocation
= ArcList
[layer
].Number
;
2894 /* draw all new polygons */
2895 position
= PolygonList
[layer
].DrawLocation
;
2896 for (; position
< PolygonList
[layer
].Number
; position
++)
2897 DrawPolygon (LAYER_PTR (layer
), POLYGONLIST_ENTRY (layer
, position
));
2898 PolygonList
[layer
].DrawLocation
= PolygonList
[layer
].Number
;
2902 /* draw all new pads */
2904 for (i
= 0; i
< 2; i
++)
2906 position
= PadList
[i
].DrawLocation
;
2908 for (; position
< PadList
[i
].Number
; position
++)
2909 DrawPad (PADLIST_ENTRY (i
, position
));
2910 PadList
[i
].DrawLocation
= PadList
[i
].Number
;
2913 /* draw all new PVs; 'PVList' holds a list of pointers to the
2914 * sorted array pointers to PV data
2916 while (PVList
.DrawLocation
< PVList
.Number
)
2918 PinType
*pv
= PVLIST_ENTRY (PVList
.DrawLocation
);
2920 if (TEST_FLAG (PINFLAG
, pv
))
2925 else if (PCB
->ViaOn
)
2927 PVList
.DrawLocation
++;
2929 /* draw the new rat-lines */
2932 position
= RatList
.DrawLocation
;
2933 for (; position
< RatList
.Number
; position
++)
2934 DrawRat (RATLIST_ENTRY (position
));
2935 RatList
.DrawLocation
= RatList
.Number
;
2939 /* ---------------------------------------------------------------------------
2940 * find all connections to pins within one element
2943 LookupElementConnections (ElementType
*Element
, FILE * FP
)
2945 /* reset all currently marked connections */
2947 TheFlag
= FOUNDFLAG
;
2948 ClearFlagOnAllObjects (true, FOUNDFLAG
);
2949 InitConnectionLookup ();
2950 PrintElementConnections (Element
, FP
, true);
2951 SetChangedFlag (true);
2952 if (Settings
.RingBellWhenFinished
)
2954 FreeConnectionLookupMemory ();
2955 IncrementUndoSerialNumber ();
2960 /* ---------------------------------------------------------------------------
2961 * find all connections to pins of all element
2964 LookupConnectionsToAllElements (FILE * FP
)
2966 /* reset all currently marked connections */
2968 TheFlag
= FOUNDFLAG
;
2969 ClearFlagOnAllObjects (false, FOUNDFLAG
);
2970 InitConnectionLookup ();
2972 ELEMENT_LOOP (PCB
->Data
);
2974 /* break if abort dialog returned true */
2975 if (PrintElementConnections (element
, FP
, false))
2978 if (Settings
.ResetAfterElement
&& n
!= 1)
2979 ClearFlagOnAllObjects (false, FOUNDFLAG
);
2982 if (Settings
.RingBellWhenFinished
)
2984 ClearFlagOnAllObjects (false, FOUNDFLAG
);
2985 FreeConnectionLookupMemory ();
2989 /*---------------------------------------------------------------------------
2990 * add the starting object to the list of found objects
2993 ListStart (int type
, void *ptr1
, void *ptr2
, void *ptr3
)
3001 if (ADD_PV_TO_LIST ((PinType
*) ptr2
))
3008 if (ADD_RAT_TO_LIST ((RatType
*) ptr1
))
3015 int layer
= GetLayerNumber (PCB
->Data
,
3016 (LayerType
*) ptr1
);
3018 if (ADD_LINE_TO_LIST (layer
, (LineType
*) ptr2
))
3025 int layer
= GetLayerNumber (PCB
->Data
,
3026 (LayerType
*) ptr1
);
3028 if (ADD_ARC_TO_LIST (layer
, (ArcType
*) ptr2
))
3035 int layer
= GetLayerNumber (PCB
->Data
,
3036 (LayerType
*) ptr1
);
3038 if (ADD_POLYGON_TO_LIST (layer
, (PolygonType
*) ptr2
))
3045 PadType
*pad
= (PadType
*) ptr2
;
3048 (ONSOLDERFLAG
, pad
) ? SOLDER_LAYER
: COMPONENT_LAYER
, pad
))
3057 /* ---------------------------------------------------------------------------
3058 * looks up all connections from the object at the given coordinates
3059 * the TheFlag (normally 'FOUNDFLAG') is set for all objects found
3060 * the objects are re-drawn if AndDraw is true
3061 * also the action is marked as undoable if AndDraw is true
3064 LookupConnection (Coord X
, Coord Y
, bool AndDraw
, Coord Range
, int which_flag
,
3067 void *ptr1
, *ptr2
, *ptr3
;
3071 /* check if there are any pins or pads at that position */
3073 reassign_no_drc_flags ();
3076 = SearchObjectByLocation (LOOKUP_FIRST
, &ptr1
, &ptr2
, &ptr3
, X
, Y
, Range
);
3077 if (type
== NO_TYPE
)
3079 type
= SearchObjectByLocation (
3080 LOOKUP_MORE
& ~(AndRats
? RATLINE_TYPE
: 0),
3081 &ptr1
, &ptr2
, &ptr3
, X
, Y
, Range
);
3082 if (type
== NO_TYPE
)
3084 if (type
& SILK_TYPE
)
3086 int laynum
= GetLayerNumber (PCB
->Data
,
3087 (LayerType
*) ptr1
);
3089 /* don't mess with non-conducting objects! */
3090 if (laynum
>= max_copper_layer
|| ((LayerType
*)ptr1
)->no_drc
)
3095 name
= ConnectionName (type
, ptr1
, ptr2
);
3096 hid_actionl ("NetlistShow", name
, NULL
);
3098 TheFlag
= which_flag
;
3100 InitConnectionLookup ();
3102 /* now add the object to the appropriate list and start scanning
3103 * This is step (1) from the description
3105 ListStart (type
, ptr1
, ptr2
, ptr3
);
3106 DoIt (AndRats
, AndDraw
);
3108 IncrementUndoSerialNumber ();
3114 if (AndDraw
&& Settings
.RingBellWhenFinished
)
3116 FreeConnectionLookupMemory ();
3119 /* ---------------------------------------------------------------------------
3120 * find connections for rats nesting
3121 * assumes InitConnectionLookup() has already been done
3124 RatFindHook (int type
, void *ptr1
, void *ptr2
, void *ptr3
,
3125 bool undo
, int flag
, bool AndRats
)
3130 ListStart (type
, ptr1
, ptr2
, ptr3
);
3131 DoIt (AndRats
, false);
3135 /* ---------------------------------------------------------------------------
3136 * find all unused pins of all element
3139 LookupUnusedPins (FILE * FP
)
3141 /* reset all currently marked connections */
3143 TheFlag
= FOUNDFLAG
;
3144 ClearFlagOnAllObjects (true, FOUNDFLAG
);
3145 InitConnectionLookup ();
3147 ELEMENT_LOOP (PCB
->Data
);
3149 /* break if abort dialog returned true;
3150 * passing NULL as filedescriptor discards the normal output
3152 if (PrintAndSelectUnusedPinsAndPadsOfElement (element
, FP
))
3157 if (Settings
.RingBellWhenFinished
)
3159 FreeConnectionLookupMemory ();
3160 IncrementUndoSerialNumber ();
3165 /* ---------------------------------------------------------------------------
3166 * resets all used flags of pins and vias
3169 ClearFlagOnPinsViasAndPads (bool AndDraw
, int flag
)
3171 bool change
= false;
3173 VIA_LOOP (PCB
->Data
);
3175 if (TEST_FLAG (flag
, via
))
3178 AddObjectToFlagUndoList (VIA_TYPE
, via
, via
, via
);
3179 CLEAR_FLAG (flag
, via
);
3186 ELEMENT_LOOP (PCB
->Data
);
3190 if (TEST_FLAG (flag
, pin
))
3193 AddObjectToFlagUndoList (PIN_TYPE
, element
, pin
, pin
);
3194 CLEAR_FLAG (flag
, pin
);
3203 if (TEST_FLAG (flag
, pad
))
3206 AddObjectToFlagUndoList (PAD_TYPE
, element
, pad
, pad
);
3207 CLEAR_FLAG (flag
, pad
);
3217 SetChangedFlag (true);
3221 /* ---------------------------------------------------------------------------
3222 * resets all used flags of LOs
3225 ClearFlagOnLinesAndPolygons (bool AndDraw
, int flag
)
3227 bool change
= false;
3229 RAT_LOOP (PCB
->Data
);
3231 if (TEST_FLAG (flag
, line
))
3234 AddObjectToFlagUndoList (RATLINE_TYPE
, line
, line
, line
);
3235 CLEAR_FLAG (flag
, line
);
3242 COPPERLINE_LOOP (PCB
->Data
);
3244 if (TEST_FLAG (flag
, line
))
3247 AddObjectToFlagUndoList (LINE_TYPE
, layer
, line
, line
);
3248 CLEAR_FLAG (flag
, line
);
3250 DrawLine (layer
, line
);
3255 COPPERARC_LOOP (PCB
->Data
);
3257 if (TEST_FLAG (flag
, arc
))
3260 AddObjectToFlagUndoList (ARC_TYPE
, layer
, arc
, arc
);
3261 CLEAR_FLAG (flag
, arc
);
3263 DrawArc (layer
, arc
);
3268 COPPERPOLYGON_LOOP (PCB
->Data
);
3270 if (TEST_FLAG (flag
, polygon
))
3273 AddObjectToFlagUndoList (POLYGON_TYPE
, layer
, polygon
, polygon
);
3274 CLEAR_FLAG (flag
, polygon
);
3276 DrawPolygon (layer
, polygon
);
3282 SetChangedFlag (true);
3286 /* ---------------------------------------------------------------------------
3287 * resets all found connections
3290 ClearFlagOnAllObjects (bool AndDraw
, int flag
)
3292 bool change
= false;
3294 change
= ClearFlagOnPinsViasAndPads (AndDraw
, flag
) || change
;
3295 change
= ClearFlagOnLinesAndPolygons (AndDraw
, flag
) || change
;
3300 /*----------------------------------------------------------------------------
3301 * Dumps the list contents
3308 for (i
= 0; i
< 2; i
++)
3310 PadList
[i
].Number
= 0;
3311 PadList
[i
].Location
= 0;
3312 PadList
[i
].DrawLocation
= 0;
3316 PVList
.Location
= 0;
3318 for (i
= 0; i
< max_copper_layer
; i
++)
3320 LineList
[i
].Location
= 0;
3321 LineList
[i
].DrawLocation
= 0;
3322 LineList
[i
].Number
= 0;
3323 ArcList
[i
].Location
= 0;
3324 ArcList
[i
].DrawLocation
= 0;
3325 ArcList
[i
].Number
= 0;
3326 PolygonList
[i
].Location
= 0;
3327 PolygonList
[i
].DrawLocation
= 0;
3328 PolygonList
[i
].Number
= 0;
3331 RatList
.Location
= 0;
3332 RatList
.DrawLocation
= 0;
3335 /*-----------------------------------------------------------------------------
3336 * Check for DRC violations on a single net starting from the pad or pin
3337 * sees if the connectivity changes when everything is bloated, or shrunk
3340 DRCFind (int What
, void *ptr1
, void *ptr2
, void *ptr3
)
3344 long int *object_id_list
;
3345 int *object_type_list
;
3346 DrcViolationType
*violation
;
3348 if (PCB
->Shrink
!= 0)
3350 Bloat
= -PCB
->Shrink
;
3351 TheFlag
= DRCFLAG
| SELECTEDFLAG
;
3352 ListStart (What
, ptr1
, ptr2
, ptr3
);
3354 /* ok now the shrunk net has the SELECTEDFLAG set */
3356 TheFlag
= FOUNDFLAG
;
3357 ListStart (What
, ptr1
, ptr2
, ptr3
);
3359 drc
= true; /* abort the search if we find anything not already found */
3360 if (DoIt (true, false))
3363 /* make the flag changes undoable */
3364 TheFlag
= FOUNDFLAG
| SELECTEDFLAG
;
3365 ClearFlagOnAllObjects (false, TheFlag
);
3368 Bloat
= -PCB
->Shrink
;
3369 TheFlag
= SELECTEDFLAG
;
3370 ListStart (What
, ptr1
, ptr2
, ptr3
);
3373 ListStart (What
, ptr1
, ptr2
, ptr3
);
3374 TheFlag
= FOUNDFLAG
;
3382 LocateError (&x
, &y
);
3383 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3384 violation
= pcb_drc_violation_new (_("Potential for broken trace"),
3385 _("Insufficient overlap between objects can lead to broken tracks\n"
3386 "due to registration errors with old wheel style photo-plotters."),
3388 0, /* ANGLE OF ERROR UNKNOWN */
3389 FALSE
, /* MEASUREMENT OF ERROR UNKNOWN */
3390 0, /* MAGNITUDE OF ERROR UNKNOWN */
3395 append_drc_violation (violation
);
3396 pcb_drc_violation_free (violation
);
3397 free (object_id_list
);
3398 free (object_type_list
);
3400 if (!throw_drc_dialog())
3402 IncrementUndoSerialNumber ();
3407 /* now check the bloated condition */
3409 ClearFlagOnAllObjects (false, TheFlag
);
3410 TheFlag
= FOUNDFLAG
;
3411 ListStart (What
, ptr1
, ptr2
, ptr3
);
3414 while (DoIt (true, false))
3417 /* make the flag changes undoable */
3418 TheFlag
= FOUNDFLAG
| SELECTEDFLAG
;
3419 ClearFlagOnAllObjects (false, TheFlag
);
3423 TheFlag
= SELECTEDFLAG
;
3424 ListStart (What
, ptr1
, ptr2
, ptr3
);
3427 TheFlag
= FOUNDFLAG
;
3428 ListStart (What
, ptr1
, ptr2
, ptr3
);
3434 LocateError (&x
, &y
);
3435 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3436 violation
= pcb_drc_violation_new (_("Copper areas too close"),
3437 _("Circuits that are too close may bridge during imaging, etching,\n"
3438 "plating, or soldering processes resulting in a direct short."),
3440 0, /* ANGLE OF ERROR UNKNOWN */
3441 FALSE
, /* MEASUREMENT OF ERROR UNKNOWN */
3442 0, /* MAGNITUDE OF ERROR UNKNOWN */
3447 append_drc_violation (violation
);
3448 pcb_drc_violation_free (violation
);
3449 free (object_id_list
);
3450 free (object_type_list
);
3453 if (!throw_drc_dialog())
3455 IncrementUndoSerialNumber ();
3457 /* highlight the rest of the encroaching net so it's not reported again */
3458 TheFlag
|= SELECTEDFLAG
;
3460 ListStart (thing_type
, thing_ptr1
, thing_ptr2
, thing_ptr3
);
3465 ListStart (What
, ptr1
, ptr2
, ptr3
);
3469 TheFlag
= FOUNDFLAG
| SELECTEDFLAG
;
3470 ClearFlagOnAllObjects (false, TheFlag
);
3474 /* DRC clearance callback */
3477 drc_callback (DataType
*data
, LayerType
*layer
, PolygonType
*polygon
,
3478 int type
, void *ptr1
, void *ptr2
)
3483 long int *object_id_list
;
3484 int *object_type_list
;
3485 DrcViolationType
*violation
;
3487 LineType
*line
= (LineType
*) ptr2
;
3488 ArcType
*arc
= (ArcType
*) ptr2
;
3489 PinType
*pin
= (PinType
*) ptr2
;
3490 PadType
*pad
= (PadType
*) ptr2
;
3499 if (line
->Clearance
< 2 * PCB
->Bloat
)
3501 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr2
);
3502 SET_FLAG (TheFlag
, line
);
3503 message
= _("Line with insufficient clearance inside polygon\n");
3508 if (arc
->Clearance
< 2 * PCB
->Bloat
)
3510 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr2
);
3511 SET_FLAG (TheFlag
, arc
);
3512 message
= _("Arc with insufficient clearance inside polygon\n");
3517 if (pad
->Clearance
&& pad
->Clearance
< 2 * PCB
->Bloat
)
3518 if (IsPadInPolygon(pad
,polygon
))
3520 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr2
);
3521 SET_FLAG (TheFlag
, pad
);
3522 message
= _("Pad with insufficient clearance inside polygon\n");
3527 if (pin
->Clearance
&& pin
->Clearance
< 2 * PCB
->Bloat
)
3529 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr2
);
3530 SET_FLAG (TheFlag
, pin
);
3531 message
= _("Pin with insufficient clearance inside polygon\n");
3536 if (pin
->Clearance
&& pin
->Clearance
< 2 * PCB
->Bloat
)
3538 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr2
);
3539 SET_FLAG (TheFlag
, pin
);
3540 message
= _("Via with insufficient clearance inside polygon\n");
3545 Message ("hace: Bad Plow object in callback\n");
3550 AddObjectToFlagUndoList (POLYGON_TYPE
, layer
, polygon
, polygon
);
3551 SET_FLAG (FOUNDFLAG
, polygon
);
3552 DrawPolygon (layer
, polygon
);
3553 DrawObject (type
, ptr1
, ptr2
);
3555 LocateError (&x
, &y
);
3556 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3557 violation
= pcb_drc_violation_new (message
,
3558 _("Circuits that are too close may bridge during imaging, etching,\n"
3559 "plating, or soldering processes resulting in a direct short."),
3561 0, /* ANGLE OF ERROR UNKNOWN */
3562 FALSE
, /* MEASUREMENT OF ERROR UNKNOWN */
3563 0, /* MAGNITUDE OF ERROR UNKNOWN */
3568 append_drc_violation (violation
);
3569 pcb_drc_violation_free (violation
);
3570 free (object_id_list
);
3571 free (object_type_list
);
3573 if (!throw_drc_dialog())
3576 IncrementUndoSerialNumber ();
3581 /*-----------------------------------------------------------------------------
3582 * Check for DRC violations
3583 * see if the connectivity changes when everything is bloated, or shrunk
3590 long int *object_id_list
;
3591 int *object_type_list
;
3592 DrcViolationType
*violation
;
3597 reset_drc_dialog_message();
3601 SaveStackAndVisibility ();
3602 ResetStackAndVisibility ();
3603 hid_action ("LayersChanged");
3604 InitConnectionLookup ();
3606 TheFlag
= FOUNDFLAG
| DRCFLAG
| SELECTEDFLAG
;
3608 if (ClearFlagOnAllObjects (true, TheFlag
))
3610 IncrementUndoSerialNumber ();
3616 ELEMENT_LOOP (PCB
->Data
);
3620 if (!TEST_FLAG (DRCFLAG
, pin
)
3621 && DRCFind (PIN_TYPE
, (void *) element
, (void *) pin
, (void *) pin
))
3633 /* count up how many pads have no solderpaste openings */
3634 if (TEST_FLAG (NOPASTEFLAG
, pad
))
3637 if (!TEST_FLAG (DRCFLAG
, pad
)
3638 && DRCFind (PAD_TYPE
, (void *) element
, (void *) pad
, (void *) pad
))
3650 VIA_LOOP (PCB
->Data
);
3652 if (!TEST_FLAG (DRCFLAG
, via
)
3653 && DRCFind (VIA_TYPE
, (void *) via
, (void *) via
, (void *) via
))
3661 TheFlag
= (IsBad
) ? DRCFLAG
: (FOUNDFLAG
| DRCFLAG
| SELECTEDFLAG
);
3662 ClearFlagOnAllObjects (false, TheFlag
);
3663 TheFlag
= SELECTEDFLAG
;
3664 /* check minimum widths and polygon clearances */
3667 COPPERLINE_LOOP (PCB
->Data
);
3669 /* check line clearances in polygons */
3670 if (PlowsPolygon (PCB
->Data
, LINE_TYPE
, layer
, line
, drc_callback
))
3675 if (line
->Thickness
< PCB
->minWid
)
3677 AddObjectToFlagUndoList (LINE_TYPE
, layer
, line
, line
);
3678 SET_FLAG (TheFlag
, line
);
3679 DrawLine (layer
, line
);
3681 SetThing (LINE_TYPE
, layer
, line
, line
);
3682 LocateError (&x
, &y
);
3683 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3684 violation
= pcb_drc_violation_new (_("Line width is too thin"),
3685 _("Process specifications dictate a minimum feature-width\n"
3686 "that can reliably be reproduced"),
3688 0, /* ANGLE OF ERROR UNKNOWN */
3689 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3695 append_drc_violation (violation
);
3696 pcb_drc_violation_free (violation
);
3697 free (object_id_list
);
3698 free (object_type_list
);
3699 if (!throw_drc_dialog())
3704 IncrementUndoSerialNumber ();
3712 COPPERARC_LOOP (PCB
->Data
);
3714 if (PlowsPolygon (PCB
->Data
, ARC_TYPE
, layer
, arc
, drc_callback
))
3719 if (arc
->Thickness
< PCB
->minWid
)
3721 AddObjectToFlagUndoList (ARC_TYPE
, layer
, arc
, arc
);
3722 SET_FLAG (TheFlag
, arc
);
3723 DrawArc (layer
, arc
);
3725 SetThing (ARC_TYPE
, layer
, arc
, arc
);
3726 LocateError (&x
, &y
);
3727 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3728 violation
= pcb_drc_violation_new (_("Arc width is too thin"),
3729 _("Process specifications dictate a minimum feature-width\n"
3730 "that can reliably be reproduced"),
3732 0, /* ANGLE OF ERROR UNKNOWN */
3733 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3739 append_drc_violation (violation
);
3740 pcb_drc_violation_free (violation
);
3741 free (object_id_list
);
3742 free (object_type_list
);
3743 if (!throw_drc_dialog())
3748 IncrementUndoSerialNumber ();
3756 ALLPIN_LOOP (PCB
->Data
);
3758 if (PlowsPolygon (PCB
->Data
, PIN_TYPE
, element
, pin
, drc_callback
))
3763 if (!TEST_FLAG (HOLEFLAG
, pin
) &&
3764 pin
->Thickness
- pin
->DrillingHole
< 2 * PCB
->minRing
)
3766 AddObjectToFlagUndoList (PIN_TYPE
, element
, pin
, pin
);
3767 SET_FLAG (TheFlag
, pin
);
3770 SetThing (PIN_TYPE
, element
, pin
, pin
);
3771 LocateError (&x
, &y
);
3772 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3773 violation
= pcb_drc_violation_new (_("Pin annular ring too small"),
3774 _("Annular rings that are too small may erode during etching,\n"
3775 "resulting in a broken connection"),
3777 0, /* ANGLE OF ERROR UNKNOWN */
3778 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3779 (pin
->Thickness
- pin
->DrillingHole
) / 2,
3784 append_drc_violation (violation
);
3785 pcb_drc_violation_free (violation
);
3786 free (object_id_list
);
3787 free (object_type_list
);
3788 if (!throw_drc_dialog())
3793 IncrementUndoSerialNumber ();
3796 if (pin
->DrillingHole
< PCB
->minDrill
)
3798 AddObjectToFlagUndoList (PIN_TYPE
, element
, pin
, pin
);
3799 SET_FLAG (TheFlag
, pin
);
3802 SetThing (PIN_TYPE
, element
, pin
, pin
);
3803 LocateError (&x
, &y
);
3804 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3805 violation
= pcb_drc_violation_new (_("Pin drill size is too small"),
3806 _("Process rules dictate the minimum drill size which can be used"),
3808 0, /* ANGLE OF ERROR UNKNOWN */
3809 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3815 append_drc_violation (violation
);
3816 pcb_drc_violation_free (violation
);
3817 free (object_id_list
);
3818 free (object_type_list
);
3819 if (!throw_drc_dialog())
3824 IncrementUndoSerialNumber ();
3832 ALLPAD_LOOP (PCB
->Data
);
3834 if (PlowsPolygon (PCB
->Data
, PAD_TYPE
, element
, pad
, drc_callback
))
3839 if (pad
->Thickness
< PCB
->minWid
)
3841 AddObjectToFlagUndoList (PAD_TYPE
, element
, pad
, pad
);
3842 SET_FLAG (TheFlag
, pad
);
3845 SetThing (PAD_TYPE
, element
, pad
, pad
);
3846 LocateError (&x
, &y
);
3847 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3848 violation
= pcb_drc_violation_new (_("Pad is too thin"),
3849 _("Pads which are too thin may erode during etching,\n"
3850 "resulting in a broken or unreliable connection"),
3852 0, /* ANGLE OF ERROR UNKNOWN */
3853 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3859 append_drc_violation (violation
);
3860 pcb_drc_violation_free (violation
);
3861 free (object_id_list
);
3862 free (object_type_list
);
3863 if (!throw_drc_dialog())
3868 IncrementUndoSerialNumber ();
3876 VIA_LOOP (PCB
->Data
);
3878 if (PlowsPolygon (PCB
->Data
, VIA_TYPE
, via
, via
, drc_callback
))
3883 if (!TEST_FLAG (HOLEFLAG
, via
) &&
3884 via
->Thickness
- via
->DrillingHole
< 2 * PCB
->minRing
)
3886 AddObjectToFlagUndoList (VIA_TYPE
, via
, via
, via
);
3887 SET_FLAG (TheFlag
, via
);
3890 SetThing (VIA_TYPE
, via
, via
, via
);
3891 LocateError (&x
, &y
);
3892 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3893 violation
= pcb_drc_violation_new (_("Via annular ring too small"),
3894 _("Annular rings that are too small may erode during etching,\n"
3895 "resulting in a broken connection"),
3897 0, /* ANGLE OF ERROR UNKNOWN */
3898 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3899 (via
->Thickness
- via
->DrillingHole
) / 2,
3904 append_drc_violation (violation
);
3905 pcb_drc_violation_free (violation
);
3906 free (object_id_list
);
3907 free (object_type_list
);
3908 if (!throw_drc_dialog())
3913 IncrementUndoSerialNumber ();
3916 if (via
->DrillingHole
< PCB
->minDrill
)
3918 AddObjectToFlagUndoList (VIA_TYPE
, via
, via
, via
);
3919 SET_FLAG (TheFlag
, via
);
3922 SetThing (VIA_TYPE
, via
, via
, via
);
3923 LocateError (&x
, &y
);
3924 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3925 violation
= pcb_drc_violation_new (_("Via drill size is too small"),
3926 _("Process rules dictate the minimum drill size which can be used"),
3928 0, /* ANGLE OF ERROR UNKNOWN */
3929 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3935 append_drc_violation (violation
);
3936 pcb_drc_violation_free (violation
);
3937 free (object_id_list
);
3938 free (object_type_list
);
3939 if (!throw_drc_dialog())
3944 IncrementUndoSerialNumber ();
3951 FreeConnectionLookupMemory ();
3952 TheFlag
= FOUNDFLAG
;
3955 /* check silkscreen minimum widths outside of elements */
3956 /* XXX - need to check text and polygons too! */
3957 TheFlag
= SELECTEDFLAG
;
3960 SILKLINE_LOOP (PCB
->Data
);
3962 if (line
->Thickness
< PCB
->minSlk
)
3964 SET_FLAG (TheFlag
, line
);
3965 DrawLine (layer
, line
);
3967 SetThing (LINE_TYPE
, layer
, line
, line
);
3968 LocateError (&x
, &y
);
3969 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3970 violation
= pcb_drc_violation_new (_("Silk line is too thin"),
3971 _("Process specifications dictate a minimum silkscreen feature-width\n"
3972 "that can reliably be reproduced"),
3974 0, /* ANGLE OF ERROR UNKNOWN */
3975 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3981 append_drc_violation (violation
);
3982 pcb_drc_violation_free (violation
);
3983 free (object_id_list
);
3984 free (object_type_list
);
3985 if (!throw_drc_dialog())
3995 /* check silkscreen minimum widths inside of elements */
3996 /* XXX - need to check text and polygons too! */
3997 TheFlag
= SELECTEDFLAG
;
4000 ELEMENT_LOOP (PCB
->Data
);
4003 ELEMENTLINE_LOOP (element
);
4005 if (line
->Thickness
< PCB
->minSlk
)
4016 SET_FLAG (TheFlag
, element
);
4017 DrawElement (element
);
4019 SetThing (ELEMENT_TYPE
, element
, element
, element
);
4020 LocateError (&x
, &y
);
4021 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
4023 title
= _("Element %s has %i silk lines which are too thin");
4024 name
= (char *)UNKNOWN (NAMEONPCB_NAME (element
));
4026 /* -4 is for the %s and %i place-holders */
4027 /* +11 is the max printed length for a 32 bit integer */
4028 /* +1 is for the \0 termination */
4029 buflen
= strlen (title
) - 4 + strlen (name
) + 11 + 1;
4030 buffer
= (char *)malloc (buflen
);
4031 snprintf (buffer
, buflen
, title
, name
, tmpcnt
);
4033 violation
= pcb_drc_violation_new (buffer
,
4034 _("Process specifications dictate a minimum silkscreen\n"
4035 "feature-width that can reliably be reproduced"),
4037 0, /* ANGLE OF ERROR UNKNOWN */
4038 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
4039 0, /* MINIMUM OFFENDING WIDTH UNKNOWN */
4045 append_drc_violation (violation
);
4046 pcb_drc_violation_free (violation
);
4047 free (object_id_list
);
4048 free (object_type_list
);
4049 if (!throw_drc_dialog())
4062 IncrementUndoSerialNumber ();
4066 RestoreStackAndVisibility ();
4067 hid_action ("LayersChanged");
4068 gui
->invalidate_all ();
4072 Message (_("Warning: %d pad%s the nopaste flag set.\n"),
4074 nopastecnt
> 1 ? "s have" : " has");
4076 return IsBad
? -drcerr_count
: drcerr_count
;
4079 /*----------------------------------------------------------------------------
4080 * Locate the coordinatates of offending item (thing)
4083 LocateError (Coord
*x
, Coord
*y
)
4089 LineType
*line
= (LineType
*) thing_ptr3
;
4090 *x
= (line
->Point1
.X
+ line
->Point2
.X
) / 2;
4091 *y
= (line
->Point1
.Y
+ line
->Point2
.Y
) / 2;
4096 ArcType
*arc
= (ArcType
*) thing_ptr3
;
4103 PolygonType
*polygon
= (PolygonType
*) thing_ptr3
;
4105 (polygon
->Clipped
->contours
->xmin
+
4106 polygon
->Clipped
->contours
->xmax
) / 2;
4108 (polygon
->Clipped
->contours
->ymin
+
4109 polygon
->Clipped
->contours
->ymax
) / 2;
4115 PinType
*pin
= (PinType
*) thing_ptr3
;
4122 PadType
*pad
= (PadType
*) thing_ptr3
;
4123 *x
= (pad
->Point1
.X
+ pad
->Point2
.X
) / 2;
4124 *y
= (pad
->Point1
.Y
+ pad
->Point2
.Y
) / 2;
4129 ElementType
*element
= (ElementType
*) thing_ptr3
;
4130 *x
= element
->MarkX
;
4131 *y
= element
->MarkY
;
4140 /*----------------------------------------------------------------------------
4141 * Build a list of the of offending items by ID. (Currently just "thing")
4144 BuildObjectList (int *object_count
, long int **object_id_list
, int **object_type_list
)
4147 *object_id_list
= NULL
;
4148 *object_type_list
= NULL
;
4161 *object_id_list
= (long int *)malloc (sizeof (long int));
4162 *object_type_list
= (int *)malloc (sizeof (int));
4163 **object_id_list
= ((AnyObjectType
*)thing_ptr3
)->ID
;
4164 **object_type_list
= thing_type
;
4169 _("Internal error in BuildObjectList: unknown object type %i\n"),
4175 /*----------------------------------------------------------------------------
4176 * center the display to show the offending item (thing)
4183 LocateError (&X
, &Y
);
4190 ChangeGroupVisibility (
4191 GetLayerNumber (PCB
->Data
, (LayerType
*) thing_ptr1
),
4194 CenterDisplay (X
, Y
);
4198 InitConnectionLookup (void)
4200 InitComponentLookup ();
4201 InitLayoutLookup ();
4205 FreeConnectionLookupMemory (void)
4207 FreeComponentLookupMemory ();
4208 FreeLayoutLookupMemory ();