GAL show markers for zone outlines gap test

Moved a DRC function (BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines)
from BOARD class to DRC (DRC::TestZoneToZoneOutline). Added BOARD_COMMITs
to handle marker visibility updates.

Fixes: lp:1619124
* https://bugs.launchpad.net/kicad/+bug/1619124
This commit is contained in:
Maciej Suminski 2017-12-08 11:25:13 +01:00
parent 693c8bce40
commit 9b5dc5c215
5 changed files with 185 additions and 190 deletions

View File

@ -1121,21 +1121,6 @@ public:
ZONE_CONTAINER* area_ref,
ZONE_CONTAINER* area_to_combine );
/**
* Function Test_Drc_Areas_Outlines_To_Areas_Outlines
* tests area outlines for DRC:
* Tests areas inside other areas.
* Tests areas too close.
*
* @param aArea_To_Examine: area to compare with other areas, or if NULL then
* all areas are compared to all others.
* @param aCreate_Markers: if true create DRC markers. False: do not creates anything
* @return errors count
*/
int Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_Examine,
bool aCreate_Markers );
/**
* Function GetViaByPosition
* finds the first via at \a aPosition on \a aLayer.

View File

@ -41,6 +41,7 @@
#include <class_draw_panel_gal.h>
#include <view/view.h>
#include <geometry/seg.h>
#include <math_for_graphics.h>
#include <connectivity_data.h>
#include <connectivity_algo.h>
@ -89,13 +90,15 @@ void DRC::ShowDRCDialog( wxWindow* aParent )
}
}
void DRC::addMarkerToPcb( MARKER_PCB* aMarker )
{
BOARD_COMMIT commit ( m_pcbEditorFrame );
BOARD_COMMIT commit( m_pcbEditorFrame );
commit.Add( aMarker );
commit.Push( wxEmptyString, false );
}
void DRC::DestroyDRCDialog( int aReason )
{
if( m_drcDialog )
@ -176,6 +179,168 @@ int DRC::Drc( TRACK* aRefSegm, TRACK* aList )
}
int DRC::TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers )
{
BOARD* board = m_pcbEditorFrame->GetBoard();
BOARD_COMMIT commit( m_pcbEditorFrame );
int nerrors = 0;
// iterate through all areas
for( int ia = 0; ia < board->GetAreaCount(); ia++ )
{
ZONE_CONTAINER* zoneRef = board->GetArea( ia );
SHAPE_POLY_SET refSmoothedPoly;
zoneRef->BuildSmoothedPoly( refSmoothedPoly );
if( !zoneRef->IsOnCopperLayer() )
continue;
// When testing only a single area, skip all others
if( aZone && ( aZone != zoneRef) )
continue;
for( int ia2 = 0; ia2 < board->GetAreaCount(); ia2++ )
{
ZONE_CONTAINER* zoneToTest = board->GetArea( ia2 );
SHAPE_POLY_SET testSmoothedPoly;
zoneToTest->BuildSmoothedPoly( testSmoothedPoly );
if( zoneRef == zoneToTest )
continue;
// test for same layer
if( zoneRef->GetLayer() != zoneToTest->GetLayer() )
continue;
// Test for same net
if( zoneRef->GetNetCode() == zoneToTest->GetNetCode() && zoneRef->GetNetCode() >= 0 )
continue;
// test for different priorities
if( zoneRef->GetPriority() != zoneToTest->GetPriority() )
continue;
// test for different types
if( zoneRef->GetIsKeepout() != zoneToTest->GetIsKeepout() )
continue;
// Examine a candidate zone: compare zoneToTest to zoneRef
// 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 = zoneRef->GetClearance( zoneToTest );
// Keepout areas have no clearance, so set zone2zoneClearance to 1
// ( zone2zoneClearance = 0 can create problems in test functions)
if( zoneRef->GetIsKeepout() )
zone2zoneClearance = 1;
// test for some corners of zoneRef inside zoneToTest
for( auto iterator = refSmoothedPoly.IterateWithHoles(); iterator; iterator++ )
{
VECTOR2I currentVertex = *iterator;
if( testSmoothedPoly.Contains( currentVertex ) )
{
// COPPERAREA_COPPERAREA error: copper area ref corner inside copper area
if( aCreateMarkers )
{
wxPoint pt( currentVertex.x, currentVertex.y );
wxString msg1 = zoneRef->GetSelectMenuText();
wxString msg2 = zoneToTest->GetSelectMenuText();
MARKER_PCB* marker = new MARKER_PCB( COPPERAREA_INSIDE_COPPERAREA,
pt, msg1, pt, msg2, pt );
commit.Add( marker );
}
nerrors++;
}
}
// test for some corners of zoneToTest inside zoneRef
for( auto iterator = testSmoothedPoly.IterateWithHoles(); iterator; iterator++ )
{
VECTOR2I currentVertex = *iterator;
if( refSmoothedPoly.Contains( currentVertex ) )
{
// COPPERAREA_COPPERAREA error: copper area corner inside copper area ref
if( aCreateMarkers )
{
wxPoint pt( currentVertex.x, currentVertex.y );
wxString msg1 = zoneToTest->GetSelectMenuText();
wxString msg2 = zoneRef->GetSelectMenuText();
MARKER_PCB* marker = new MARKER_PCB( COPPERAREA_INSIDE_COPPERAREA,
pt, msg1, pt, msg2, pt );
commit.Add( marker );
}
nerrors++;
}
}
// Iterate through all the segments of refSmoothedPoly
for( auto refIt = refSmoothedPoly.IterateSegmentsWithHoles(); refIt; refIt++ )
{
// Build ref segment
SEG refSegment = *refIt;
// Iterate through all the segments in testSmoothedPoly
for( auto testIt = testSmoothedPoly.IterateSegmentsWithHoles(); testIt; testIt++ )
{
// Build test segment
SEG testSegment = *testIt;
wxPoint pt;
int ax1, ay1, ax2, ay2;
ax1 = refSegment.A.x;
ay1 = refSegment.A.y;
ax2 = refSegment.B.x;
ay2 = refSegment.B.y;
int bx1, by1, bx2, by2;
bx1 = testSegment.A.x;
by1 = testSegment.A.y;
bx2 = testSegment.B.x;
by2 = testSegment.B.y;
int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
0,
ax1, ay1, ax2, ay2,
0,
zone2zoneClearance,
&pt.x, &pt.y );
if( d < zone2zoneClearance )
{
// COPPERAREA_COPPERAREA error : intersect or too close
if( aCreateMarkers )
{
wxString msg1 = zoneRef->GetSelectMenuText();
wxString msg2 = zoneToTest->GetSelectMenuText();
MARKER_PCB* marker = new MARKER_PCB( COPPERAREA_CLOSE_TO_COPPERAREA,
pt, msg1, pt, msg2, pt );
commit.Add( marker );
}
nerrors++;
}
}
}
}
}
if( aCreateMarkers )
commit.Push( wxEmptyString, false );
return nerrors;
}
int DRC::Drc( ZONE_CONTAINER* aArea, int aCornerIndex )
{
updatePointers();
@ -609,7 +774,7 @@ void DRC::testZones()
}
// Test copper areas outlines, and create markers when needed
m_pcb->Test_Drc_Areas_Outlines_To_Areas_Outlines( NULL, true );
TestZoneToZoneOutline( NULL, true );
}

View File

@ -458,6 +458,15 @@ public:
return doTrackKeepoutDrc( aRefSeg ) ? OK_DRC : BAD_DRC;
}
/*
* Tests whether distance between zones complies with the DRC rules.
*
* @param aZone: zone to compare with other zones, or if NULL then
* all zones are compared to all others.
* @param aCreateMarkers: if true create DRC markers. False: do not creates anything
* @return Errors count
*/
int TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers );
/**
* Function ShowDRCDialog

View File

@ -167,8 +167,10 @@ void PCB_EDIT_FRAME::duplicateZone( wxDC* aDC, ZONE_CONTAINER* aZone )
GetBoard()->RedrawAreasOutlines( m_canvas, aDC, GR_OR, newZone->GetLayer() );
GetBoard()->RedrawFilledAreas( m_canvas, aDC, GR_OR, newZone->GetLayer() );
DRC drc( this );
if( GetBoard()->GetAreaIndex( newZone ) >= 0
&& GetBoard()->Test_Drc_Areas_Outlines_To_Areas_Outlines( newZone, true ) )
&& drc.TestZoneToZoneOutline( newZone, true ) )
{
DisplayInfoMessage( this, _( "Warning: The new zone fails DRC" ) );
}
@ -367,7 +369,8 @@ void PCB_EDIT_FRAME::End_Move_Zone_Corner_Or_Outlines( wxDC* DC, ZONE_CONTAINER*
SaveCopyInUndoList(s_PickedList, UR_UNSPECIFIED);
s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items
int error_count = GetBoard()->Test_Drc_Areas_Outlines_To_Areas_Outlines( aZone, true );
DRC drc( this );
int error_count = drc.TestZoneToZoneOutline( aZone, true );
if( error_count )
{
@ -425,7 +428,8 @@ void PCB_EDIT_FRAME::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER* aZone )
if( ii < 0 )
aZone = NULL; // aZone does not exist anymore, after combining zones
int error_count = GetBoard()->Test_Drc_Areas_Outlines_To_Areas_Outlines( aZone, true );
DRC drc( this );
int error_count = drc.TestZoneToZoneOutline( aZone, true );
if( error_count )
{
@ -811,7 +815,8 @@ bool PCB_EDIT_FRAME::End_Zone( wxDC* DC )
if( ii < 0 )
zone = NULL; // was removed by combining zones
int error_count = GetBoard()->Test_Drc_Areas_Outlines_To_Areas_Outlines( zone, true );
DRC drc( this );
int error_count = drc.TestZoneToZoneOutline( zone, true );
if( error_count )
{

View File

@ -284,175 +284,6 @@ bool BOARD::CombineAreas( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_
}
int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_Examine,
bool aCreate_Markers )
{
int nerrors = 0;
// iterate through all areas
for( int ia = 0; ia < GetAreaCount(); ia++ )
{
ZONE_CONTAINER* Area_Ref = GetArea( ia );
SHAPE_POLY_SET refSmoothedPoly;
Area_Ref->BuildSmoothedPoly( refSmoothedPoly );
if( !Area_Ref->IsOnCopperLayer() )
continue;
// When testing only a single area, 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 );
SHAPE_POLY_SET testSmoothedPoly;
area_to_test->BuildSmoothedPoly( testSmoothedPoly );
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->GetNetCode() == area_to_test->GetNetCode() && Area_Ref->GetNetCode() >= 0 )
continue;
// test for different priorities
if( Area_Ref->GetPriority() != area_to_test->GetPriority() )
continue;
// test for different types
if( Area_Ref->GetIsKeepout() != area_to_test->GetIsKeepout() )
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 );
// Keepout areas have no clearance, so set zone2zoneClearance to 1
// ( zone2zoneClearance = 0 can create problems in test functions)
if( Area_Ref->GetIsKeepout() )
zone2zoneClearance = 1;
// test for some corners of Area_Ref inside area_to_test
for( auto iterator = refSmoothedPoly.IterateWithHoles(); iterator; iterator++ )
{
VECTOR2I currentVertex = *iterator;
if( testSmoothedPoly.Contains( currentVertex ) )
{
// COPPERAREA_COPPERAREA error: copper area ref corner inside copper area
if( aCreate_Markers )
{
int x = currentVertex.x;
int y = currentVertex.y;
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( auto iterator = testSmoothedPoly.IterateWithHoles(); iterator; iterator++ )
{
VECTOR2I currentVertex = *iterator;
if( refSmoothedPoly.Contains( currentVertex ) )
{
// COPPERAREA_COPPERAREA error: copper area corner inside copper area ref
if( aCreate_Markers )
{
int x = currentVertex.x;
int y = currentVertex.y;
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++;
}
}
// Iterate through all the segments of refSmoothedPoly
for( auto refIt = refSmoothedPoly.IterateSegmentsWithHoles(); refIt; refIt++ )
{
// Build ref segment
SEG refSegment = *refIt;
// Iterate through all the segments in testSmoothedPoly
for( auto testIt = testSmoothedPoly.IterateSegmentsWithHoles(); testIt; testIt++ )
{
// Build test segment
SEG testSegment = *testIt;
int x, y;
int ax1, ay1, ax2, ay2;
ax1 = refSegment.A.x;
ay1 = refSegment.A.y;
ax2 = refSegment.B.x;
ay2 = refSegment.B.y;
int bx1, by1, bx2, by2;
bx1 = testSegment.A.x;
by1 = testSegment.A.y;
bx2 = testSegment.B.x;
by2 = testSegment.B.y;
int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
0,
ax1, ay1, ax2, ay2,
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;
}
bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex )
{
if( !aArea->IsOnCopperLayer() ) // Cannot have a Drc error if not on copper layer