/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }