From fa472950b770bb67df1c0ba4b939701ba2e0697e Mon Sep 17 00:00:00 2001 From: charras Date: Fri, 28 Nov 2008 20:10:05 +0000 Subject: [PATCH] pcbnew: better protection against malformed zones --- pcbnew/ioascii.cpp | 7 +- pcbnew/zone_filling_algorithm.cpp | 62 ++++++++++++++ pcbnew/zones_by_polygon.cpp | 2 +- pcbnew/zones_non_copper_type_functions.cpp | 55 ------------- pcbnew/zones_test_and_combine_areas.cpp | 96 ++++------------------ 5 files changed, 80 insertions(+), 142 deletions(-) diff --git a/pcbnew/ioascii.cpp b/pcbnew/ioascii.cpp index 442bfc616be..447227f1298 100644 --- a/pcbnew/ioascii.cpp +++ b/pcbnew/ioascii.cpp @@ -7,7 +7,6 @@ /* ioascii.cpp */ #include "fctsys.h" -#include "gr_basic.h" #include "common.h" #include "pcbnew.h" @@ -22,8 +21,6 @@ #include "cvpcb.h" #endif -#include "protos.h" - /* Format des structures de sauvegarde type ASCII : Structure PAD: @@ -859,7 +856,9 @@ int WinEDA_PcbFrame::ReadPcbFile( FILE* File, bool Append ) { ZONE_CONTAINER * zone_descr = new ZONE_CONTAINER(m_Pcb); zone_descr->ReadDescr( File, &LineNum ); - m_Pcb->Add(zone_descr); + if ( zone_descr->GetNumCorners( ) > 2 ) // should not occur + m_Pcb->Add(zone_descr); + else delete zone_descr; continue; } diff --git a/pcbnew/zone_filling_algorithm.cpp b/pcbnew/zone_filling_algorithm.cpp index f9c6be1d7c3..256c9098873 100644 --- a/pcbnew/zone_filling_algorithm.cpp +++ b/pcbnew/zone_filling_algorithm.cpp @@ -21,6 +21,68 @@ static void Genere_Segments_Zone( WinEDA_PcbFrame* frame, wxDC* DC, int net_code static bool Zone_Debug = false; static unsigned long s_TimeStamp; /* Time stamp common to all segments relative to the new created zone */ + + + +/***********************************************************/ +int ZONE_CONTAINER::BuildFilledPolysListData( BOARD * aPcb ) +/***********************************************************/ +/** function BuildFilledPolysListData + * Build m_FilledPolysList data from real outlines (m_Poly) + * in order to have drawable (and plottable) filled polygons + * drawable filled polygons are polygons without hole + * @param aPcb: the current board (can be NULL for non copper zones) + * @return number of polygons + * This function does not add holes for pads and tracks but calls + * AddClearanceAreasPolygonsToPolysList() to do that for copper layers + */ +{ + + // Currently, for copper zones, we can use segment filling or filling by polygon areas + // if m_GridFillValue == 0 polygon areas will be used (No Grid) + if ( IsOnCopperLayer() && ( m_GridFillValue != 0 ) ) + return 0; + + m_FilledPolysList.clear(); + /* convert outlines + holes to outlines without holes (adding extra segments if necessary) + * m_Poly data is expected normalized, i.e. NormalizeAreaOutlines was used after building this zone + */ + + if ( GetNumCorners( ) <= 2 ) // malformed zone. Kbool does not like it ... + return 0; + + m_Poly->MakeKboolPoly( -1, -1, NULL, true ); + int count = 0; + while( m_Poly->GetKboolEngine()->StartPolygonGet() ) + { + CPolyPt corner(0,0,false); + while( m_Poly->GetKboolEngine()->PolygonHasMorePoints() ) + { + corner.x = (int)m_Poly->GetKboolEngine()->GetPolygonXPoint(); + corner.y = (int)m_Poly->GetKboolEngine()->GetPolygonYPoint(); + corner.end_contour = false; + m_FilledPolysList.push_back(corner); + count ++; + } + corner.end_contour = true; + m_FilledPolysList.pop_back(); + m_FilledPolysList.push_back(corner); + m_Poly->GetKboolEngine()->EndPolygonGet(); + } + + m_Poly->FreeKboolEngine(); + + /* For copper layers, we now must add holes in the Polygon list. + holes are pads and tracks with their clearance area + */ + + if ( IsOnCopperLayer() ) + AddClearanceAreasPolygonsToPolysList( aPcb ); + + return count; +} + + /*****************************************************************************/ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose ) /*****************************************************************************/ diff --git a/pcbnew/zones_by_polygon.cpp b/pcbnew/zones_by_polygon.cpp index 67ad430a072..3cb24fa736e 100644 --- a/pcbnew/zones_by_polygon.cpp +++ b/pcbnew/zones_by_polygon.cpp @@ -356,7 +356,7 @@ void WinEDA_PcbFrame::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_contain { DrawPanel->PostDirtyRect( zone_container->GetBoundingBox() ); if( DC ) - { + { // Remove the full zone because this is no more an area Delete_Zone_Fill( DC, NULL, zone_container->m_TimeStamp ); zone_container->DrawFilledArea( DrawPanel, DC, GR_XOR ); } diff --git a/pcbnew/zones_non_copper_type_functions.cpp b/pcbnew/zones_non_copper_type_functions.cpp index a738b8e9519..03b6d7d7f27 100644 --- a/pcbnew/zones_non_copper_type_functions.cpp +++ b/pcbnew/zones_non_copper_type_functions.cpp @@ -164,58 +164,3 @@ void DialogNonCopperZonesEditor::OnCancelClick( wxCommandEvent& event ) EndModal( ZONE_ABORT ); } - - -/***********************************************************/ -int ZONE_CONTAINER::BuildFilledPolysListData( BOARD * aPcb ) -/***********************************************************/ -/** function BuildFilledPolysListData - * Build m_FilledPolysList data from real outlines (m_Poly) - * in order to have drawable (and plottable) filled polygons - * drawable filled polygons are polygons without hole - * @param aPcb: the current board (can be NULL for non copper zones) - * @return number of polygons - * This function does not add holes for pads and tracks but calls - * AddClearanceAreasPolygonsToPolysList() to do that for copper layers - */ -{ - - // Currently, for copper zones, we can use segment filling or filling by polygon areas - // if m_GridFillValue == 0 polygon areas will be used (No Grid) - if ( IsOnCopperLayer() && ( m_GridFillValue != 0 ) ) - return 0; - - m_FilledPolysList.clear(); - /* convert outlines + holes to outlines without holes (adding extra segments if necessary) - * m_Poly data is expected normalized, i.e. NormalizeAreaOutlines was used after building this zone - */ - m_Poly->MakeKboolPoly( -1, -1, NULL, true ); - int count = 0; - while( m_Poly->GetKboolEngine()->StartPolygonGet() ) - { - CPolyPt corner(0,0,false); - while( m_Poly->GetKboolEngine()->PolygonHasMorePoints() ) - { - corner.x = (int)m_Poly->GetKboolEngine()->GetPolygonXPoint(); - corner.y = (int)m_Poly->GetKboolEngine()->GetPolygonYPoint(); - corner.end_contour = false; - m_FilledPolysList.push_back(corner); - count ++; - } - corner.end_contour = true; - m_FilledPolysList.pop_back(); - m_FilledPolysList.push_back(corner); - m_Poly->GetKboolEngine()->EndPolygonGet(); - } - - m_Poly->FreeKboolEngine(); - - /* For copper layers, we now must add holes in the Polygon list. - holes are pads and tracks with their clearance area - */ - - if ( IsOnCopperLayer() ) - AddClearanceAreasPolygonsToPolysList( aPcb ); - - return count; -} diff --git a/pcbnew/zones_test_and_combine_areas.cpp b/pcbnew/zones_test_and_combine_areas.cpp index b61d93be782..a252d7f35ff 100644 --- a/pcbnew/zones_test_and_combine_areas.cpp +++ b/pcbnew/zones_test_and_combine_areas.cpp @@ -336,7 +336,18 @@ int BOARD::AreaPolygonModified( ZONE_CONTAINER* modified_area, m_ZoneDescriptorList[ia]->BuildFilledPolysListData( this ); } } - return test; + // Test for bad areas: all zones must have more than 2 corners: + // Note: should not happen, but just in case. + for( unsigned ia1 = 0; ia1 < m_ZoneDescriptorList.size() - 1; ) + { + ZONE_CONTAINER* zone = m_ZoneDescriptorList[ia1]; + if( zone->GetNumCorners( ) >= 3 ) + ia1++; + // Remove zone because it is incorrect: + else + RemoveArea( zone ); + } + return test; } @@ -387,21 +398,6 @@ int BOARD::CombineAllAreasInNet( int aNetCode, bool bMessageBox, bool bUseUtilit ret = CombineAreas( curr_area, area2 ); if( ret == 1 ) { - if( bMessageBox && bDontShowIntersectionWarning == false ) - { - wxString str; - str.Printf( - wxT( - "Areas %d and %d of net \"%s\" intersect and will be combined.\n" ), - ia1 + 1, - ia2 + 1, - curr_area->m_Netname.GetData() ); - str += wxT( - "If they are complex, this may take a few seconds." ); - wxMessageBox( str ); - -// bDontShowIntersectionWarning = dlg.bDontShowBoxState; - } mod_ia1 = true; } else if( ret == 2 ) @@ -428,7 +424,8 @@ int BOARD::CombineAllAreasInNet( int aNetCode, bool bMessageBox, bool bUseUtilit ia1--; // if modified, we need to check it again } } - return 0; + + return 0; } @@ -683,13 +680,6 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi { if( area_ref == area_to_combine ) ASSERT( 0 ); -#if 0 - - // test for intersection - int test = TestAreaIntersection( area_ref, area_to_combine ); - if( test != 1 ) - return test; // no intersection -#endif // polygons intersect, combine them std::vector arc_array1; @@ -798,64 +788,6 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi } -#if 0 // Currently not used: work in progress - -/** - * Function Is_Area_Inside_Area - * Test a given area to see if it is inside an other area, or an other area is inside the given area - * an area is inside an other are if ALL its edges are inside the other area - * @param Area_Ref: the given area to compare with other areas - * used to remove redundant areas - */ -ZONE_CONTAINER* BOARD::Is_Area_Inside_Area( ZONE_CONTAINER* Area_Ref ) -{ - int corners_inside_count; - - for( int ia = 0; ia < GetAreaCount(); ia++ ) - { - ZONE_CONTAINER* Area_To_Test = GetArea( ia ); - - if( Area_Ref == Area_To_Test ) - continue; - - // test for same layer - if( Area_Ref->GetLayer() != Area_To_Test->GetLayer() ) - continue; - - // test if Area_Ref inside Area_To_Test - corners_inside_count = Area_Ref->m_Poly->GetNumCorners(); - for( int ic = 0; ic < Area_Ref->m_Poly->GetNumCorners(); ic++ ) - { - int x = Area_Ref->m_Poly->GetX( ic ); - int y = Area_Ref->m_Poly->GetY( ic ); - if( Area_To_Test->m_Poly->TestPointInside( x, y ) ) - corners_inside_count--; - } - - if( corners_inside_count == 0 ) - return Area_Ref; - - // test if Area_To_Test inside Area_Ref - corners_inside_count = Area_To_Test->m_Poly->GetNumCorners(); - for( int ic2 = 0; ic2 < Area_To_Test->m_Poly->GetNumCorners(); ic2++ ) - { - int x = Area_To_Test->m_Poly->GetX( ic2 ); - int y = Area_To_Test->m_Poly->GetY( ic2 ); - if( Area_Ref->m_Poly->TestPointInside( x, y ) ) - corners_inside_count--; - } - - if( corners_inside_count == 0 ) - return Area_Ref; - } - - return NULL; -} - - -#endif - - /** * Function Test_Drc_Areas_Outlines_To_Areas_Outlines * Test Areas outlines for DRC: