Ejemplo n.º 1
0
/**
 * Function IsPolygonSelfIntersecting
 * Test a CPolyLine for self-intersection of vertex (all contours).
 *
 * @return :
 *  false if no intersecting sides
 *  true if intersecting sides
 * When a CPolyLine is self intersectic, it need to be normalized.
 * (converted to non intersecting polygons)
 */
bool CPolyLine::IsPolygonSelfIntersecting()
{
    // first, check for sides intersecting other sides
    int n_cont  = GetContoursCount();

    // make bounding rect for each contour
    std::vector<EDA_RECT> cr;
    cr.reserve( n_cont );

    for( int icont = 0; icont<n_cont; icont++ )
        cr.push_back( GetBoundingBox( icont ) );

    for( int icont = 0; icont<n_cont; icont++ )
    {
        int is_start = GetContourStart( icont );
        int is_end   = GetContourEnd( icont );

        for( int is = is_start; is<=is_end; is++ )
        {
            int is_prev = is - 1;

            if( is_prev < is_start )
                is_prev = is_end;

            int is_next = is + 1;

            if( is_next > is_end )
                is_next = is_start;

            int x1i   = GetX( is );
            int y1i   = GetY( is );
            int x1f   = GetX( is_next );
            int y1f   = GetY( is_next );

            // check for intersection with any other sides
            for( int icont2 = icont; icont2 < n_cont; icont2++ )
            {
                if( !cr[icont].Intersects( cr[icont2] ) )
                {
                    // rectangles don't overlap, do nothing
                }
                else
                {
                    int is2_start = GetContourStart( icont2 );
                    int is2_end   = GetContourEnd( icont2 );

                    for( int is2 = is2_start; is2<=is2_end; is2++ )
                    {
                        int is2_prev = is2 - 1;

                        if( is2_prev < is2_start )
                            is2_prev = is2_end;

                        int is2_next = is2 + 1;

                        if( is2_next > is2_end )
                            is2_next = is2_start;

                        if( icont != icont2
                           || ( is2 != is && is2 != is_prev && is2 != is_next &&
                                is != is2_prev && is != is2_next )
                          )
                        {
                            int x2i    = GetX( is2 );
                            int y2i    = GetY( is2 );
                            int x2f    = GetX( is2_next );
                            int y2f    = GetY( is2_next );
                            int ret    = FindSegmentIntersections( x1i, y1i, x1f, y1f,
                                                                   x2i, y2i, x2f, y2f );
                            if( ret )
                            {
                                // intersection between non-adjacent sides
                                return true;
                            }
                        }
                    }
                }
            }
        }
    }

    return false;
}
bool BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_test )
{
    // see if areas are on same layer
    if( area_ref->GetLayer() != area_to_test->GetLayer() )
        return false;

    CPolyLine* poly1 = area_ref->Outline();
    CPolyLine* poly2 = area_to_test->Outline();

    // test bounding rects
    EDA_RECT      b1 = poly1->GetBoundingBox();
    EDA_RECT      b2 = poly2->GetBoundingBox();

    if( ! b1.Intersects( b2 ) )
        return false;

    // now test for intersecting segments
    for( int icont1 = 0; icont1<poly1->GetContoursCount(); icont1++ )
    {
        int is1 = poly1->GetContourStart( icont1 );
        int ie1 = poly1->GetContourEnd( icont1 );

        for( int ic1 = is1; ic1<=ie1; ic1++ )
        {
            int xi1 = poly1->GetX( ic1 );
            int yi1 = poly1->GetY( ic1 );
            int xf1, yf1;

            if( ic1 < ie1 )
            {
                xf1 = poly1->GetX( ic1 + 1 );
                yf1 = poly1->GetY( ic1 + 1 );
            }
            else
            {
                xf1 = poly1->GetX( is1 );
                yf1 = poly1->GetY( is1 );
            }

            for( int icont2 = 0; icont2<poly2->GetContoursCount(); icont2++ )
            {
                int is2 = poly2->GetContourStart( icont2 );
                int ie2 = poly2->GetContourEnd( icont2 );

                for( int ic2 = is2; ic2<=ie2; ic2++ )
                {
                    int xi2 = poly2->GetX( ic2 );
                    int yi2 = poly2->GetY( ic2 );
                    int xf2, yf2;

                    if( ic2 < ie2 )
                    {
                        xf2 = poly2->GetX( ic2 + 1 );
                        yf2 = poly2->GetY( ic2 + 1 );
                    }
                    else
                    {
                        xf2 = poly2->GetX( is2 );
                        yf2 = poly2->GetY( is2 );
                    }

                    bool intersect = FindSegmentIntersections( xi1, yi1, xf1, yf1,
                                     xi2, yi2, xf2, yf2 );
                    if( intersect )
                        return true;
                }
            }
        }
    }

    // If a contour is inside an other contour, no segments intersects, but the zones
    // can be combined if a corner is inside an outline (only one corner is enought)
    for( int ic2 = 0; ic2 < poly2->GetCornersCount(); ic2++ )
    {
        int x = poly2->GetX( ic2 );
        int y = poly2->GetY( ic2 );

        if( poly1->TestPointInside( x, y ) )
        {
            return true;
        }
    }

    for( int ic1 = 0; ic1 < poly1->GetCornersCount(); ic1++ )
    {
        int x = poly1->GetX( ic1 );
        int y = poly1->GetY( ic1 );

        if( poly2->TestPointInside( x, y ) )
        {
            return true;
        }
    }

    return false;
}
Ejemplo n.º 3
0
/**
 * Function TestAreaIntersections
 * Check for intersection of a given copper area with other areas in same net
 * @param area_to_test = area to compare to all other areas in the same net
 */
bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
{
    CPolyLine* poly1 = area_to_test->m_Poly;

    for( unsigned ia2 = 0; ia2 < m_ZoneDescriptorList.size(); ia2++ )
    {
        ZONE_CONTAINER* area2 = m_ZoneDescriptorList[ia2];

        if( area_to_test->GetNet() != area2->GetNet() )
            continue;

        if( area_to_test == area2 )
            continue;

        // see if areas are on same layer
        if( area_to_test->GetLayer() != area2->GetLayer() )
            continue;

        if( area_to_test->GetPriority() != area2->GetPriority() )
            continue;

        CPolyLine* poly2 = area2->m_Poly;

        // test bounding rects
        CRect      b1 = poly1->GetCornerBounds();
        CRect      b2 = poly2->GetCornerBounds();

        if(  b1.bottom > b2.top
          || b1.top < b2.bottom
          || b1.left > b2.right
          || b1.right < b2.left )
            continue;

        // test for intersecting segments
        for( int icont1 = 0; icont1<poly1->GetNumContours(); icont1++ )
        {
            int is1 = poly1->GetContourStart( icont1 );
            int ie1 = poly1->GetContourEnd( icont1 );

            for( int ic1 = is1; ic1<=ie1; ic1++ )
            {
                int xi1 = poly1->GetX( ic1 );
                int yi1 = poly1->GetY( ic1 );
                int xf1, yf1, style1;

                if( ic1 < ie1 )
                {
                    xf1 = poly1->GetX( ic1 + 1 );
                    yf1 = poly1->GetY( ic1 + 1 );
                }
                else
                {
                    xf1 = poly1->GetX( is1 );
                    yf1 = poly1->GetY( is1 );
                }

                style1 = poly1->GetSideStyle( ic1 );

                for( int icont2 = 0; icont2 < poly2->GetNumContours(); icont2++ )
                {
                    int is2 = poly2->GetContourStart( icont2 );
                    int ie2 = poly2->GetContourEnd( icont2 );

                    for( int ic2 = is2; ic2<=ie2; ic2++ )
                    {
                        int xi2 = poly2->GetX( ic2 );
                        int yi2 = poly2->GetY( ic2 );
                        int xf2, yf2, style2;

                        if( ic2 < ie2 )
                        {
                            xf2 = poly2->GetX( ic2 + 1 );
                            yf2 = poly2->GetY( ic2 + 1 );
                        }
                        else
                        {
                            xf2 = poly2->GetX( is2 );
                            yf2 = poly2->GetY( is2 );
                        }

                        style2 = poly2->GetSideStyle( ic2 );
                        int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, style1,
                                                              xi2, yi2, xf2, yf2, style2 );
                        if( n_int )
                            return true;
                    }
                }
            }
        }

        // If a contour is inside an other contour, no segments intersects, but the zones can
        // be combined test a corner inside an outline (only one corner is enought)
        for( int ic2 = 0; ic2 < poly2->GetNumCorners(); ic2++ )
        {
            int x = poly2->GetX( ic2 );
            int y = poly2->GetY( ic2 );

            if( poly1->TestPointInside( x, y ) )
            {
                return true;
            }
        }

        for( int ic1 = 0; ic1 < poly1->GetNumCorners(); ic1++ )
        {
            int x = poly1->GetX( ic1 );
            int y = poly1->GetY( ic1 );

            if( poly2->TestPointInside( x, y ) )
            {
                return true;
            }
        }
    }

    return false;
}
Ejemplo n.º 4
0
/**
 * Function TestAreaIntersection
 * Test for intersection of 2 copper areas
 * area_to_test must be after area_ref in m_ZoneDescriptorList
 * @param area_ref = area reference
 * @param area_to_test = area to compare for intersection calculations
 * @return : 0 if no intersection
 *         1 if intersection
 *         2 if arcs intersect
 */
int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_test )
{
    // see if areas are on same layer
    if( area_ref->GetLayer() != area_to_test->GetLayer() )
        return 0;

    CPolyLine* poly1 = area_ref->m_Poly;
    CPolyLine* poly2 = area_to_test->m_Poly;

    // test bounding rects
    CRect      b1 = poly1->GetCornerBounds();
    CRect      b2 = poly2->GetCornerBounds();

    if(  b1.bottom > b2.top
      || b1.top < b2.bottom
      || b1.left > b2.right
      || b1.right < b2.left )
        return 0;

    // now test for intersecting segments
    bool bInt    = false;
    bool bArcInt = false;

    for( int icont1 = 0; icont1<poly1->GetNumContours(); icont1++ )
    {
        int is1 = poly1->GetContourStart( icont1 );
        int ie1 = poly1->GetContourEnd( icont1 );

        for( int ic1 = is1; ic1<=ie1; ic1++ )
        {
            int xi1 = poly1->GetX( ic1 );
            int yi1 = poly1->GetY( ic1 );
            int xf1, yf1, style1;

            if( ic1 < ie1 )
            {
                xf1 = poly1->GetX( ic1 + 1 );
                yf1 = poly1->GetY( ic1 + 1 );
            }
            else
            {
                xf1 = poly1->GetX( is1 );
                yf1 = poly1->GetY( is1 );
            }

            style1 = poly1->GetSideStyle( ic1 );

            for( int icont2 = 0; icont2<poly2->GetNumContours(); icont2++ )
            {
                int is2 = poly2->GetContourStart( icont2 );
                int ie2 = poly2->GetContourEnd( icont2 );

                for( int ic2 = is2; ic2<=ie2; ic2++ )
                {
                    int xi2 = poly2->GetX( ic2 );
                    int yi2 = poly2->GetY( ic2 );
                    int xf2, yf2, style2;

                    if( ic2 < ie2 )
                    {
                        xf2 = poly2->GetX( ic2 + 1 );
                        yf2 = poly2->GetY( ic2 + 1 );
                    }
                    else
                    {
                        xf2 = poly2->GetX( is2 );
                        yf2 = poly2->GetY( is2 );
                    }

                    style2 = poly2->GetSideStyle( ic2 );
                    int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, style1,
                                                          xi2, yi2, xf2, yf2, style2 );
                    if( n_int )
                    {
                        bInt = true;

                        if( style1 != CPolyLine::STRAIGHT || style2 != CPolyLine::STRAIGHT )
                            bArcInt = true;

                        break;
                    }
                }

                if( bArcInt )
                    break;
            }

            if( bArcInt )
                break;
        }

        if( bArcInt )
            break;
    }

    if( !bInt )
    {
        if( bArcInt )
            return 0;

        // If a contour is inside an other contour, no segments intersects, but the zones
        // can be combined test a corner inside an outline (only one corner is enought)
        for( int ic2 = 0; ic2 < poly2->GetNumCorners(); ic2++ )
        {
            int x = poly2->GetX( ic2 );
            int y = poly2->GetY( ic2 );

            if( poly1->TestPointInside( x, y ) )
            {
                return 1;
            }
        }

        for( int ic1 = 0; ic1 < poly1->GetNumCorners(); ic1++ )
        {
            int x = poly1->GetX( ic1 );
            int y = poly1->GetY( ic1 );

            if( poly2->TestPointInside( x, y ) )
            {
                return 1;
            }
        }

        return 0;
    }

    if( bArcInt )
        return 2;

    return 1;
}
Ejemplo n.º 5
0
/**
 * Function TestAreaPolygon
 * Test an area for self-intersection.
 *
 * @param CurrArea = copper area to test
 * @return :
 * -1 if arcs intersect other sides
 *  0 if no intersecting sides
 *  1 if intersecting sides, but no intersecting arcs
 * Also sets utility2 flag of area with return value
 */
int BOARD::TestAreaPolygon( ZONE_CONTAINER* CurrArea )
{
    CPolyLine*         p = CurrArea->m_Poly;

    // first, check for sides intersecting other sides, especially arcs
    bool               bInt    = false;
    bool               bArcInt = false;
    int                n_cont  = p->GetNumContours();

    // make bounding rect for each contour
    std::vector<CRect> cr;
    cr.reserve( n_cont );

    for( int icont = 0; icont<n_cont; icont++ )
        cr.push_back( p->GetCornerBounds( icont ) );

    for( int icont = 0; icont<n_cont; icont++ )
    {
        int is_start = p->GetContourStart( icont );
        int is_end   = p->GetContourEnd( icont );

        for( int is = is_start; is<=is_end; is++ )
        {
            int is_prev = is - 1;

            if( is_prev < is_start )
                is_prev = is_end;

            int is_next = is + 1;

            if( is_next > is_end )
                is_next = is_start;

            int style = p->GetSideStyle( is );
            int x1i   = p->GetX( is );
            int y1i   = p->GetY( is );
            int x1f   = p->GetX( is_next );
            int y1f   = p->GetY( is_next );

            // check for intersection with any other sides
            for( int icont2 = icont; icont2<n_cont; icont2++ )
            {
                if( cr[icont].left > cr[icont2].right
                    || cr[icont].bottom > cr[icont2].top
                    || cr[icont2].left > cr[icont].right
                    || cr[icont2].bottom > cr[icont].top )
                {
                    // rectangles don't overlap, do nothing
                }
                else
                {
                    int is2_start = p->GetContourStart( icont2 );
                    int is2_end   = p->GetContourEnd( icont2 );

                    for( int is2 = is2_start; is2<=is2_end; is2++ )
                    {
                        int is2_prev = is2 - 1;

                        if( is2_prev < is2_start )
                            is2_prev = is2_end;

                        int is2_next = is2 + 1;

                        if( is2_next > is2_end )
                            is2_next = is2_start;

                        if( icont != icont2
                           || (is2 != is && is2 != is_prev && is2 != is_next && is != is2_prev
                               && is !=
                               is2_next ) )
                        {
                            int style2 = p->GetSideStyle( is2 );
                            int x2i    = p->GetX( is2 );
                            int y2i    = p->GetY( is2 );
                            int x2f    = p->GetX( is2_next );
                            int y2f    = p->GetY( is2_next );
                            int ret    = FindSegmentIntersections( x1i, y1i, x1f, y1f, style,
                                                                   x2i, y2i, x2f, y2f, style2 );
                            if( ret )
                            {
                                // intersection between non-adjacent sides
                                bInt = true;

                                if( style != CPolyLine::STRAIGHT || style2 != CPolyLine::STRAIGHT )
                                {
                                    bArcInt = true;
                                    break;
                                }
                            }
                        }
                    }
                }

                if( bArcInt )
                    break;
            }

            if( bArcInt )
                break;
        }

        if( bArcInt )
            break;
    }

    if( bArcInt )
        CurrArea->utility2 = -1;
    else if( bInt )
        CurrArea->utility2 = 1;
    else
        CurrArea->utility2 = 0;

    return CurrArea->utility2;
}