int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_Examine, bool aCreate_Markers ) { wxString str; int nerrors = 0; // iterate through all areas for( int ia = 0; ia < GetAreaCount(); ia++ ) { ZONE_CONTAINER* Area_Ref = GetArea( ia ); CPolyLine* refSmoothedPoly = Area_Ref->GetSmoothedPoly(); if( !Area_Ref->IsOnCopperLayer() ) continue; // If testing only a single area, then skip all others if( aArea_To_Examine && (aArea_To_Examine != Area_Ref) ) continue; for( int ia2 = 0; ia2 < GetAreaCount(); ia2++ ) { ZONE_CONTAINER* Area_To_Test = GetArea( ia2 ); CPolyLine* testSmoothedPoly = Area_To_Test->GetSmoothedPoly(); if( Area_Ref == Area_To_Test ) continue; // test for same layer if( Area_Ref->GetLayer() != Area_To_Test->GetLayer() ) continue; // Test for same net if( Area_Ref->GetNet() == Area_To_Test->GetNet() && Area_Ref->GetNet() >= 0 ) continue; // test for different priorities if( Area_Ref->GetPriority() != Area_To_Test->GetPriority() ) continue; // Examine a candidate zone: compare Area_To_Test to Area_Ref // Get clearance used in zone to zone test. The policy used to // obtain that value is now part of the zone object itself by way of // ZONE_CONTAINER::GetClearance(). int zone2zoneClearance = Area_Ref->GetClearance( Area_To_Test ); // test for some corners of Area_Ref inside Area_To_Test for( int ic = 0; ic < refSmoothedPoly->GetNumCorners(); ic++ ) { int x = refSmoothedPoly->GetX( ic ); int y = refSmoothedPoly->GetY( ic ); if( testSmoothedPoly->TestPointInside( x, y ) ) { // COPPERAREA_COPPERAREA error: copper area ref corner inside copper area if( aCreate_Markers ) { wxString msg1 = Area_Ref->GetSelectMenuText(); wxString msg2 = Area_To_Test->GetSelectMenuText(); MARKER_PCB* marker = new MARKER_PCB( COPPERAREA_INSIDE_COPPERAREA, wxPoint( x, y ), msg1, wxPoint( x, y ), msg2, wxPoint( x, y ) ); Add( marker ); } nerrors++; } } // test for some corners of Area_To_Test inside Area_Ref for( int ic2 = 0; ic2 < testSmoothedPoly->GetNumCorners(); ic2++ ) { int x = testSmoothedPoly->GetX( ic2 ); int y = testSmoothedPoly->GetY( ic2 ); if( refSmoothedPoly->TestPointInside( x, y ) ) { // COPPERAREA_COPPERAREA error: copper area corner inside copper area ref if( aCreate_Markers ) { wxString msg1 = Area_To_Test->GetSelectMenuText(); wxString msg2 = Area_Ref->GetSelectMenuText(); MARKER_PCB* marker = new MARKER_PCB( COPPERAREA_INSIDE_COPPERAREA, wxPoint( x, y ), msg1, wxPoint( x, y ), msg2, wxPoint( x, y ) ); Add( marker ); } nerrors++; } } // now test spacing between areas for( int icont = 0; icont < refSmoothedPoly->GetNumContours(); icont++ ) { int ic_start = refSmoothedPoly->GetContourStart( icont ); int ic_end = refSmoothedPoly->GetContourEnd( icont ); for( int ic = ic_start; ic<=ic_end; ic++ ) { int ax1 = refSmoothedPoly->GetX( ic ); int ay1 = refSmoothedPoly->GetY( ic ); int ax2, ay2; if( ic == ic_end ) { ax2 = refSmoothedPoly->GetX( ic_start ); ay2 = refSmoothedPoly->GetY( ic_start ); } else { ax2 = refSmoothedPoly->GetX( ic + 1 ); ay2 = refSmoothedPoly->GetY( ic + 1 ); } int astyle = refSmoothedPoly->GetSideStyle( ic ); for( int icont2 = 0; icont2 < testSmoothedPoly->GetNumContours(); icont2++ ) { int ic_start2 = testSmoothedPoly->GetContourStart( icont2 ); int ic_end2 = testSmoothedPoly->GetContourEnd( icont2 ); for( int ic2 = ic_start2; ic2<=ic_end2; ic2++ ) { int bx1 = testSmoothedPoly->GetX( ic2 ); int by1 = testSmoothedPoly->GetY( ic2 ); int bx2, by2; if( ic2 == ic_end2 ) { bx2 = testSmoothedPoly->GetX( ic_start2 ); by2 = testSmoothedPoly->GetY( ic_start2 ); } else { bx2 = testSmoothedPoly->GetX( ic2 + 1 ); by2 = testSmoothedPoly->GetY( ic2 + 1 ); } int bstyle = testSmoothedPoly->GetSideStyle( ic2 ); int x, y; int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2, bstyle, 0, ax1, ay1, ax2, ay2, astyle, 0, zone2zoneClearance, &x, &y ); if( d < zone2zoneClearance ) { // COPPERAREA_COPPERAREA error : intersect or too close if( aCreate_Markers ) { wxString msg1 = Area_Ref->GetSelectMenuText(); wxString msg2 = Area_To_Test->GetSelectMenuText(); MARKER_PCB* marker = new MARKER_PCB( COPPERAREA_CLOSE_TO_COPPERAREA, wxPoint( x, y ), msg1, wxPoint( x, y ), msg2, wxPoint( x, y ) ); Add( marker ); } nerrors++; } } } } } } } return nerrors; }
/** * 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; }