pcbnew: better protection against malformed zones
This commit is contained in:
parent
55bc5be7a9
commit
fa472950b7
|
@ -7,7 +7,6 @@
|
||||||
/* ioascii.cpp */
|
/* ioascii.cpp */
|
||||||
|
|
||||||
#include "fctsys.h"
|
#include "fctsys.h"
|
||||||
#include "gr_basic.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "pcbnew.h"
|
#include "pcbnew.h"
|
||||||
|
@ -22,8 +21,6 @@
|
||||||
#include "cvpcb.h"
|
#include "cvpcb.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "protos.h"
|
|
||||||
|
|
||||||
/* Format des structures de sauvegarde type ASCII :
|
/* Format des structures de sauvegarde type ASCII :
|
||||||
|
|
||||||
Structure PAD:
|
Structure PAD:
|
||||||
|
@ -859,7 +856,9 @@ int WinEDA_PcbFrame::ReadPcbFile( FILE* File, bool Append )
|
||||||
{
|
{
|
||||||
ZONE_CONTAINER * zone_descr = new ZONE_CONTAINER(m_Pcb);
|
ZONE_CONTAINER * zone_descr = new ZONE_CONTAINER(m_Pcb);
|
||||||
zone_descr->ReadDescr( File, &LineNum );
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,68 @@ static void Genere_Segments_Zone( WinEDA_PcbFrame* frame, wxDC* DC, int net_code
|
||||||
static bool Zone_Debug = false;
|
static bool Zone_Debug = false;
|
||||||
static unsigned long s_TimeStamp; /* Time stamp common to all segments relative to the new created zone */
|
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 )
|
int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose )
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
|
@ -356,7 +356,7 @@ void WinEDA_PcbFrame::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_contain
|
||||||
{
|
{
|
||||||
DrawPanel->PostDirtyRect( zone_container->GetBoundingBox() );
|
DrawPanel->PostDirtyRect( zone_container->GetBoundingBox() );
|
||||||
if( DC )
|
if( DC )
|
||||||
{
|
{ // Remove the full zone because this is no more an area
|
||||||
Delete_Zone_Fill( DC, NULL, zone_container->m_TimeStamp );
|
Delete_Zone_Fill( DC, NULL, zone_container->m_TimeStamp );
|
||||||
zone_container->DrawFilledArea( DrawPanel, DC, GR_XOR );
|
zone_container->DrawFilledArea( DrawPanel, DC, GR_XOR );
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,58 +164,3 @@ void DialogNonCopperZonesEditor::OnCancelClick( wxCommandEvent& event )
|
||||||
EndModal( ZONE_ABORT );
|
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -336,7 +336,18 @@ int BOARD::AreaPolygonModified( ZONE_CONTAINER* modified_area,
|
||||||
m_ZoneDescriptorList[ia]->BuildFilledPolysListData( this );
|
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 );
|
ret = CombineAreas( curr_area, area2 );
|
||||||
if( ret == 1 )
|
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;
|
mod_ia1 = true;
|
||||||
}
|
}
|
||||||
else if( ret == 2 )
|
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
|
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 )
|
if( area_ref == area_to_combine )
|
||||||
ASSERT( 0 );
|
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
|
// polygons intersect, combine them
|
||||||
std::vector<CArc> arc_array1;
|
std::vector<CArc> 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
|
* Function Test_Drc_Areas_Outlines_To_Areas_Outlines
|
||||||
* Test Areas outlines for DRC:
|
* Test Areas outlines for DRC:
|
||||||
|
|
Loading…
Reference in New Issue