Index: src/action.c =================================================================== --- src/action.c (revision 954) +++ src/action.c (revision 955) @@ -771,14 +771,11 @@ } else if (Settings.Mode == ARROW_MODE) { - box.X1 = MIN (Crosshair.AttachedBox.Point1.X, - Crosshair.AttachedBox.Point2.X); - box.Y1 = MIN (Crosshair.AttachedBox.Point1.Y, - Crosshair.AttachedBox.Point2.Y); - box.X2 = MAX (Crosshair.AttachedBox.Point1.X, - Crosshair.AttachedBox.Point2.X); - box.Y2 = MAX (Crosshair.AttachedBox.Point1.Y, - Crosshair.AttachedBox.Point2.Y); + box.X1 = Crosshair.AttachedBox.Point1.X; + box.Y1 = Crosshair.AttachedBox.Point1.Y; + box.X2 = Crosshair.AttachedBox.Point2.X; + box.Y2 = Crosshair.AttachedBox.Point2.Y; + RestoreUndoSerialNumber (); if (SelectBlock (&box, true)) SetChangedFlag (true); Index: src/search.c =================================================================== --- src/search.c (revision 954) +++ src/search.c (revision 955) @@ -1569,3 +1569,45 @@ X, Y, PCB->Grid / 2); return (ans); } + +int lines_intersect(Coord ax1, Coord ay1, Coord ax2, Coord ay2, Coord bx1, Coord by1, Coord bx2, Coord by2) +{ +/* TODO: this should eb long double if Coord is 64 bits */ + double ua, ub, xi, yi, X1, Y1, X2, Y2, X3, Y3, X4, Y4, tmp; + + /* maths from http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ */ + + X1 = ax1; + X2 = ax2; + X3 = bx1; + X4 = bx2; + Y1 = ay1; + Y2 = ay2; + Y3 = by1; + Y4 = by2; + + tmp = ((Y4-Y3)*(X2-X1) - (X4-X3)*(Y2-Y1)); + ua=((X4-X3)*(Y1-Y3) - (Y4-Y3)*(X1-X3)) / tmp; + ub=((X2-X1)*(Y1-Y3) - (Y2-Y1)*(X1-X3)) / tmp; + xi = X1 + ua * (X2 - X1); + yi = Y1 + ua * (Y2 - Y1); + +#define check(e1, e2, i) \ + if (e1 < e2) { \ + if ((i < e1) || (i > e2)) \ + return 0; \ + } \ + else { \ + if ((i > e1) || (i < e2)) \ + return 0; \ + } + + check(ax1, ax2, xi); + check(bx1, bx2, xi); + check(ay1, ay2, yi); + check(by1, by2, yi); + return 1; +} + + + Index: src/search.h =================================================================== --- src/search.h (revision 954) +++ src/search.h (revision 955) @@ -33,6 +33,8 @@ #include "global.h" +int lines_intersect(Coord ax1, Coord ay1, Coord ax2, Coord ay2, Coord bx1, Coord by1, Coord bx2, Coord by2); + #define SLOP 5 /* --------------------------------------------------------------------------- * some useful macros @@ -68,6 +70,74 @@ #define ARC_IN_BOX(a,b) \ (BOX_IN_BOX(&((a)->BoundingBox), (b))) +/* == the same but accept if any part of the object touches the box == */ +#define POINT_IN_CIRCLE(x, y, cx, cy, r) \ + (((x)-(cx)) * ((x)-(cx)) + ((y)-(cy)) * ((y)-(cy)) <= (r)*(r)) + +#define CIRCLE_TOUCH_BOX(cx, cy, r, b) \ + ( POINT_IN_BOX((cx)-(r),(cy),(b)) || POINT_IN_BOX((cx)+(r),(cy),(b)) || POINT_IN_BOX((cx),(cy)-(r),(b)) || POINT_IN_BOX((cx),(cy)+(r),(b)) \ + || POINT_IN_CIRCLE((b)->X1, (b)->Y1, (cx), (cy), (r)) || POINT_IN_CIRCLE((b)->X2, (b)->Y1, (cx), (cy), (r)) || POINT_IN_CIRCLE((b)->X1, (b)->Y2, (cx), (cy), (r)) || POINT_IN_CIRCLE((b)->X2, (b)->Y2, (cx), (cy), (r))) + +#define VIA_OR_PIN_TOUCHES_BOX(v,b) \ + CIRCLE_TOUCH_BOX((v)->X,(v)->Y,((v)->Thickness + (v)->DrillingHole/2),(b)) + +#define LINE_TOUCHES_BOX(l,b) \ + ( lines_intersect((l)->Point1.X,(l)->Point1.Y,(l)->Point2.X,(l)->Point2.Y, (b)->X1, (b)->Y1, (b)->X2, (b)->Y1) \ + || lines_intersect((l)->Point1.X,(l)->Point1.Y,(l)->Point2.X,(l)->Point2.Y, (b)->X1, (b)->Y1, (b)->X1, (b)->Y2) \ + || lines_intersect((l)->Point1.X,(l)->Point1.Y,(l)->Point2.X,(l)->Point2.Y, (b)->X2, (b)->Y2, (b)->X1, (b)->Y2) \ + || lines_intersect((l)->Point1.X,(l)->Point1.Y,(l)->Point2.X,(l)->Point2.Y, (b)->X2, (b)->Y2, (b)->X2, (b)->Y1)) + +#define PAD_TOUCHES_BOX(p,b) LINE_TOUCHES_BOX((LineTypePtr)(p),(b)) + +/* a corner of either box is within the other, or edges cross */ +#define BOX_TOUCHES_BOX(b1,b2) \ + ( POINT_IN_BOX((b1)->X1,(b1)->Y1,b2) || POINT_IN_BOX((b1)->X1,(b1)->Y2,b2) || POINT_IN_BOX((b1)->X2,(b1)->Y1,b2) || POINT_IN_BOX((b1)->X2,(b1)->Y2,b2) \ + || POINT_IN_BOX((b2)->X1,(b2)->Y1,b1) || POINT_IN_BOX((b2)->X1,(b2)->Y2,b1) || POINT_IN_BOX((b2)->X2,(b2)->Y1,b1) || POINT_IN_BOX((b2)->X2,(b2)->Y2,b1) \ + || lines_intersect((b1)->X1,(b1)->Y1, (b1)->X2,(b1)->Y1, (b2)->X1,(b2)->Y1, (b2)->X1,(b2)->Y2) \ + || lines_intersect((b2)->X1,(b2)->Y1, (b2)->X2,(b2)->Y1, (b1)->X1,(b1)->Y1, (b1)->X1,(b1)->Y2)) + +#define TEXT_TOUCHES_BOX(t,b) \ + (BOX_TOUCHES_BOX(&((t)->BoundingBox), (b))) + +#define POLYGON_TOUCHES_BOX(p,b) \ + (BOX_TOUCHES_BOX(&((p)->BoundingBox), (b))) + +#define ELEMENT_TOUCHES_BOX(e,b) \ + (BOX_TOUCHES_BOX(&((e)->BoundingBox), (b))) + +#define ARC_TOUCHES_BOX(a,b) \ + (BOX_TOUCHES_BOX(&((a)->BoundingBox), (b))) + + +/* == the combination of *_IN_* and *_TOUCHES_*: use IN for positive boxes == */ +#define IS_BOX_NEGATIVE(b) (((b)->X2 < (b)->X1) || ((b)->Y2 < (b)->Y1)) + +#define BOX_NEAR_BOX(b1,b) \ + (IS_BOX_NEGATIVE(b) ? BOX_TOUCHES_BOX(b1,b) : BOX_IN_BOX(b1,b)) + +#define VIA_OR_PIN_NEAR_BOX(v,b) \ + (IS_BOX_NEGATIVE(b) ? VIA_OR_PIN_TOUCHES_BOX(v,b) : VIA_OR_PIN_IN_BOX(v,b)) + +#define LINE_NEAR_BOX(l,b) \ + (IS_BOX_NEGATIVE(b) ? LINE_TOUCHES_BOX(l,b) : LINE_IN_BOX(l,b)) + +#define PAD_NEAR_BOX(p,b) \ + (IS_BOX_NEGATIVE(b) ? PAD_TOUCHES_BOX(p,b) : PAD_IN_BOX(p,b)) + +#define TEXT_NEAR_BOX(t,b) \ + (IS_BOX_NEGATIVE(b) ? TEXT_TOUCHES_BOX(t,b) : TEXT_IN_BOX(t,b)) + +#define POLYGON_NEAR_BOX(p,b) \ + (IS_BOX_NEGATIVE(b) ? POLYGON_TOUCHES_BOX(p,b) : POLYGON_IN_BOX(p,b)) + +#define ELEMENT_NEAR_BOX(e,b) \ + (IS_BOX_NEGATIVE(b) ? ELEMENT_TOUCHES_BOX(e,b) : ELEMENT_IN_BOX(e,b)) + +#define ARC_NEAR_BOX(a,b) \ + (IS_BOX_NEGATIVE(b) ? ARC_TOUCHES_BOX(a,b) : ARC_IN_BOX(a,b)) + + + /* --------------------------------------------------------------------------- * prototypes */ Index: src/select.c =================================================================== --- src/select.c (revision 954) +++ src/select.c (revision 955) @@ -243,11 +243,16 @@ changed = 1; \ } while(0) + if (IS_BOX_NEGATIVE(Box) && ((Box->X1 == Box->X2) || (Box->Y2 == Box->Y1))) { + if (len != NULL) + *len = 0; + return NULL; + } if (PCB->RatOn || !Flag) RAT_LOOP (PCB->Data); { - if (LINE_IN_BOX ((LineTypePtr) line, Box) && + if (LINE_NEAR_BOX ((LineTypePtr) line, Box) && !TEST_FLAG (LOCKFLAG, line) && TEST_FLAG (SELECTEDFLAG, line) != Flag) { append(RATLINE_TYPE, line, line); @@ -276,7 +281,7 @@ LINE_LOOP (layer); { - if (LINE_IN_BOX (line, Box) + if (LINE_NEAR_BOX (line, Box) && !TEST_FLAG (LOCKFLAG, line) && TEST_FLAG (SELECTEDFLAG, line) != Flag) { @@ -288,7 +293,7 @@ END_LOOP; ARC_LOOP (layer); { - if (ARC_IN_BOX (arc, Box) + if (ARC_NEAR_BOX (arc, Box) && !TEST_FLAG (LOCKFLAG, arc) && TEST_FLAG (SELECTEDFLAG, arc) != Flag) { @@ -302,7 +307,7 @@ { if (!Flag || TEXT_IS_VISIBLE(PCB, layer, text)) { - if (TEXT_IN_BOX (text, Box) + if (TEXT_NEAR_BOX (text, Box) && !TEST_FLAG (LOCKFLAG, text) && TEST_FLAG (SELECTEDFLAG, text) != Flag) { @@ -315,7 +320,7 @@ END_LOOP; POLYGON_LOOP (layer); { - if (POLYGON_IN_BOX (polygon, Box) + if (POLYGON_NEAR_BOX (polygon, Box) && !TEST_FLAG (LOCKFLAG, polygon) && TEST_FLAG (SELECTEDFLAG, polygon) != Flag) { @@ -338,7 +343,7 @@ && ((TEST_FLAG (ONSOLDERFLAG, element) != 0) == SWAP_IDENT || PCB->InvisibleObjectsOn)) { - if (BOX_IN_BOX + if (BOX_NEAR_BOX (&ELEMENT_TEXT (PCB, element).BoundingBox, Box) && !TEST_FLAG (LOCKFLAG, &ELEMENT_TEXT (PCB, element)) && TEST_FLAG (SELECTEDFLAG, @@ -353,7 +358,7 @@ if (PCB->ElementOn) DrawElementName (element); } - if ((PCB->PinOn || !Flag) && ELEMENT_IN_BOX (element, Box)) + if ((PCB->PinOn || !Flag) && ELEMENT_NEAR_BOX (element, Box)) if (TEST_FLAG (SELECTEDFLAG, element) != Flag) { append(ELEMENT_TYPE, element, element); @@ -386,7 +391,7 @@ { PIN_LOOP (element); { - if ((VIA_OR_PIN_IN_BOX (pin, Box) + if ((VIA_OR_PIN_NEAR_BOX (pin, Box) && TEST_FLAG (SELECTEDFLAG, pin) != Flag)) { append(PIN_TYPE, element, pin); @@ -397,7 +402,7 @@ END_LOOP; PAD_LOOP (element); { - if (PAD_IN_BOX (pad, Box) + if (PAD_NEAR_BOX (pad, Box) && TEST_FLAG (SELECTEDFLAG, pad) != Flag && (TEST_FLAG (ONSOLDERFLAG, pad) == SWAP_IDENT || PCB->InvisibleObjectsOn @@ -417,7 +422,7 @@ if (PCB->ViaOn || !Flag) VIA_LOOP (PCB->Data); { - if (VIA_OR_PIN_IN_BOX (via, Box) + if (VIA_OR_PIN_NEAR_BOX (via, Box) && !TEST_FLAG (LOCKFLAG, via) && TEST_FLAG (SELECTEDFLAG, via) != Flag) {