bool DIMENSION::HitTest( const wxPoint& aPosition ) const
{
    if( m_Text.TextHitTest( aPosition ) )
        return true;

    int dist_max = m_Width / 2;

    // Locate SEGMENTS

    if( TestSegmentHit( aPosition, m_crossBarO, m_crossBarF, dist_max ) )
        return true;

    if( TestSegmentHit( aPosition, m_featureLineGO, m_featureLineGF, dist_max ) )
        return true;

    if( TestSegmentHit( aPosition, m_featureLineDO, m_featureLineDF, dist_max ) )
        return true;

    if( TestSegmentHit( aPosition, m_crossBarF, m_arrowD1F, dist_max ) )
        return true;

    if( TestSegmentHit( aPosition, m_crossBarF, m_arrowD2F, dist_max ) )
        return true;

    if( TestSegmentHit( aPosition, m_crossBarO, m_arrowG1F, dist_max ) )
        return true;

    if( TestSegmentHit( aPosition, m_crossBarO, m_arrowG2F, dist_max ) )
        return true;

    return false;
}
bool LIB_RECTANGLE::HitTest( wxPoint aPosition, int aThreshold, const TRANSFORM& aTransform )
{
    if( aThreshold < 0 )
        aThreshold = GetPenSize() / 2;

    wxPoint actualStart = aTransform.TransformCoordinate( m_Pos );
    wxPoint actualEnd   = aTransform.TransformCoordinate( m_End );

    // locate lower segment
    wxPoint start, end;

    start = actualStart;
    end.x = actualEnd.x;
    end.y = actualStart.y;

    if( TestSegmentHit( aPosition, start, end, aThreshold ) )
        return true;

    // locate right segment
    start.x = actualEnd.x;
    end.y   = actualEnd.y;

    if( TestSegmentHit( aPosition, start, end, aThreshold ) )
        return true;

    // locate upper segment
    start.y = actualEnd.y;
    end.x   = actualStart.x;

    if( TestSegmentHit( aPosition, start, end, aThreshold ) )
        return true;

    // locate left segment
    start = actualStart;
    end.x = actualStart.x;
    end.y = actualEnd.y;

    if( TestSegmentHit( aPosition, start, end, aThreshold ) )
        return true;

    return false;
}
bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos )
{
    // calculate aRefPos in XY gerber axis:
    wxPoint ref_pos = GetXYPosition( aRefPos );

    // TODO: a better analyze of the shape (perhaps create a D_CODE::HitTest for flashed items)
    int     radius = std::min( m_Size.x, m_Size.y ) >> 1;

    if( m_Flashed )
        return HitTestPoints( m_Start, ref_pos, radius );
    else
        return TestSegmentHit( ref_pos, m_Start, m_End, radius );
}
Exemple #4
0
bool LIB_POLYLINE::HitTest( const wxPoint &aPosition, int aThreshold, const TRANSFORM& aTransform ) const
{
    wxPoint ref, start, end;

    if( aThreshold < 0 )
        aThreshold = GetPenSize() / 2;

    for( unsigned ii = 1; ii < GetCornerCount(); ii++ )
    {
        start = aTransform.TransformCoordinate( m_PolyPoints[ii - 1] );
        end   = aTransform.TransformCoordinate( m_PolyPoints[ii] );

        if( TestSegmentHit( aPosition, start, end, aThreshold ) )
            return true;
    }

    return false;
}
/* compare a polygon to a point and return true if distance > aDist
 * do not use this function for horizontal or vertical rectangles
 * because there is a faster an easier way to compare the distance
 */
bool convex2pointDRC( wxPoint* aTref, int aTrefCount, wxPoint aPcompare, int aDist )
{
    /* Test if aPcompare point is contained in the polygon.
     * This case is not covered by the following check if this point is inside the polygon
     */
    if( TestPointInsidePolygon( aTref, aTrefCount, aPcompare ) )
    {
        return false;
    }

    // Test distance between aPcompare and each segment of the polygon:
    for( int ii = 0, jj = aTrefCount - 1; ii < aTrefCount; jj = ii, ii++ )  // for all edge in polygon
    {
        if( TestSegmentHit( aPcompare, aTref[ii], aTref[jj], aDist ) )
            return false;
    }

    return true;
}
bool D_PAD::HitTest( const wxPoint& aPosition ) const
{
    int     dx, dy;

    wxPoint shape_pos = ShapePos();

    wxPoint delta = aPosition - shape_pos;

    // first test: a test point must be inside a minimum sized bounding circle.
    int radius = GetBoundingRadius();

    if( ( abs( delta.x ) > radius ) || ( abs( delta.y ) > radius ) )
        return false;

    dx = m_Size.x >> 1; // dx also is the radius for rounded pads
    dy = m_Size.y >> 1;

    switch( GetShape() )
    {
    case PAD_SHAPE_CIRCLE:
        if( KiROUND( EuclideanNorm( delta ) ) <= dx )
            return true;

        break;

    case PAD_SHAPE_TRAPEZOID:
    {
        wxPoint poly[4];
        BuildPadPolygon( poly, wxSize(0,0), 0 );
        RotatePoint( &delta, -m_Orient );
        return TestPointInsidePolygon( poly, 4, delta );
    }

    case PAD_SHAPE_OVAL:
    {
        RotatePoint( &delta, -m_Orient );
        // An oval pad has the same shape as a segment with rounded ends
        // After rotation, the test point is relative to an horizontal pad
        int dist;
        wxPoint offset;
        if( dy > dx )   // shape is a vertical oval
        {
            offset.y = dy - dx;
            dist = dx;
        }
        else    //if( dy <= dx ) shape is an horizontal oval
        {
            offset.x = dy - dx;
            dist = dy;
        }
        return TestSegmentHit( delta, - offset, offset, dist );
    }
        break;

    case PAD_SHAPE_RECT:
        RotatePoint( &delta, -m_Orient );

        if( (abs( delta.x ) <= dx ) && (abs( delta.y ) <= dy) )
            return true;

        break;
    }

    return false;
}
Exemple #7
0
bool D_PAD::HitTest( const wxPoint& aPosition ) const
{
    int dx, dy;

    wxPoint shape_pos = ShapePos();

    wxPoint delta = aPosition - shape_pos;

    // first test: a test point must be inside a minimum sized bounding circle.
    int radius = GetBoundingRadius();

    if( ( abs( delta.x ) > radius ) || ( abs( delta.y ) > radius ) )
        return false;

    dx = m_Size.x >> 1; // dx also is the radius for rounded pads
    dy = m_Size.y >> 1;

    switch( GetShape() )
    {
    case PAD_SHAPE_CIRCLE:
        if( KiROUND( EuclideanNorm( delta ) ) <= dx )
            return true;

        break;

    case PAD_SHAPE_TRAPEZOID:
    {
        wxPoint poly[4];
        BuildPadPolygon( poly, wxSize(0,0), 0 );
        RotatePoint( &delta, -m_Orient );

        return TestPointInsidePolygon( poly, 4, delta );
    }

    case PAD_SHAPE_OVAL:
    {
        RotatePoint( &delta, -m_Orient );
        // An oval pad has the same shape as a segment with rounded ends
        // After rotation, the test point is relative to an horizontal pad
        int dist;
        wxPoint offset;
        if( dy > dx )   // shape is a vertical oval
        {
            offset.y = dy - dx;
            dist = dx;
        }
        else    //if( dy <= dx ) shape is an horizontal oval
        {
            offset.x = dy - dx;
            dist = dy;
        }
        return TestSegmentHit( delta, - offset, offset, dist );
    }
        break;

    case PAD_SHAPE_RECT:
        RotatePoint( &delta, -m_Orient );

        if( (abs( delta.x ) <= dx ) && (abs( delta.y ) <= dy) )
            return true;

        break;

    case PAD_SHAPE_ROUNDRECT:
    {
        // Check for hit in polygon
        SHAPE_POLY_SET outline;
        const int segmentToCircleCount = 32;
        TransformRoundRectToPolygon( outline, wxPoint(0,0), GetSize(), m_Orient,
                                 GetRoundRectCornerRadius(), segmentToCircleCount );

        const SHAPE_LINE_CHAIN &poly = outline.COutline( 0 );
        return TestPointInsidePolygon( (const wxPoint*)&poly.CPoint(0), poly.PointCount(), delta );
    }
        break;

    case PAD_SHAPE_CUSTOM:
        // Check for hit in polygon
        RotatePoint( &delta, -m_Orient );

        if( m_customShapeAsPolygon.OutlineCount() )
        {
            const SHAPE_LINE_CHAIN& poly = m_customShapeAsPolygon.COutline( 0 );
            return TestPointInsidePolygon( (const wxPoint*)&poly.CPoint(0), poly.PointCount(), delta );
        }
        break;
    }

    return false;
}
bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos ) const
{
    // In case the item has a very tiny width defined, allow it to be selected
    const int MIN_HIT_TEST_RADIUS = Millimeter2iu( 0.01 );

    // calculate aRefPos in XY gerber axis:
    wxPoint ref_pos = GetXYPosition( aRefPos );

    SHAPE_POLY_SET poly;

    switch( m_Shape )
    {
    case GBR_POLYGON:
        poly = m_Polygon;
        return poly.Contains( VECTOR2I( ref_pos ), 0 );

    case GBR_SPOT_POLY:
        poly = GetDcodeDescr()->m_Polygon;
        poly.Move( m_Start );
        return poly.Contains( VECTOR2I( ref_pos ), 0 );

    case GBR_SPOT_RECT:
        return GetBoundingBox().Contains( aRefPos );

    case GBR_ARC:
        {
            double radius = GetLineLength( m_Start, m_ArcCentre );
            VECTOR2D test_radius = VECTOR2D( ref_pos ) - VECTOR2D( m_ArcCentre );

            int size = ( ( m_Size.x < MIN_HIT_TEST_RADIUS ) ? MIN_HIT_TEST_RADIUS
                                                            : m_Size.x );

            // Are we close enough to the radius?
            bool radius_hit = ( std::fabs( test_radius.EuclideanNorm() - radius) < size );

            if( radius_hit )
            {
                // Now check that we are within the arc angle

                VECTOR2D start = VECTOR2D( m_Start ) - VECTOR2D( m_ArcCentre );
                VECTOR2D end = VECTOR2D( m_End ) - VECTOR2D( m_ArcCentre );

                double start_angle = NormalizeAngleRadiansPos( start.Angle() );
                double end_angle = NormalizeAngleRadiansPos( end.Angle() );

                if( m_Start == m_End )
                {
                    start_angle = 0;
                    end_angle = 2 * M_PI;
                }
                else if( end_angle < start_angle )
                {
                    end_angle += 2 * M_PI;
                }

                double test_angle = NormalizeAngleRadiansPos( test_radius.Angle() );

                return ( test_angle > start_angle && test_angle < end_angle );
            }

            return false;
        }

    case GBR_SPOT_MACRO:
        // Aperture macro polygons are already in absolute coordinates
        auto p = GetDcodeDescr()->GetMacro()->GetApertureMacroShape( this, m_Start );
        for( int i = 0; i < p->OutlineCount(); ++i )
        {
            if( p->Contains( VECTOR2I( aRefPos ), i ) )
                return true;
        }
        return false;
    }

    // TODO: a better analyze of the shape (perhaps create a D_CODE::HitTest for flashed items)
    int radius = std::min( m_Size.x, m_Size.y ) >> 1;

    if( radius < MIN_HIT_TEST_RADIUS )
        radius = MIN_HIT_TEST_RADIUS;

    if( m_Flashed )
        return HitTestPoints( m_Start, ref_pos, radius );
    else
        return TestSegmentHit( ref_pos, m_Start, m_End, radius );
}
Exemple #9
0
bool SCH_BUS_ENTRY_BASE::HitTest( const wxPoint& aPosition, int aAccuracy ) const
{
    return TestSegmentHit( aPosition, m_pos, m_End(), aAccuracy );
}
bool TRACK::HitTest( const wxPoint& aPosition ) const
{
    return TestSegmentHit( aPosition, m_Start, m_End, m_Width / 2 );
}
bool DRAWSEGMENT::HitTest( const wxPoint& aPosition )
{
    switch( m_Shape )
    {
    case S_CIRCLE:
    case S_ARC:
        {
            wxPoint relPos = aPosition - GetCenter();
            int radius = GetRadius();
            int dist   = KiROUND( EuclideanNorm( relPos ) );

            if( abs( radius - dist ) <= ( m_Width / 2 ) )
            {
                if( m_Shape == S_CIRCLE )
                    return true;

                // For arcs, the test point angle must be >= arc angle start
                // and <= arc angle end
                // However angle values > 360 deg are not easy to handle
                // so we calculate the relative angle between arc start point and teast point
                // this relative arc should be < arc angle if arc angle > 0 (CW arc)
                // and > arc angle if arc angle < 0 (CCW arc)
                double arc_angle_start = GetArcAngleStart();    // Always 0.0 ... 360 deg, in 0.1 deg

                double arc_hittest = ArcTangente( relPos.y, relPos.x );

                // Calculate relative angle between the starting point of the arc, and the test point
                arc_hittest -= arc_angle_start;

                // Normalise arc_hittest between 0 ... 360 deg
                NORMALIZE_ANGLE_POS( arc_hittest );

                // Check angle: inside the arc angle when it is > 0
                // and outside the not drawn arc when it is < 0
                if( GetAngle() >= 0.0 )
                {
                    if( arc_hittest <= GetAngle() )
                        return true;
                }
                else
                {
                    if( arc_hittest >= (3600.0 + GetAngle()) )
                        return true;
                }
            }
        }
        break;

    case S_CURVE:
        for( unsigned int i= 1; i < m_BezierPoints.size(); i++)
        {
            if( TestSegmentHit( aPosition, m_BezierPoints[i-1], m_BezierPoints[i-1], m_Width / 2 ) )
                return true;
        }
        break;

    case S_SEGMENT:
        if( TestSegmentHit( aPosition, m_Start, m_End, m_Width / 2 ) )
            return true;
        break;

    default:
        wxASSERT( 0 );
        break;
    }
    return false;
}