4 * \brief Routines to find connections between pins, vias, lines ...
8 * <li> Lists for pins and vias, lines, arcs, pads and for polygons are
10 * Every object that has to be checked is added to its list.\n
11 * Coarse searching is accomplished with the data rtrees.</li>
12 * <li> There's no 'speed-up' mechanism for polygons because they are
13 * not used as often as other objects.</li>
14 * <li> The maximum distance between line and pin ... would depend on
15 * the angle between them. To speed up computation the limit is set
16 * to one half of the thickness of the objects (cause of square
20 * PV: means pin or via (objects that connect layers).\n
21 * LO: all non PV objects (layer objects like lines, arcs, polygons,
25 * <li> First, the LO or PV at the given coordinates is looked
27 * <li> All LO connections to that PV are looked up next.</li>
28 * <li> Lookup of all LOs connected to LOs from (2).\n
29 * This step is repeated until no more new connections are found.</li>
30 * <li> Lookup all PVs connected to the LOs from (2) and (3).</li>
31 * <li> Start again with (1) for all new PVs from (4).</li>
34 * Intersection of line <--> circle:\n
36 * <li> Calculate the signed distance from the line to the center,
37 * return false if abs(distance) > R.</li>
38 * <li> Get the distance from the line <--> distancevector intersection
39 * to (X1,Y1) in range [0,1], return true if 0 <= distance <= 1.</li>
40 * <li> Depending on (r > 1.0 or r < 0.0) check the distance of X2,Y2 or
44 * Intersection of line <--> line:\n
46 * <li> See the description of 'LineLineIntersect()'.</li>
51 * <h1><b>Copyright.</b></h1>\n
53 * PCB, interactive printed circuit board design
55 * Copyright (C) 1994,1995,1996, 2005 Thomas Nau
57 * This program is free software; you can redistribute it and/or modify
58 * it under the terms of the GNU General Public License as published by
59 * the Free Software Foundation; either version 2 of the License, or
60 * (at your option) any later version.
62 * This program is distributed in the hope that it will be useful,
63 * but WITHOUT ANY WARRANTY; without even the implied warranty of
64 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
65 * GNU General Public License for more details.
67 * You should have received a copy of the GNU General Public License
68 * along with this program; if not, write to the Free Software
69 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
71 * Contact addresses for paper mail and Email:
72 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
73 * Thomas.Nau@rz.uni-ulm.de
92 #include "pcb-printf.h"
98 #ifdef HAVE_LIBDMALLOC
104 /* ---------------------------------------------------------------------------
108 #define SEPARATE(FP) \
112 for (i = Settings.CharPerLine; i; i--) \
117 #define LIST_ENTRY(list,I) (((AnyObjectType **)list->Data)[(I)])
118 #define PADLIST_ENTRY(L,I) (((PadType **)PadList[(L)].Data)[(I)])
119 #define LINELIST_ENTRY(L,I) (((LineType **)LineList[(L)].Data)[(I)])
120 #define ARCLIST_ENTRY(L,I) (((ArcType **)ArcList[(L)].Data)[(I)])
121 #define RATLIST_ENTRY(I) (((RatType **)RatList.Data)[(I)])
122 #define POLYGONLIST_ENTRY(L,I) (((PolygonType **)PolygonList[(L)].Data)[(I)])
123 #define PVLIST_ENTRY(I) (((PinType **)PVList.Data)[(I)])
125 #define IS_PV_ON_RAT(PV, Rat) \
126 (IsPointOnLineEnd((PV)->X,(PV)->Y, (Rat)))
128 #define IS_PV_ON_ARC(PV, Arc) \
129 (TEST_FLAG(SQUAREFLAG, (PV)) ? \
131 (PV)->X -MAX(((PV)->Thickness+1)/2 +Bloat,0), (PV)->Y -MAX(((PV)->Thickness+1)/2 +Bloat,0), \
132 (PV)->X +MAX(((PV)->Thickness+1)/2 +Bloat,0), (PV)->Y +MAX(((PV)->Thickness+1)/2 +Bloat,0), \
134 IsPointOnArc((PV)->X,(PV)->Y,MAX((PV)->Thickness/2.0 + Bloat,0.0), (Arc)))
136 #define IS_PV_ON_PAD(PV,Pad) \
137 ( IsPointInPad((PV)->X, (PV)->Y, MAX((PV)->Thickness/2 +Bloat,0), (Pad)))
140 static DrcViolationType
141 *pcb_drc_violation_new (const char *title
,
142 const char *explanation
,
146 Coord measured_value
,
147 Coord required_value
,
149 long int *object_id_list
,
150 int *object_type_list
)
152 DrcViolationType
*violation
= (DrcViolationType
*)malloc (sizeof (DrcViolationType
));
154 violation
->title
= strdup (title
);
155 violation
->explanation
= strdup (explanation
);
158 violation
->angle
= angle
;
159 violation
->have_measured
= have_measured
;
160 violation
->measured_value
= measured_value
;
161 violation
->required_value
= required_value
;
162 violation
->object_count
= object_count
;
163 violation
->object_id_list
= object_id_list
;
164 violation
->object_type_list
= object_type_list
;
170 pcb_drc_violation_free (DrcViolationType
*violation
)
172 free (violation
->title
);
173 free (violation
->explanation
);
177 static GString
*drc_dialog_message
;
179 reset_drc_dialog_message(void)
181 if (drc_dialog_message
)
182 g_string_free (drc_dialog_message
, FALSE
);
183 drc_dialog_message
= g_string_new ("");
184 if (gui
->drc_gui
!= NULL
)
186 gui
->drc_gui
->reset_drc_dialog_message ();
190 append_drc_dialog_message(const char *fmt
, ...)
195 new_str
= pcb_vprintf (fmt
, ap
);
196 g_string_append (drc_dialog_message
, new_str
);
201 static void GotoError (void);
204 append_drc_violation (DrcViolationType
*violation
)
206 if (gui
->drc_gui
!= NULL
)
208 gui
->drc_gui
->append_drc_violation (violation
);
212 /* Fallback to formatting the violation message as text */
213 append_drc_dialog_message ("%s\n", violation
->title
);
214 append_drc_dialog_message (_("%m+near %$mD\n"),
215 Settings
.grid_unit
->allow
,
216 violation
->x
, violation
->y
);
220 if (gui
->drc_gui
== NULL
|| gui
->drc_gui
->log_drc_violations
)
222 Message (_("WARNING! Design Rule error - %s\n"), violation
->title
);
223 Message (_("%m+near location %$mD\n"),
224 Settings
.grid_unit
->allow
,
225 violation
->x
, violation
->y
);
229 #define DRC_CONTINUE _("Press Next to continue DRC checking")
230 #define DRC_NEXT _("Next")
231 #define DRC_CANCEL _("Cancel")
234 * \brief Message when asked about continuing DRC checks after next
235 * violation is found.
238 throw_drc_dialog(void)
242 if (gui
->drc_gui
!= NULL
)
244 r
= gui
->drc_gui
->throw_drc_dialog ();
248 /* Fallback to formatting the violation message as text */
249 append_drc_dialog_message (DRC_CONTINUE
);
250 r
= gui
->confirm_dialog (drc_dialog_message
->str
, DRC_CANCEL
, DRC_NEXT
);
251 reset_drc_dialog_message();
257 * \brief Some local types.
259 * The two 'dummy' structs for PVs and Pads are necessary for creating
260 * connection lists which include the element's name.
264 void **Data
; /*!< Pointer to index data. */
265 Cardinal Location
, /*!< Currently used position. */
266 DrawLocation
, Number
, /*!< Number of objects in list. */
270 /* ---------------------------------------------------------------------------
271 * some local identifiers
273 static Coord Bloat
= 0;
274 static void *thing_ptr1
, *thing_ptr2
, *thing_ptr3
;
275 static int thing_type
;
276 static bool User
= false; /*!< User action causing this. */
277 static bool drc
= false; /*!< Whether to stop if finding something not found. */
278 static Cardinal drcerr_count
; /*!< Count of drc errors */
279 static Cardinal TotalP
, TotalV
;
280 static ListType LineList
[MAX_LAYER
], /*!< List of objects to. */
281 PolygonList
[MAX_LAYER
], ArcList
[MAX_LAYER
], PadList
[2], RatList
, PVList
;
283 /* ---------------------------------------------------------------------------
284 * some local prototypes
286 static bool LookupLOConnectionsToLine (LineType
*, Cardinal
, int, bool, bool);
287 static bool LookupLOConnectionsToPad (PadType
*, Cardinal
, int, bool);
288 static bool LookupLOConnectionsToPolygon (PolygonType
*, Cardinal
, int, bool);
289 static bool LookupLOConnectionsToArc (ArcType
*, Cardinal
, int, bool);
290 static bool LookupLOConnectionsToRatEnd (PointType
*, Cardinal
, int);
291 static bool IsRatPointOnLineEnd (PointType
*, LineType
*);
292 static bool ArcArcIntersect (ArcType
*, ArcType
*);
293 static bool PrepareNextLoop (FILE *);
294 static void DrawNewConnections (void);
295 static void DumpList (void);
296 static void LocateError (Coord
*, Coord
*);
297 static void BuildObjectList (int *, long int **, int **);
298 static bool SetThing (int, void *, void *, void *);
299 static bool IsArcInPolygon (ArcType
*, PolygonType
*);
300 static bool IsLineInPolygon (LineType
*, PolygonType
*);
301 static bool IsPadInPolygon (PadType
*, PolygonType
*);
302 static bool IsPolygonInPolygon (PolygonType
*, PolygonType
*);
307 * Some of the 'pad' routines are the same as for lines because the 'pad'
308 * struct starts with a line struct. See global.h for details.
311 LinePadIntersect (LineType
*Line
, PadType
*Pad
)
313 return LineLineIntersect ((Line
), (LineType
*)Pad
);
317 ArcPadIntersect (ArcType
*Arc
, PadType
*Pad
)
319 return LineArcIntersect ((LineType
*) (Pad
), (Arc
));
323 add_object_to_list (ListType
*list
, int type
, void *ptr1
, void *ptr2
, void *ptr3
, int flag
)
325 AnyObjectType
*object
= (AnyObjectType
*)ptr2
;
328 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr3
);
330 SET_FLAG (flag
, object
);
331 LIST_ENTRY (list
, list
->Number
) = object
;
335 if (list
.Number
> list
.Size
)
336 printf ("add_object_to_list overflow! type=%i num=%d size=%d\n", type
, list
.Number
, list
.Size
);
339 if (drc
&& !TEST_FLAG (SELECTEDFLAG
, object
))
340 return (SetThing (type
, ptr1
, ptr2
, ptr3
));
345 ADD_PV_TO_LIST (PinType
*Pin
, int flag
)
347 return add_object_to_list (&PVList
, Pin
->Element
? PIN_TYPE
: VIA_TYPE
,
348 Pin
->Element
? Pin
->Element
: Pin
, Pin
, Pin
, flag
);
352 ADD_PAD_TO_LIST (Cardinal L
, PadType
*Pad
, int flag
)
354 return add_object_to_list (&PadList
[L
], PAD_TYPE
, Pad
->Element
, Pad
, Pad
, flag
);
358 ADD_LINE_TO_LIST (Cardinal L
, LineType
*Ptr
, int flag
)
360 return add_object_to_list (&LineList
[L
], LINE_TYPE
, LAYER_PTR (L
), Ptr
, Ptr
, flag
);
364 ADD_ARC_TO_LIST (Cardinal L
, ArcType
*Ptr
, int flag
)
366 return add_object_to_list (&ArcList
[L
], ARC_TYPE
, LAYER_PTR (L
), Ptr
, Ptr
, flag
);
370 ADD_RAT_TO_LIST (RatType
*Ptr
, int flag
)
372 return add_object_to_list (&RatList
, RATLINE_TYPE
, Ptr
, Ptr
, Ptr
, flag
);
376 ADD_POLYGON_TO_LIST (Cardinal L
, PolygonType
*Ptr
, int flag
)
378 return add_object_to_list (&PolygonList
[L
], POLYGON_TYPE
, LAYER_PTR (L
), Ptr
, Ptr
, flag
);
382 expand_bounds (BoxType
*box_in
)
384 BoxType box_out
= *box_in
;
398 PinLineIntersect (PinType
*PV
, LineType
*Line
)
400 /* IsLineInRectangle already has Bloat factor */
401 return TEST_FLAG (SQUAREFLAG
,
402 PV
) ? IsLineInRectangle (PV
->X
- (PIN_SIZE (PV
) + 1) / 2,
403 PV
->Y
- (PIN_SIZE (PV
) + 1) / 2,
404 PV
->X
+ (PIN_SIZE (PV
) + 1) / 2,
405 PV
->Y
+ (PIN_SIZE (PV
) + 1) / 2,
406 Line
) : IsPointInPad (PV
->X
,
418 SetThing (int type
, void *ptr1
, void *ptr2
, void *ptr3
)
428 BoxBoxIntersection (BoxType
*b1
, BoxType
*b2
)
430 if (b2
->X2
< b1
->X1
|| b2
->X1
> b1
->X2
)
432 if (b2
->Y2
< b1
->Y1
|| b2
->Y1
> b1
->Y2
)
438 PadPadIntersect (PadType
*p1
, PadType
*p2
)
440 return LinePadIntersect ((LineType
*) p1
, p2
);
444 PV_TOUCH_PV (PinType
*PV1
, PinType
*PV2
)
449 t1
= MAX (PV1
->Thickness
/ 2.0 + Bloat
, 0);
450 t2
= MAX (PV2
->Thickness
/ 2.0 + Bloat
, 0);
451 if (IsPointOnPin (PV1
->X
, PV1
->Y
, t1
, PV2
)
452 || IsPointOnPin (PV2
->X
, PV2
->Y
, t2
, PV1
))
454 if (!TEST_FLAG (SQUAREFLAG
, PV1
) || !TEST_FLAG (SQUAREFLAG
, PV2
))
456 /* check for square/square overlap */
461 t2
= PV2
->Thickness
/ 2.0;
466 return BoxBoxIntersection (&b1
, &b2
);
470 * \brief Releases all allocated memory.
473 FreeLayoutLookupMemory (void)
477 for (i
= 0; i
< max_copper_layer
; i
++)
479 free (LineList
[i
].Data
);
480 LineList
[i
].Data
= NULL
;
481 free (ArcList
[i
].Data
);
482 ArcList
[i
].Data
= NULL
;
483 free (PolygonList
[i
].Data
);
484 PolygonList
[i
].Data
= NULL
;
493 FreeComponentLookupMemory (void)
495 free (PadList
[0].Data
);
496 PadList
[0].Data
= NULL
;
497 free (PadList
[1].Data
);
498 PadList
[1].Data
= NULL
;
502 * \brief Allocates memory for component related stacks ...
504 * Initializes index and sorts it by X1 and X2.
507 InitComponentLookup (void)
509 Cardinal NumberOfPads
[2];
512 /* initialize pad data; start by counting the total number
513 * on each of the two possible layers
515 NumberOfPads
[TOP_SIDE
] = NumberOfPads
[BOTTOM_SIDE
] = 0;
516 ALLPAD_LOOP (PCB
->Data
);
518 if (TEST_FLAG (ONSOLDERFLAG
, pad
))
519 NumberOfPads
[BOTTOM_SIDE
]++;
521 NumberOfPads
[TOP_SIDE
]++;
524 for (i
= 0; i
< 2; i
++)
526 /* allocate memory for working list */
527 PadList
[i
].Data
= (void **)calloc (NumberOfPads
[i
], sizeof (PadType
*));
529 /* clear some struct members */
530 PadList
[i
].Location
= 0;
531 PadList
[i
].DrawLocation
= 0;
532 PadList
[i
].Number
= 0;
533 PadList
[i
].Size
= NumberOfPads
[i
];
538 * \brief Allocates memory for layout related stacks ...
540 * Initializes index and sorts it by X1 and X2.
543 InitLayoutLookup (void)
547 /* initialize line arc and polygon data */
548 for (i
= 0; i
< max_copper_layer
; i
++)
550 LayerType
*layer
= LAYER_PTR (i
);
554 /* allocate memory for line pointer lists */
555 LineList
[i
].Data
= (void **)calloc (layer
->LineN
, sizeof (LineType
*));
556 LineList
[i
].Size
= layer
->LineN
;
560 ArcList
[i
].Data
= (void **)calloc (layer
->ArcN
, sizeof (ArcType
*));
561 ArcList
[i
].Size
= layer
->ArcN
;
565 /* allocate memory for polygon list */
568 PolygonList
[i
].Data
= (void **)calloc (layer
->PolygonN
, sizeof (PolygonType
*));
569 PolygonList
[i
].Size
= layer
->PolygonN
;
572 /* clear some struct members */
573 LineList
[i
].Location
= 0;
574 LineList
[i
].DrawLocation
= 0;
575 LineList
[i
].Number
= 0;
576 ArcList
[i
].Location
= 0;
577 ArcList
[i
].DrawLocation
= 0;
578 ArcList
[i
].Number
= 0;
579 PolygonList
[i
].Location
= 0;
580 PolygonList
[i
].DrawLocation
= 0;
581 PolygonList
[i
].Number
= 0;
584 if (PCB
->Data
->pin_tree
)
585 TotalP
= PCB
->Data
->pin_tree
->size
;
588 if (PCB
->Data
->via_tree
)
589 TotalV
= PCB
->Data
->via_tree
->size
;
592 /* allocate memory for 'new PV to check' list and clear struct */
593 PVList
.Data
= (void **)calloc (TotalP
+ TotalV
, sizeof (PinType
*));
594 PVList
.Size
= TotalP
+ TotalV
;
596 PVList
.DrawLocation
= 0;
598 /* Initialize ratline data */
599 RatList
.Data
= (void **)calloc (PCB
->Data
->RatN
, sizeof (RatType
*));
600 RatList
.Size
= PCB
->Data
->RatN
;
601 RatList
.Location
= 0;
602 RatList
.DrawLocation
= 0;
615 LOCtoPVline_callback (const BoxType
* b
, void *cl
)
617 LineType
*line
= (LineType
*) b
;
618 struct pv_info
*i
= (struct pv_info
*) cl
;
620 if (!TEST_FLAG (i
->flag
, line
) && PinLineIntersect (i
->pv
, line
) &&
621 !TEST_FLAG (HOLEFLAG
, i
->pv
))
623 if (ADD_LINE_TO_LIST (i
->layer
, line
, i
->flag
))
630 LOCtoPVarc_callback (const BoxType
* b
, void *cl
)
632 ArcType
*arc
= (ArcType
*) b
;
633 struct pv_info
*i
= (struct pv_info
*) cl
;
635 if (!TEST_FLAG (i
->flag
, arc
) && IS_PV_ON_ARC (i
->pv
, arc
) &&
636 !TEST_FLAG (HOLEFLAG
, i
->pv
))
638 if (ADD_ARC_TO_LIST (i
->layer
, arc
, i
->flag
))
645 LOCtoPVpad_callback (const BoxType
* b
, void *cl
)
647 PadType
*pad
= (PadType
*) b
;
648 struct pv_info
*i
= (struct pv_info
*) cl
;
650 if (!TEST_FLAG (i
->flag
, pad
) && IS_PV_ON_PAD (i
->pv
, pad
) &&
651 !TEST_FLAG (HOLEFLAG
, i
->pv
) &&
652 ADD_PAD_TO_LIST (TEST_FLAG (ONSOLDERFLAG
, pad
) ? BOTTOM_SIDE
:
653 TOP_SIDE
, pad
, i
->flag
))
659 LOCtoPVrat_callback (const BoxType
* b
, void *cl
)
661 RatType
*rat
= (RatType
*) b
;
662 struct pv_info
*i
= (struct pv_info
*) cl
;
664 if (!TEST_FLAG (i
->flag
, rat
) && IS_PV_ON_RAT (i
->pv
, rat
) &&
665 ADD_RAT_TO_LIST (rat
, i
->flag
))
670 LOCtoPVpoly_callback (const BoxType
* b
, void *cl
)
672 PolygonType
*polygon
= (PolygonType
*) b
;
673 struct pv_info
*i
= (struct pv_info
*) cl
;
675 /* if the pin doesn't have a therm and polygon is clearing
676 * then it can't touch due to clearance, so skip the expensive
677 * test. If it does have a therm, you still need to test
678 * because it might not be inside the polygon, or it could
679 * be on an edge such that it doesn't actually touch.
681 if (!TEST_FLAG (i
->flag
, polygon
) && !TEST_FLAG (HOLEFLAG
, i
->pv
) &&
682 (TEST_THERM (i
->layer
, i
->pv
) ||
683 !TEST_FLAG (CLEARPOLYFLAG
,
685 || !i
->pv
->Clearance
))
687 double wide
= MAX (0.5 * i
->pv
->Thickness
+ Bloat
, 0);
688 if (TEST_FLAG (SQUAREFLAG
, i
->pv
))
690 Coord x1
= i
->pv
->X
- (i
->pv
->Thickness
+ 1 + Bloat
) / 2;
691 Coord x2
= i
->pv
->X
+ (i
->pv
->Thickness
+ 1 + Bloat
) / 2;
692 Coord y1
= i
->pv
->Y
- (i
->pv
->Thickness
+ 1 + Bloat
) / 2;
693 Coord y2
= i
->pv
->Y
+ (i
->pv
->Thickness
+ 1 + Bloat
) / 2;
694 if (IsRectangleInPolygon (x1
, y1
, x2
, y2
, polygon
)
695 && ADD_POLYGON_TO_LIST (i
->layer
, polygon
, i
->flag
))
698 else if (TEST_FLAG (OCTAGONFLAG
, i
->pv
))
700 POLYAREA
*oct
= OctagonPoly (i
->pv
->X
, i
->pv
->Y
, i
->pv
->Thickness
/ 2);
701 if (isects (oct
, polygon
, true)
702 && ADD_POLYGON_TO_LIST (i
->layer
, polygon
, i
->flag
))
705 else if (IsPointInPolygon (i
->pv
->X
, i
->pv
->Y
, wide
,
707 && ADD_POLYGON_TO_LIST (i
->layer
, polygon
, i
->flag
))
714 * \brief Checks if a PV is connected to LOs, if it is, the LO is added
715 * to the appropriate list and the 'used' flag is set.
718 LookupLOConnectionsToPVList (int flag
, bool AndRats
)
725 /* loop over all PVs currently on list */
726 while (PVList
.Location
< PVList
.Number
)
730 /* get pointer to data */
731 info
.pv
= PVLIST_ENTRY (PVList
.Location
);
732 search_box
= expand_bounds (&info
.pv
->BoundingBox
);
735 if (setjmp (info
.env
) == 0)
736 r_search (PCB
->Data
->pad_tree
, &search_box
, NULL
,
737 LOCtoPVpad_callback
, &info
);
741 /* now all lines, arcs and polygons of the several layers */
742 for (layer_no
= 0; layer_no
< max_copper_layer
; layer_no
++)
744 LayerType
*layer
= LAYER_PTR (layer_no
);
749 info
.layer
= layer_no
;
751 /* add touching lines */
752 if (setjmp (info
.env
) == 0)
753 r_search (layer
->line_tree
, &search_box
,
754 NULL
, LOCtoPVline_callback
, &info
);
757 /* add touching arcs */
758 if (setjmp (info
.env
) == 0)
759 r_search (layer
->arc_tree
, &search_box
,
760 NULL
, LOCtoPVarc_callback
, &info
);
763 /* check all polygons */
764 if (setjmp (info
.env
) == 0)
765 r_search (layer
->polygon_tree
, &search_box
,
766 NULL
, LOCtoPVpoly_callback
, &info
);
770 /* Check for rat-lines that may intersect the PV */
773 if (setjmp (info
.env
) == 0)
774 r_search (PCB
->Data
->rat_tree
, &search_box
, NULL
,
775 LOCtoPVrat_callback
, &info
);
785 * \brief Find all connections between LO at the current list position
789 LookupLOConnectionsToLOList (int flag
, bool AndRats
)
792 Cardinal i
, group
, layer
, ratposition
,
793 lineposition
[MAX_LAYER
],
794 polyposition
[MAX_LAYER
], arcposition
[MAX_LAYER
], padposition
[2];
796 /* copy the current LO list positions; the original data is changed
797 * by 'LookupPVConnectionsToLOList()' which has to check the same
798 * list entries plus the new ones
800 for (i
= 0; i
< max_copper_layer
; i
++)
802 lineposition
[i
] = LineList
[i
].Location
;
803 polyposition
[i
] = PolygonList
[i
].Location
;
804 arcposition
[i
] = ArcList
[i
].Location
;
806 for (i
= 0; i
< 2; i
++)
807 padposition
[i
] = PadList
[i
].Location
;
808 ratposition
= RatList
.Location
;
810 /* loop over all new LOs in the list; recurse until no
811 * more new connections in the layergroup were found
819 position
= &ratposition
;
820 for (; *position
< RatList
.Number
; (*position
)++)
822 group
= RATLIST_ENTRY (*position
)->group1
;
823 if (LookupLOConnectionsToRatEnd
824 (&(RATLIST_ENTRY (*position
)->Point1
), group
, flag
))
826 group
= RATLIST_ENTRY (*position
)->group2
;
827 if (LookupLOConnectionsToRatEnd
828 (&(RATLIST_ENTRY (*position
)->Point2
), group
, flag
))
832 /* loop over all layergroups */
833 for (group
= 0; group
< max_group
; group
++)
837 for (entry
= 0; entry
< PCB
->LayerGroups
.Number
[group
]; entry
++)
839 layer
= PCB
->LayerGroups
.Entries
[group
][entry
];
841 /* be aware that the layer number equal max_copper_layer
842 * and max_copper_layer+1 have a special meaning for pads
844 if (layer
< max_copper_layer
)
846 /* try all new lines */
847 position
= &lineposition
[layer
];
848 for (; *position
< LineList
[layer
].Number
; (*position
)++)
849 if (LookupLOConnectionsToLine
850 (LINELIST_ENTRY (layer
, *position
), group
, flag
, true, AndRats
))
853 /* try all new arcs */
854 position
= &arcposition
[layer
];
855 for (; *position
< ArcList
[layer
].Number
; (*position
)++)
856 if (LookupLOConnectionsToArc
857 (ARCLIST_ENTRY (layer
, *position
), group
, flag
, AndRats
))
860 /* try all new polygons */
861 position
= &polyposition
[layer
];
862 for (; *position
< PolygonList
[layer
].Number
; (*position
)++)
863 if (LookupLOConnectionsToPolygon
864 (POLYGONLIST_ENTRY (layer
, *position
), group
, flag
, AndRats
))
869 /* try all new pads */
870 layer
-= max_copper_layer
;
873 Message (_("bad layer number %d max_copper_layer=%d in find.c\n"),
874 layer
, max_copper_layer
);
877 position
= &padposition
[layer
];
878 for (; *position
< PadList
[layer
].Number
; (*position
)++)
879 if (LookupLOConnectionsToPad
880 (PADLIST_ENTRY (layer
, *position
), group
, flag
, AndRats
))
886 /* check if all lists are done; Later for-loops
887 * may have changed the prior lists
889 done
= !AndRats
|| ratposition
>= RatList
.Number
;
890 done
= done
&& padposition
[0] >= PadList
[0].Number
&&
891 padposition
[1] >= PadList
[1].Number
;
892 for (layer
= 0; layer
< max_copper_layer
; layer
++)
894 lineposition
[layer
] >= LineList
[layer
].Number
&&
895 arcposition
[layer
] >= ArcList
[layer
].Number
&&
896 polyposition
[layer
] >= PolygonList
[layer
].Number
;
903 pv_pv_callback (const BoxType
* b
, void *cl
)
905 PinType
*pin
= (PinType
*) b
;
906 struct pv_info
*i
= (struct pv_info
*) cl
;
908 if (!TEST_FLAG (i
->flag
, pin
) && PV_TOUCH_PV (i
->pv
, pin
))
910 if (TEST_FLAG (HOLEFLAG
, pin
) || TEST_FLAG (HOLEFLAG
, i
->pv
))
912 SET_FLAG (WARNFLAG
, pin
);
913 Settings
.RatWarn
= true;
915 Message (_("WARNING: Hole too close to pin.\n"));
917 Message (_("WARNING: Hole too close to via.\n"));
919 else if (ADD_PV_TO_LIST (pin
, i
->flag
))
926 * \brief Searches for new PVs that are connected to PVs on the list.
929 LookupPVConnectionsToPVList (int flag
)
936 /* loop over all PVs on list */
937 save_place
= PVList
.Location
;
938 while (PVList
.Location
< PVList
.Number
)
942 /* get pointer to data */
943 info
.pv
= PVLIST_ENTRY (PVList
.Location
);
944 search_box
= expand_bounds ((BoxType
*)info
.pv
);
946 if (setjmp (info
.env
) == 0)
947 r_search (PCB
->Data
->via_tree
, &search_box
, NULL
,
948 pv_pv_callback
, &info
);
951 if (setjmp (info
.env
) == 0)
952 r_search (PCB
->Data
->pin_tree
, &search_box
, NULL
,
953 pv_pv_callback
, &info
);
958 PVList
.Location
= save_place
;
968 PolygonType
*polygon
;
975 pv_line_callback (const BoxType
* b
, void *cl
)
977 PinType
*pv
= (PinType
*) b
;
978 struct lo_info
*i
= (struct lo_info
*) cl
;
980 if (!TEST_FLAG (i
->flag
, pv
) && PinLineIntersect (pv
, i
->line
))
982 if (TEST_FLAG (HOLEFLAG
, pv
))
984 SET_FLAG (WARNFLAG
, pv
);
985 Settings
.RatWarn
= true;
986 Message (_("WARNING: Hole too close to line.\n"));
988 else if (ADD_PV_TO_LIST (pv
, i
->flag
))
995 pv_pad_callback (const BoxType
* b
, void *cl
)
997 PinType
*pv
= (PinType
*) b
;
998 struct lo_info
*i
= (struct lo_info
*) cl
;
1000 if (!TEST_FLAG (i
->flag
, pv
) && IS_PV_ON_PAD (pv
, i
->pad
))
1002 if (TEST_FLAG (HOLEFLAG
, pv
))
1004 SET_FLAG (WARNFLAG
, pv
);
1005 Settings
.RatWarn
= true;
1006 Message (_("WARNING: Hole too close to pad.\n"));
1008 else if (ADD_PV_TO_LIST (pv
, i
->flag
))
1009 longjmp (i
->env
, 1);
1015 pv_arc_callback (const BoxType
* b
, void *cl
)
1017 PinType
*pv
= (PinType
*) b
;
1018 struct lo_info
*i
= (struct lo_info
*) cl
;
1020 if (!TEST_FLAG (i
->flag
, pv
) && IS_PV_ON_ARC (pv
, i
->arc
))
1022 if (TEST_FLAG (HOLEFLAG
, pv
))
1024 SET_FLAG (WARNFLAG
, pv
);
1025 Settings
.RatWarn
= true;
1026 Message (_("WARNING: Hole touches arc.\n"));
1028 else if (ADD_PV_TO_LIST (pv
, i
->flag
))
1029 longjmp (i
->env
, 1);
1035 pv_poly_callback (const BoxType
* b
, void *cl
)
1037 PinType
*pv
= (PinType
*) b
;
1038 struct lo_info
*i
= (struct lo_info
*) cl
;
1040 /* note that holes in polygons are ok, so they don't generate warnings. */
1041 if (!TEST_FLAG (i
->flag
, pv
) && !TEST_FLAG (HOLEFLAG
, pv
) &&
1042 (TEST_THERM (i
->layer
, pv
) ||
1043 !TEST_FLAG (CLEARPOLYFLAG
, i
->polygon
) ||
1046 if (TEST_FLAG (SQUAREFLAG
, pv
))
1048 Coord x1
, x2
, y1
, y2
;
1049 x1
= pv
->X
- (PIN_SIZE (pv
) + 1 + Bloat
) / 2;
1050 x2
= pv
->X
+ (PIN_SIZE (pv
) + 1 + Bloat
) / 2;
1051 y1
= pv
->Y
- (PIN_SIZE (pv
) + 1 + Bloat
) / 2;
1052 y2
= pv
->Y
+ (PIN_SIZE (pv
) + 1 + Bloat
) / 2;
1053 if (IsRectangleInPolygon (x1
, y1
, x2
, y2
, i
->polygon
)
1054 && ADD_PV_TO_LIST (pv
, i
->flag
))
1055 longjmp (i
->env
, 1);
1057 else if (TEST_FLAG (OCTAGONFLAG
, pv
))
1059 POLYAREA
*oct
= OctagonPoly (pv
->X
, pv
->Y
, PIN_SIZE (pv
) / 2);
1060 if (isects (oct
, i
->polygon
, true) && ADD_PV_TO_LIST (pv
, i
->flag
))
1061 longjmp (i
->env
, 1);
1065 if (IsPointInPolygon
1066 (pv
->X
, pv
->Y
, PIN_SIZE (pv
) * 0.5 + Bloat
, i
->polygon
)
1067 && ADD_PV_TO_LIST (pv
, i
->flag
))
1068 longjmp (i
->env
, 1);
1075 pv_rat_callback (const BoxType
* b
, void *cl
)
1077 PinType
*pv
= (PinType
*) b
;
1078 struct lo_info
*i
= (struct lo_info
*) cl
;
1080 /* rats can't cause DRC so there is no early exit */
1081 if (!TEST_FLAG (i
->flag
, pv
) && IS_PV_ON_RAT (pv
, i
->rat
))
1082 ADD_PV_TO_LIST (pv
, i
->flag
);
1087 * \brief Searches for new PVs that are connected to NEW LOs on the list.
1089 * This routine updates the position counter of the lists too.
1092 LookupPVConnectionsToLOList (int flag
, bool AndRats
)
1095 struct lo_info info
;
1099 /* loop over all layers */
1100 for (layer_no
= 0; layer_no
< max_copper_layer
; layer_no
++)
1102 LayerType
*layer
= LAYER_PTR (layer_no
);
1106 /* do nothing if there are no PV's */
1107 if (TotalP
+ TotalV
== 0)
1109 LineList
[layer_no
].Location
= LineList
[layer_no
].Number
;
1110 ArcList
[layer_no
].Location
= ArcList
[layer_no
].Number
;
1111 PolygonList
[layer_no
].Location
= PolygonList
[layer_no
].Number
;
1115 /* check all lines */
1116 while (LineList
[layer_no
].Location
< LineList
[layer_no
].Number
)
1120 info
.line
= LINELIST_ENTRY (layer_no
, LineList
[layer_no
].Location
);
1121 search_box
= expand_bounds ((BoxType
*)info
.line
);
1123 if (setjmp (info
.env
) == 0)
1124 r_search (PCB
->Data
->via_tree
, &search_box
, NULL
,
1125 pv_line_callback
, &info
);
1128 if (setjmp (info
.env
) == 0)
1129 r_search (PCB
->Data
->pin_tree
, &search_box
, NULL
,
1130 pv_line_callback
, &info
);
1133 LineList
[layer_no
].Location
++;
1136 /* check all arcs */
1137 while (ArcList
[layer_no
].Location
< ArcList
[layer_no
].Number
)
1141 info
.arc
= ARCLIST_ENTRY (layer_no
, ArcList
[layer_no
].Location
);
1142 search_box
= expand_bounds ((BoxType
*)info
.arc
);
1144 if (setjmp (info
.env
) == 0)
1145 r_search (PCB
->Data
->via_tree
, &search_box
, NULL
,
1146 pv_arc_callback
, &info
);
1149 if (setjmp (info
.env
) == 0)
1150 r_search (PCB
->Data
->pin_tree
, &search_box
, NULL
,
1151 pv_arc_callback
, &info
);
1154 ArcList
[layer_no
].Location
++;
1157 /* now all polygons */
1158 info
.layer
= layer_no
;
1159 while (PolygonList
[layer_no
].Location
< PolygonList
[layer_no
].Number
)
1163 info
.polygon
= POLYGONLIST_ENTRY (layer_no
, PolygonList
[layer_no
].Location
);
1164 search_box
= expand_bounds ((BoxType
*)info
.polygon
);
1166 if (setjmp (info
.env
) == 0)
1167 r_search (PCB
->Data
->via_tree
, &search_box
, NULL
,
1168 pv_poly_callback
, &info
);
1171 if (setjmp (info
.env
) == 0)
1172 r_search (PCB
->Data
->pin_tree
, &search_box
, NULL
,
1173 pv_poly_callback
, &info
);
1176 PolygonList
[layer_no
].Location
++;
1180 /* loop over all pad-layers */
1181 for (layer_no
= 0; layer_no
< 2; layer_no
++)
1183 /* do nothing if there are no PV's */
1184 if (TotalP
+ TotalV
== 0)
1186 PadList
[layer_no
].Location
= PadList
[layer_no
].Number
;
1190 /* check all pads; for a detailed description see
1191 * the handling of lines in this subroutine
1193 while (PadList
[layer_no
].Location
< PadList
[layer_no
].Number
)
1197 info
.pad
= PADLIST_ENTRY (layer_no
, PadList
[layer_no
].Location
);
1198 search_box
= expand_bounds ((BoxType
*)info
.pad
);
1200 if (setjmp (info
.env
) == 0)
1201 r_search (PCB
->Data
->via_tree
, &search_box
, NULL
,
1202 pv_pad_callback
, &info
);
1205 if (setjmp (info
.env
) == 0)
1206 r_search (PCB
->Data
->pin_tree
, &search_box
, NULL
,
1207 pv_pad_callback
, &info
);
1210 PadList
[layer_no
].Location
++;
1214 /* do nothing if there are no PV's */
1215 if (TotalP
+ TotalV
== 0)
1216 RatList
.Location
= RatList
.Number
;
1218 /* check all rat-lines */
1221 while (RatList
.Location
< RatList
.Number
)
1223 info
.rat
= RATLIST_ENTRY (RatList
.Location
);
1224 r_search_pt (PCB
->Data
->via_tree
, & info
.rat
->Point1
, 1, NULL
,
1225 pv_rat_callback
, &info
);
1226 r_search_pt (PCB
->Data
->via_tree
, & info
.rat
->Point2
, 1, NULL
,
1227 pv_rat_callback
, &info
);
1228 r_search_pt (PCB
->Data
->pin_tree
, & info
.rat
->Point1
, 1, NULL
,
1229 pv_rat_callback
, &info
);
1230 r_search_pt (PCB
->Data
->pin_tree
, & info
.rat
->Point2
, 1, NULL
,
1231 pv_rat_callback
, &info
);
1240 * \brief Reduce arc start angle and delta to 0..360.
1243 normalize_angles (Angle
*sa
, Angle
*d
)
1250 if (*d
> 360) /* full circle */
1252 *sa
= NormalizeAngle (*sa
);
1256 radius_crosses_arc (double x
, double y
, ArcType
*arc
)
1258 double alpha
= atan2 (y
- arc
->Y
, -x
+ arc
->X
) * RAD_TO_DEG
;
1259 Angle sa
= arc
->StartAngle
, d
= arc
->Delta
;
1261 normalize_angles (&sa
, &d
);
1265 return (sa
+ d
) >= alpha
;
1266 return (sa
+ d
- 360) >= alpha
;
1270 get_arc_ends (Coord
*box
, ArcType
*arc
)
1272 box
[0] = arc
->X
- arc
->Width
* cos (M180
* arc
->StartAngle
);
1273 box
[1] = arc
->Y
+ arc
->Height
* sin (M180
* arc
->StartAngle
);
1274 box
[2] = arc
->X
- arc
->Width
* cos (M180
* (arc
->StartAngle
+ arc
->Delta
));
1275 box
[3] = arc
->Y
+ arc
->Height
* sin (M180
* (arc
->StartAngle
+ arc
->Delta
));
1279 * \brief Check if two arcs intersect.
1281 * First we check for circle intersections,
1282 * then find the actual points of intersection
1283 * and test them to see if they are on arcs.
1285 * Consider a, the distance from the center of arc 1
1286 * to the point perpendicular to the intersecting points.
1288 * \ta = (r1^2 - r2^2 + l^2)/(2l)
1290 * The perpendicular distance to the point of intersection
1293 * \td = sqrt(r1^2 - a^2)
1295 * The points of intersection would then be:
1297 * \tx = X1 + a/l dx +- d/l dy
1299 * \ty = Y1 + a/l dy -+ d/l dx
1301 * Where dx = X2 - X1 and dy = Y2 - Y1.
1304 ArcArcIntersect (ArcType
*Arc1
, ArcType
*Arc2
)
1306 double x
, y
, dx
, dy
, r1
, r2
, a
, d
, l
, t
, t1
, t2
, dl
;
1310 t
= 0.5 * Arc1
->Thickness
+ Bloat
;
1311 t2
= 0.5 * Arc2
->Thickness
;
1315 if (t
< 0 || t1
< 0)
1318 /* try the end points first */
1319 get_arc_ends (&box
[0], Arc1
);
1320 get_arc_ends (&box
[4], Arc2
);
1321 if (IsPointOnArc (box
[0], box
[1], t
, Arc2
)
1322 || IsPointOnArc (box
[2], box
[3], t
, Arc2
)
1323 || IsPointOnArc (box
[4], box
[5], t
, Arc1
)
1324 || IsPointOnArc (box
[6], box
[7], t
, Arc1
))
1327 pdx
= Arc2
->X
- Arc1
->X
;
1328 pdy
= Arc2
->Y
- Arc1
->Y
;
1329 dl
= Distance (Arc1
->X
, Arc1
->Y
, Arc2
->X
, Arc2
->Y
);
1330 /* concentric arcs, simpler intersection conditions */
1333 if ((Arc1
->Width
- t
>= Arc2
->Width
- t2
1334 && Arc1
->Width
- t
<= Arc2
->Width
+ t2
)
1335 || (Arc1
->Width
+ t
>= Arc2
->Width
- t2
1336 && Arc1
->Width
+ t
<= Arc2
->Width
+ t2
))
1338 Angle sa1
= Arc1
->StartAngle
, d1
= Arc1
->Delta
;
1339 Angle sa2
= Arc2
->StartAngle
, d2
= Arc2
->Delta
;
1340 /* NB the endpoints have already been checked,
1341 so we just compare the angles */
1343 normalize_angles (&sa1
, &d1
);
1344 normalize_angles (&sa2
, &d2
);
1345 /* sa1 == sa2 was caught when checking endpoints */
1347 if (sa1
< sa2
+ d2
|| sa1
+ d1
- 360 > sa2
)
1350 if (sa2
< sa1
+ d1
|| sa2
+ d2
- 360 > sa1
)
1357 /* arcs centerlines are too far or too near */
1358 if (dl
> r1
+ r2
|| dl
+ r1
< r2
|| dl
+ r2
< r1
)
1360 /* check the nearest to the other arc's center point */
1363 if (dl
+ r1
< r2
) /* Arc1 inside Arc2 */
1369 if (radius_crosses_arc (Arc1
->X
+ dx
, Arc1
->Y
+ dy
, Arc1
)
1370 && IsPointOnArc (Arc1
->X
+ dx
, Arc1
->Y
+ dy
, t
, Arc2
))
1373 dx
= - pdx
* r2
/ dl
;
1374 dy
= - pdy
* r2
/ dl
;
1375 if (dl
+ r2
< r1
) /* Arc2 inside Arc1 */
1381 if (radius_crosses_arc (Arc2
->X
+ dx
, Arc2
->Y
+ dy
, Arc2
)
1382 && IsPointOnArc (Arc2
->X
+ dx
, Arc2
->Y
+ dy
, t1
, Arc1
))
1390 a
= 0.5 * (r1
- r2
+ l
) / l
;
1393 /* the circles are too far apart to touch or probably just touch:
1394 check the nearest point */
1399 x
= Arc1
->X
+ a
* pdx
;
1400 y
= Arc1
->Y
+ a
* pdy
;
1403 if (radius_crosses_arc (x
+ dy
, y
- dx
, Arc1
)
1404 && IsPointOnArc (x
+ dy
, y
- dx
, t
, Arc2
))
1406 if (radius_crosses_arc (x
+ dy
, y
- dx
, Arc2
)
1407 && IsPointOnArc (x
+ dy
, y
- dx
, t1
, Arc1
))
1410 if (radius_crosses_arc (x
- dy
, y
+ dx
, Arc1
)
1411 && IsPointOnArc (x
- dy
, y
+ dx
, t
, Arc2
))
1413 if (radius_crosses_arc (x
- dy
, y
+ dx
, Arc2
)
1414 && IsPointOnArc (x
- dy
, y
+ dx
, t1
, Arc1
))
1420 * \brief Tests if point is same as line end point.
1423 IsRatPointOnLineEnd (PointType
*Point
, LineType
*Line
)
1425 if ((Point
->X
== Line
->Point1
.X
1426 && Point
->Y
== Line
->Point1
.Y
)
1427 || (Point
->X
== Line
->Point2
.X
&& Point
->Y
== Line
->Point2
.Y
))
1433 * \brief Writes vertices of a squared line.
1436 form_slanted_rectangle (PointType p
[4], LineType
*l
)
1438 double dwx
= 0, dwy
= 0;
1439 if (l
->Point1
.Y
== l
->Point2
.Y
)
1440 dwx
= l
->Thickness
/ 2.0;
1441 else if (l
->Point1
.X
== l
->Point2
.X
)
1442 dwy
= l
->Thickness
/ 2.0;
1445 Coord dX
= l
->Point2
.X
- l
->Point1
.X
;
1446 Coord dY
= l
->Point2
.Y
- l
->Point1
.Y
;
1447 double r
= Distance (l
->Point1
.X
, l
->Point1
.Y
, l
->Point2
.X
, l
->Point2
.Y
);
1448 dwx
= l
->Thickness
/ 2.0 / r
* dX
;
1449 dwy
= l
->Thickness
/ 2.0 / r
* dY
;
1451 p
[0].X
= l
->Point1
.X
- dwx
+ dwy
; p
[0].Y
= l
->Point1
.Y
- dwy
- dwx
;
1452 p
[1].X
= l
->Point1
.X
- dwx
- dwy
; p
[1].Y
= l
->Point1
.Y
- dwy
+ dwx
;
1453 p
[2].X
= l
->Point2
.X
+ dwx
- dwy
; p
[2].Y
= l
->Point2
.Y
+ dwy
+ dwx
;
1454 p
[3].X
= l
->Point2
.X
+ dwx
+ dwy
; p
[3].Y
= l
->Point2
.Y
+ dwy
- dwx
;
1458 * \brief Checks if two lines intersect.
1463 * Let A,B,C,D be 2-space position vectors.
1465 * Then the directed line segments AB & CD are given by:
1467 * AB=A+r(B-A), r in [0,1]
1469 * CD=C+s(D-C), s in [0,1]
1471 * If AB & CD intersect, then
1473 * A+r(B-A)=C+s(D-C), or
1475 * XA+r(XB-XA)=XC+s*(XD-XC)
1477 * YA+r(YB-YA)=YC+s(YD-YC) for some r,s in [0,1]
1479 * Solving the above for r and s yields
1481 * (YA-YC)(XD-XC)-(XA-XC)(YD-YC)
1482 * r = ----------------------------- (eqn 1)
1483 * (XB-XA)(YD-YC)-(YB-YA)(XD-XC)
1485 * (YA-YC)(XB-XA)-(XA-XC)(YB-YA)
1486 * s = ----------------------------- (eqn 2)
1487 * (XB-XA)(YD-YC)-(YB-YA)(XD-XC)
1489 * Let I be the position vector of the intersection point, then:
1497 * By examining the values of r & s, you can also determine some
1498 * other limiting conditions:
1500 * If 0<=r<=1 & 0<=s<=1, intersection exists
1502 * r<0 or r>1 or s<0 or s>1 line segments do not intersect
1504 * If the denominator in eqn 1 is zero, AB & CD are parallel
1506 * If the numerator in eqn 1 is also zero, AB & CD are coincident
1508 * If the intersection point of the 2 lines are needed (lines in this
1509 * context mean infinite lines) regardless whether the two line
1510 * segments intersect, then
1512 * If r>1, I is located on extension of AB
1513 * If r<0, I is located on extension of BA
1514 * If s>1, I is located on extension of CD
1515 * If s<0, I is located on extension of DC
1517 * Also note that the denominators of eqn 1 & 2 are identical.
1521 LineLineIntersect (LineType
*Line1
, LineType
*Line2
)
1524 double line1_dx
, line1_dy
, line2_dx
, line2_dy
,
1525 point1_dx
, point1_dy
;
1526 if (TEST_FLAG (SQUAREFLAG
, Line1
))/* pretty reckless recursion */
1529 form_slanted_rectangle (p
, Line1
);
1530 return IsLineInQuadrangle (p
, Line2
);
1532 /* here come only round Line1 because IsLineInQuadrangle()
1533 calls LineLineIntersect() with first argument rounded*/
1534 if (TEST_FLAG (SQUAREFLAG
, Line2
))
1537 form_slanted_rectangle (p
, Line2
);
1538 return IsLineInQuadrangle (p
, Line1
);
1540 /* now all lines are round */
1542 /* Check endpoints: this provides a quick exit, catches
1543 * cases where the "real" lines don't intersect but the
1544 * thick lines touch, and ensures that the dx/dy business
1545 * below does not cause a divide-by-zero. */
1546 if (IsPointInPad (Line2
->Point1
.X
, Line2
->Point1
.Y
,
1547 MAX (Line2
->Thickness
/ 2 + Bloat
, 0),
1549 || IsPointInPad (Line2
->Point2
.X
, Line2
->Point2
.Y
,
1550 MAX (Line2
->Thickness
/ 2 + Bloat
, 0),
1552 || IsPointInPad (Line1
->Point1
.X
, Line1
->Point1
.Y
,
1553 MAX (Line1
->Thickness
/ 2 + Bloat
, 0),
1555 || IsPointInPad (Line1
->Point2
.X
, Line1
->Point2
.Y
,
1556 MAX (Line1
->Thickness
/ 2 + Bloat
, 0),
1560 /* setup some constants */
1561 line1_dx
= Line1
->Point2
.X
- Line1
->Point1
.X
;
1562 line1_dy
= Line1
->Point2
.Y
- Line1
->Point1
.Y
;
1563 line2_dx
= Line2
->Point2
.X
- Line2
->Point1
.X
;
1564 line2_dy
= Line2
->Point2
.Y
- Line2
->Point1
.Y
;
1565 point1_dx
= Line1
->Point1
.X
- Line2
->Point1
.X
;
1566 point1_dy
= Line1
->Point1
.Y
- Line2
->Point1
.Y
;
1568 /* If either line is a point, we have failed already, since the
1569 * endpoint check above will have caught an "intersection". */
1570 if ((line1_dx
== 0 && line1_dy
== 0)
1571 || (line2_dx
== 0 && line2_dy
== 0))
1574 /* set s to cross product of Line1 and the line
1575 * Line1.Point1--Line2.Point1 (as vectors) */
1576 s
= point1_dy
* line1_dx
- point1_dx
* line1_dy
;
1578 /* set r to cross product of both lines (as vectors) */
1579 r
= line1_dx
* line2_dy
- line1_dy
* line2_dx
;
1581 /* No cross product means parallel lines, or maybe Line2 is
1582 * zero-length. In either case, since we did a bounding-box
1583 * check before getting here, the above IsPointInPad() checks
1584 * will have caught any intersections. */
1589 r
= (point1_dy
* line2_dx
- point1_dx
* line2_dy
) / r
;
1591 /* intersection is at least on AB */
1592 if (r
>= 0.0 && r
<= 1.0)
1593 return (s
>= 0.0 && s
<= 1.0);
1595 /* intersection is at least on CD */
1596 /* [removed this case since it always returns false --asp] */
1601 * \brief Check for line intersection with an arc.
1603 * Mostly this is like the circle/line intersection
1604 * found in IsPointOnLine (search.c) see the detailed
1605 * discussion for the basics there.
1607 * Since this is only an arc, not a full circle we need
1608 * to find the actual points of intersection with the
1609 * circle, and see if they are on the arc.
1611 * To do this, we translate along the line from the point Q
1612 * plus or minus a distance delta = sqrt(Radius^2 - d^2)
1613 * but it's handy to normalize with respect to l, the line
1614 * length so a single projection is done (e.g. we don't first
1618 * The projection is now of the form:
1620 * Px = X1 + (r +- r2)(X2 - X1)
1621 * Py = Y1 + (r +- r2)(Y2 - Y1)
1624 * Where r2 sqrt(Radius^2 l^2 - d^2)/l^2
1625 * note that this is the variable d, not the symbol d described in
1626 * IsPointOnLine (variable d = symbol d * l).
1628 * The end points are hell so they are checked individually.
1631 LineArcIntersect (LineType
*Line
, ArcType
*Arc
)
1633 double dx
, dy
, dx1
, dy1
, l
, d
, r
, r2
, Radius
;
1636 dx
= Line
->Point2
.X
- Line
->Point1
.X
;
1637 dy
= Line
->Point2
.Y
- Line
->Point1
.Y
;
1638 dx1
= Line
->Point1
.X
- Arc
->X
;
1639 dy1
= Line
->Point1
.Y
- Arc
->Y
;
1640 l
= dx
* dx
+ dy
* dy
;
1641 d
= dx
* dy1
- dy
* dx1
;
1644 /* use the larger diameter circle first */
1646 Arc
->Width
+ MAX (0.5 * (Arc
->Thickness
+ Line
->Thickness
) + Bloat
, 0.0);
1648 r2
= Radius
* l
- d
;
1649 /* projection doesn't even intersect circle when r2 < 0 */
1652 /* check the ends of the line in case the projected point */
1653 /* of intersection is beyond the line end */
1655 (Line
->Point1
.X
, Line
->Point1
.Y
,
1656 MAX (0.5 * Line
->Thickness
+ Bloat
, 0.0), Arc
))
1659 (Line
->Point2
.X
, Line
->Point2
.Y
,
1660 MAX (0.5 * Line
->Thickness
+ Bloat
, 0.0), Arc
))
1665 Radius
= -(dx
* dx1
+ dy
* dy1
);
1666 r
= (Radius
+ r2
) / l
;
1667 if (r
>= 0 && r
<= 1
1668 && IsPointOnArc (Line
->Point1
.X
+ r
* dx
,
1669 Line
->Point1
.Y
+ r
* dy
,
1670 MAX (0.5 * Line
->Thickness
+ Bloat
, 0.0), Arc
))
1672 r
= (Radius
- r2
) / l
;
1673 if (r
>= 0 && r
<= 1
1674 && IsPointOnArc (Line
->Point1
.X
+ r
* dx
,
1675 Line
->Point1
.Y
+ r
* dy
,
1676 MAX (0.5 * Line
->Thickness
+ Bloat
, 0.0), Arc
))
1678 /* check arc end points */
1679 box
= GetArcEnds (Arc
);
1680 if (IsPointInPad (box
->X1
, box
->Y1
, Arc
->Thickness
* 0.5 + Bloat
, (PadType
*)Line
))
1682 if (IsPointInPad (box
->X2
, box
->Y2
, Arc
->Thickness
* 0.5 + Bloat
, (PadType
*)Line
))
1688 LOCtoArcLine_callback (const BoxType
* b
, void *cl
)
1690 LineType
*line
= (LineType
*) b
;
1691 struct lo_info
*i
= (struct lo_info
*) cl
;
1693 if (!TEST_FLAG (i
->flag
, line
) && LineArcIntersect (line
, i
->arc
))
1695 if (ADD_LINE_TO_LIST (i
->layer
, line
, i
->flag
))
1696 longjmp (i
->env
, 1);
1702 LOCtoArcArc_callback (const BoxType
* b
, void *cl
)
1704 ArcType
*arc
= (ArcType
*) b
;
1705 struct lo_info
*i
= (struct lo_info
*) cl
;
1707 if (!arc
->Thickness
)
1709 if (!TEST_FLAG (i
->flag
, arc
) && ArcArcIntersect (i
->arc
, arc
))
1711 if (ADD_ARC_TO_LIST (i
->layer
, arc
, i
->flag
))
1712 longjmp (i
->env
, 1);
1718 LOCtoArcPad_callback (const BoxType
* b
, void *cl
)
1720 PadType
*pad
= (PadType
*) b
;
1721 struct lo_info
*i
= (struct lo_info
*) cl
;
1723 if (!TEST_FLAG (i
->flag
, pad
) && i
->layer
==
1724 (TEST_FLAG (ONSOLDERFLAG
, pad
) ? BOTTOM_SIDE
: TOP_SIDE
)
1725 && ArcPadIntersect (i
->arc
, pad
) && ADD_PAD_TO_LIST (i
->layer
, pad
, i
->flag
))
1726 longjmp (i
->env
, 1);
1731 * \brief Searches all LOs that are connected to the given arc on the
1734 * All found connections are added to the list.
1736 * The notation that is used is:\n
1737 * Xij means Xj at arc i.
1740 LookupLOConnectionsToArc (ArcType
*Arc
, Cardinal LayerGroup
, int flag
, bool AndRats
)
1743 struct lo_info info
;
1748 search_box
= expand_bounds ((BoxType
*)info
.arc
);
1750 /* loop over all layers of the group */
1751 for (entry
= 0; entry
< PCB
->LayerGroups
.Number
[LayerGroup
]; entry
++)
1757 layer_no
= PCB
->LayerGroups
.Entries
[LayerGroup
][entry
];
1758 layer
= LAYER_PTR (layer_no
);
1760 /* handle normal layers */
1761 if (layer_no
< max_copper_layer
)
1763 info
.layer
= layer_no
;
1765 if (setjmp (info
.env
) == 0)
1766 r_search (layer
->line_tree
, &search_box
,
1767 NULL
, LOCtoArcLine_callback
, &info
);
1771 if (setjmp (info
.env
) == 0)
1772 r_search (layer
->arc_tree
, &search_box
,
1773 NULL
, LOCtoArcArc_callback
, &info
);
1777 /* now check all polygons */
1778 for (i
= layer
->Polygon
; i
!= NULL
; i
= g_list_next (i
))
1780 PolygonType
*polygon
= i
->data
;
1781 if (!TEST_FLAG (flag
, polygon
) && IsArcInPolygon (Arc
, polygon
)
1782 && ADD_POLYGON_TO_LIST (layer_no
, polygon
, flag
))
1788 info
.layer
= layer_no
- max_copper_layer
;
1789 if (setjmp (info
.env
) == 0)
1790 r_search (PCB
->Data
->pad_tree
, &search_box
, NULL
,
1791 LOCtoArcPad_callback
, &info
);
1800 LOCtoLineLine_callback (const BoxType
* b
, void *cl
)
1802 LineType
*line
= (LineType
*) b
;
1803 struct lo_info
*i
= (struct lo_info
*) cl
;
1805 if (!TEST_FLAG (i
->flag
, line
) && LineLineIntersect (i
->line
, line
))
1807 if (ADD_LINE_TO_LIST (i
->layer
, line
, i
->flag
))
1808 longjmp (i
->env
, 1);
1814 LOCtoLineArc_callback (const BoxType
* b
, void *cl
)
1816 ArcType
*arc
= (ArcType
*) b
;
1817 struct lo_info
*i
= (struct lo_info
*) cl
;
1819 if (!arc
->Thickness
)
1821 if (!TEST_FLAG (i
->flag
, arc
) && LineArcIntersect (i
->line
, arc
))
1823 if (ADD_ARC_TO_LIST (i
->layer
, arc
, i
->flag
))
1824 longjmp (i
->env
, 1);
1830 LOCtoLineRat_callback (const BoxType
* b
, void *cl
)
1832 RatType
*rat
= (RatType
*) b
;
1833 struct lo_info
*i
= (struct lo_info
*) cl
;
1835 if (!TEST_FLAG (i
->flag
, rat
))
1837 if ((rat
->group1
== i
->layer
)
1838 && IsRatPointOnLineEnd (&rat
->Point1
, i
->line
))
1840 if (ADD_RAT_TO_LIST (rat
, i
->flag
))
1841 longjmp (i
->env
, 1);
1843 else if ((rat
->group2
== i
->layer
)
1844 && IsRatPointOnLineEnd (&rat
->Point2
, i
->line
))
1846 if (ADD_RAT_TO_LIST (rat
, i
->flag
))
1847 longjmp (i
->env
, 1);
1854 LOCtoLinePad_callback (const BoxType
* b
, void *cl
)
1856 PadType
*pad
= (PadType
*) b
;
1857 struct lo_info
*i
= (struct lo_info
*) cl
;
1859 if (!TEST_FLAG (i
->flag
, pad
) && i
->layer
==
1860 (TEST_FLAG (ONSOLDERFLAG
, pad
) ? BOTTOM_SIDE
: TOP_SIDE
)
1861 && LinePadIntersect (i
->line
, pad
) && ADD_PAD_TO_LIST (i
->layer
, pad
, i
->flag
))
1862 longjmp (i
->env
, 1);
1867 * \brief Searches all LOs that are connected to the given line on the
1870 * All found connections are added to the list.
1872 * The notation that is used is:
1873 * Xij means Xj at line i.
1876 LookupLOConnectionsToLine (LineType
*Line
, Cardinal LayerGroup
,
1877 int flag
, bool PolysTo
, bool AndRats
)
1880 struct lo_info info
;
1884 info
.layer
= LayerGroup
;
1886 search_box
= expand_bounds ((BoxType
*)info
.line
);
1890 /* add the new rat lines */
1891 if (setjmp (info
.env
) == 0)
1892 r_search (PCB
->Data
->rat_tree
, &search_box
, NULL
,
1893 LOCtoLineRat_callback
, &info
);
1898 /* loop over all layers of the group */
1899 for (entry
= 0; entry
< PCB
->LayerGroups
.Number
[LayerGroup
]; entry
++)
1904 layer_no
= PCB
->LayerGroups
.Entries
[LayerGroup
][entry
];
1905 layer
= LAYER_PTR (layer_no
);
1907 /* handle normal layers */
1908 if (layer_no
< max_copper_layer
)
1910 info
.layer
= layer_no
;
1912 if (setjmp (info
.env
) == 0)
1913 r_search (layer
->line_tree
, &search_box
,
1914 NULL
, LOCtoLineLine_callback
, &info
);
1918 if (setjmp (info
.env
) == 0)
1919 r_search (layer
->arc_tree
, &search_box
,
1920 NULL
, LOCtoLineArc_callback
, &info
);
1923 /* now check all polygons */
1927 for (i
= layer
->Polygon
; i
!= NULL
; i
= g_list_next (i
))
1929 PolygonType
*polygon
= i
->data
;
1930 if (!TEST_FLAG (flag
, polygon
) && IsLineInPolygon (Line
, polygon
)
1931 && ADD_POLYGON_TO_LIST (layer_no
, polygon
, flag
))
1938 /* handle special 'pad' layers */
1939 info
.layer
= layer_no
- max_copper_layer
;
1940 if (setjmp (info
.env
) == 0)
1941 r_search (PCB
->Data
->pad_tree
, &search_box
, NULL
,
1942 LOCtoLinePad_callback
, &info
);
1959 LOCtoRat_callback (const BoxType
* b
, void *cl
)
1961 LineType
*line
= (LineType
*) b
;
1962 struct rat_info
*i
= (struct rat_info
*) cl
;
1964 if (!TEST_FLAG (i
->flag
, line
) &&
1965 ((line
->Point1
.X
== i
->Point
->X
&&
1966 line
->Point1
.Y
== i
->Point
->Y
) ||
1967 (line
->Point2
.X
== i
->Point
->X
&& line
->Point2
.Y
== i
->Point
->Y
)))
1969 if (ADD_LINE_TO_LIST (i
->layer
, line
, i
->flag
))
1970 longjmp (i
->env
, 1);
1975 PolygonToRat_callback (const BoxType
* b
, void *cl
)
1977 PolygonType
*polygon
= (PolygonType
*) b
;
1978 struct rat_info
*i
= (struct rat_info
*) cl
;
1980 if (!TEST_FLAG (i
->flag
, polygon
) && polygon
->Clipped
&&
1981 (i
->Point
->X
== polygon
->Clipped
->contours
->head
.point
[0]) &&
1982 (i
->Point
->Y
== polygon
->Clipped
->contours
->head
.point
[1]))
1984 if (ADD_POLYGON_TO_LIST (i
->layer
, polygon
, i
->flag
))
1985 longjmp (i
->env
, 1);
1991 LOCtoPad_callback (const BoxType
* b
, void *cl
)
1993 PadType
*pad
= (PadType
*) b
;
1994 struct rat_info
*i
= (struct rat_info
*) cl
;
1996 if (!TEST_FLAG (i
->flag
, pad
) && i
->layer
==
1997 (TEST_FLAG (ONSOLDERFLAG
, pad
) ? BOTTOM_SIDE
: TOP_SIDE
) &&
1998 ((pad
->Point1
.X
== i
->Point
->X
&& pad
->Point1
.Y
== i
->Point
->Y
) ||
1999 (pad
->Point2
.X
== i
->Point
->X
&& pad
->Point2
.Y
== i
->Point
->Y
) ||
2000 ((pad
->Point1
.X
+ pad
->Point2
.X
) / 2 == i
->Point
->X
&&
2001 (pad
->Point1
.Y
+ pad
->Point2
.Y
) / 2 == i
->Point
->Y
)) &&
2002 ADD_PAD_TO_LIST (i
->layer
, pad
, i
->flag
))
2003 longjmp (i
->env
, 1);
2008 * \brief Searches all LOs that are connected to the given rat-line on
2009 * the given layergroup.
2011 * All found connections are added to the list.
2013 * The notation that is used is:
2014 * Xij means Xj at line i.
2017 LookupLOConnectionsToRatEnd (PointType
*Point
, Cardinal LayerGroup
, int flag
)
2020 struct rat_info info
;
2024 /* loop over all layers of this group */
2025 for (entry
= 0; entry
< PCB
->LayerGroups
.Number
[LayerGroup
]; entry
++)
2030 layer_no
= PCB
->LayerGroups
.Entries
[LayerGroup
][entry
];
2031 layer
= LAYER_PTR (layer_no
);
2032 /* handle normal layers
2033 rats don't ever touch
2037 if (layer_no
< max_copper_layer
)
2039 info
.layer
= layer_no
;
2040 if (setjmp (info
.env
) == 0)
2041 r_search_pt (layer
->line_tree
, Point
, 1, NULL
,
2042 LOCtoRat_callback
, &info
);
2045 if (setjmp (info
.env
) == 0)
2046 r_search_pt (layer
->polygon_tree
, Point
, 1,
2047 NULL
, PolygonToRat_callback
, &info
);
2051 /* handle special 'pad' layers */
2052 info
.layer
= layer_no
- max_copper_layer
;
2053 if (setjmp (info
.env
) == 0)
2054 r_search_pt (PCB
->Data
->pad_tree
, Point
, 1, NULL
,
2055 LOCtoPad_callback
, &info
);
2064 LOCtoPadLine_callback (const BoxType
* b
, void *cl
)
2066 LineType
*line
= (LineType
*) b
;
2067 struct lo_info
*i
= (struct lo_info
*) cl
;
2069 if (!TEST_FLAG (i
->flag
, line
) && LinePadIntersect (line
, i
->pad
))
2071 if (ADD_LINE_TO_LIST (i
->layer
, line
, i
->flag
))
2072 longjmp (i
->env
, 1);
2078 LOCtoPadArc_callback (const BoxType
* b
, void *cl
)
2080 ArcType
*arc
= (ArcType
*) b
;
2081 struct lo_info
*i
= (struct lo_info
*) cl
;
2083 if (!arc
->Thickness
)
2085 if (!TEST_FLAG (i
->flag
, arc
) && ArcPadIntersect (arc
, i
->pad
))
2087 if (ADD_ARC_TO_LIST (i
->layer
, arc
, i
->flag
))
2088 longjmp (i
->env
, 1);
2094 LOCtoPadPoly_callback (const BoxType
* b
, void *cl
)
2096 PolygonType
*polygon
= (PolygonType
*) b
;
2097 struct lo_info
*i
= (struct lo_info
*) cl
;
2100 if (!TEST_FLAG (i
->flag
, polygon
) &&
2101 (!TEST_FLAG (CLEARPOLYFLAG
, polygon
) || !i
->pad
->Clearance
))
2103 if (IsPadInPolygon (i
->pad
, polygon
) &&
2104 ADD_POLYGON_TO_LIST (i
->layer
, polygon
, i
->flag
))
2105 longjmp (i
->env
, 1);
2111 LOCtoPadRat_callback (const BoxType
* b
, void *cl
)
2113 RatType
*rat
= (RatType
*) b
;
2114 struct lo_info
*i
= (struct lo_info
*) cl
;
2116 if (!TEST_FLAG (i
->flag
, rat
))
2118 if (rat
->group1
== i
->layer
&&
2119 ((rat
->Point1
.X
== i
->pad
->Point1
.X
&& rat
->Point1
.Y
== i
->pad
->Point1
.Y
) ||
2120 (rat
->Point1
.X
== i
->pad
->Point2
.X
&& rat
->Point1
.Y
== i
->pad
->Point2
.Y
) ||
2121 (rat
->Point1
.X
== (i
->pad
->Point1
.X
+ i
->pad
->Point2
.X
) / 2 &&
2122 rat
->Point1
.Y
== (i
->pad
->Point1
.Y
+ i
->pad
->Point2
.Y
) / 2)))
2124 if (ADD_RAT_TO_LIST (rat
, i
->flag
))
2125 longjmp (i
->env
, 1);
2127 else if (rat
->group2
== i
->layer
&&
2128 ((rat
->Point2
.X
== i
->pad
->Point1
.X
&& rat
->Point2
.Y
== i
->pad
->Point1
.Y
) ||
2129 (rat
->Point2
.X
== i
->pad
->Point2
.X
&& rat
->Point2
.Y
== i
->pad
->Point2
.Y
) ||
2130 (rat
->Point2
.X
== (i
->pad
->Point1
.X
+ i
->pad
->Point2
.X
) / 2 &&
2131 rat
->Point2
.Y
== (i
->pad
->Point1
.Y
+ i
->pad
->Point2
.Y
) / 2)))
2133 if (ADD_RAT_TO_LIST (rat
, i
->flag
))
2134 longjmp (i
->env
, 1);
2141 LOCtoPadPad_callback (const BoxType
* b
, void *cl
)
2143 PadType
*pad
= (PadType
*) b
;
2144 struct lo_info
*i
= (struct lo_info
*) cl
;
2146 if (!TEST_FLAG (i
->flag
, pad
) && i
->layer
==
2147 (TEST_FLAG (ONSOLDERFLAG
, pad
) ? BOTTOM_SIDE
: TOP_SIDE
)
2148 && PadPadIntersect (pad
, i
->pad
) && ADD_PAD_TO_LIST (i
->layer
, pad
, i
->flag
))
2149 longjmp (i
->env
, 1);
2154 * \brief Searches all LOs that are connected to the given pad on the
2157 * All found connections are added to the list.
2160 LookupLOConnectionsToPad (PadType
*Pad
, Cardinal LayerGroup
, int flag
, bool AndRats
)
2163 struct lo_info info
;
2166 if (!TEST_FLAG (SQUAREFLAG
, Pad
))
2167 return (LookupLOConnectionsToLine ((LineType
*) Pad
, LayerGroup
, flag
, false, AndRats
));
2171 search_box
= expand_bounds ((BoxType
*)info
.pad
);
2173 /* add the new rat lines */
2174 info
.layer
= LayerGroup
;
2178 if (setjmp (info
.env
) == 0)
2179 r_search (PCB
->Data
->rat_tree
, &search_box
, NULL
,
2180 LOCtoPadRat_callback
, &info
);
2185 /* loop over all layers of the group */
2186 for (entry
= 0; entry
< PCB
->LayerGroups
.Number
[LayerGroup
]; entry
++)
2191 layer_no
= PCB
->LayerGroups
.Entries
[LayerGroup
][entry
];
2192 layer
= LAYER_PTR (layer_no
);
2193 /* handle normal layers */
2194 if (layer_no
< max_copper_layer
)
2196 info
.layer
= layer_no
;
2198 if (setjmp (info
.env
) == 0)
2199 r_search (layer
->line_tree
, &search_box
,
2200 NULL
, LOCtoPadLine_callback
, &info
);
2204 if (setjmp (info
.env
) == 0)
2205 r_search (layer
->arc_tree
, &search_box
,
2206 NULL
, LOCtoPadArc_callback
, &info
);
2210 if (setjmp (info
.env
) == 0)
2211 r_search (layer
->polygon_tree
, &search_box
,
2212 NULL
, LOCtoPadPoly_callback
, &info
);
2218 /* handle special 'pad' layers */
2219 info
.layer
= layer_no
- max_copper_layer
;
2220 if (setjmp (info
.env
) == 0)
2221 r_search (PCB
->Data
->pad_tree
, &search_box
, NULL
,
2222 LOCtoPadPad_callback
, &info
);
2232 LOCtoPolyLine_callback (const BoxType
* b
, void *cl
)
2234 LineType
*line
= (LineType
*) b
;
2235 struct lo_info
*i
= (struct lo_info
*) cl
;
2237 if (!TEST_FLAG (i
->flag
, line
) && IsLineInPolygon (line
, i
->polygon
))
2239 if (ADD_LINE_TO_LIST (i
->layer
, line
, i
->flag
))
2240 longjmp (i
->env
, 1);
2246 LOCtoPolyArc_callback (const BoxType
* b
, void *cl
)
2248 ArcType
*arc
= (ArcType
*) b
;
2249 struct lo_info
*i
= (struct lo_info
*) cl
;
2251 if (!arc
->Thickness
)
2253 if (!TEST_FLAG (i
->flag
, arc
) && IsArcInPolygon (arc
, i
->polygon
))
2255 if (ADD_ARC_TO_LIST (i
->layer
, arc
, i
->flag
))
2256 longjmp (i
->env
, 1);
2262 LOCtoPolyPad_callback (const BoxType
* b
, void *cl
)
2264 PadType
*pad
= (PadType
*) b
;
2265 struct lo_info
*i
= (struct lo_info
*) cl
;
2267 if (!TEST_FLAG (i
->flag
, pad
) && i
->layer
==
2268 (TEST_FLAG (ONSOLDERFLAG
, pad
) ? BOTTOM_SIDE
: TOP_SIDE
)
2269 && IsPadInPolygon (pad
, i
->polygon
))
2271 if (ADD_PAD_TO_LIST (i
->layer
, pad
, i
->flag
))
2272 longjmp (i
->env
, 1);
2278 LOCtoPolyRat_callback (const BoxType
* b
, void *cl
)
2280 RatType
*rat
= (RatType
*) b
;
2281 struct lo_info
*i
= (struct lo_info
*) cl
;
2283 if (!TEST_FLAG (i
->flag
, rat
))
2285 if ((rat
->Point1
.X
== (i
->polygon
->Clipped
->contours
->head
.point
[0]) &&
2286 rat
->Point1
.Y
== (i
->polygon
->Clipped
->contours
->head
.point
[1]) &&
2287 rat
->group1
== i
->layer
) ||
2288 (rat
->Point2
.X
== (i
->polygon
->Clipped
->contours
->head
.point
[0]) &&
2289 rat
->Point2
.Y
== (i
->polygon
->Clipped
->contours
->head
.point
[1]) &&
2290 rat
->group2
== i
->layer
))
2291 if (ADD_RAT_TO_LIST (rat
, i
->flag
))
2292 longjmp (i
->env
, 1);
2299 * \brief Looks up LOs that are connected to the given polygon on the
2302 * All found connections are added to the list.
2305 LookupLOConnectionsToPolygon (PolygonType
*Polygon
, Cardinal LayerGroup
, int flag
, bool AndRats
)
2308 struct lo_info info
;
2311 if (!Polygon
->Clipped
)
2315 info
.polygon
= Polygon
;
2316 search_box
= expand_bounds ((BoxType
*)info
.polygon
);
2318 info
.layer
= LayerGroup
;
2323 if (setjmp (info
.env
) == 0)
2324 r_search (PCB
->Data
->rat_tree
, &search_box
, NULL
,
2325 LOCtoPolyRat_callback
, &info
);
2330 /* loop over all layers of the group */
2331 for (entry
= 0; entry
< PCB
->LayerGroups
.Number
[LayerGroup
]; entry
++)
2336 layer_no
= PCB
->LayerGroups
.Entries
[LayerGroup
][entry
];
2337 layer
= LAYER_PTR (layer_no
);
2339 /* handle normal layers */
2340 if (layer_no
< max_copper_layer
)
2344 /* check all polygons */
2345 for (i
= layer
->Polygon
; i
!= NULL
; i
= g_list_next (i
))
2347 PolygonType
*polygon
= i
->data
;
2348 if (!TEST_FLAG (flag
, polygon
)
2349 && IsPolygonInPolygon (polygon
, Polygon
)
2350 && ADD_POLYGON_TO_LIST (layer_no
, polygon
, flag
))
2354 info
.layer
= layer_no
;
2355 /* check all lines */
2356 if (setjmp (info
.env
) == 0)
2357 r_search (layer
->line_tree
, &search_box
,
2358 NULL
, LOCtoPolyLine_callback
, &info
);
2361 /* check all arcs */
2362 if (setjmp (info
.env
) == 0)
2363 r_search (layer
->arc_tree
, &search_box
,
2364 NULL
, LOCtoPolyArc_callback
, &info
);
2370 info
.layer
= layer_no
- max_copper_layer
;
2371 if (setjmp (info
.env
) == 0)
2372 r_search (PCB
->Data
->pad_tree
, &search_box
,
2373 NULL
, LOCtoPolyPad_callback
, &info
);
2382 * \brief Checks if an arc has a connection to a polygon.
2384 * - first check if the arc can intersect with the polygon by
2385 * evaluating the bounding boxes.
2386 * - check the two end points of the arc. If none of them matches
2387 * - check all segments of the polygon against the arc.
2390 IsArcInPolygon (ArcType
*Arc
, PolygonType
*Polygon
)
2392 BoxType
*Box
= (BoxType
*) Arc
;
2394 /* arcs with clearance never touch polys */
2395 if (TEST_FLAG (CLEARPOLYFLAG
, Polygon
) && TEST_FLAG (CLEARLINEFLAG
, Arc
))
2397 if (!Polygon
->Clipped
)
2399 if (Box
->X1
<= Polygon
->Clipped
->contours
->xmax
+ Bloat
2400 && Box
->X2
>= Polygon
->Clipped
->contours
->xmin
- Bloat
2401 && Box
->Y1
<= Polygon
->Clipped
->contours
->ymax
+ Bloat
2402 && Box
->Y2
>= Polygon
->Clipped
->contours
->ymin
- Bloat
)
2406 if (!(ap
= ArcPoly (Arc
, Arc
->Thickness
+ Bloat
)))
2407 return false; /* error */
2408 return isects (ap
, Polygon
, true);
2414 * \brief Checks if a line has a connection to a polygon.
2416 * - first check if the line can intersect with the polygon by
2417 * evaluating the bounding boxes
2418 * - check the two end points of the line. If none of them matches
2419 * - check all segments of the polygon against the line.
2422 IsLineInPolygon (LineType
*Line
, PolygonType
*Polygon
)
2424 BoxType
*Box
= (BoxType
*) Line
;
2427 /* lines with clearance never touch polygons */
2428 if (TEST_FLAG (CLEARPOLYFLAG
, Polygon
) && TEST_FLAG (CLEARLINEFLAG
, Line
))
2430 if (!Polygon
->Clipped
)
2432 if (TEST_FLAG(SQUAREFLAG
,Line
)&&(Line
->Point1
.X
==Line
->Point2
.X
||Line
->Point1
.Y
==Line
->Point2
.Y
))
2434 Coord wid
= (Line
->Thickness
+ Bloat
+ 1) / 2;
2435 Coord x1
, x2
, y1
, y2
;
2437 x1
= MIN (Line
->Point1
.X
, Line
->Point2
.X
) - wid
;
2438 y1
= MIN (Line
->Point1
.Y
, Line
->Point2
.Y
) - wid
;
2439 x2
= MAX (Line
->Point1
.X
, Line
->Point2
.X
) + wid
;
2440 y2
= MAX (Line
->Point1
.Y
, Line
->Point2
.Y
) + wid
;
2441 return IsRectangleInPolygon (x1
, y1
, x2
, y2
, Polygon
);
2443 if (Box
->X1
<= Polygon
->Clipped
->contours
->xmax
+ Bloat
2444 && Box
->X2
>= Polygon
->Clipped
->contours
->xmin
- Bloat
2445 && Box
->Y1
<= Polygon
->Clipped
->contours
->ymax
+ Bloat
2446 && Box
->Y2
>= Polygon
->Clipped
->contours
->ymin
- Bloat
)
2448 if (!(lp
= LinePoly (Line
, Line
->Thickness
+ Bloat
)))
2449 return FALSE
; /* error */
2450 return isects (lp
, Polygon
, true);
2456 * \brief Checks if a pad connects to a non-clearing polygon.
2458 * The polygon is assumed to already have been proven non-clearing.
2461 IsPadInPolygon (PadType
*pad
, PolygonType
*polygon
)
2463 return IsLineInPolygon ((LineType
*) pad
, polygon
);
2467 * \brief Checks if a polygon has a connection to a second one.
2469 * First check all points out of P1 against P2 and vice versa.
2470 * If both fail check all lines of P1 against the ones of P2.
2473 IsPolygonInPolygon (PolygonType
*P1
, PolygonType
*P2
)
2475 if (!P1
->Clipped
|| !P2
->Clipped
)
2477 assert (P1
->Clipped
->contours
);
2478 assert (P2
->Clipped
->contours
);
2480 /* first check if both bounding boxes intersect. If not, return quickly */
2481 if (P1
->Clipped
->contours
->xmin
- Bloat
> P2
->Clipped
->contours
->xmax
||
2482 P1
->Clipped
->contours
->xmax
+ Bloat
< P2
->Clipped
->contours
->xmin
||
2483 P1
->Clipped
->contours
->ymin
- Bloat
> P2
->Clipped
->contours
->ymax
||
2484 P1
->Clipped
->contours
->ymax
+ Bloat
< P2
->Clipped
->contours
->ymin
)
2487 /* first check un-bloated case */
2488 if (isects (P1
->Clipped
, P2
, false))
2491 /* now the difficult case of bloated */
2495 for (c
= P1
->Clipped
->contours
; c
; c
= c
->next
)
2498 VNODE
*v
= &c
->head
;
2499 if (c
->xmin
- Bloat
<= P2
->Clipped
->contours
->xmax
&&
2500 c
->xmax
+ Bloat
>= P2
->Clipped
->contours
->xmin
&&
2501 c
->ymin
- Bloat
<= P2
->Clipped
->contours
->ymax
&&
2502 c
->ymax
+ Bloat
>= P2
->Clipped
->contours
->ymin
)
2505 line
.Point1
.X
= v
->point
[0];
2506 line
.Point1
.Y
= v
->point
[1];
2507 line
.Thickness
= Bloat
;
2508 /* Another Bloat is added by IsLineInPolygon, making the correct
2509 * 2x Bloat. Perhaps we should change it there, but doing so
2510 * breaks some other DRC checks which rely on the behaviour
2511 * in IsLineInPolygon.
2514 line
.Flags
= NoFlags ();
2515 for (v
= v
->next
; v
!= &c
->head
; v
= v
->next
)
2517 line
.Point2
.X
= v
->point
[0];
2518 line
.Point2
.Y
= v
->point
[1];
2519 SetLineBoundingBox (&line
);
2520 if (IsLineInPolygon (&line
, P2
))
2522 line
.Point1
.X
= line
.Point2
.X
;
2523 line
.Point1
.Y
= line
.Point2
.Y
;
2533 * \brief Writes the several names of an element to a file.
2536 PrintElementNameList (ElementType
*Element
, FILE * FP
)
2538 static DynamicStringType cname
, pname
, vname
;
2540 CreateQuotedString (&cname
, (char *)EMPTY (DESCRIPTION_NAME (Element
)));
2541 CreateQuotedString (&pname
, (char *)EMPTY (NAMEONPCB_NAME (Element
)));
2542 CreateQuotedString (&vname
, (char *)EMPTY (VALUE_NAME (Element
)));
2543 fprintf (FP
, "(%s %s %s)\n", cname
.Data
, pname
.Data
, vname
.Data
);
2547 * \brief Writes the several names of an element to a file.
2550 PrintConnectionElementName (ElementType
*Element
, FILE * FP
)
2552 fputs ("Element", FP
);
2553 PrintElementNameList (Element
, FP
);
2558 * \brief Prints one {pin,pad,via}/element entry of connection lists.
2561 PrintConnectionListEntry (char *ObjName
, ElementType
*Element
,
2562 bool FirstOne
, FILE * FP
)
2564 static DynamicStringType oname
;
2566 CreateQuotedString (&oname
, ObjName
);
2568 fprintf (FP
, "\t%s\n\t{\n", oname
.Data
);
2571 fprintf (FP
, "\t\t%s ", oname
.Data
);
2573 PrintElementNameList (Element
, FP
);
2575 fputs ("(__VIA__)\n", FP
);
2580 * \brief Prints all found connections of a pads to file FP
2581 * the connections are stacked in 'PadList'.
2584 PrintPadConnections (Cardinal Layer
, FILE * FP
, bool IsFirst
)
2589 if (!PadList
[Layer
].Number
)
2592 /* the starting pad */
2595 ptr
= PADLIST_ENTRY (Layer
, 0);
2597 PrintConnectionListEntry ((char *)UNKNOWN (ptr
->Name
), NULL
, true, FP
);
2599 printf ("Skipping NULL ptr in 1st part of PrintPadConnections\n");
2602 /* we maybe have to start with i=1 if we are handling the
2603 * starting-pad itself
2605 for (i
= IsFirst
? 1 : 0; i
< PadList
[Layer
].Number
; i
++)
2607 ptr
= PADLIST_ENTRY (Layer
, i
);
2609 PrintConnectionListEntry ((char *)EMPTY (ptr
->Name
), (ElementType
*)ptr
->Element
, false, FP
);
2611 printf ("Skipping NULL ptr in 2nd part of PrintPadConnections\n");
2616 * \brief Prints all found connections of a pin to file FP
2617 * the connections are stacked in 'PVList'.
2620 PrintPinConnections (FILE * FP
, bool IsFirst
)
2630 /* the starting pin */
2631 pv
= PVLIST_ENTRY (0);
2632 PrintConnectionListEntry ((char *)EMPTY (pv
->Name
), NULL
, true, FP
);
2635 /* we maybe have to start with i=1 if we are handling the
2636 * starting-pin itself
2638 for (i
= IsFirst
? 1 : 0; i
< PVList
.Number
; i
++)
2640 /* get the elements name or assume that its a via */
2641 pv
= PVLIST_ENTRY (i
);
2642 PrintConnectionListEntry ((char *)EMPTY (pv
->Name
), (ElementType
*)pv
->Element
, false, FP
);
2647 * \brief Checks if all lists of new objects are handled.
2650 ListsEmpty (bool AndRats
)
2655 empty
= (PVList
.Location
>= PVList
.Number
);
2657 empty
= empty
&& (RatList
.Location
>= RatList
.Number
);
2658 for (i
= 0; i
< max_copper_layer
&& empty
; i
++)
2659 if (!LAYER_PTR (i
)->no_drc
)
2660 empty
= empty
&& LineList
[i
].Location
>= LineList
[i
].Number
2661 && ArcList
[i
].Location
>= ArcList
[i
].Number
2662 && PolygonList
[i
].Location
>= PolygonList
[i
].Number
;
2667 reassign_no_drc_flags (void)
2671 for (layer
= 0; layer
< max_copper_layer
; layer
++)
2673 LayerType
*l
= LAYER_PTR (layer
);
2674 l
->no_drc
= AttributeGet (l
, "PCB::skip-drc") != NULL
;
2682 * \brief Loops till no more connections are found.
2685 DoIt (int flag
, bool AndRats
, bool AndDraw
)
2687 bool newone
= false;
2688 reassign_no_drc_flags ();
2691 /* lookup connections; these are the steps (2) to (4)
2692 * from the description
2694 newone
= LookupPVConnectionsToPVList (flag
) ||
2695 LookupLOConnectionsToPVList (flag
, AndRats
) ||
2696 LookupLOConnectionsToLOList (flag
, AndRats
) ||
2697 LookupPVConnectionsToLOList (flag
, AndRats
);
2699 DrawNewConnections ();
2701 while (!newone
&& !ListsEmpty (AndRats
));
2708 * \brief Prints all unused pins of an element to file FP.
2711 PrintAndSelectUnusedPinsAndPadsOfElement (ElementType
*Element
, FILE * FP
, int flag
)
2715 static DynamicStringType oname
;
2717 /* check all pins in element */
2721 if (!TEST_FLAG (HOLEFLAG
, pin
))
2723 /* pin might have bee checked before, add to list if not */
2724 if (!TEST_FLAG (flag
, pin
) && FP
)
2727 if (ADD_PV_TO_LIST (pin
, flag
))
2729 DoIt (flag
, true, true);
2730 number
= PadList
[TOP_SIDE
].Number
2731 + PadList
[BOTTOM_SIDE
].Number
+ PVList
.Number
;
2732 /* the pin has no connection if it's the only
2733 * list entry; don't count vias
2735 for (i
= 0; i
< PVList
.Number
; i
++)
2736 if (!PVLIST_ENTRY (i
)->Element
)
2740 /* output of element name if not already done */
2743 PrintConnectionElementName (Element
, FP
);
2747 /* write name to list and draw selected object */
2748 CreateQuotedString (&oname
, (char *)EMPTY (pin
->Name
));
2749 fprintf (FP
, "\t%s\n", oname
.Data
);
2750 SET_FLAG (SELECTEDFLAG
, pin
);
2754 /* reset found objects for the next pin */
2755 if (PrepareNextLoop (FP
))
2762 /* check all pads in element */
2765 /* lookup pad in list */
2766 /* pad might has bee checked before, add to list if not */
2767 if (!TEST_FLAG (flag
, pad
) && FP
)
2770 if (ADD_PAD_TO_LIST (TEST_FLAG (ONSOLDERFLAG
, pad
)
2771 ? BOTTOM_SIDE
: TOP_SIDE
, pad
, flag
))
2773 DoIt (flag
, true, true);
2774 number
= PadList
[TOP_SIDE
].Number
2775 + PadList
[BOTTOM_SIDE
].Number
+ PVList
.Number
;
2776 /* the pin has no connection if it's the only
2777 * list entry; don't count vias
2779 for (i
= 0; i
< PVList
.Number
; i
++)
2780 if (!PVLIST_ENTRY (i
)->Element
)
2784 /* output of element name if not already done */
2787 PrintConnectionElementName (Element
, FP
);
2791 /* write name to list and draw selected object */
2792 CreateQuotedString (&oname
, (char *)EMPTY (pad
->Name
));
2793 fprintf (FP
, "\t%s\n", oname
.Data
);
2794 SET_FLAG (SELECTEDFLAG
, pad
);
2798 /* reset found objects for the next pin */
2799 if (PrepareNextLoop (FP
))
2805 /* print separator if element has unused pins or pads */
2808 fputs ("}\n\n", FP
);
2815 * \brief Resets some flags for looking up the next pin/pad.
2818 PrepareNextLoop (FILE * FP
)
2822 /* reset found LOs for the next pin */
2823 for (layer
= 0; layer
< max_copper_layer
; layer
++)
2825 LineList
[layer
].Location
= LineList
[layer
].Number
= 0;
2826 ArcList
[layer
].Location
= ArcList
[layer
].Number
= 0;
2827 PolygonList
[layer
].Location
= PolygonList
[layer
].Number
= 0;
2830 /* reset found pads */
2831 for (layer
= 0; layer
< 2; layer
++)
2832 PadList
[layer
].Location
= PadList
[layer
].Number
= 0;
2835 PVList
.Number
= PVList
.Location
= 0;
2836 RatList
.Number
= RatList
.Location
= 0;
2842 * \brief Finds all connections to the pins of the passed element.
2844 * The result is written to file FP.
2846 * \return true if operation was aborted.
2849 PrintElementConnections (ElementType
*Element
, FILE * FP
, int flag
, bool AndDraw
)
2851 PrintConnectionElementName (Element
, FP
);
2853 /* check all pins in element */
2856 /* pin might have been checked before, add to list if not */
2857 if (TEST_FLAG (flag
, pin
))
2859 PrintConnectionListEntry ((char *)EMPTY (pin
->Name
), NULL
, true, FP
);
2860 fputs ("\t\t__CHECKED_BEFORE__\n\t}\n", FP
);
2863 if (ADD_PV_TO_LIST (pin
, flag
))
2865 DoIt (flag
, true, AndDraw
);
2866 /* printout all found connections */
2867 PrintPinConnections (FP
, true);
2868 PrintPadConnections (TOP_SIDE
, FP
, false);
2869 PrintPadConnections (BOTTOM_SIDE
, FP
, false);
2870 fputs ("\t}\n", FP
);
2871 if (PrepareNextLoop (FP
))
2876 /* check all pads in element */
2880 /* pad might have been checked before, add to list if not */
2881 if (TEST_FLAG (flag
, pad
))
2883 PrintConnectionListEntry ((char *)EMPTY (pad
->Name
), NULL
, true, FP
);
2884 fputs ("\t\t__CHECKED_BEFORE__\n\t}\n", FP
);
2887 layer
= TEST_FLAG (ONSOLDERFLAG
, pad
) ? BOTTOM_SIDE
: TOP_SIDE
;
2888 if (ADD_PAD_TO_LIST (layer
, pad
, flag
))
2890 DoIt (flag
, true, AndDraw
);
2891 /* print all found connections */
2892 PrintPadConnections (layer
, FP
, true);
2893 PrintPadConnections (layer
==
2894 (TOP_SIDE
? BOTTOM_SIDE
: TOP_SIDE
),
2896 PrintPinConnections (FP
, false);
2897 fputs ("\t}\n", FP
);
2898 if (PrepareNextLoop (FP
))
2902 fputs ("}\n\n", FP
);
2907 * \brief Draws all new connections which have been found since the
2908 * routine was called the last time.
2911 DrawNewConnections (void)
2916 /* decrement 'i' to keep layerstack order */
2917 for (i
= max_copper_layer
- 1; i
!= -1; i
--)
2919 Cardinal layer
= LayerStack
[i
];
2921 if (PCB
->Data
->Layer
[layer
].On
)
2923 /* draw all new lines */
2924 position
= LineList
[layer
].DrawLocation
;
2925 for (; position
< LineList
[layer
].Number
; position
++)
2926 DrawLine (LAYER_PTR (layer
), LINELIST_ENTRY (layer
, position
));
2927 LineList
[layer
].DrawLocation
= LineList
[layer
].Number
;
2929 /* draw all new arcs */
2930 position
= ArcList
[layer
].DrawLocation
;
2931 for (; position
< ArcList
[layer
].Number
; position
++)
2932 DrawArc (LAYER_PTR (layer
), ARCLIST_ENTRY (layer
, position
));
2933 ArcList
[layer
].DrawLocation
= ArcList
[layer
].Number
;
2935 /* draw all new polygons */
2936 position
= PolygonList
[layer
].DrawLocation
;
2937 for (; position
< PolygonList
[layer
].Number
; position
++)
2938 DrawPolygon (LAYER_PTR (layer
), POLYGONLIST_ENTRY (layer
, position
));
2939 PolygonList
[layer
].DrawLocation
= PolygonList
[layer
].Number
;
2943 /* draw all new pads */
2945 for (i
= 0; i
< 2; i
++)
2947 position
= PadList
[i
].DrawLocation
;
2949 for (; position
< PadList
[i
].Number
; position
++)
2950 DrawPad (PADLIST_ENTRY (i
, position
));
2951 PadList
[i
].DrawLocation
= PadList
[i
].Number
;
2954 /* draw all new PVs; 'PVList' holds a list of pointers to the
2955 * sorted array pointers to PV data
2957 while (PVList
.DrawLocation
< PVList
.Number
)
2959 PinType
*pv
= PVLIST_ENTRY (PVList
.DrawLocation
);
2961 if (TEST_FLAG (PINFLAG
, pv
))
2966 else if (PCB
->ViaOn
)
2968 PVList
.DrawLocation
++;
2970 /* draw the new rat-lines */
2973 position
= RatList
.DrawLocation
;
2974 for (; position
< RatList
.Number
; position
++)
2975 DrawRat (RATLIST_ENTRY (position
));
2976 RatList
.DrawLocation
= RatList
.Number
;
2981 * \brief Find all connections to pins within one element.
2984 LookupElementConnections (ElementType
*Element
, FILE * FP
)
2986 /* reset all currently marked connections */
2988 ClearFlagOnAllObjects (true, FOUNDFLAG
);
2989 InitConnectionLookup ();
2990 PrintElementConnections (Element
, FP
, FOUNDFLAG
, true);
2991 SetChangedFlag (true);
2992 if (Settings
.RingBellWhenFinished
)
2994 FreeConnectionLookupMemory ();
2995 IncrementUndoSerialNumber ();
3001 * \brief Find all connections to pins of all element.
3004 LookupConnectionsToAllElements (FILE * FP
)
3006 /* reset all currently marked connections */
3008 ClearFlagOnAllObjects (false, FOUNDFLAG
);
3009 InitConnectionLookup ();
3011 ELEMENT_LOOP (PCB
->Data
);
3013 /* break if abort dialog returned true */
3014 if (PrintElementConnections (element
, FP
, FOUNDFLAG
, false))
3017 if (Settings
.ResetAfterElement
&& n
!= 1)
3018 ClearFlagOnAllObjects (false, FOUNDFLAG
);
3021 if (Settings
.RingBellWhenFinished
)
3023 ClearFlagOnAllObjects (false, FOUNDFLAG
);
3024 FreeConnectionLookupMemory ();
3029 * \brief Add the starting object to the list of found objects.
3032 ListStart (int type
, void *ptr1
, void *ptr2
, void *ptr3
, int flag
)
3040 if (ADD_PV_TO_LIST ((PinType
*) ptr2
, flag
))
3047 if (ADD_RAT_TO_LIST ((RatType
*) ptr1
, flag
))
3054 int layer
= GetLayerNumber (PCB
->Data
,
3055 (LayerType
*) ptr1
);
3057 if (ADD_LINE_TO_LIST (layer
, (LineType
*) ptr2
, flag
))
3064 int layer
= GetLayerNumber (PCB
->Data
,
3065 (LayerType
*) ptr1
);
3067 if (ADD_ARC_TO_LIST (layer
, (ArcType
*) ptr2
, flag
))
3074 int layer
= GetLayerNumber (PCB
->Data
,
3075 (LayerType
*) ptr1
);
3077 if (ADD_POLYGON_TO_LIST (layer
, (PolygonType
*) ptr2
, flag
))
3084 PadType
*pad
= (PadType
*) ptr2
;
3087 (ONSOLDERFLAG
, pad
) ? BOTTOM_SIDE
: TOP_SIDE
, pad
, flag
))
3097 * \brief Looks up all connections from the object at the given
3098 * coordinates the TheFlag (normally 'FOUNDFLAG') is set for all objects
3101 * The objects are re-drawn if AndDraw is true, also the action is
3102 * marked as undoable if AndDraw is true.
3105 LookupConnection (Coord X
, Coord Y
, bool AndDraw
, Coord Range
, int flag
,
3108 void *ptr1
, *ptr2
, *ptr3
;
3112 /* check if there are any pins or pads at that position */
3114 reassign_no_drc_flags ();
3117 = SearchObjectByLocation (LOOKUP_FIRST
, &ptr1
, &ptr2
, &ptr3
, X
, Y
, Range
);
3118 if (type
== NO_TYPE
)
3120 type
= SearchObjectByLocation (
3121 LOOKUP_MORE
& ~(AndRats
? 0 : RATLINE_TYPE
),
3122 &ptr1
, &ptr2
, &ptr3
, X
, Y
, Range
);
3123 if (type
== NO_TYPE
)
3125 if (type
& SILK_TYPE
)
3127 int laynum
= GetLayerNumber (PCB
->Data
,
3128 (LayerType
*) ptr1
);
3130 /* don't mess with non-conducting objects! */
3131 if (laynum
>= max_copper_layer
|| ((LayerType
*)ptr1
)->no_drc
)
3136 name
= ConnectionName (type
, ptr1
, ptr2
);
3137 hid_actionl ("NetlistShow", name
, NULL
);
3140 InitConnectionLookup ();
3142 /* now add the object to the appropriate list and start scanning
3143 * This is step (1) from the description
3145 ListStart (type
, ptr1
, ptr2
, ptr3
, flag
);
3146 DoIt (flag
, AndRats
, AndDraw
);
3148 IncrementUndoSerialNumber ();
3154 if (AndDraw
&& Settings
.RingBellWhenFinished
)
3156 FreeConnectionLookupMemory ();
3160 * \brief Find connections for rats nesting.
3162 * Assumes InitConnectionLookup() has already been done.
3165 RatFindHook (int type
, void *ptr1
, void *ptr2
, void *ptr3
,
3166 bool undo
, int flag
, bool AndRats
)
3170 ListStart (type
, ptr1
, ptr2
, ptr3
, flag
);
3171 DoIt (flag
, AndRats
, false);
3176 * \brief Find all unused pins of all elements.
3179 LookupUnusedPins (FILE * FP
)
3181 /* reset all currently marked connections */
3183 ClearFlagOnAllObjects (true, FOUNDFLAG
);
3184 InitConnectionLookup ();
3186 ELEMENT_LOOP (PCB
->Data
);
3188 /* break if abort dialog returned true;
3189 * passing NULL as filedescriptor discards the normal output
3191 if (PrintAndSelectUnusedPinsAndPadsOfElement (element
, FP
, FOUNDFLAG
))
3196 if (Settings
.RingBellWhenFinished
)
3198 FreeConnectionLookupMemory ();
3199 IncrementUndoSerialNumber ();
3205 * \brief Resets all used flags of pins and vias.
3208 ClearFlagOnPinsViasAndPads (bool AndDraw
, int flag
)
3210 bool change
= false;
3212 VIA_LOOP (PCB
->Data
);
3214 if (TEST_FLAG (flag
, via
))
3217 AddObjectToFlagUndoList (VIA_TYPE
, via
, via
, via
);
3218 CLEAR_FLAG (flag
, via
);
3225 ELEMENT_LOOP (PCB
->Data
);
3229 if (TEST_FLAG (flag
, pin
))
3232 AddObjectToFlagUndoList (PIN_TYPE
, element
, pin
, pin
);
3233 CLEAR_FLAG (flag
, pin
);
3242 if (TEST_FLAG (flag
, pad
))
3245 AddObjectToFlagUndoList (PAD_TYPE
, element
, pad
, pad
);
3246 CLEAR_FLAG (flag
, pad
);
3256 SetChangedFlag (true);
3261 * \brief Resets all used flags of LOs.
3264 ClearFlagOnLinesAndPolygons (bool AndDraw
, int flag
)
3266 bool change
= false;
3268 RAT_LOOP (PCB
->Data
);
3270 if (TEST_FLAG (flag
, line
))
3273 AddObjectToFlagUndoList (RATLINE_TYPE
, line
, line
, line
);
3274 CLEAR_FLAG (flag
, line
);
3281 COPPERLINE_LOOP (PCB
->Data
);
3283 if (TEST_FLAG (flag
, line
))
3286 AddObjectToFlagUndoList (LINE_TYPE
, layer
, line
, line
);
3287 CLEAR_FLAG (flag
, line
);
3289 DrawLine (layer
, line
);
3294 COPPERARC_LOOP (PCB
->Data
);
3296 if (TEST_FLAG (flag
, arc
))
3299 AddObjectToFlagUndoList (ARC_TYPE
, layer
, arc
, arc
);
3300 CLEAR_FLAG (flag
, arc
);
3302 DrawArc (layer
, arc
);
3307 COPPERPOLYGON_LOOP (PCB
->Data
);
3309 if (TEST_FLAG (flag
, polygon
))
3312 AddObjectToFlagUndoList (POLYGON_TYPE
, layer
, polygon
, polygon
);
3313 CLEAR_FLAG (flag
, polygon
);
3315 DrawPolygon (layer
, polygon
);
3321 SetChangedFlag (true);
3326 * \brief Resets all found connections.
3329 ClearFlagOnAllObjects (bool AndDraw
, int flag
)
3331 bool change
= false;
3333 change
= ClearFlagOnPinsViasAndPads (AndDraw
, flag
) || change
;
3334 change
= ClearFlagOnLinesAndPolygons (AndDraw
, flag
) || change
;
3340 * \brief Dumps the list contents.
3347 for (i
= 0; i
< 2; i
++)
3349 PadList
[i
].Number
= 0;
3350 PadList
[i
].Location
= 0;
3351 PadList
[i
].DrawLocation
= 0;
3355 PVList
.Location
= 0;
3357 for (i
= 0; i
< max_copper_layer
; i
++)
3359 LineList
[i
].Location
= 0;
3360 LineList
[i
].DrawLocation
= 0;
3361 LineList
[i
].Number
= 0;
3362 ArcList
[i
].Location
= 0;
3363 ArcList
[i
].DrawLocation
= 0;
3364 ArcList
[i
].Number
= 0;
3365 PolygonList
[i
].Location
= 0;
3366 PolygonList
[i
].DrawLocation
= 0;
3367 PolygonList
[i
].Number
= 0;
3370 RatList
.Location
= 0;
3371 RatList
.DrawLocation
= 0;
3380 * \brief Check for DRC violations on a single net starting from the pad
3383 * Sees if the connectivity changes when everything is bloated, or
3387 DRCFind (int What
, void *ptr1
, void *ptr2
, void *ptr3
)
3391 long int *object_id_list
;
3392 int *object_type_list
;
3393 DrcViolationType
*violation
;
3396 if (PCB
->Shrink
!= 0)
3398 Bloat
= -PCB
->Shrink
;
3399 ListStart (What
, ptr1
, ptr2
, ptr3
, DRCFLAG
| SELECTEDFLAG
);
3400 DoIt (DRCFLAG
| SELECTEDFLAG
, true, false);
3401 /* ok now the shrunk net has the SELECTEDFLAG set */
3403 ListStart (What
, ptr1
, ptr2
, ptr3
, FOUNDFLAG
);
3405 drc
= true; /* abort the search if we find anything not already found */
3406 if (DoIt (FOUNDFLAG
, true, false))
3409 /* make the flag changes undoable */
3410 ClearFlagOnAllObjects (false, FOUNDFLAG
| SELECTEDFLAG
);
3413 Bloat
= -PCB
->Shrink
;
3414 ListStart (What
, ptr1
, ptr2
, ptr3
, SELECTEDFLAG
);
3415 DoIt (SELECTEDFLAG
, true, true);
3417 ListStart (What
, ptr1
, ptr2
, ptr3
, FOUNDFLAG
);
3420 DoIt (FOUNDFLAG
, true, true);
3425 LocateError (&x
, &y
);
3426 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3427 violation
= pcb_drc_violation_new (_("Potential for broken trace"),
3428 _("Insufficient overlap between objects can lead to broken tracks\n"
3429 "due to registration errors with old wheel style photo-plotters."),
3431 0, /* ANGLE OF ERROR UNKNOWN */
3432 FALSE
, /* MEASUREMENT OF ERROR UNKNOWN */
3433 0, /* MAGNITUDE OF ERROR UNKNOWN */
3438 append_drc_violation (violation
);
3439 pcb_drc_violation_free (violation
);
3440 free (object_id_list
);
3441 free (object_type_list
);
3443 if (!throw_drc_dialog())
3445 IncrementUndoSerialNumber ();
3450 /* now check the bloated condition */
3452 ClearFlagOnAllObjects (false, FOUNDFLAG
| SELECTEDFLAG
);
3454 ListStart (What
, ptr1
, ptr2
, ptr3
, SELECTEDFLAG
);
3455 DoIt (SELECTEDFLAG
, true, false);
3458 ListStart (What
, ptr1
, ptr2
, ptr3
, flag
);
3461 while (DoIt (flag
, true, false))
3464 /* make the flag changes undoable */
3465 ClearFlagOnAllObjects (false, FOUNDFLAG
| SELECTEDFLAG
);
3469 ListStart (What
, ptr1
, ptr2
, ptr3
, SELECTEDFLAG
);
3470 DoIt (SELECTEDFLAG
, true, true);
3472 ListStart (What
, ptr1
, ptr2
, ptr3
, FOUNDFLAG
);
3475 DoIt (FOUNDFLAG
, true, true);
3478 LocateError (&x
, &y
);
3479 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3480 violation
= pcb_drc_violation_new (_("Copper areas too close"),
3481 _("Circuits that are too close may bridge during imaging, etching,\n"
3482 "plating, or soldering processes resulting in a direct short."),
3484 0, /* ANGLE OF ERROR UNKNOWN */
3485 FALSE
, /* MEASUREMENT OF ERROR UNKNOWN */
3486 0, /* MAGNITUDE OF ERROR UNKNOWN */
3491 append_drc_violation (violation
);
3492 pcb_drc_violation_free (violation
);
3493 free (object_id_list
);
3494 free (object_type_list
);
3497 if (!throw_drc_dialog())
3499 IncrementUndoSerialNumber ();
3501 /* highlight the rest of the encroaching net so it's not reported again */
3502 flag
= FOUNDFLAG
| SELECTEDFLAG
;
3504 ListStart (thing_type
, thing_ptr1
, thing_ptr2
, thing_ptr3
, flag
);
3505 DoIt (flag
, true, true);
3509 ListStart (What
, ptr1
, ptr2
, ptr3
, flag
);
3513 ClearFlagOnAllObjects (false, FOUNDFLAG
| SELECTEDFLAG
);
3518 * \brief DRC clearance callback.
3521 drc_callback (DataType
*data
, LayerType
*layer
, PolygonType
*polygon
,
3522 int type
, void *ptr1
, void *ptr2
, void *userdata
)
3524 struct drc_info
*i
= (struct drc_info
*) userdata
;
3528 long int *object_id_list
;
3529 int *object_type_list
;
3530 DrcViolationType
*violation
;
3532 LineType
*line
= (LineType
*) ptr2
;
3533 ArcType
*arc
= (ArcType
*) ptr2
;
3534 PinType
*pin
= (PinType
*) ptr2
;
3535 PadType
*pad
= (PadType
*) ptr2
;
3537 SetThing (type
, ptr1
, ptr2
, ptr2
);
3542 if (line
->Clearance
< 2 * PCB
->Bloat
)
3544 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr2
);
3545 SET_FLAG (i
->flag
, line
);
3546 message
= _("Line with insufficient clearance inside polygon\n");
3551 if (arc
->Clearance
< 2 * PCB
->Bloat
)
3553 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr2
);
3554 SET_FLAG (i
->flag
, arc
);
3555 message
= _("Arc with insufficient clearance inside polygon\n");
3560 if (pad
->Clearance
&& pad
->Clearance
< 2 * PCB
->Bloat
)
3561 if (IsPadInPolygon(pad
,polygon
))
3563 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr2
);
3564 SET_FLAG (i
->flag
, pad
);
3565 message
= _("Pad with insufficient clearance inside polygon\n");
3570 if (pin
->Clearance
&& pin
->Clearance
< 2 * PCB
->Bloat
)
3572 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr2
);
3573 SET_FLAG (i
->flag
, pin
);
3574 message
= _("Pin with insufficient clearance inside polygon\n");
3579 if (pin
->Clearance
&& pin
->Clearance
< 2 * PCB
->Bloat
)
3581 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr2
);
3582 SET_FLAG (i
->flag
, pin
);
3583 message
= _("Via with insufficient clearance inside polygon\n");
3588 Message ("hace: Bad Plow object in callback\n");
3593 AddObjectToFlagUndoList (POLYGON_TYPE
, layer
, polygon
, polygon
);
3594 SET_FLAG (FOUNDFLAG
, polygon
);
3595 DrawPolygon (layer
, polygon
);
3596 DrawObject (type
, ptr1
, ptr2
);
3598 LocateError (&x
, &y
);
3599 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3600 violation
= pcb_drc_violation_new (message
,
3601 _("Circuits that are too close may bridge during imaging, etching,\n"
3602 "plating, or soldering processes resulting in a direct short."),
3604 0, /* ANGLE OF ERROR UNKNOWN */
3605 FALSE
, /* MEASUREMENT OF ERROR UNKNOWN */
3606 0, /* MAGNITUDE OF ERROR UNKNOWN */
3611 append_drc_violation (violation
);
3612 pcb_drc_violation_free (violation
);
3613 free (object_id_list
);
3614 free (object_type_list
);
3616 if (!throw_drc_dialog())
3619 IncrementUndoSerialNumber ();
3625 * \brief Check for DRC violations.
3627 * See if the connectivity changes when everything is bloated, or shrunk.
3634 long int *object_id_list
;
3635 int *object_type_list
;
3636 DrcViolationType
*violation
;
3640 struct drc_info info
;
3642 reset_drc_dialog_message();
3646 SaveStackAndVisibility ();
3647 ResetStackAndVisibility ();
3648 hid_action ("LayersChanged");
3649 InitConnectionLookup ();
3651 if (ClearFlagOnAllObjects (true, FOUNDFLAG
| DRCFLAG
| SELECTEDFLAG
))
3653 IncrementUndoSerialNumber ();
3659 ELEMENT_LOOP (PCB
->Data
);
3663 if (!TEST_FLAG (DRCFLAG
, pin
)
3664 && DRCFind (PIN_TYPE
, (void *) element
, (void *) pin
, (void *) pin
))
3676 /* count up how many pads have no solderpaste openings */
3677 if (TEST_FLAG (NOPASTEFLAG
, pad
))
3680 if (!TEST_FLAG (DRCFLAG
, pad
)
3681 && DRCFind (PAD_TYPE
, (void *) element
, (void *) pad
, (void *) pad
))
3693 VIA_LOOP (PCB
->Data
);
3695 if (!TEST_FLAG (DRCFLAG
, via
)
3696 && DRCFind (VIA_TYPE
, (void *) via
, (void *) via
, (void *) via
))
3704 ClearFlagOnAllObjects (false, IsBad
? DRCFLAG
: (FOUNDFLAG
| DRCFLAG
| SELECTEDFLAG
));
3705 info
.flag
= SELECTEDFLAG
;
3706 /* check minimum widths and polygon clearances */
3709 COPPERLINE_LOOP (PCB
->Data
);
3711 /* check line clearances in polygons */
3712 if (PlowsPolygon (PCB
->Data
, LINE_TYPE
, layer
, line
, drc_callback
, &info
))
3717 if (line
->Thickness
< PCB
->minWid
)
3719 AddObjectToFlagUndoList (LINE_TYPE
, layer
, line
, line
);
3720 SET_FLAG (SELECTEDFLAG
, line
);
3721 DrawLine (layer
, line
);
3723 SetThing (LINE_TYPE
, layer
, line
, line
);
3724 LocateError (&x
, &y
);
3725 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3726 violation
= pcb_drc_violation_new (_("Line width is too thin"),
3727 _("Process specifications dictate a minimum feature-width\n"
3728 "that can reliably be reproduced"),
3730 0, /* ANGLE OF ERROR UNKNOWN */
3731 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3737 append_drc_violation (violation
);
3738 pcb_drc_violation_free (violation
);
3739 free (object_id_list
);
3740 free (object_type_list
);
3741 if (!throw_drc_dialog())
3746 IncrementUndoSerialNumber ();
3754 COPPERARC_LOOP (PCB
->Data
);
3756 if (PlowsPolygon (PCB
->Data
, ARC_TYPE
, layer
, arc
, drc_callback
, &info
))
3761 if (arc
->Thickness
< PCB
->minWid
)
3763 AddObjectToFlagUndoList (ARC_TYPE
, layer
, arc
, arc
);
3764 SET_FLAG (SELECTEDFLAG
, arc
);
3765 DrawArc (layer
, arc
);
3767 SetThing (ARC_TYPE
, layer
, arc
, arc
);
3768 LocateError (&x
, &y
);
3769 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3770 violation
= pcb_drc_violation_new (_("Arc width is too thin"),
3771 _("Process specifications dictate a minimum feature-width\n"
3772 "that can reliably be reproduced"),
3774 0, /* ANGLE OF ERROR UNKNOWN */
3775 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3781 append_drc_violation (violation
);
3782 pcb_drc_violation_free (violation
);
3783 free (object_id_list
);
3784 free (object_type_list
);
3785 if (!throw_drc_dialog())
3790 IncrementUndoSerialNumber ();
3798 ALLPIN_LOOP (PCB
->Data
);
3800 if (PlowsPolygon (PCB
->Data
, PIN_TYPE
, element
, pin
, drc_callback
, &info
))
3805 if (!TEST_FLAG (HOLEFLAG
, pin
) &&
3806 pin
->Thickness
- pin
->DrillingHole
< 2 * PCB
->minRing
)
3808 AddObjectToFlagUndoList (PIN_TYPE
, element
, pin
, pin
);
3809 SET_FLAG (SELECTEDFLAG
, pin
);
3812 SetThing (PIN_TYPE
, element
, pin
, pin
);
3813 LocateError (&x
, &y
);
3814 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3815 violation
= pcb_drc_violation_new (_("Pin annular ring too small"),
3816 _("Annular rings that are too small may erode during etching,\n"
3817 "resulting in a broken connection"),
3819 0, /* ANGLE OF ERROR UNKNOWN */
3820 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3821 (pin
->Thickness
- pin
->DrillingHole
) / 2,
3826 append_drc_violation (violation
);
3827 pcb_drc_violation_free (violation
);
3828 free (object_id_list
);
3829 free (object_type_list
);
3830 if (!throw_drc_dialog())
3835 IncrementUndoSerialNumber ();
3838 if (pin
->DrillingHole
< PCB
->minDrill
)
3840 AddObjectToFlagUndoList (PIN_TYPE
, element
, pin
, pin
);
3841 SET_FLAG (SELECTEDFLAG
, pin
);
3844 SetThing (PIN_TYPE
, element
, pin
, pin
);
3845 LocateError (&x
, &y
);
3846 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3847 violation
= pcb_drc_violation_new (_("Pin drill size is too small"),
3848 _("Process rules dictate the minimum drill size which can be used"),
3850 0, /* ANGLE OF ERROR UNKNOWN */
3851 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3857 append_drc_violation (violation
);
3858 pcb_drc_violation_free (violation
);
3859 free (object_id_list
);
3860 free (object_type_list
);
3861 if (!throw_drc_dialog())
3866 IncrementUndoSerialNumber ();
3874 ALLPAD_LOOP (PCB
->Data
);
3876 if (PlowsPolygon (PCB
->Data
, PAD_TYPE
, element
, pad
, drc_callback
, &info
))
3881 if (pad
->Thickness
< PCB
->minWid
)
3883 AddObjectToFlagUndoList (PAD_TYPE
, element
, pad
, pad
);
3884 SET_FLAG (SELECTEDFLAG
, pad
);
3887 SetThing (PAD_TYPE
, element
, pad
, pad
);
3888 LocateError (&x
, &y
);
3889 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3890 violation
= pcb_drc_violation_new (_("Pad is too thin"),
3891 _("Pads which are too thin may erode during etching,\n"
3892 "resulting in a broken or unreliable connection"),
3894 0, /* ANGLE OF ERROR UNKNOWN */
3895 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3901 append_drc_violation (violation
);
3902 pcb_drc_violation_free (violation
);
3903 free (object_id_list
);
3904 free (object_type_list
);
3905 if (!throw_drc_dialog())
3910 IncrementUndoSerialNumber ();
3918 VIA_LOOP (PCB
->Data
);
3920 if (PlowsPolygon (PCB
->Data
, VIA_TYPE
, via
, via
, drc_callback
, &info
))
3925 if (!TEST_FLAG (HOLEFLAG
, via
) &&
3926 via
->Thickness
- via
->DrillingHole
< 2 * PCB
->minRing
)
3928 AddObjectToFlagUndoList (VIA_TYPE
, via
, via
, via
);
3929 SET_FLAG (SELECTEDFLAG
, via
);
3932 SetThing (VIA_TYPE
, via
, via
, via
);
3933 LocateError (&x
, &y
);
3934 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3935 violation
= pcb_drc_violation_new (_("Via annular ring too small"),
3936 _("Annular rings that are too small may erode during etching,\n"
3937 "resulting in a broken connection"),
3939 0, /* ANGLE OF ERROR UNKNOWN */
3940 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3941 (via
->Thickness
- via
->DrillingHole
) / 2,
3946 append_drc_violation (violation
);
3947 pcb_drc_violation_free (violation
);
3948 free (object_id_list
);
3949 free (object_type_list
);
3950 if (!throw_drc_dialog())
3955 IncrementUndoSerialNumber ();
3958 if (via
->DrillingHole
< PCB
->minDrill
)
3960 AddObjectToFlagUndoList (VIA_TYPE
, via
, via
, via
);
3961 SET_FLAG (SELECTEDFLAG
, via
);
3964 SetThing (VIA_TYPE
, via
, via
, via
);
3965 LocateError (&x
, &y
);
3966 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
3967 violation
= pcb_drc_violation_new (_("Via drill size is too small"),
3968 _("Process rules dictate the minimum drill size which can be used"),
3970 0, /* ANGLE OF ERROR UNKNOWN */
3971 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
3977 append_drc_violation (violation
);
3978 pcb_drc_violation_free (violation
);
3979 free (object_id_list
);
3980 free (object_type_list
);
3981 if (!throw_drc_dialog())
3986 IncrementUndoSerialNumber ();
3993 FreeConnectionLookupMemory ();
3996 /* check silkscreen minimum widths outside of elements */
3997 /* XXX - need to check text and polygons too! */
4000 SILKLINE_LOOP (PCB
->Data
);
4002 if (line
->Thickness
< PCB
->minSlk
)
4004 SET_FLAG (SELECTEDFLAG
, line
);
4005 DrawLine (layer
, line
);
4007 SetThing (LINE_TYPE
, layer
, line
, line
);
4008 LocateError (&x
, &y
);
4009 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
4010 violation
= pcb_drc_violation_new (_("Silk line is too thin"),
4011 _("Process specifications dictate a minimum silkscreen\n"
4012 "feature-width that can reliably be reproduced"),
4014 0, /* ANGLE OF ERROR UNKNOWN */
4015 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
4021 append_drc_violation (violation
);
4022 pcb_drc_violation_free (violation
);
4023 free (object_id_list
);
4024 free (object_type_list
);
4025 if (!throw_drc_dialog())
4035 /* check silkscreen minimum widths inside of elements */
4036 /* XXX - need to check text and polygons too! */
4039 ELEMENT_LOOP (PCB
->Data
);
4042 ELEMENTLINE_LOOP (element
);
4044 if (line
->Thickness
< PCB
->minSlk
)
4055 SET_FLAG (SELECTEDFLAG
, element
);
4056 DrawElement (element
);
4058 SetThing (ELEMENT_TYPE
, element
, element
, element
);
4059 LocateError (&x
, &y
);
4060 BuildObjectList (&object_count
, &object_id_list
, &object_type_list
);
4062 title
= _("Element %s has %i silk lines which are too thin");
4063 name
= (char *)UNKNOWN (NAMEONPCB_NAME (element
));
4065 /* -4 is for the %s and %i place-holders */
4066 /* +11 is the max printed length for a 32 bit integer */
4067 /* +1 is for the \0 termination */
4068 buflen
= strlen (title
) - 4 + strlen (name
) + 11 + 1;
4069 buffer
= (char *)malloc (buflen
);
4070 snprintf (buffer
, buflen
, title
, name
, tmpcnt
);
4072 violation
= pcb_drc_violation_new (buffer
,
4073 _("Process specifications dictate a minimum silkscreen\n"
4074 "feature-width that can reliably be reproduced"),
4076 0, /* ANGLE OF ERROR UNKNOWN */
4077 TRUE
, /* MEASUREMENT OF ERROR KNOWN */
4078 0, /* MINIMUM OFFENDING WIDTH UNKNOWN */
4084 append_drc_violation (violation
);
4085 pcb_drc_violation_free (violation
);
4086 free (object_id_list
);
4087 free (object_type_list
);
4088 if (!throw_drc_dialog())
4101 IncrementUndoSerialNumber ();
4105 RestoreStackAndVisibility ();
4106 hid_action ("LayersChanged");
4107 gui
->invalidate_all ();
4111 Message (ngettext ("Warning: %d pad has the nopaste flag set.\n",
4112 "Warning: %d pads have the nopaste flag set.\n",
4113 nopastecnt
), nopastecnt
);
4115 return IsBad
? -drcerr_count
: drcerr_count
;
4119 * \brief Locate the coordinatates of offending item (thing).
4122 LocateError (Coord
*x
, Coord
*y
)
4128 LineType
*line
= (LineType
*) thing_ptr3
;
4129 *x
= (line
->Point1
.X
+ line
->Point2
.X
) / 2;
4130 *y
= (line
->Point1
.Y
+ line
->Point2
.Y
) / 2;
4135 ArcType
*arc
= (ArcType
*) thing_ptr3
;
4142 PolygonType
*polygon
= (PolygonType
*) thing_ptr3
;
4144 (polygon
->Clipped
->contours
->xmin
+
4145 polygon
->Clipped
->contours
->xmax
) / 2;
4147 (polygon
->Clipped
->contours
->ymin
+
4148 polygon
->Clipped
->contours
->ymax
) / 2;
4154 PinType
*pin
= (PinType
*) thing_ptr3
;
4161 PadType
*pad
= (PadType
*) thing_ptr3
;
4162 *x
= (pad
->Point1
.X
+ pad
->Point2
.X
) / 2;
4163 *y
= (pad
->Point1
.Y
+ pad
->Point2
.Y
) / 2;
4168 ElementType
*element
= (ElementType
*) thing_ptr3
;
4169 *x
= element
->MarkX
;
4170 *y
= element
->MarkY
;
4180 * \brief Build a list of the of offending items by ID.
4182 * (Currently just "thing").
4185 BuildObjectList (int *object_count
, long int **object_id_list
, int **object_type_list
)
4188 *object_id_list
= NULL
;
4189 *object_type_list
= NULL
;
4202 *object_id_list
= (long int *)malloc (sizeof (long int));
4203 *object_type_list
= (int *)malloc (sizeof (int));
4204 **object_id_list
= ((AnyObjectType
*)thing_ptr3
)->ID
;
4205 **object_type_list
= thing_type
;
4210 _("Internal error in BuildObjectList: unknown object type %i\n"),
4217 * \brief Center the display to show the offending item (thing).
4224 LocateError (&X
, &Y
);
4231 ChangeGroupVisibility (
4232 GetLayerNumber (PCB
->Data
, (LayerType
*) thing_ptr1
),
4235 CenterDisplay (X
, Y
, false);
4239 InitConnectionLookup (void)
4241 InitComponentLookup ();
4242 InitLayoutLookup ();
4246 FreeConnectionLookupMemory (void)
4248 FreeComponentLookupMemory ();
4249 FreeLayoutLookupMemory ();