Commit e9713bb2 authored by jean-pierre charras's avatar jean-pierre charras
Browse files

Pcbnew: Block selection enhancement, from Bug #593997 (whishlist)

1. block created from-left-to-right selects only 100%inside selection objects (as it now does)
2.block created from-right-to-left selects all overlapping objects inside selection
From the patch sent by mathieulj (mathieulj), and some fixes and code cleaning.
parent d5ecafd5
Loading
Loading
Loading
Loading
+30 −0
Original line number Original line Diff line number Diff line
@@ -320,6 +320,36 @@ bool EDA_RECT::Contains( const EDA_RECT& aRect ) const
}
}




/* Intersects
 * test for a common area between segment and rect.
 * return true if at least a common point is found
 */
bool EDA_RECT::Intersects( const wxPoint& aPoint1, const wxPoint& aPoint2 ) const
{
    wxPoint point2, point4;

    if( Contains( aPoint1 ) || Contains( aPoint2 ) )
        return true;

    point2.x = GetEnd().x;
    point2.y = GetOrigin().y;
    point4.x = GetOrigin().x;
    point4.y = GetEnd().y;

    //Only need to test 3 sides since a straight line cant enter and exit on same side
    if( SegmentIntersectsSegment( aPoint1, aPoint2, GetOrigin() , point2 ) )
        return true;

    if( SegmentIntersectsSegment( aPoint1, aPoint2, point2      , GetEnd() ) )
        return true;

    if( SegmentIntersectsSegment( aPoint1, aPoint2, GetEnd()    , point4 ) )
        return true;

    return false;
}


/* Intersects
/* Intersects
 * test for a common area between 2 rect.
 * test for a common area between 2 rect.
 * return true if at least a common point is found
 * return true if at least a common point is found
+67 −2
Original line number Original line Diff line number Diff line
@@ -9,6 +9,71 @@
#include <common.h>
#include <common.h>
#include <math_for_graphics.h>
#include <math_for_graphics.h>



bool SegmentIntersectsSegment( const wxPoint &a_p1_l1, const wxPoint &a_p2_l1,
                               const wxPoint &a_p1_l2, const wxPoint &a_p2_l2 )
{

    //We are forced to use 64bit ints because the internal units can oveflow 32bit ints when
    // multiplied with each other, the alternative would be to scale the units down (i.e. divide
    // by a fixed number).
    long long dX_a, dY_a, dX_b, dY_b, dX_ab, dY_ab;
    long long num_a, num_b, den;

    //Test for intersection within the bounds of both line segments using line equations of the
    // form:
    // x_k(u_k) = u_k * dX_k + x_k(0)
    // y_k(u_k) = u_k * dY_k + y_k(0)
    // with  0 <= u_k <= 1 and k = [ a, b ]

    dX_a  = a_p2_l1.x - a_p1_l1.x;
    dY_a  = a_p2_l1.y - a_p1_l1.y;
    dX_b  = a_p2_l2.x - a_p1_l2.x;
    dY_b  = a_p2_l2.y - a_p1_l2.y;
    dX_ab = a_p1_l2.x - a_p1_l1.x;
    dY_ab = a_p1_l2.y - a_p1_l1.y;

    den   = dY_a  * dX_b - dY_b * dX_a ;

    //Check if lines are parallel
    if( den == 0 )
        return false;

    num_a = dY_ab * dX_b - dY_b * dX_ab;
    num_b = dY_ab * dX_a - dY_a * dX_ab;

    //We wont calculate directly the u_k of the intersection point to avoid floating point
    // division but they could be calculated with:
    // u_a = (float) num_a / (float) den;
    // u_b = (float) num_b / (float) den;

    if( den < 0 )
    {
        den   = -den;
        num_a = -num_a;
        num_b = -num_b;
    }

    //Test sign( u_a ) and return false if negative
    if( num_a < 0 )
        return false;

    //Test sign( u_b ) and return false if negative
    if( num_b < 0 )
        return false;

    //Test to ensure (u_a <= 1)
    if( num_a > den )
        return false;

    //Test to ensure (u_b <= 1)
    if( num_b > den )
        return false;

    return true;
}


/* Function TestSegmentHit
/* Function TestSegmentHit
 * test for hit on line segment
 * test for hit on line segment
 * i.e. a reference point is within a given distance from segment
 * i.e. a reference point is within a given distance from segment
+14 −12
Original line number Original line Diff line number Diff line
@@ -300,11 +300,25 @@ public:


    /**
    /**
     * Function Intersects
     * Function Intersects
     * tests for a common area between rectangles.
     *
     * @param aRect A rectangle to test intersection with.
     * @return bool - true if the argument rectangle intersects this rectangle.
     * @return bool - true if the argument rectangle intersects this rectangle.
     * (i.e. if the 2 rectangles have at least a common point)
     * (i.e. if the 2 rectangles have at least a common point)
     */
     */
    bool Intersects( const EDA_RECT& aRect ) const;
    bool Intersects( const EDA_RECT& aRect ) const;


    /**
     * Function Intersects
     * tests for a common area between a segment and this rectangle.
     *
     * @param aPoint1 First point of the segment to test intersection with.
     * @param aPoint2 Second point of the segment to test intersection with.
     * @return bool - true if the argument segment intersects this rectangle.
     * (i.e. if the segment and rectangle have at least a common point)
     */
    bool Intersects( const wxPoint& aPoint1, const wxPoint& aPoint2 ) const;

    /**
    /**
     * Function operator(wxRect)
     * Function operator(wxRect)
     * overloads the cast operator to return a wxRect
     * overloads the cast operator to return a wxRect
@@ -530,18 +544,6 @@ public:
        return false;   // derived classes should override this function
        return false;   // derived classes should override this function
    }
    }


    /**
     * Function HitTest
     * tests if the \a aRect intersects this object.
     * For now, an ending point must be inside \a aRect.
     *
     * @param aRect A reference to an EDA_RECT object containg the area to test.
     * @return True if \a aRect intersects the object, otherwise false.
     */
    virtual bool HitTest( const EDA_RECT& aRect ) const
    {
        return false;   // derived classes should override this function
    }


    /**
    /**
     * Function GetBoundingBox
     * Function GetBoundingBox
+20 −0
Original line number Original line Diff line number Diff line
@@ -223,6 +223,26 @@ public:
     */
     */
    wxString GetLayerName() const;
    wxString GetLayerName() const;


    virtual bool HitTest( const wxPoint& aPosition )
    {
        return EDA_ITEM::HitTest( aPosition );
    }

    /**
     * Function HitTest
     * tests if the \a aRect intersects or contains this object (depending on \a aContained).
     *
     * @param aRect A reference to an EDA_RECT object containg the area to test.
     * @param aContained Test if \a aRect contains this object completly.
     * @param aAccuracy Increase the item bounding box by this amount.
     * @return bool - True if \a aRect contains this object completly or if \a aRect intersects
     *  the object and \a aContained is False, otherwise false.
     */
    virtual bool HitTest( const EDA_RECT& aRect, bool aContained = true, int aAccuracy = 0) const
    {
        return false;   // derived classes should override this function
    }



    /**
    /**
     * Function FormatInternalUnits
     * Function FormatInternalUnits
+13 −0
Original line number Original line Diff line number Diff line
@@ -31,6 +31,19 @@
#include <math.h>
#include <math.h>
#include <wx/gdicmn.h> // For wxPoint
#include <wx/gdicmn.h> // For wxPoint


/**
 * Function SegmentIntersectsSegment
 *
 * @param a_p1_l1 The first point of the first line.
 * @param a_p2_l1 The second point of the first line.
 * @param a_p1_l2 The first point of the second line.
 * @param a_p2_l2 The second point of the second line.
 * @return bool - true if the two segments defined by four points intersect.
 * (i.e. if the 2 segments have at least a common point)
 */
bool SegmentIntersectsSegment( const wxPoint &a_p1_l1, const wxPoint &a_p2_l1,
                               const wxPoint &a_p1_l2, const wxPoint &a_p2_l2 );

/*
/*
 * Calculate the new point of coord coord pX, pY,
 * Calculate the new point of coord coord pX, pY,
 * for a rotation center 0, 0, and angle in (1 / 10 degree)
 * for a rotation center 0, 0, and angle in (1 / 10 degree)
Loading