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 Boolean
SearchLineByLocation (int, LayerTypePtr
*, LineTypePtr
*,
75 static Boolean
SearchArcByLocation (int, LayerTypePtr
*, ArcTypePtr
*,
77 static Boolean
SearchRatLineByLocation (int, RatTypePtr
*, RatTypePtr
*,
79 static Boolean
SearchTextByLocation (int, LayerTypePtr
*, TextTypePtr
*,
81 static Boolean
SearchPolygonByLocation (int, LayerTypePtr
*, PolygonTypePtr
*,
83 static Boolean
SearchPinByLocation (int, ElementTypePtr
*, PinTypePtr
*,
85 static Boolean
SearchPadByLocation (int, ElementTypePtr
*, PadTypePtr
*,
86 PadTypePtr
*, Boolean
);
87 static Boolean
SearchViaByLocation (int, PinTypePtr
*, PinTypePtr
*,
89 static Boolean
SearchElementNameByLocation (int, ElementTypePtr
*,
90 TextTypePtr
*, TextTypePtr
*,
92 static Boolean
SearchLinePointByLocation (int, LayerTypePtr
*, LineTypePtr
*,
94 static Boolean
SearchPointByLocation (int, LayerTypePtr
*, PolygonTypePtr
*,
96 static Boolean
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
, Boolean 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
)
509 Boolean found
= False
;
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
)
1044 register float x
, y
, dx
, dy
, r1
, r2
, a
, d
, l
;
1045 register float pdx
, pdy
;
1046 int ang1
, ang2
, delta
;
1047 int startAngle
, arcDelta
;
1051 l
= pdx
* pdx
+ pdy
* pdy
;
1052 /* concentric arcs, simpler intersection conditions */
1055 if (Arc
->Width
<= Radius
+ 0.5 * Arc
->Thickness
)
1062 r2
= Radius
+ 0.5 * Arc
->Thickness
;
1064 a
= 0.5 * (r1
- r2
+ l
) / l
;
1066 /* add a tiny positive number for round-off problems */
1067 d
= r1
- a
* a
+ 1e-5;
1068 /* the circles are too far apart to touch */
1071 /* project the points of intersection */
1077 /* arrgh! calculate the angles, and put them in a standard range */
1078 startAngle
= Arc
->StartAngle
;
1079 arcDelta
= Arc
->Delta
;
1080 while (startAngle
< 0)
1084 startAngle
+= arcDelta
;
1085 arcDelta
= -arcDelta
;
1086 while (startAngle
< 0)
1089 ang1
= RAD_TO_DEG
* atan2 ((y
+ dy
), -(x
+ dx
));
1092 ang2
= RAD_TO_DEG
* atan2 ((y
- dy
), -(x
- dx
));
1095 delta
= ang2
- ang1
;
1098 else if (delta
< -180)
1107 if (ang1
>= startAngle
&& ang1
<= startAngle
+ arcDelta
)
1109 if (startAngle
>= ang1
&& startAngle
<= ang1
+ delta
)
1111 if (startAngle
+ arcDelta
>= 360 && ang1
<= startAngle
+ arcDelta
- 360)
1113 if (ang1
+ delta
>= 360 && startAngle
<= ang1
+ delta
- 360)
1118 /* ---------------------------------------------------------------------------
1119 * searches for any kind of object or for a set of object types
1120 * the calling routine passes two pointers to allocated memory for storing
1122 * A type value is returned too which is NO_TYPE if no objects has been found.
1123 * A set of object types is passed in.
1124 * The object is located by it's position.
1126 * The layout is checked in the following order:
1127 * polygon-point, pin, via, line, text, elementname, polygon, element
1129 * Note that if Type includes LOCKED_TYPE, then the search includes
1130 * locked items. Otherwise, locked items are ignored.
1133 SearchObjectByLocation (int Type
,
1134 void **Result1
, void **Result2
, void **Result3
,
1135 LocationType X
, LocationType Y
, BDimension Radius
)
1138 void **pr1
= &r1
, **pr2
= &r2
, **pr3
= &r3
;
1140 float HigherBound
= 0;
1141 int HigherAvail
= NO_TYPE
;
1142 int locked
= Type
& LOCKED_TYPE
;
1143 /* setup variables used by local functions */
1146 SearchRadius
= Radius
;
1149 SearchBox
.X1
= X
- Radius
;
1150 SearchBox
.Y1
= Y
- Radius
;
1151 SearchBox
.X2
= X
+ Radius
;
1152 SearchBox
.Y2
= Y
+ Radius
;
1156 SearchBox
= point_box (X
, Y
);
1159 if (TEST_FLAG (LOCKNAMESFLAG
, PCB
)
1160 || TEST_FLAG (HIDENAMESFLAG
, PCB
))
1162 Type
&= ~ (ELEMENTNAME_TYPE
| TEXT_TYPE
);
1164 if (TEST_FLAG (ONLYNAMESFLAG
, PCB
))
1166 Type
&= (ELEMENTNAME_TYPE
| TEXT_TYPE
);
1168 if (TEST_FLAG (THINDRAWFLAG
, PCB
) || TEST_FLAG (THINDRAWPOLYFLAG
, PCB
))
1170 Type
&= ~POLYGON_TYPE
;
1173 if (Type
& RATLINE_TYPE
&& PCB
->RatOn
&&
1174 SearchRatLineByLocation (locked
,
1175 (RatTypePtr
*) Result1
,
1176 (RatTypePtr
*) Result2
,
1177 (RatTypePtr
*) Result3
))
1178 return (RATLINE_TYPE
);
1180 if (Type
& VIA_TYPE
&&
1181 SearchViaByLocation (locked
,
1182 (PinTypePtr
*) Result1
,
1183 (PinTypePtr
*) Result2
, (PinTypePtr
*) Result3
))
1186 if (Type
& PIN_TYPE
&&
1187 SearchPinByLocation (locked
,
1188 (ElementTypePtr
*) pr1
,
1189 (PinTypePtr
*) pr2
, (PinTypePtr
*) pr3
))
1190 HigherAvail
= PIN_TYPE
;
1192 if (!HigherAvail
&& Type
& PAD_TYPE
&&
1193 SearchPadByLocation (locked
,
1194 (ElementTypePtr
*) pr1
,
1195 (PadTypePtr
*) pr2
, (PadTypePtr
*) pr3
, False
))
1196 HigherAvail
= PAD_TYPE
;
1198 if (!HigherAvail
&& Type
& ELEMENTNAME_TYPE
&&
1199 SearchElementNameByLocation (locked
,
1200 (ElementTypePtr
*) pr1
,
1201 (TextTypePtr
*) pr2
, (TextTypePtr
*) pr3
,
1204 BoxTypePtr box
= &((TextTypePtr
) r2
)->BoundingBox
;
1205 HigherBound
= (float) (box
->X2
- box
->X1
) * (float) (box
->Y2
- box
->Y1
);
1206 HigherAvail
= ELEMENTNAME_TYPE
;
1209 if (!HigherAvail
&& Type
& ELEMENT_TYPE
&&
1210 SearchElementByLocation (locked
,
1211 (ElementTypePtr
*) pr1
,
1212 (ElementTypePtr
*) pr2
,
1213 (ElementTypePtr
*) pr3
, False
))
1215 BoxTypePtr box
= &((ElementTypePtr
) r1
)->BoundingBox
;
1216 HigherBound
= (float) (box
->X2
- box
->X1
) * (float) (box
->Y2
- box
->Y1
);
1217 HigherAvail
= ELEMENT_TYPE
;
1220 for (i
= -1; i
< max_layer
+ 1; i
++)
1223 SearchLayer
= &PCB
->Data
->SILKLAYER
;
1224 else if (i
< max_layer
)
1225 SearchLayer
= LAYER_ON_STACK (i
);
1228 SearchLayer
= &PCB
->Data
->BACKSILKLAYER
;
1229 if (!PCB
->InvisibleObjectsOn
)
1232 if (SearchLayer
->On
)
1234 if ((HigherAvail
& (PIN_TYPE
| PAD_TYPE
)) == 0 &&
1235 Type
& POLYGONPOINT_TYPE
&&
1236 SearchPointByLocation (locked
,
1237 (LayerTypePtr
*) Result1
,
1238 (PolygonTypePtr
*) Result2
,
1239 (PointTypePtr
*) Result3
))
1240 return (POLYGONPOINT_TYPE
);
1242 if ((HigherAvail
& (PIN_TYPE
| PAD_TYPE
)) == 0 &&
1243 Type
& LINEPOINT_TYPE
&&
1244 SearchLinePointByLocation (locked
,
1245 (LayerTypePtr
*) Result1
,
1246 (LineTypePtr
*) Result2
,
1247 (PointTypePtr
*) Result3
))
1248 return (LINEPOINT_TYPE
);
1250 if ((HigherAvail
& (PIN_TYPE
| PAD_TYPE
)) == 0 && Type
& LINE_TYPE
1251 && SearchLineByLocation (locked
,
1252 (LayerTypePtr
*) Result1
,
1253 (LineTypePtr
*) Result2
,
1254 (LineTypePtr
*) Result3
))
1257 if ((HigherAvail
& (PIN_TYPE
| PAD_TYPE
)) == 0 && Type
& ARC_TYPE
&&
1258 SearchArcByLocation (locked
,
1259 (LayerTypePtr
*) Result1
,
1260 (ArcTypePtr
*) Result2
,
1261 (ArcTypePtr
*) Result3
))
1264 if ((HigherAvail
& (PIN_TYPE
| PAD_TYPE
)) == 0 && Type
& TEXT_TYPE
1265 && SearchTextByLocation (locked
,
1266 (LayerTypePtr
*) Result1
,
1267 (TextTypePtr
*) Result2
,
1268 (TextTypePtr
*) Result3
))
1271 if (Type
& POLYGON_TYPE
&&
1272 SearchPolygonByLocation (locked
,
1273 (LayerTypePtr
*) Result1
,
1274 (PolygonTypePtr
*) Result2
,
1275 (PolygonTypePtr
*) Result3
))
1280 &(*(PolygonTypePtr
*) Result2
)->BoundingBox
;
1282 (float) (box
->X2
- box
->X1
) * (float) (box
->X2
- box
->X1
);
1283 if (HigherBound
< area
)
1286 return (POLYGON_TYPE
);
1289 return (POLYGON_TYPE
);
1293 /* return any previously found objects */
1294 if (HigherAvail
& PIN_TYPE
)
1302 if (HigherAvail
& PAD_TYPE
)
1310 if (HigherAvail
& ELEMENTNAME_TYPE
)
1315 return (ELEMENTNAME_TYPE
);
1318 if (HigherAvail
& ELEMENT_TYPE
)
1323 return (ELEMENT_TYPE
);
1326 /* search the 'invisible objects' last */
1327 if (!PCB
->InvisibleObjectsOn
)
1330 if (Type
& PAD_TYPE
&&
1331 SearchPadByLocation (locked
,
1332 (ElementTypePtr
*) Result1
,
1333 (PadTypePtr
*) Result2
, (PadTypePtr
*) Result3
,
1337 if (Type
& ELEMENTNAME_TYPE
&&
1338 SearchElementNameByLocation (locked
,
1339 (ElementTypePtr
*) Result1
,
1340 (TextTypePtr
*) Result2
,
1341 (TextTypePtr
*) Result3
, True
))
1342 return (ELEMENTNAME_TYPE
);
1344 if (Type
& ELEMENT_TYPE
&&
1345 SearchElementByLocation (locked
,
1346 (ElementTypePtr
*) Result1
,
1347 (ElementTypePtr
*) Result2
,
1348 (ElementTypePtr
*) Result3
, True
))
1349 return (ELEMENT_TYPE
);
1354 /* ---------------------------------------------------------------------------
1355 * searches for a object by it's unique ID. It doesn't matter if
1356 * the object is visible or not. The search is performed on a PCB, a
1357 * buffer or on the remove list.
1358 * The calling routine passes two pointers to allocated memory for storing
1360 * A type value is returned too which is NO_TYPE if no objects has been found.
1363 SearchObjectByID (DataTypePtr Base
,
1364 void **Result1
, void **Result2
, void **Result3
, int ID
,
1367 if (type
== LINE_TYPE
|| type
== LINEPOINT_TYPE
)
1369 ALLLINE_LOOP (Base
);
1373 *Result1
= (void *) layer
;
1374 *Result2
= *Result3
= (void *) line
;
1377 if (line
->Point1
.ID
== ID
)
1379 *Result1
= (void *) layer
;
1380 *Result2
= (void *) line
;
1381 *Result3
= (void *) &line
->Point1
;
1382 return (LINEPOINT_TYPE
);
1384 if (line
->Point2
.ID
== ID
)
1386 *Result1
= (void *) layer
;
1387 *Result2
= (void *) line
;
1388 *Result3
= (void *) &line
->Point2
;
1389 return (LINEPOINT_TYPE
);
1394 if (type
== ARC_TYPE
)
1400 *Result1
= (void *) layer
;
1401 *Result2
= *Result3
= (void *) arc
;
1408 if (type
== TEXT_TYPE
)
1410 ALLTEXT_LOOP (Base
);
1414 *Result1
= (void *) layer
;
1415 *Result2
= *Result3
= (void *) text
;
1422 if (type
== POLYGON_TYPE
|| type
== POLYGONPOINT_TYPE
)
1424 ALLPOLYGON_LOOP (Base
);
1426 if (polygon
->ID
== ID
)
1428 *Result1
= (void *) layer
;
1429 *Result2
= *Result3
= (void *) polygon
;
1430 return (POLYGON_TYPE
);
1432 if (type
== POLYGONPOINT_TYPE
)
1433 POLYGONPOINT_LOOP (polygon
);
1435 if (point
->ID
== ID
)
1437 *Result1
= (void *) layer
;
1438 *Result2
= (void *) polygon
;
1439 *Result3
= (void *) point
;
1440 return (POLYGONPOINT_TYPE
);
1447 if (type
== VIA_TYPE
)
1453 *Result1
= *Result2
= *Result3
= (void *) via
;
1460 if (type
== RATLINE_TYPE
|| type
== LINEPOINT_TYPE
)
1466 *Result1
= *Result2
= *Result3
= (void *) line
;
1467 return (RATLINE_TYPE
);
1469 if (line
->Point1
.ID
== ID
)
1471 *Result1
= (void *) NULL
;
1472 *Result2
= (void *) line
;
1473 *Result3
= (void *) &line
->Point1
;
1474 return (LINEPOINT_TYPE
);
1476 if (line
->Point2
.ID
== ID
)
1478 *Result1
= (void *) NULL
;
1479 *Result2
= (void *) line
;
1480 *Result3
= (void *) &line
->Point2
;
1481 return (LINEPOINT_TYPE
);
1487 if (type
== ELEMENT_TYPE
|| type
== PAD_TYPE
|| type
== PIN_TYPE
1488 || type
== ELEMENTLINE_TYPE
|| type
== ELEMENTNAME_TYPE
1489 || type
== ELEMENTARC_TYPE
)
1490 /* check pins and elementnames too */
1491 ELEMENT_LOOP (Base
);
1493 if (element
->ID
== ID
)
1495 *Result1
= *Result2
= *Result3
= (void *) element
;
1496 return (ELEMENT_TYPE
);
1498 if (type
== ELEMENTLINE_TYPE
)
1499 ELEMENTLINE_LOOP (element
);
1503 *Result1
= (void *) element
;
1504 *Result2
= *Result3
= (void *) line
;
1505 return (ELEMENTLINE_TYPE
);
1509 if (type
== ELEMENTARC_TYPE
)
1514 *Result1
= (void *) element
;
1515 *Result2
= *Result3
= (void *) arc
;
1516 return (ELEMENTARC_TYPE
);
1520 if (type
== ELEMENTNAME_TYPE
)
1521 ELEMENTTEXT_LOOP (element
);
1525 *Result1
= (void *) element
;
1526 *Result2
= *Result3
= (void *) text
;
1527 return (ELEMENTNAME_TYPE
);
1531 if (type
== PIN_TYPE
)
1536 *Result1
= (void *) element
;
1537 *Result2
= *Result3
= (void *) pin
;
1542 if (type
== PAD_TYPE
)
1547 *Result1
= (void *) element
;
1548 *Result2
= *Result3
= (void *) pad
;
1556 Message ("hace: Internal error, search for ID %d failed\n", ID
);
1560 /* ---------------------------------------------------------------------------
1561 * searches for an element by its board name.
1562 * The function returns a pointer to the element, NULL if not found
1565 SearchElementByName (DataTypePtr Base
, char *Name
)
1567 ElementTypePtr result
= NULL
;
1569 ELEMENT_LOOP (Base
);
1571 if (element
->Name
[1].TextString
&&
1572 NSTRCMP (element
->Name
[1].TextString
, Name
) == 0)
1582 /* ---------------------------------------------------------------------------
1583 * searches the cursor position for the type
1586 SearchScreen (LocationType X
, LocationType Y
, int Type
, void **Result1
,
1587 void **Result2
, void **Result3
)
1591 ans
= SearchObjectByLocation (Type
, Result1
, Result2
, Result3
,
1592 X
, Y
, SLOP
* pixel_slop
);