6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
31 * some of the functions use dummy parameters
53 #ifdef HAVE_LIBDMALLOC
60 /* ---------------------------------------------------------------------------
61 * some local identifiers
63 static float PosX
, /* search position for subroutines */
65 static BDimension SearchRadius
;
66 static BoxType SearchBox
;
67 static LayerTypePtr SearchLayer
;
69 /* ---------------------------------------------------------------------------
70 * some local prototypes. The first parameter includes LOCKED_TYPE if we
71 * want to include locked types in the search.
73 static bool SearchLineByLocation (int, LayerTypePtr
*, LineTypePtr
*,
75 static bool SearchArcByLocation (int, LayerTypePtr
*, ArcTypePtr
*,
77 static bool SearchRatLineByLocation (int, RatTypePtr
*, RatTypePtr
*,
79 static bool SearchTextByLocation (int, LayerTypePtr
*, TextTypePtr
*,
81 static bool SearchPolygonByLocation (int, LayerTypePtr
*, PolygonTypePtr
*,
83 static bool SearchPinByLocation (int, ElementTypePtr
*, PinTypePtr
*,
85 static bool SearchPadByLocation (int, ElementTypePtr
*, PadTypePtr
*,
87 static bool SearchViaByLocation (int, PinTypePtr
*, PinTypePtr
*,
89 static bool SearchElementNameByLocation (int, ElementTypePtr
*,
90 TextTypePtr
*, TextTypePtr
*,
92 static bool SearchLinePointByLocation (int, LayerTypePtr
*, LineTypePtr
*,
94 static bool SearchPointByLocation (int, LayerTypePtr
*, PolygonTypePtr
*,
96 static bool SearchElementByLocation (int, ElementTypePtr
*,
97 ElementTypePtr
*, ElementTypePtr
*,
100 /* ---------------------------------------------------------------------------
105 void **ptr1
, **ptr2
, **ptr3
;
109 int locked
; /* This will be zero or LOCKFLAG */
113 pinorvia_callback (const BoxType
* box
, void *cl
)
115 struct ans_info
*i
= (struct ans_info
*) cl
;
116 PinTypePtr pin
= (PinTypePtr
) box
;
118 if (TEST_FLAG (i
->locked
, pin
))
121 if (!IsPointOnPin (PosX
, PosY
, SearchRadius
, pin
))
123 *i
->ptr1
= pin
->Element
? pin
->Element
: pin
;
124 *i
->ptr2
= *i
->ptr3
= pin
;
126 return 1; /* never reached */
130 SearchViaByLocation (int locked
, PinTypePtr
* Via
, PinTypePtr
* Dummy1
,
133 struct ans_info info
;
135 /* search only if via-layer is visible */
139 info
.ptr1
= (void **) Via
;
140 info
.ptr2
= (void **) Dummy1
;
141 info
.ptr3
= (void **) Dummy2
;
142 info
.locked
= (locked
& LOCKED_TYPE
) ? 0 : LOCKFLAG
;
144 if (setjmp (info
.env
) == 0)
146 r_search (PCB
->Data
->via_tree
, &SearchBox
, NULL
, pinorvia_callback
,
153 /* ---------------------------------------------------------------------------
155 * starts with the newest element
158 SearchPinByLocation (int locked
, ElementTypePtr
* Element
, PinTypePtr
* Pin
,
161 struct ans_info info
;
163 /* search only if pin-layer is visible */
166 info
.ptr1
= (void **) Element
;
167 info
.ptr2
= (void **) Pin
;
168 info
.ptr3
= (void **) Dummy
;
169 info
.locked
= (locked
& LOCKED_TYPE
) ? 0 : LOCKFLAG
;
171 if (setjmp (info
.env
) == 0)
172 r_search (PCB
->Data
->pin_tree
, &SearchBox
, NULL
, pinorvia_callback
,
180 pad_callback (const BoxType
* b
, void *cl
)
182 PadTypePtr pad
= (PadTypePtr
) b
;
183 struct ans_info
*i
= (struct ans_info
*) cl
;
185 if (TEST_FLAG (i
->locked
, pad
))
188 if (FRONT (pad
) || i
->BackToo
)
190 if (IsPointInPad (PosX
, PosY
, SearchRadius
, pad
))
192 *i
->ptr1
= pad
->Element
;
193 *i
->ptr2
= *i
->ptr3
= pad
;
200 /* ---------------------------------------------------------------------------
202 * starts with the newest element
205 SearchPadByLocation (int locked
, ElementTypePtr
* Element
, PadTypePtr
* Pad
,
206 PadTypePtr
* Dummy
, bool BackToo
)
208 struct ans_info info
;
210 /* search only if pin-layer is visible */
213 info
.ptr1
= (void **) Element
;
214 info
.ptr2
= (void **) Pad
;
215 info
.ptr3
= (void **) Dummy
;
216 info
.locked
= (locked
& LOCKED_TYPE
) ? 0 : LOCKFLAG
;
217 info
.BackToo
= (BackToo
&& PCB
->InvisibleObjectsOn
);
218 if (setjmp (info
.env
) == 0)
219 r_search (PCB
->Data
->pad_tree
, &SearchBox
, NULL
, pad_callback
, &info
);
225 /* ---------------------------------------------------------------------------
226 * searches ordinary line on the SearchLayer
239 line_callback (const BoxType
* box
, void *cl
)
241 struct line_info
*i
= (struct line_info
*) cl
;
242 LineTypePtr l
= (LineTypePtr
) box
;
244 if (TEST_FLAG (i
->locked
, l
))
247 if (!IsPointInPad (PosX
, PosY
, SearchRadius
, (PadTypePtr
)l
))
250 *i
->Point
= (PointTypePtr
) l
;
252 return 1; /* never reached */
257 SearchLineByLocation (int locked
, LayerTypePtr
* Layer
, LineTypePtr
* Line
,
260 struct line_info info
;
263 info
.Point
= (PointTypePtr
*) Dummy
;
264 info
.locked
= (locked
& LOCKED_TYPE
) ? 0 : LOCKFLAG
;
266 *Layer
= SearchLayer
;
267 if (setjmp (info
.env
) == 0)
269 r_search (SearchLayer
->line_tree
, &SearchBox
, NULL
, line_callback
,
277 rat_callback (const BoxType
* box
, void *cl
)
279 LineTypePtr line
= (LineTypePtr
) box
;
280 struct ans_info
*i
= (struct ans_info
*) cl
;
282 if (TEST_FLAG (i
->locked
, line
))
285 if (TEST_FLAG (VIAFLAG
, line
) ?
286 (SQUARE (line
->Point1
.X
- PosX
) + SQUARE (line
->Point1
.Y
- PosY
) <=
287 SQUARE (line
->Thickness
* 2 + SearchRadius
)) :
288 IsPointOnLine (PosX
, PosY
, SearchRadius
, line
))
290 *i
->ptr1
= *i
->ptr2
= *i
->ptr3
= line
;
296 /* ---------------------------------------------------------------------------
297 * searches rat lines if they are visible
300 SearchRatLineByLocation (int locked
, RatTypePtr
* Line
, RatTypePtr
* Dummy1
,
303 struct ans_info info
;
305 info
.ptr1
= (void **) Line
;
306 info
.ptr2
= (void **) Dummy1
;
307 info
.ptr3
= (void **) Dummy2
;
308 info
.locked
= (locked
& LOCKED_TYPE
) ? 0 : LOCKFLAG
;
310 if (setjmp (info
.env
) == 0)
312 r_search (PCB
->Data
->rat_tree
, &SearchBox
, NULL
, rat_callback
, &info
);
318 /* ---------------------------------------------------------------------------
319 * searches arc on the SearchLayer
323 ArcTypePtr
*Arc
, *Dummy
;
329 arc_callback (const BoxType
* box
, void *cl
)
331 struct arc_info
*i
= (struct arc_info
*) cl
;
332 ArcTypePtr a
= (ArcTypePtr
) box
;
334 if (TEST_FLAG (i
->locked
, a
))
337 if (!IsPointOnArc (PosX
, PosY
, SearchRadius
, a
))
342 return 1; /* never reached */
347 SearchArcByLocation (int locked
, LayerTypePtr
* Layer
, ArcTypePtr
* Arc
,
350 struct arc_info info
;
354 info
.locked
= (locked
& LOCKED_TYPE
) ? 0 : LOCKFLAG
;
356 *Layer
= SearchLayer
;
357 if (setjmp (info
.env
) == 0)
359 r_search (SearchLayer
->arc_tree
, &SearchBox
, NULL
, arc_callback
, &info
);
366 text_callback (const BoxType
* box
, void *cl
)
368 TextTypePtr text
= (TextTypePtr
) box
;
369 struct ans_info
*i
= (struct ans_info
*) cl
;
371 if (TEST_FLAG (i
->locked
, text
))
374 if (POINT_IN_BOX (PosX
, PosY
, &text
->BoundingBox
))
376 *i
->ptr2
= *i
->ptr3
= text
;
382 /* ---------------------------------------------------------------------------
383 * searches text on the SearchLayer
386 SearchTextByLocation (int locked
, LayerTypePtr
* Layer
, TextTypePtr
* Text
,
389 struct ans_info info
;
391 *Layer
= SearchLayer
;
392 info
.ptr2
= (void **) Text
;
393 info
.ptr3
= (void **) Dummy
;
394 info
.locked
= (locked
& LOCKED_TYPE
) ? 0 : LOCKFLAG
;
396 if (setjmp (info
.env
) == 0)
398 r_search (SearchLayer
->text_tree
, &SearchBox
, NULL
, text_callback
,
406 polygon_callback (const BoxType
* box
, void *cl
)
408 PolygonTypePtr polygon
= (PolygonTypePtr
) box
;
409 struct ans_info
*i
= (struct ans_info
*) cl
;
411 if (TEST_FLAG (i
->locked
, polygon
))
414 if (IsPointInPolygon (PosX
, PosY
, SearchRadius
, polygon
))
416 *i
->ptr2
= *i
->ptr3
= polygon
;
423 /* ---------------------------------------------------------------------------
424 * searches a polygon on the SearchLayer
427 SearchPolygonByLocation (int locked
, LayerTypePtr
* Layer
,
428 PolygonTypePtr
* Polygon
, PolygonTypePtr
* Dummy
)
430 struct ans_info info
;
432 *Layer
= SearchLayer
;
433 info
.ptr2
= (void **) Polygon
;
434 info
.ptr3
= (void **) Dummy
;
435 info
.locked
= (locked
& LOCKED_TYPE
) ? 0 : LOCKFLAG
;
437 if (setjmp (info
.env
) == 0)
439 r_search (SearchLayer
->polygon_tree
, &SearchBox
, NULL
, polygon_callback
,
447 linepoint_callback (const BoxType
* b
, void *cl
)
449 LineTypePtr line
= (LineTypePtr
) b
;
450 struct line_info
*i
= (struct line_info
*) cl
;
454 if (TEST_FLAG (i
->locked
, line
))
457 /* some stupid code to check both points */
458 d
= SQUARE (PosX
- line
->Point1
.X
) + SQUARE (PosY
- line
->Point1
.Y
);
463 *i
->Point
= &line
->Point1
;
467 d
= SQUARE (PosX
- line
->Point2
.X
) + SQUARE (PosY
- line
->Point2
.Y
);
472 *i
->Point
= &line
->Point2
;
478 /* ---------------------------------------------------------------------------
479 * searches a line-point on all the search layer
482 SearchLinePointByLocation (int locked
, LayerTypePtr
* Layer
,
483 LineTypePtr
* Line
, PointTypePtr
* Point
)
485 struct line_info info
;
486 *Layer
= SearchLayer
;
491 (MAX_LINE_POINT_DISTANCE
+ SearchRadius
) * (MAX_LINE_POINT_DISTANCE
+
493 info
.locked
= (locked
& LOCKED_TYPE
) ? 0 : LOCKFLAG
;
495 (SearchLayer
->line_tree
, &SearchBox
, NULL
, linepoint_callback
, &info
))
500 /* ---------------------------------------------------------------------------
501 * searches a polygon-point on all layers that are switched on
502 * in layerstack order
505 SearchPointByLocation (int locked
, LayerTypePtr
* Layer
,
506 PolygonTypePtr
* Polygon
, PointTypePtr
* Point
)
511 least
= SQUARE (SearchRadius
+ MAX_POLYGON_POINT_DISTANCE
);
512 *Layer
= SearchLayer
;
513 POLYGON_LOOP (*Layer
);
515 POLYGONPOINT_LOOP (polygon
);
517 d
= SQUARE (point
->X
- PosX
) + SQUARE (point
->Y
- PosY
);
535 name_callback (const BoxType
* box
, void *cl
)
537 TextTypePtr text
= (TextTypePtr
) box
;
538 struct ans_info
*i
= (struct ans_info
*) cl
;
539 ElementTypePtr element
= (ElementTypePtr
) text
->Element
;
542 if (TEST_FLAG (i
->locked
, text
))
545 if ((FRONT (element
) || i
->BackToo
) && !TEST_FLAG (HIDENAMEFLAG
, element
) &&
546 POINT_IN_BOX (PosX
, PosY
, &text
->BoundingBox
))
548 /* use the text with the smallest bounding box */
549 newarea
= (text
->BoundingBox
.X2
- text
->BoundingBox
.X1
) *
550 (float) (text
->BoundingBox
.Y2
- text
->BoundingBox
.Y1
);
551 if (newarea
< i
->area
)
555 *i
->ptr2
= *i
->ptr3
= text
;
562 /* ---------------------------------------------------------------------------
563 * searches the name of an element
564 * the search starts with the last element and goes back to the beginning
567 SearchElementNameByLocation (int locked
, ElementTypePtr
* Element
,
568 TextTypePtr
* Text
, TextTypePtr
* Dummy
,
571 struct ans_info info
;
573 /* package layer have to be switched on */
576 info
.ptr1
= (void **) Element
;
577 info
.ptr2
= (void **) Text
;
578 info
.ptr3
= (void **) Dummy
;
579 info
.area
= SQUARE (MAX_COORD
);
580 info
.BackToo
= (BackToo
&& PCB
->InvisibleObjectsOn
);
581 info
.locked
= (locked
& LOCKED_TYPE
) ? 0 : LOCKFLAG
;
582 if (r_search (PCB
->Data
->name_tree
[NAME_INDEX (PCB
)], &SearchBox
, NULL
,
583 name_callback
, &info
))
590 element_callback (const BoxType
* box
, void *cl
)
592 ElementTypePtr element
= (ElementTypePtr
) box
;
593 struct ans_info
*i
= (struct ans_info
*) cl
;
596 if (TEST_FLAG (i
->locked
, element
))
599 if ((FRONT (element
) || i
->BackToo
) &&
600 POINT_IN_BOX (PosX
, PosY
, &element
->VBox
))
602 /* use the element with the smallest bounding box */
603 newarea
= (element
->VBox
.X2
- element
->VBox
.X1
) *
604 (float) (element
->VBox
.Y2
- element
->VBox
.Y1
);
605 if (newarea
< i
->area
)
608 *i
->ptr1
= *i
->ptr2
= *i
->ptr3
= element
;
615 /* ---------------------------------------------------------------------------
616 * searches an element
617 * the search starts with the last element and goes back to the beginning
618 * if more than one element matches, the smallest one is taken
621 SearchElementByLocation (int locked
,
622 ElementTypePtr
* Element
,
623 ElementTypePtr
* Dummy1
, ElementTypePtr
* Dummy2
,
626 struct ans_info info
;
628 /* Both package layers have to be switched on */
629 if (PCB
->ElementOn
&& PCB
->PinOn
)
631 info
.ptr1
= (void **) Element
;
632 info
.ptr2
= (void **) Dummy1
;
633 info
.ptr3
= (void **) Dummy2
;
634 info
.area
= SQUARE (MAX_COORD
);
635 info
.BackToo
= (BackToo
&& PCB
->InvisibleObjectsOn
);
636 info
.locked
= (locked
& LOCKED_TYPE
) ? 0 : LOCKFLAG
;
638 (PCB
->Data
->element_tree
, &SearchBox
, NULL
, element_callback
,
645 /* ---------------------------------------------------------------------------
646 * checks if a point is on a pin
649 IsPointOnPin (float X
, float Y
, float Radius
, PinTypePtr pin
)
651 if (TEST_FLAG (SQUAREFLAG
, pin
))
654 BDimension t
= pin
->Thickness
/ 2;
660 if (IsPointInBox (X
, Y
, &b
, Radius
))
663 else if (SQUARE (pin
->X
- X
) + SQUARE (pin
->Y
- Y
) <=
664 SQUARE (pin
->Thickness
/ 2 + Radius
))
669 /* ---------------------------------------------------------------------------
670 * checks if a rat-line end is on a PV
673 IsPointOnLineEnd (LocationType X
, LocationType Y
, RatTypePtr Line
)
675 if (((X
== Line
->Point1
.X
) && (Y
== Line
->Point1
.Y
)) ||
676 ((X
== Line
->Point2
.X
) && (Y
== Line
->Point2
.Y
)))
681 /* ---------------------------------------------------------------------------
682 * checks if a line intersects with a PV
683 * constant recognition by the optimizer is assumed
685 * let the point be (X,Y) and the line (X1,Y1)(X2,Y2)
686 * the length of the line is
688 * l = ((X2-X1)^2 + (Y2-Y1)^2)^0.5
690 * let Q be the point of perpendicular projection of (X,Y) onto the line
695 * with (from vector geometry)
697 * (Y1-Y)(Y1-Y2)+(X1-X)(X1-X2)
698 * r = ---------------------------
701 * r < 0 Q is on backward extension of the line
702 * r > 1 Q is on forward extension of the line
703 * else Q is on the line
705 * the signed distance from (X,Y) to Q is
707 * (Y2-Y1)(X-X1)-(X2-X1)(Y-Y1)
708 * d = ----------------------------
712 IsPointOnLine (float X
, float Y
, float Radius
, LineTypePtr Line
)
714 register float dx
, dy
, dx1
, dy1
, l
, d
, r
;
715 Radius
+= ((float) Line
->Thickness
+ 1.) / 2.0;
716 if (Y
+ Radius
< MIN (Line
->Point1
.Y
, Line
->Point2
.Y
) ||
717 Y
- Radius
> MAX (Line
->Point1
.Y
, Line
->Point2
.Y
))
719 dx
= (float) (Line
->Point2
.X
- Line
->Point1
.X
);
720 dy
= (float) (Line
->Point2
.Y
- Line
->Point1
.Y
);
721 dx1
= (float) (Line
->Point1
.X
- X
);
722 dy1
= (float) (Line
->Point1
.Y
- Y
);
723 d
= dx
* dy1
- dy
* dx1
;
725 /* check distance from PV to line */
727 if ((l
= dx
* dx
+ dy
* dy
) == 0.0)
729 l
= SQUARE (Line
->Point1
.X
- X
) + SQUARE (Line
->Point1
.Y
- Y
);
730 return ((l
<= Radius
) ? true : false);
732 if (d
* d
> Radius
* l
)
735 /* they intersect if Q is on line */
736 r
= -(dx
* dx1
+ dy
* dy1
);
737 if (r
>= 0 && r
<= l
)
740 /* we have to check P1 or P2 depending on the sign of r */
742 return ((dx1
* dx1
+ dy1
* dy1
) <= Radius
);
743 dx1
= Line
->Point2
.X
- X
;
744 dy1
= Line
->Point2
.Y
- Y
;
745 return ((dx1
* dx1
+ dy1
* dy1
) <= Radius
);
748 /* ---------------------------------------------------------------------------
749 * checks if a line crosses a rectangle
752 IsLineInRectangle (LocationType X1
, LocationType Y1
,
753 LocationType X2
, LocationType Y2
, LineTypePtr Line
)
757 /* first, see if point 1 is inside the rectangle */
758 /* in case the whole line is inside the rectangle */
759 if (X1
< Line
->Point1
.X
&& X2
> Line
->Point1
.X
&&
760 Y1
< Line
->Point1
.Y
&& Y2
> Line
->Point1
.Y
)
762 /* construct a set of dummy lines and check each of them */
764 line
.Flags
= NoFlags ();
766 /* upper-left to upper-right corner */
767 line
.Point1
.Y
= line
.Point2
.Y
= Y1
;
770 if (LineLineIntersect (&line
, Line
))
773 /* upper-right to lower-right corner */
777 if (LineLineIntersect (&line
, Line
))
780 /* lower-right to lower-left corner */
784 if (LineLineIntersect (&line
, Line
))
787 /* lower-left to upper-left corner */
791 if (LineLineIntersect (&line
, Line
))
797 sign(float x
){return x
<0?-1:x
>0?1:0;}
798 static int /*checks if a point (of null radius) is in a slanted rectangle*/
799 IsPointInQuadrangle(PointType p
[4],PointTypePtr l
)
804 dx
= p
[1].X
- p
[0].X
;
805 dy
= p
[1].Y
- p
[0].Y
;
808 prod0
= (float)x
* dx
+ (float)y
* dy
;
811 prod1
= (float)x
* dx
+ (float)y
* dy
;
812 if (sign (prod0
) * sign (prod1
) <= 0)
814 dx
= p
[1].X
- p
[2].X
;
815 dy
= p
[1].Y
- p
[2].Y
;
816 prod0
= (float)x
* dx
+ (float)y
* dy
;
819 prod1
= (float)x
* dx
+ (float)y
* dy
;
820 if (sign (prod0
) * sign (prod1
) <= 0)
825 /* ---------------------------------------------------------------------------
826 * checks if a line crosses a quadrangle: almost copied from IsLineInRectangle()
827 * Note: actually this quadrangle is a slanted rectangle
830 IsLineInQuadrangle (PointType p
[4], LineTypePtr Line
)
834 /* first, see if point 1 is inside the rectangle */
835 /* in case the whole line is inside the rectangle */
836 if (IsPointInQuadrangle(p
,&(Line
->Point1
)))
838 if (IsPointInQuadrangle(p
,&(Line
->Point2
)))
840 /* construct a set of dummy lines and check each of them */
842 line
.Flags
= NoFlags ();
844 /* upper-left to upper-right corner */
845 line
.Point1
.X
= p
[0].X
; line
.Point1
.Y
= p
[0].Y
;
846 line
.Point2
.X
= p
[1].X
; line
.Point2
.Y
= p
[1].Y
;
847 if (LineLineIntersect (&line
, Line
))
850 /* upper-right to lower-right corner */
851 line
.Point1
.X
= p
[2].X
; line
.Point1
.Y
= p
[2].Y
;
852 if (LineLineIntersect (&line
, Line
))
855 /* lower-right to lower-left corner */
856 line
.Point2
.X
= p
[3].X
; line
.Point2
.Y
= p
[3].Y
;
857 if (LineLineIntersect (&line
, Line
))
860 /* lower-left to upper-left corner */
861 line
.Point1
.X
= p
[0].X
; line
.Point1
.Y
= p
[0].Y
;
862 if (LineLineIntersect (&line
, Line
))
867 /* ---------------------------------------------------------------------------
868 * checks if an arc crosses a square
871 IsArcInRectangle (LocationType X1
, LocationType Y1
,
872 LocationType X2
, LocationType Y2
, ArcTypePtr Arc
)
876 /* construct a set of dummy lines and check each of them */
878 line
.Flags
= NoFlags ();
880 /* upper-left to upper-right corner */
881 line
.Point1
.Y
= line
.Point2
.Y
= Y1
;
884 if (LineArcIntersect (&line
, Arc
))
887 /* upper-right to lower-right corner */
888 line
.Point1
.X
= line
.Point2
.X
= X2
;
891 if (LineArcIntersect (&line
, Arc
))
894 /* lower-right to lower-left corner */
895 line
.Point1
.Y
= line
.Point2
.Y
= Y2
;
898 if (LineArcIntersect (&line
, Arc
))
901 /* lower-left to upper-left corner */
902 line
.Point1
.X
= line
.Point2
.X
= X1
;
905 if (LineArcIntersect (&line
, Arc
))
911 /* ---------------------------------------------------------------------------
912 * Check if a circle of Radius with center at (X, Y) intersects a Pad.
913 * Written to enable arbitrary pad directions; for rounded pads, too.
916 IsPointInPad (LocationType X
, LocationType Y
, BDimension Radius
,
921 BDimension t2
= (Pad
->Thickness
+ 1) / 2, range
;
924 /* series of transforms saving range */
925 /* move Point1 to the origin */
929 pad
.Point2
.X
-= pad
.Point1
.X
;
930 pad
.Point2
.Y
-= pad
.Point1
.Y
;
931 /* so, pad.Point1.X = pad.Point1.Y = 0; */
933 /* rotate round (0, 0) so that Point2 coordinates be (r, 0) */
934 r
= sqrt ((double)pad
.Point2
.X
* pad
.Point2
.X
+
935 (double)pad
.Point2
.Y
* pad
.Point2
.Y
);
943 Sin
= pad
.Point2
.Y
/ r
;
944 Cos
= pad
.Point2
.X
/ r
;
947 X
= X
* Cos
+ Y
* Sin
;
948 Y
= Y
* Cos
- x
* Sin
;
949 /* now pad.Point2.X = r; pad.Point2.Y = 0; */
951 /* take into account the ends */
952 if (TEST_FLAG (SQUAREFLAG
, Pad
))
958 Y
= -Y
; /* range value is evident now*/
960 if (TEST_FLAG (SQUAREFLAG
, Pad
))
964 if ( Y
<= t2
) range
= -X
; else
965 return (Radius
>= 0) && (Radius
* (double)Radius
>
966 (double)(t2
- Y
) * (t2
- Y
) + (double)X
* X
);
970 if ( Y
<= t2
) range
= X
- r
; else
971 return (Radius
>= 0) && (Radius
* (double)Radius
>
972 (double)(t2
- Y
) * (t2
- Y
) + (double)(X
- r
) * (X
- r
));
977 else/*Rounded pad: even more simple*/
980 return (Radius
+ t2
>= 0) && ((Radius
+ t2
) * (double)(Radius
+ t2
) >
981 (double)X
* X
+ (double)Y
* Y
);
983 return (Radius
+ t2
>= 0) && ((Radius
+ t2
) * (double)(Radius
+ t2
) >
984 (double)(X
- r
) * (X
- r
) + (double)Y
* Y
);
988 return range
< Radius
;
992 IsPointInBox (LocationType X
, LocationType Y
, BoxTypePtr box
, BDimension Radius
)
994 BDimension width
, height
, range
;
996 /* NB: Assumes box has point1 with numerically lower X and Y coordinates */
998 /* Compute coordinates relative to Point1 */
1002 width
= box
->X2
- box
->X1
;
1003 height
= box
->Y2
- box
->Y1
;
1008 return (Radius
>= 0) && (Radius
* (double)Radius
>
1009 (double)Y
* Y
+ (double)X
* X
);
1010 else if (Y
> height
)
1011 return (Radius
>= 0) && (Radius
* (double)Radius
>
1012 (double)(Y
- height
) * (Y
- height
) + (double)X
* X
);
1016 else if (X
>= width
)
1019 return (Radius
>= 0) && (Radius
* (double)Radius
>
1020 (double)Y
* Y
+ (double)(X
- width
) * (X
- width
));
1021 else if (Y
> height
)
1022 return (Radius
>= 0) && (Radius
* (double)Radius
>
1023 (double)(Y
- height
) * (Y
- height
) + (double)(X
- width
) * (X
- width
));
1031 else if (Y
> height
)
1037 return range
< Radius
;
1041 IsPointOnArc (float X
, float Y
, float Radius
, ArcTypePtr Arc
)
1043 double x
, y
, dx
, dy
, r1
, r2
, a
, d
, l
;
1045 double ang1
, ang2
, ang0
, delta
;
1046 int startAngle
, arcDelta
;
1050 l
= pdx
* pdx
+ pdy
* pdy
;
1051 Radius
+= 0.5 * Arc
->Thickness
;
1052 if (Radius
< 0) /* thin arc: trivial condition */
1054 /* concentric arcs, simpler intersection conditions */
1057 if (Arc
->Width
<= Radius
)
1064 if (sqrt (l
) < r2
- r1
) /* the arc merged in the circle */
1068 a
= 0.5 * (r1
- r2
+ l
) / l
;
1071 /* the circles are too far apart to touch or probably just touch */
1074 /* project the points of intersection */
1080 /* arrgh! calculate the angles, and put them in a standard range */
1081 startAngle
= Arc
->StartAngle
;
1082 arcDelta
= Arc
->Delta
;
1085 startAngle
+= arcDelta
;
1086 arcDelta
= -arcDelta
;
1090 while (startAngle
< 0)
1092 while (startAngle
> 360)
1094 ang1
= RAD_TO_DEG
* atan2 ((y
+ dy
), -(x
+ dx
));
1097 ang2
= RAD_TO_DEG
* atan2 ((y
- dy
), -(x
- dx
));
1106 delta
= ang2
- ang1
;
1107 /* ang0 does not belong to intersection range */
1108 ang0
= RAD_TO_DEG
* atan2 (-pdy
, pdx
);
1111 if (ang0
> ang1
&& ang0
< ang2
) /* we need the other part of circle */
1114 delta
= 360 - delta
;
1116 if (ang1
>= startAngle
&& ang1
<= startAngle
+ arcDelta
)
1118 if (startAngle
>= ang1
&& startAngle
<= ang1
+ delta
)
1120 if (startAngle
+ arcDelta
>= 360 && ang1
<= startAngle
+ arcDelta
- 360)
1122 if (ang1
+ delta
>= 360 && startAngle
<= ang1
+ delta
- 360)
1127 /* ---------------------------------------------------------------------------
1128 * searches for any kind of object or for a set of object types
1129 * the calling routine passes two pointers to allocated memory for storing
1131 * A type value is returned too which is NO_TYPE if no objects has been found.
1132 * A set of object types is passed in.
1133 * The object is located by it's position.
1135 * The layout is checked in the following order:
1136 * polygon-point, pin, via, line, text, elementname, polygon, element
1138 * Note that if Type includes LOCKED_TYPE, then the search includes
1139 * locked items. Otherwise, locked items are ignored.
1142 SearchObjectByLocation (int Type
,
1143 void **Result1
, void **Result2
, void **Result3
,
1144 LocationType X
, LocationType Y
, BDimension Radius
)
1147 void **pr1
= &r1
, **pr2
= &r2
, **pr3
= &r3
;
1149 float HigherBound
= 0;
1150 int HigherAvail
= NO_TYPE
;
1151 int locked
= Type
& LOCKED_TYPE
;
1152 /* setup variables used by local functions */
1155 SearchRadius
= Radius
;
1158 SearchBox
.X1
= X
- Radius
;
1159 SearchBox
.Y1
= Y
- Radius
;
1160 SearchBox
.X2
= X
+ Radius
;
1161 SearchBox
.Y2
= Y
+ Radius
;
1165 SearchBox
= point_box (X
, Y
);
1168 if (TEST_FLAG (LOCKNAMESFLAG
, PCB
)
1169 || TEST_FLAG (HIDENAMESFLAG
, PCB
))
1171 Type
&= ~ (ELEMENTNAME_TYPE
| TEXT_TYPE
);
1173 if (TEST_FLAG (ONLYNAMESFLAG
, PCB
))
1175 Type
&= (ELEMENTNAME_TYPE
| TEXT_TYPE
);
1177 if (TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG (THINDRAWPOLYFLAG
, PCB
))
1179 Type
&= ~POLYGON_TYPE
;
1182 if (Type
& RATLINE_TYPE
&& PCB
->RatOn
&&
1183 SearchRatLineByLocation (locked
,
1184 (RatTypePtr
*) Result1
,
1185 (RatTypePtr
*) Result2
,
1186 (RatTypePtr
*) Result3
))
1187 return (RATLINE_TYPE
);
1189 if (Type
& VIA_TYPE
&&
1190 SearchViaByLocation (locked
,
1191 (PinTypePtr
*) Result1
,
1192 (PinTypePtr
*) Result2
, (PinTypePtr
*) Result3
))
1195 if (Type
& PIN_TYPE
&&
1196 SearchPinByLocation (locked
,
1197 (ElementTypePtr
*) pr1
,
1198 (PinTypePtr
*) pr2
, (PinTypePtr
*) pr3
))
1199 HigherAvail
= PIN_TYPE
;
1201 if (!HigherAvail
&& Type
& PAD_TYPE
&&
1202 SearchPadByLocation (locked
,
1203 (ElementTypePtr
*) pr1
,
1204 (PadTypePtr
*) pr2
, (PadTypePtr
*) pr3
, false))
1205 HigherAvail
= PAD_TYPE
;
1207 if (!HigherAvail
&& Type
& ELEMENTNAME_TYPE
&&
1208 SearchElementNameByLocation (locked
,
1209 (ElementTypePtr
*) pr1
,
1210 (TextTypePtr
*) pr2
, (TextTypePtr
*) pr3
,
1213 BoxTypePtr box
= &((TextTypePtr
) r2
)->BoundingBox
;
1214 HigherBound
= (float) (box
->X2
- box
->X1
) * (float) (box
->Y2
- box
->Y1
);
1215 HigherAvail
= ELEMENTNAME_TYPE
;
1218 if (!HigherAvail
&& Type
& ELEMENT_TYPE
&&
1219 SearchElementByLocation (locked
,
1220 (ElementTypePtr
*) pr1
,
1221 (ElementTypePtr
*) pr2
,
1222 (ElementTypePtr
*) pr3
, false))
1224 BoxTypePtr box
= &((ElementTypePtr
) r1
)->BoundingBox
;
1225 HigherBound
= (float) (box
->X2
- box
->X1
) * (float) (box
->Y2
- box
->Y1
);
1226 HigherAvail
= ELEMENT_TYPE
;
1229 for (i
= -1; i
< max_copper_layer
+ 1; i
++)
1232 SearchLayer
= &PCB
->Data
->SILKLAYER
;
1233 else if (i
< max_copper_layer
)
1234 SearchLayer
= LAYER_ON_STACK (i
);
1237 SearchLayer
= &PCB
->Data
->BACKSILKLAYER
;
1238 if (!PCB
->InvisibleObjectsOn
)
1241 if (SearchLayer
->On
)
1243 if ((HigherAvail
& (PIN_TYPE
| PAD_TYPE
)) == 0 &&
1244 Type
& POLYGONPOINT_TYPE
&&
1245 SearchPointByLocation (locked
,
1246 (LayerTypePtr
*) Result1
,
1247 (PolygonTypePtr
*) Result2
,
1248 (PointTypePtr
*) Result3
))
1249 return (POLYGONPOINT_TYPE
);
1251 if ((HigherAvail
& (PIN_TYPE
| PAD_TYPE
)) == 0 &&
1252 Type
& LINEPOINT_TYPE
&&
1253 SearchLinePointByLocation (locked
,
1254 (LayerTypePtr
*) Result1
,
1255 (LineTypePtr
*) Result2
,
1256 (PointTypePtr
*) Result3
))
1257 return (LINEPOINT_TYPE
);
1259 if ((HigherAvail
& (PIN_TYPE
| PAD_TYPE
)) == 0 && Type
& LINE_TYPE
1260 && SearchLineByLocation (locked
,
1261 (LayerTypePtr
*) Result1
,
1262 (LineTypePtr
*) Result2
,
1263 (LineTypePtr
*) Result3
))
1266 if ((HigherAvail
& (PIN_TYPE
| PAD_TYPE
)) == 0 && Type
& ARC_TYPE
&&
1267 SearchArcByLocation (locked
,
1268 (LayerTypePtr
*) Result1
,
1269 (ArcTypePtr
*) Result2
,
1270 (ArcTypePtr
*) Result3
))
1273 if ((HigherAvail
& (PIN_TYPE
| PAD_TYPE
)) == 0 && Type
& TEXT_TYPE
1274 && SearchTextByLocation (locked
,
1275 (LayerTypePtr
*) Result1
,
1276 (TextTypePtr
*) Result2
,
1277 (TextTypePtr
*) Result3
))
1280 if (Type
& POLYGON_TYPE
&&
1281 SearchPolygonByLocation (locked
,
1282 (LayerTypePtr
*) Result1
,
1283 (PolygonTypePtr
*) Result2
,
1284 (PolygonTypePtr
*) Result3
))
1289 &(*(PolygonTypePtr
*) Result2
)->BoundingBox
;
1291 (float) (box
->X2
- box
->X1
) * (float) (box
->X2
- box
->X1
);
1292 if (HigherBound
< area
)
1295 return (POLYGON_TYPE
);
1298 return (POLYGON_TYPE
);
1302 /* return any previously found objects */
1303 if (HigherAvail
& PIN_TYPE
)
1311 if (HigherAvail
& PAD_TYPE
)
1319 if (HigherAvail
& ELEMENTNAME_TYPE
)
1324 return (ELEMENTNAME_TYPE
);
1327 if (HigherAvail
& ELEMENT_TYPE
)
1332 return (ELEMENT_TYPE
);
1335 /* search the 'invisible objects' last */
1336 if (!PCB
->InvisibleObjectsOn
)
1339 if (Type
& PAD_TYPE
&&
1340 SearchPadByLocation (locked
,
1341 (ElementTypePtr
*) Result1
,
1342 (PadTypePtr
*) Result2
, (PadTypePtr
*) Result3
,
1346 if (Type
& ELEMENTNAME_TYPE
&&
1347 SearchElementNameByLocation (locked
,
1348 (ElementTypePtr
*) Result1
,
1349 (TextTypePtr
*) Result2
,
1350 (TextTypePtr
*) Result3
, true))
1351 return (ELEMENTNAME_TYPE
);
1353 if (Type
& ELEMENT_TYPE
&&
1354 SearchElementByLocation (locked
,
1355 (ElementTypePtr
*) Result1
,
1356 (ElementTypePtr
*) Result2
,
1357 (ElementTypePtr
*) Result3
, true))
1358 return (ELEMENT_TYPE
);
1363 /* ---------------------------------------------------------------------------
1364 * searches for a object by it's unique ID. It doesn't matter if
1365 * the object is visible or not. The search is performed on a PCB, a
1366 * buffer or on the remove list.
1367 * The calling routine passes two pointers to allocated memory for storing
1369 * A type value is returned too which is NO_TYPE if no objects has been found.
1372 SearchObjectByID (DataTypePtr Base
,
1373 void **Result1
, void **Result2
, void **Result3
, int ID
,
1376 if (type
== LINE_TYPE
|| type
== LINEPOINT_TYPE
)
1378 ALLLINE_LOOP (Base
);
1382 *Result1
= (void *) layer
;
1383 *Result2
= *Result3
= (void *) line
;
1386 if (line
->Point1
.ID
== ID
)
1388 *Result1
= (void *) layer
;
1389 *Result2
= (void *) line
;
1390 *Result3
= (void *) &line
->Point1
;
1391 return (LINEPOINT_TYPE
);
1393 if (line
->Point2
.ID
== ID
)
1395 *Result1
= (void *) layer
;
1396 *Result2
= (void *) line
;
1397 *Result3
= (void *) &line
->Point2
;
1398 return (LINEPOINT_TYPE
);
1403 if (type
== ARC_TYPE
)
1409 *Result1
= (void *) layer
;
1410 *Result2
= *Result3
= (void *) arc
;
1417 if (type
== TEXT_TYPE
)
1419 ALLTEXT_LOOP (Base
);
1423 *Result1
= (void *) layer
;
1424 *Result2
= *Result3
= (void *) text
;
1431 if (type
== POLYGON_TYPE
|| type
== POLYGONPOINT_TYPE
)
1433 ALLPOLYGON_LOOP (Base
);
1435 if (polygon
->ID
== ID
)
1437 *Result1
= (void *) layer
;
1438 *Result2
= *Result3
= (void *) polygon
;
1439 return (POLYGON_TYPE
);
1441 if (type
== POLYGONPOINT_TYPE
)
1442 POLYGONPOINT_LOOP (polygon
);
1444 if (point
->ID
== ID
)
1446 *Result1
= (void *) layer
;
1447 *Result2
= (void *) polygon
;
1448 *Result3
= (void *) point
;
1449 return (POLYGONPOINT_TYPE
);
1456 if (type
== VIA_TYPE
)
1462 *Result1
= *Result2
= *Result3
= (void *) via
;
1469 if (type
== RATLINE_TYPE
|| type
== LINEPOINT_TYPE
)
1475 *Result1
= *Result2
= *Result3
= (void *) line
;
1476 return (RATLINE_TYPE
);
1478 if (line
->Point1
.ID
== ID
)
1480 *Result1
= (void *) NULL
;
1481 *Result2
= (void *) line
;
1482 *Result3
= (void *) &line
->Point1
;
1483 return (LINEPOINT_TYPE
);
1485 if (line
->Point2
.ID
== ID
)
1487 *Result1
= (void *) NULL
;
1488 *Result2
= (void *) line
;
1489 *Result3
= (void *) &line
->Point2
;
1490 return (LINEPOINT_TYPE
);
1496 if (type
== ELEMENT_TYPE
|| type
== PAD_TYPE
|| type
== PIN_TYPE
1497 || type
== ELEMENTLINE_TYPE
|| type
== ELEMENTNAME_TYPE
1498 || type
== ELEMENTARC_TYPE
)
1499 /* check pins and elementnames too */
1500 ELEMENT_LOOP (Base
);
1502 if (element
->ID
== ID
)
1504 *Result1
= *Result2
= *Result3
= (void *) element
;
1505 return (ELEMENT_TYPE
);
1507 if (type
== ELEMENTLINE_TYPE
)
1508 ELEMENTLINE_LOOP (element
);
1512 *Result1
= (void *) element
;
1513 *Result2
= *Result3
= (void *) line
;
1514 return (ELEMENTLINE_TYPE
);
1518 if (type
== ELEMENTARC_TYPE
)
1523 *Result1
= (void *) element
;
1524 *Result2
= *Result3
= (void *) arc
;
1525 return (ELEMENTARC_TYPE
);
1529 if (type
== ELEMENTNAME_TYPE
)
1530 ELEMENTTEXT_LOOP (element
);
1534 *Result1
= (void *) element
;
1535 *Result2
= *Result3
= (void *) text
;
1536 return (ELEMENTNAME_TYPE
);
1540 if (type
== PIN_TYPE
)
1545 *Result1
= (void *) element
;
1546 *Result2
= *Result3
= (void *) pin
;
1551 if (type
== PAD_TYPE
)
1556 *Result1
= (void *) element
;
1557 *Result2
= *Result3
= (void *) pad
;
1565 Message ("hace: Internal error, search for ID %d failed\n", ID
);
1569 /* ---------------------------------------------------------------------------
1570 * searches for an element by its board name.
1571 * The function returns a pointer to the element, NULL if not found
1574 SearchElementByName (DataTypePtr Base
, char *Name
)
1576 ElementTypePtr result
= NULL
;
1578 ELEMENT_LOOP (Base
);
1580 if (element
->Name
[1].TextString
&&
1581 NSTRCMP (element
->Name
[1].TextString
, Name
) == 0)
1591 /* ---------------------------------------------------------------------------
1592 * searches the cursor position for the type
1595 SearchScreen (LocationType X
, LocationType Y
, int Type
, void **Result1
,
1596 void **Result2
, void **Result3
)
1600 ans
= SearchObjectByLocation (Type
, Result1
, Result2
, Result3
,
1601 X
, Y
, SLOP
* pixel_slop
);
1605 /* ---------------------------------------------------------------------------
1606 * searches the cursor position for the type
1609 SearchScreenGridSlop (LocationType X
, LocationType Y
, int Type
, void **Result1
,
1610 void **Result2
, void **Result3
)
1614 ans
= SearchObjectByLocation (Type
, Result1
, Result2
, Result3
,
1615 X
, Y
, PCB
->Grid
/ 2);