On line DRC when creating a zone outline

This commit is contained in:
CHARRAS 2008-01-20 19:55:22 +00:00
parent da3f44305b
commit e9b3322fc0
16 changed files with 634 additions and 386 deletions

View File

@ -4,6 +4,12 @@ Started 2007-June-11
Please add newer entries at the top, list the date and your name with Please add newer entries at the top, list the date and your name with
email address. email address.
2008-Jan-20 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
+pcbnew:
On line DRC when creating a zone outline.
Needs more work to display errors DRC.
2008-Jan-18 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr> 2008-Jan-18 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================ ================================================================================

View File

@ -491,10 +491,11 @@ public:
/** /**
* Function End_Zone * Function End_Zone
* terminates the zone edge creation process * terminates (if no DRC error ) the zone edge creation process
* @param DC = current Device Context * @param DC = current Device Context
* @return true if Ok, false if DRC error
*/ */
void End_Zone( wxDC* DC ); bool End_Zone( wxDC* DC );
/** Function Fill_Zone() /** Function Fill_Zone()
* Calculate the zone filling for the outline zone_container * Calculate the zone filling for the outline zone_container

View File

@ -56,7 +56,7 @@ public:
* Is virtual from EDA_BaseStruct. * Is virtual from EDA_BaseStruct.
* @param frame A WinEDA_BasePcbFrame in which to print status information. * @param frame A WinEDA_BasePcbFrame in which to print status information.
*/ */
void Display_Infos( WinEDA_DrawFrame* frame ); virtual void Display_Infos( WinEDA_DrawFrame* frame );
/** /**

View File

@ -70,7 +70,10 @@ wxString DRC_ITEM::GetErrorText() const
case COPPERAREA_INSIDE_COPPERAREA: case COPPERAREA_INSIDE_COPPERAREA:
return wxString( _("Copper area inside copper area")); return wxString( _("Copper area inside copper area"));
case COPPERAREA_CLOSE_TO_COPPERAREA: case COPPERAREA_CLOSE_TO_COPPERAREA:
return wxString( _("Copper areas intersect or too close")); return wxString( _("Copper areas intersect or are too close"));
case DRCE_NON_EXISTANT_NET_FOR_ZONE_OUTLINE:
return wxString( _("Copper area has a non existent net name"));
default: default:
return wxString( wxT("PROGRAM BUG, PLEASE LEAVE THE ROOM.") ); return wxString( wxT("PROGRAM BUG, PLEASE LEAVE THE ROOM.") );

View File

@ -37,7 +37,6 @@ enum Mod_Attribut /* Attributs d'un module */
class MODULE : public BOARD_ITEM class MODULE : public BOARD_ITEM
{ {
public: public:
wxPoint m_Pos; // Real coord on board wxPoint m_Pos; // Real coord on board
D_PAD* m_Pads; /* Pad list (linked list) */ D_PAD* m_Pads; /* Pad list (linked list) */
@ -46,6 +45,8 @@ public:
TEXTE_MODULE* m_Reference; // texte reference du composant (U34, R18..) TEXTE_MODULE* m_Reference; // texte reference du composant (U34, R18..)
TEXTE_MODULE* m_Value; // texte valeur du composant (74LS00, 22K..) TEXTE_MODULE* m_Value; // texte valeur du composant (74LS00, 22K..)
wxString m_LibRef; /* nom du module en librairie */ wxString m_LibRef; /* nom du module en librairie */
wxString m_AlternateReference; /* Used when m_Reference cannot be used to
* identify the footprint ( after a full reannotation of the schematic */
int m_Attributs; /* Flags bits a bit ( voir enum Mod_Attribut ) */ int m_Attributs; /* Flags bits a bit ( voir enum Mod_Attribut ) */
int m_Orient; /* orientation en 1/10 degres */ int m_Orient; /* orientation en 1/10 degres */
@ -216,6 +217,7 @@ public:
#if defined (DEBUG) #if defined (DEBUG)
/** /**
* Function Show * Function Show
* is used to output the object tree, currently for debugging only. * is used to output the object tree, currently for debugging only.
@ -226,5 +228,4 @@ public:
virtual void Show( int nestLevel, std::ostream& os ); virtual void Show( int nestLevel, std::ostream& os );
#endif #endif
}; };

View File

@ -63,19 +63,8 @@ wxString TRACK::ShowWidth()
{ {
wxString msg; wxString msg;
#if 0
double value = To_User_Unit( g_UnitMetric, m_Width, PCB_INTERNAL_UNIT );
if( g_UnitMetric == INCHES ) // Affichage en mils
msg.Printf( wxT( "%.1f" ), value * 1000 );
else
msg.Printf( wxT( "%.3f" ), value );
#else
valeur_param( m_Width, msg ); valeur_param( m_Width, msg );
#endif
return msg; return msg;
} }
@ -673,6 +662,26 @@ void TRACK::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode )
GRLine( &panel->m_ClipBox, DC, m_Start.x - by, m_Start.y + bx , GRLine( &panel->m_ClipBox, DC, m_Start.x - by, m_Start.y + bx ,
m_Start.x - ay, m_Start.y + ax, 0, color ); m_Start.x - ay, m_Start.y + ax, 0, color );
} }
// for Buried Vias, draw a partial line :
// orient depending on layer pair
// (so we can see superimposed buried vias ):
if ( Shape() == VIA_BLIND_BURIED )
{
int ax = 0, ay = rayon, bx = 0, by = drill_rayon;
int layer_top, layer_bottom ;
((SEGVIA*)this)->ReturnLayerPair(&layer_top, &layer_bottom);
/* lines for the top layer */
RotatePoint( &ax, &ay, layer_top * 3600 / g_DesignSettings.m_CopperLayerCount);
RotatePoint( &bx, &by, layer_top * 3600 / g_DesignSettings.m_CopperLayerCount);
GRLine( &panel->m_ClipBox, DC, m_Start.x - ax , m_Start.y - ay,
m_Start.x - bx , m_Start.y - by, 0, color );
/* lines for the bottom layer */
ax = 0; ay = rayon; bx = 0; by = drill_rayon;
RotatePoint( &ax, &ay, layer_bottom * 3600 / g_DesignSettings.m_CopperLayerCount);
RotatePoint( &bx, &by, layer_bottom * 3600 / g_DesignSettings.m_CopperLayerCount);
GRLine( &panel->m_ClipBox, DC, m_Start.x - ax , m_Start.y - ay,
m_Start.x - bx , m_Start.y - by, 0, color );
}
} }
return; return;
} }

View File

@ -15,12 +15,17 @@
/**********************/ /**********************/
/* Class EDGE_ZONE */ /* Class EDGE_ZONE */
/**********************/ /**********************/
/* now used only to create a zone outline
* TODO: remove this class and use only the ZONE_CONTAINER::m_Poly
* to create outlines
*/
/* Constructor */ /* Constructor */
EDGE_ZONE::EDGE_ZONE( BOARD_ITEM* parent ) : EDGE_ZONE::EDGE_ZONE( BOARD* parent ) :
DRAWSEGMENT( parent, TYPEEDGEZONE ) DRAWSEGMENT( parent, TYPEEDGEZONE )
{ {
m_Width = 2; // a minimum for visibility, while dragging m_Width = 2; // a minimum for visibility, while dragging
SetNet(0);
} }
@ -32,10 +37,42 @@ EDGE_ZONE:: ~EDGE_ZONE()
/****************************************/ /****************************************/
bool EDGE_ZONE::Save( FILE* aFile ) const bool EDGE_ZONE::Save( FILE* aFile ) const
/****************************************/ /****************************************/
/* edge_zone is a temporary item only used when creating a zone area.
* it will not saved in file
*/
{ {
return true; return true;
} }
// see pcbstruct.h
void EDGE_ZONE::Display_Infos( WinEDA_DrawFrame* frame )
{
int itype;
wxString msg;
frame->MsgPanel->EraseMsgBox();
itype = m_Type & 0x0F;
msg = wxT( "Edge Zone" );
Affiche_1_Parametre( frame, 1, _( "Type" ), msg, DARKCYAN );
Affiche_1_Parametre( frame, 16, _( "Layer" ),
ReturnPcbLayerName( GetLayer() ), BROWN );
msg.Empty(); msg << GetNet();
Affiche_1_Parametre( frame, 25, _( "Netcode" ), msg, RED );
msg = wxT("???");
if ( m_Parent )
{
EQUIPOT* net = ((BOARD*) m_Parent)->FindNet( GetNet() );
if( net )
msg = net->m_Netname;
}
Affiche_1_Parametre( frame, 34, _( "Netname" ), msg, RED );
}
/************************/ /************************/
/* class ZONE_CONTAINER */ /* class ZONE_CONTAINER */
@ -330,26 +367,22 @@ bool ZONE_CONTAINER::HitTest( const wxPoint& refPos )
/** /**
* Function HitTestForCorner * Function HitTestForCorner
* tests if the given wxPoint near a corner, or near the segment define by 2 corners. * tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* "near" means MIN_DIST_IN_PIXELS pixels * "near" means CORNER_MIN_DIST_IN_PIXELS pixels
* @return -1 if none, corner index in .corner <vector> * @return -1 if none, corner index in .corner <vector>
* @param refPos : A wxPoint to test * @param refPos : A wxPoint to test
*/ */
int ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos ) int ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos )
{ {
#define MIN_DIST_IN_PIXELS 5 #define CORNER_MIN_DIST 500 // distance (in internal units) to detect a corner in a zone outline
int dist; int dist;
unsigned item_pos, lim; unsigned item_pos, lim;
lim = m_Poly->corner.size(); lim = m_Poly->corner.size();
m_CornerSelection = -1; m_CornerSelection = -1;
// Min distance to hit = MIN_DIST_IN_PIXELS pixels :
WinEDA_BasePcbFrame* frame = ((BOARD*)GetParent())->m_PcbFrame;
int min_dist = frame ? frame->GetZoom() * MIN_DIST_IN_PIXELS : 3;
for ( item_pos = 0; item_pos < lim; item_pos++ ) for ( item_pos = 0; item_pos < lim; item_pos++ )
{ {
dist = abs( m_Poly->corner[item_pos].x - refPos.x ) + abs( m_Poly->corner[item_pos].y - refPos.y ); dist = abs( m_Poly->corner[item_pos].x - refPos.x ) + abs( m_Poly->corner[item_pos].y - refPos.y );
if( dist <= min_dist ) if( dist <= CORNER_MIN_DIST )
{ {
m_CornerSelection = item_pos; m_CornerSelection = item_pos;
return item_pos; return item_pos;
@ -362,21 +395,17 @@ int ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos )
/** /**
* Function HitTestForEdge * Function HitTestForEdge
* tests if the given wxPoint near a corner, or near the segment define by 2 corners. * tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* "near" means MIN_DIST_IN_PIXELS pixels * "near" means EDGE_MIN_DIST_IN_PIXELS pixels
* @return -1 if none, or index of the starting corner in .corner <vector> * @return -1 if none, or index of the starting corner in .corner <vector>
* @param refPos : A wxPoint to test * @param refPos : A wxPoint to test
*/ */
int ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) int ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos )
{ {
#define MIN_DIST_IN_PIXELS 5 #define EDGE_MIN_DIST 200 // distance (in internal units) to detect a zone outline
int dist; int dist;
unsigned item_pos, lim; unsigned item_pos, lim;
lim = m_Poly->corner.size(); lim = m_Poly->corner.size();
// Min distance to hit = MIN_DIST_IN_PIXELS pixels :
WinEDA_BasePcbFrame* frame = ((BOARD*)GetParent())->m_PcbFrame;
int min_dist = frame ? frame->GetZoom() * MIN_DIST_IN_PIXELS : 3;
/* Test for an entire segment */ /* Test for an entire segment */
unsigned first_corner_pos = 0, end_segm; unsigned first_corner_pos = 0, end_segm;
m_CornerSelection = -1; m_CornerSelection = -1;
@ -402,7 +431,7 @@ int ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos )
m_Poly->corner[item_pos].y, m_Poly->corner[item_pos].y,
m_Poly->corner[end_segm].x, m_Poly->corner[end_segm].x,
m_Poly->corner[end_segm].y ); m_Poly->corner[end_segm].y );
if( dist <= min_dist ) if( dist <= EDGE_MIN_DIST )
{ {
m_CornerSelection = item_pos; m_CornerSelection = item_pos;
return item_pos; return item_pos;

View File

@ -62,7 +62,7 @@ public:
void Draw( WinEDA_DrawPanel* panel, wxDC* DC, void Draw( WinEDA_DrawPanel* panel, wxDC* DC,
const wxPoint& offset, int draw_mode ); const wxPoint& offset, int draw_mode );
int GetNet( void ) { return m_NetCode; } int GetNet( void ) const { return m_NetCode; }
void SetNet( int anet_code ); void SetNet( int anet_code );
/** /**
* Function HitTest * Function HitTest
@ -137,18 +137,36 @@ public:
/*******************/ /*******************/
/* class EDGE_ZONE */ /* class EDGE_ZONE */
/*******************/ /*******************/
/* Classe used temporary to create a zone outline.
*
* TODO: remove this class and use only the ZONE_CONTAINER::m_Poly
* to create outlines
*/
class EDGE_ZONE : public DRAWSEGMENT class EDGE_ZONE : public DRAWSEGMENT
{ {
private:
int m_NetCode;
public: public:
EDGE_ZONE( BOARD_ITEM* StructFather ); EDGE_ZONE( BOARD * StructFather );
EDGE_ZONE( const EDGE_ZONE& edgezone );
~EDGE_ZONE(); ~EDGE_ZONE();
EDGE_ZONE* Next() { return (EDGE_ZONE*) Pnext; } EDGE_ZONE* Next() { return (EDGE_ZONE*) Pnext; }
EDGE_ZONE* Back() { return (EDGE_ZONE*) Pback; } EDGE_ZONE* Back() { return (EDGE_ZONE*) Pback; }
int GetNet( void ) const { return m_NetCode; }
void SetNet( int anet_code ) { m_NetCode = anet_code; }
/**
* Function Display_Infos
* has knowledge about the frame and how and where to put status information
* about this object into the frame's message panel.
* Is virtual from EDA_BaseStruct.
* @param frame A WinEDA_BasePcbFrame in which to print status information.
*/
void Display_Infos( WinEDA_DrawFrame* frame );
/** /**
* Function Save * Function Save

View File

@ -139,9 +139,9 @@ DRC::~DRC()
delete m_unconnected[i]; delete m_unconnected[i];
} }
/***********************************************************************/ /*********************************************/
int DRC::Drc( TRACK* aRefSegm, TRACK* aList ) int DRC::Drc( TRACK* aRefSegm, TRACK* aList )
/***********************************************************************/ /*********************************************/
{ {
updatePointers(); updatePointers();
@ -157,6 +157,33 @@ int DRC::Drc( TRACK* aRefSegm, TRACK* aList )
} }
/*********************************************/
int DRC::Drc( const EDGE_ZONE* aEdge )
/*********************************************/
/**
* Function Drc
* tests the current EDGE_ZONE segment and returns the result and displays the error
* in the status panel only if one exists.
* Test Edge inside other areas
* Test Edge too close other areas
* @param aEdge The current segment to test.
* @return int - BAD_DRC (1) if DRC error or OK_DRC (0) if OK
*/
{
updatePointers();
if( ! doEdgeZoneDrc( aEdge ) )
{
wxASSERT( m_currentMarker );
m_currentMarker->Display_Infos( m_mainWindow );
return BAD_DRC;
}
return OK_DRC;
}
void DRC::RunTests() void DRC::RunTests()
{ {
// someone should have cleared the two lists before calling this. // someone should have cleared the two lists before calling this.
@ -169,8 +196,7 @@ void DRC::RunTests()
testTracks(); testTracks();
// test zone clearances to other zones, pads, tracks, and vias // test zone clearances to other zones, pads, tracks, and vias
if( m_doZonesTest ) testZones(m_doZonesTest);
testZones();
// find and gather unconnected pads. // find and gather unconnected pads.
if( m_doUnconnectedTest ) if( m_doUnconnectedTest )
@ -283,9 +309,23 @@ void DRC::testUnconnected()
} }
void DRC::testZones() void DRC::testZones(bool adoTestFillSegments)
{ {
// Test copper areas for valide netcodes
// if a netcode is < 0 the netname was not found when reading a netlist
for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
{
ZONE_CONTAINER* Area_To_Test = m_pcb->GetArea( ii );
if( Area_To_Test->GetNet() <= 0 )
{
m_currentMarker = fillMarker( Area_To_Test,
DRCE_NON_EXISTANT_NET_FOR_ZONE_OUTLINE, m_currentMarker );
m_pcb->Add( m_currentMarker );
m_currentMarker = 0;
}
}
// Test copper areas outlines, and create markers when needed // Test copper areas outlines, and create markers when needed
m_pcb->Test_Drc_Areas_Outlines_To_Areas_Outlines( NULL, true ); m_pcb->Test_Drc_Areas_Outlines_To_Areas_Outlines( NULL, true );
@ -296,7 +336,7 @@ void DRC::testZones()
for( zoneSeg = m_pcb->m_Zone; zoneSeg; zoneSeg = zoneSeg->Next() ) for( zoneSeg = m_pcb->m_Zone; zoneSeg; zoneSeg = zoneSeg->Next() )
++m_pcb->m_NbSegmZone; ++m_pcb->m_NbSegmZone;
*/ */
if ( ! adoTestFillSegments ) return;
for( zoneSeg = m_pcb->m_Zone; zoneSeg && zoneSeg->Next(); zoneSeg=zoneSeg->Next() ) for( zoneSeg = m_pcb->m_Zone; zoneSeg && zoneSeg->Next(); zoneSeg=zoneSeg->Next() )
{ {
// Test zoneSeg with other zone segments and with all pads // Test zoneSeg with other zone segments and with all pads
@ -407,6 +447,34 @@ MARKER* DRC::fillMarker( D_PAD* aPad, D_PAD* bPad, int aErrorCode, MARKER* fillM
return fillMe; return fillMe;
} }
MARKER* DRC::fillMarker( ZONE_CONTAINER * aArea, int aErrorCode, MARKER* fillMe )
{
wxString textA = aArea->MenuText( m_pcb );
wxPoint posA = aArea->GetPosition();
if( fillMe )
fillMe->SetData( aErrorCode, posA, textA, posA );
else
fillMe = new MARKER( aErrorCode, posA, textA, posA );
return fillMe;
}
MARKER* DRC::fillMarker( const EDGE_ZONE * aEdge, const wxPoint & aPos, int aErrorCode, MARKER* fillMe )
{
wxString textA = aEdge->MenuText( m_pcb );
wxPoint posA = aPos;
if( fillMe )
fillMe->SetData( aErrorCode, posA, textA, posA );
else
fillMe = new MARKER( aErrorCode, posA, textA, posA );
return fillMe;
}
/***********************************************************************/ /***********************************************************************/
bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart ) bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart )

View File

@ -57,6 +57,7 @@
#define DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR 21 ///< micro via's layer pair incorrect (layers must be adjacent) #define DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR 21 ///< micro via's layer pair incorrect (layers must be adjacent)
#define COPPERAREA_INSIDE_COPPERAREA 22 ///< copper area outlines intersect #define COPPERAREA_INSIDE_COPPERAREA 22 ///< copper area outlines intersect
#define COPPERAREA_CLOSE_TO_COPPERAREA 23 ///< copper area outlines are too close #define COPPERAREA_CLOSE_TO_COPPERAREA 23 ///< copper area outlines are too close
#define DRCE_NON_EXISTANT_NET_FOR_ZONE_OUTLINE 24 ///< copper area outline has an incorrect netcode due to a netname not found
/** /**
* Class DRC_ITEM * Class DRC_ITEM
@ -358,6 +359,21 @@ private:
MARKER* fillMarker( D_PAD* aPad, D_PAD* bPad, int aErrorCode, MARKER* fillMe ); MARKER* fillMarker( D_PAD* aPad, D_PAD* bPad, int aErrorCode, MARKER* fillMe );
MARKER* fillMarker( ZONE_CONTAINER * aArea, int aErrorCode, MARKER* fillMe );
/**
* Function fillMarker
* optionally creates a marker and fills it in with information,
* but does not add it to the BOARD. Use this to report any kind of
* DRC problem, or unconnected pad problem.
*
* @param aEdge edge zone to test
* @param aPos position of error
* @param aErrorCode Type of error
* @param fillMe A MARKER* which is to be filled in, or NULL if one is to
* first be allocated, then filled.
*/
MARKER* fillMarker( const EDGE_ZONE * aEdge, const wxPoint & aPos, int aErrorCode, MARKER* fillMe );
//-----<categorical group tests>----------------------------------------- //-----<categorical group tests>-----------------------------------------
@ -367,7 +383,7 @@ private:
void testUnconnected(); void testUnconnected();
void testZones(); void testZones(bool adoTestFillSegments);
//-----<single "item" tests>----------------------------------------- //-----<single "item" tests>-----------------------------------------
@ -395,6 +411,17 @@ private:
bool doTrackDrc( TRACK* aRefSeg, TRACK* aStart ); bool doTrackDrc( TRACK* aRefSeg, TRACK* aStart );
/**
* Function doEdgeZoneDrc
* tests the current EDGE_ZONE segment:
* Test Edge inside other areas
* Test Edge too close other areas
* @param aEdge The current segment to test.
* @return bool - false if DRC error or true if OK
*/
bool doEdgeZoneDrc( const EDGE_ZONE* aEdge );
//-----<single tests>---------------------------------------------- //-----<single tests>----------------------------------------------
/** /**
@ -467,6 +494,16 @@ public:
*/ */
int Drc( TRACK* aRefSeg, TRACK* aList ); int Drc( TRACK* aRefSeg, TRACK* aList );
/**
* Function Drc
* tests the current EDGE_ZONE segment and returns the result and displays the error
* in the status panel only if one exists.
* Test Edge inside other areas
* Test Edge too close other areas
* @param aEdge The current segment to test.
* @return int - BAD_DRC (1) if DRC error or OK_DRC (0) if OK
*/
int Drc( const EDGE_ZONE* aEdge );
/** /**
* Function DrcBlind * Function DrcBlind

View File

@ -810,7 +810,7 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event )
DrawPanel->MouseToCursorSchema(); DrawPanel->MouseToCursorSchema();
if( GetCurItem() && (GetCurItem()->m_Flags & IS_NEW) ) if( GetCurItem() && (GetCurItem()->m_Flags & IS_NEW) )
{ {
End_Zone( &dc ); if ( End_Zone( &dc ) )
SetCurItem( NULL ); SetCurItem( NULL );
} }
break; break;

View File

@ -406,9 +406,11 @@ void WinEDA_PcbFrame::OnLeftDClick( wxDC* DC, const wxPoint& MousePos )
break; break;
case ID_PCB_ZONES_BUTT: case ID_PCB_ZONES_BUTT:
End_Zone( DC ); if ( End_Zone( DC ) )
{
DrawPanel->m_AutoPAN_Request = FALSE; DrawPanel->m_AutoPAN_Request = FALSE;
SetCurItem( NULL ); SetCurItem( NULL );
}
break; break;
case ID_LINE_COMMENT_BUTT: case ID_LINE_COMMENT_BUTT:

View File

@ -197,7 +197,7 @@ static void Abort_Zone_Create_Outline( WinEDA_DrawPanel* Panel, wxDC* DC )
/** /**
* Function Abort_Zone_Create_Outline * Function Abort_Zone_Create_Outline
* cancels the Begin_Zone command if at least one EDGE_ZONE has been created. * cancels the Begin_Zone command if at least one EDGE_ZONE was created.
*/ */
{ {
WinEDA_PcbFrame* pcbframe = (WinEDA_PcbFrame*) Panel->m_Parent; WinEDA_PcbFrame* pcbframe = (WinEDA_PcbFrame*) Panel->m_Parent;
@ -235,7 +235,10 @@ void WinEDA_BasePcbFrame::DelLimitesZone( wxDC* DC, bool Redraw )
next = segment->Next(); next = segment->Next();
if( Redraw && DC ) if( Redraw && DC )
{
Trace_DrawSegmentPcb( DrawPanel, DC, segment, GR_OR );
Trace_DrawSegmentPcb( DrawPanel, DC, segment, GR_XOR ); Trace_DrawSegmentPcb( DrawPanel, DC, segment, GR_XOR );
}
delete segment; delete segment;
} }
@ -388,7 +391,7 @@ void WinEDA_PcbFrame::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER * zone_contai
zone_container->m_Poly->DeleteCorner(zone_container->m_CornerSelection); zone_container->m_Poly->DeleteCorner(zone_container->m_CornerSelection);
// modify zones outlines accordiing to the new zone_container shape // modify zones outlines according to the new zone_container shape
m_Pcb->AreaPolygonModified( zone_container, true, verbose ); m_Pcb->AreaPolygonModified( zone_container, true, verbose );
if ( DC ) if ( DC )
{ {
@ -506,7 +509,7 @@ EDGE_ZONE* WinEDA_PcbFrame::Begin_Zone( wxDC* DC )
break; break;
} }
if( ii == m_Pcb->GetAreaCount() ) // Not found: coul be deleted since last selection if( ii == m_Pcb->GetAreaCount() ) // Not found: could be deleted since last selection
{ {
s_AddCutoutToCurrentZone = false; s_AddCutoutToCurrentZone = false;
s_CurrentZone = NULL; s_CurrentZone = NULL;
@ -560,6 +563,14 @@ EDGE_ZONE* WinEDA_PcbFrame::Begin_Zone( wxDC* DC )
newedge->m_Flags = IS_NEW | STARTPOINT | IS_MOVED; newedge->m_Flags = IS_NEW | STARTPOINT | IS_MOVED;
newedge->m_Start = newedge->m_End = GetScreen()->m_Curseur; newedge->m_Start = newedge->m_End = GetScreen()->m_Curseur;
newedge->SetLayer( GetScreen()->m_Active_Layer ); newedge->SetLayer( GetScreen()->m_Active_Layer );
newedge->SetNet( s_NetcodeSelection );
if( Drc_On && m_drc->Drc( newedge ) == BAD_DRC )
{
delete newedge;
SetCurItem(NULL);
DisplayError(this, _("DRC error: this start point is inside or too close an other area"));
return NULL;
}
// link into list: // link into list:
newedge->Pnext = oldedge; newedge->Pnext = oldedge;
@ -578,12 +589,18 @@ EDGE_ZONE* WinEDA_PcbFrame::Begin_Zone( wxDC* DC )
/* edge in progress : the ending point coordinate was set by Show_New_Zone_Edge_While_Move_Mouse */ /* edge in progress : the ending point coordinate was set by Show_New_Zone_Edge_While_Move_Mouse */
if( oldedge->m_Start != oldedge->m_End ) if( oldedge->m_Start != oldedge->m_End )
{ {
if ( Drc_On && m_drc->Drc( oldedge ) == BAD_DRC )
{
return oldedge;
}
oldedge->m_Flags &= ~(IS_NEW | IS_MOVED); oldedge->m_Flags &= ~(IS_NEW | IS_MOVED);
newedge = new EDGE_ZONE( oldedge ); newedge = new EDGE_ZONE( m_Pcb );
newedge->m_Flags = IS_NEW | IS_MOVED; newedge->m_Flags = IS_NEW | IS_MOVED;
newedge->m_Start = newedge->m_End = oldedge->m_End; newedge->m_Start = newedge->m_End = oldedge->m_End;
newedge->SetLayer( GetScreen()->m_Active_Layer ); newedge->SetLayer( oldedge->GetLayer() );
newedge->SetNet( s_NetcodeSelection );
// link into list: // link into list:
newedge->Pnext = oldedge; newedge->Pnext = oldedge;
@ -597,44 +614,65 @@ EDGE_ZONE* WinEDA_PcbFrame::Begin_Zone( wxDC* DC )
/*********************************************/ /*********************************************/
void WinEDA_PcbFrame::End_Zone( wxDC* DC ) bool WinEDA_PcbFrame::End_Zone( wxDC* DC )
/*********************************************/ /*********************************************/
/** Function End_Zone /** Function End_Zone
* Terminates a zone outline creation * Terminates a zone outline creation
* Close the current zone outline considered as a polygon * terminates (if no DRC error ) the zone edge creation process
* put it in the main list m_Pcb->m_ZoneDescriptorList (a vector<ZONE_CONTAINER*>) * @param DC = current Device Context
* @return true if Ok, false if DRC error
* if ok, put it in the main list m_Pcb->m_ZoneDescriptorList (a vector<ZONE_CONTAINER*>)
*/ */
{ {
EDGE_ZONE* edge; if( m_Pcb->m_CurrentLimitZone == NULL ) return true;
int layer = GetScreen()->m_Active_Layer;
if( m_Pcb->m_CurrentLimitZone ) EDGE_ZONE* edge = m_Pcb->m_CurrentLimitZone;
EDGE_ZONE* last_edge = m_Pcb->m_CurrentLimitZone;
int layer = edge->GetLayer();
// Validate the current edge:
if ( edge->m_Start != edge->m_End )
{ {
Begin_Zone( DC ); Begin_Zone( DC );
if ( edge == m_Pcb->m_CurrentLimitZone ) // no new segment -> DRC error
{
return false;
}
}
/* The last segment is a stub: its lenght is 0. /* The last segment is a stub: its lenght is 0.
* Use it to close the polygon by setting its ending point coordinate = start point of first segment * Use it to close the polygon by setting its ending point coordinate = start point of first segment
*/ */
/* search first segment outline ( last item of the linked list ) */
edge = m_Pcb->m_CurrentLimitZone; edge = m_Pcb->m_CurrentLimitZone;
edge->m_Flags &= ~(IS_NEW | IS_MOVED); while( edge->Next() )
while( edge && edge->Next() )
{ {
edge = edge->Next(); edge = edge->Next();
if( edge->m_Flags & STARTPOINT )
break;
edge->m_Flags &= ~(IS_NEW | IS_MOVED); edge->m_Flags &= ~(IS_NEW | IS_MOVED);
} }
if( edge ) wxPoint curr_endpoint = m_Pcb->m_CurrentLimitZone->m_End;
{
edge->m_Flags &= ~(IS_NEW | IS_MOVED);
m_Pcb->m_CurrentLimitZone->m_End = edge->m_Start; m_Pcb->m_CurrentLimitZone->m_End = edge->m_Start;
edge = m_Pcb->m_CurrentLimitZone;
if ( Drc_On && m_drc->Drc( edge ) == BAD_DRC )
{
edge->m_End = curr_endpoint;
if ( last_edge != edge ) // Remove edge create previously
{
delete edge;
m_Pcb->m_CurrentLimitZone = edge = last_edge;
edge->Pback = NULL;
edge->m_Flags = (IS_NEW | IS_MOVED);
} }
SetCurItem( edge );
DisplayError(this, _("DRC error: closing this area creates a drc error with an other area"));
DrawPanel->MouseToCursorSchema();
return false;
}
edge->m_Flags &= ~(IS_NEW | IS_MOVED);
Trace_DrawSegmentPcb( DrawPanel, DC, m_Pcb->m_CurrentLimitZone, GR_XOR ); Trace_DrawSegmentPcb( DrawPanel, DC, m_Pcb->m_CurrentLimitZone, GR_XOR );
}
DrawPanel->ManageCurseur = NULL; DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL;
@ -642,9 +680,9 @@ void WinEDA_PcbFrame::End_Zone( wxDC* DC )
// Undraw old drawings, because they can have important changes // Undraw old drawings, because they can have important changes
for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ ) for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ )
{ {
ZONE_CONTAINER* edge_zone = m_Pcb->GetArea(ii); ZONE_CONTAINER* area = m_Pcb->GetArea(ii);
if( layer == edge_zone->GetLayer() ) if( layer == area->GetLayer() )
edge_zone->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR ); area->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR );
} }
/* Put edges in list */ /* Put edges in list */
@ -717,6 +755,7 @@ void WinEDA_PcbFrame::End_Zone( wxDC* DC )
} }
GetScreen()->SetModify(); GetScreen()->SetModify();
return true;
} }
@ -744,12 +783,6 @@ static void Show_New_Zone_Edge_While_Move_Mouse( WinEDA_DrawPanel* panel, wxDC*
} }
} }
/* Reinit layer (which can be changed) */
for( edge = pcbframe->m_Pcb->m_CurrentLimitZone; edge; edge = edge->Next() )
{
edge->SetLayer( pcbframe->GetScreen()->m_Active_Layer );
}
/* Redraw the curent edge in its new position */ /* Redraw the curent edge in its new position */
currentEdge = pcbframe->m_Pcb->m_CurrentLimitZone; currentEdge = pcbframe->m_Pcb->m_CurrentLimitZone;
if( Zone_45_Only ) if( Zone_45_Only )

View File

@ -265,7 +265,8 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
if( bMessageBoxInt && bDontShowSelfIntersectionWarning == false ) if( bMessageBoxInt && bDontShowSelfIntersectionWarning == false )
{ {
wxString str; wxString str;
str.Printf( wxT( "Area %8.8X of net \"%s\" is self-intersecting and will be clipped.\n" ), str.Printf( wxT(
"Area %8.8X of net \"%s\" is self-intersecting and will be clipped.\n" ),
CurrArea->m_TimeStamp, CurrArea->m_Netname.GetData() ); CurrArea->m_TimeStamp, CurrArea->m_Netname.GetData() );
str += wxT( "This may result in splitting the area.\n" ); str += wxT( "This may result in splitting the area.\n" );
str += wxT( "If the area is complex, this may take a few seconds." ); str += wxT( "If the area is complex, this may take a few seconds." );
@ -517,7 +518,7 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
// If a contour is inside an other contour, no segments intersects, but the zones can be combined // 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) // test a corner inside an outline (only one corner is enought)
/* for( int ic2 = 0; ic2 < poly2->GetNumCorners(); ic2++ ) for( int ic2 = 0; ic2 < poly2->GetNumCorners(); ic2++ )
{ {
int x = poly2->GetX( ic2 ); int x = poly2->GetX( ic2 );
int y = poly2->GetY( ic2 ); int y = poly2->GetY( ic2 );
@ -526,6 +527,7 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
return true; return true;
} }
} }
for( int ic1 = 0; ic1 < poly1->GetNumCorners(); ic1++ ) for( int ic1 = 0; ic1 < poly1->GetNumCorners(); ic1++ )
{ {
int x = poly1->GetX( ic1 ); int x = poly1->GetX( ic1 );
@ -535,7 +537,7 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
return true; return true;
} }
} }
*/ } }
return false; return false;
} }
@ -637,7 +639,8 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
if( !bInt ) if( !bInt )
{ {
/* if( bArcInt ) return 0; if( bArcInt )
return 0;
// If a contour is inside an other contour, no segments intersects, but the zones can be combined // 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) // test a corner inside an outline (only one corner is enought)
@ -650,6 +653,7 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
return 1; return 1;
} }
} }
for( int ic1 = 0; ic1 < poly1->GetNumCorners(); ic1++ ) for( int ic1 = 0; ic1 < poly1->GetNumCorners(); ic1++ )
{ {
int x = poly1->GetX( ic1 ); int x = poly1->GetX( ic1 );
@ -660,7 +664,7 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
} }
} }
*/ return 0; return 0;
} }
if( bArcInt ) if( bArcInt )
return 2; return 2;
@ -777,8 +781,8 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi
} }
#if 0 // Currently not used: work in progress #if 0 // Currently not used: work in progress
/** /**
* Function Is_Area_Inside_Area * 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 * Test a given area to see if it is inside an other area, or an other area is inside the given area
@ -788,14 +792,15 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi
*/ */
ZONE_CONTAINER* BOARD::Is_Area_Inside_Area( ZONE_CONTAINER* Area_Ref ) ZONE_CONTAINER* BOARD::Is_Area_Inside_Area( ZONE_CONTAINER* Area_Ref )
{ {
int corners_inside_count; int corners_inside_count;
for( int ia = 0; ia < GetAreaCount(); ia++ ) for( int ia = 0; ia < GetAreaCount(); ia++ )
{ {
ZONE_CONTAINER* Area_To_Test = GetArea( ia ); ZONE_CONTAINER* Area_To_Test = GetArea( ia );
if( Area_Ref == Area_To_Test ) if( Area_Ref == Area_To_Test )
continue; continue;
// test for same layer // test for same layer
if( Area_Ref->GetLayer() != Area_To_Test->GetLayer() ) if( Area_Ref->GetLayer() != Area_To_Test->GetLayer() )
continue; continue;
@ -809,6 +814,7 @@ ZONE_CONTAINER* BOARD::Is_Area_Inside_Area( ZONE_CONTAINER* Area_Ref)
if( Area_To_Test->m_Poly->TestPointInside( x, y ) ) if( Area_To_Test->m_Poly->TestPointInside( x, y ) )
corners_inside_count--; corners_inside_count--;
} }
if( corners_inside_count == 0 ) if( corners_inside_count == 0 )
return Area_Ref; return Area_Ref;
@ -821,13 +827,15 @@ ZONE_CONTAINER* BOARD::Is_Area_Inside_Area( ZONE_CONTAINER* Area_Ref)
if( Area_Ref->m_Poly->TestPointInside( x, y ) ) if( Area_Ref->m_Poly->TestPointInside( x, y ) )
corners_inside_count--; corners_inside_count--;
} }
if( corners_inside_count == 0 ) if( corners_inside_count == 0 )
return Area_Ref; return Area_Ref;
} }
return NULL; return NULL;
} }
#endif #endif
@ -859,11 +867,13 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E
if( Area_Ref == Area_To_Test ) if( Area_Ref == Area_To_Test )
continue; continue;
// test for same layer // test for same layer
if( Area_Ref->GetLayer() != Area_To_Test->GetLayer() ) if( Area_Ref->GetLayer() != Area_To_Test->GetLayer() )
continue; continue;
// Test for same net // Test for same net
if( Area_Ref->GetNet() == Area_To_Test->GetNet() ) if( Area_Ref->GetNet() == Area_To_Test->GetNet() && Area_Ref->GetNet() > 0 )
continue; continue;
// test for some corners of Area_Ref inside Area_To_Test // test for some corners of Area_Ref inside Area_To_Test
@ -950,21 +960,15 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E
} }
int bstyle = Area_To_Test->m_Poly->GetSideStyle( ic2 ); int bstyle = Area_To_Test->m_Poly->GetSideStyle( ic2 );
int x, y; int x, y;
int d = ::GetClearanceBetweenSegments( bx1, int d = ::GetClearanceBetweenSegments(
by1, bx1, by1, bx2, by2, bstyle,
bx2,
by2,
bstyle,
0, 0,
ax1, ax1, ay1, ax2,
ay1, ay2, astyle,
ax2,
ay2,
astyle,
0, 0,
g_DesignSettings.m_TrackClearence, g_DesignSettings.
&x, m_TrackClearence,
&y ); &x, &y );
if( d < g_DesignSettings.m_TrackClearence ) if( d < g_DesignSettings.m_TrackClearence )
{ {
// COPPERAREA_COPPERAREA error : intersect or too close // COPPERAREA_COPPERAREA error : intersect or too close
@ -972,7 +976,8 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E
{ {
wxString msg1 = Area_Ref->MenuText( this ); wxString msg1 = Area_Ref->MenuText( this );
wxString msg2 = Area_To_Test->MenuText( this ); wxString msg2 = Area_To_Test->MenuText( this );
MARKER* marker = new MARKER( COPPERAREA_CLOSE_TO_COPPERAREA, wxPoint( x, y ), MARKER* marker = new MARKER( COPPERAREA_CLOSE_TO_COPPERAREA,
wxPoint( x, y ),
msg1, wxPoint( x, y ), msg1, wxPoint( x, y ),
msg2, wxPoint( x, y ) ); msg2, wxPoint( x, y ) );
Add( marker ); Add( marker );
@ -989,3 +994,90 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E
return nerrors; return nerrors;
} }
/**
* Function doEdgeZoneDrc
* tests the current EDGE_ZONE segment and returns the result and displays the error
* in the status panel only if one exists.
* Test Edge inside other areas
* Test Edge too close other areas
* @param aEdge The current segment to test.
* @return bool - false if DRC error or true if OK
*/
bool DRC::doEdgeZoneDrc( const EDGE_ZONE* aEdge )
{
wxString str;
// iterate through all areas
for( int ia2 = 0; ia2 < m_pcb->GetAreaCount(); ia2++ )
{
ZONE_CONTAINER* Area_To_Test = m_pcb->GetArea( ia2 );
// test for same layer
if( Area_To_Test->GetLayer() != aEdge->GetLayer() )
continue;
// Test for same net
if( (aEdge->GetNet() == Area_To_Test->GetNet()) && (aEdge->GetNet() > 0) )
continue;
// test for ending line inside Area_To_Test
int x = aEdge->m_End.x;
int y = aEdge->m_End.y;
if( Area_To_Test->m_Poly->TestPointInside( x, y ) )
{
// COPPERAREA_COPPERAREA error: corner inside copper area
m_currentMarker = fillMarker( aEdge, wxPoint( x, y ),
COPPERAREA_INSIDE_COPPERAREA,
m_currentMarker );
return false;
}
// now test spacing between areas
int astyle = CPolyLine::STRAIGHT;
int ax1 = aEdge->m_Start.x;
int ay1 = aEdge->m_Start.y;
int ax2 = aEdge->m_End.x;
int ay2 = aEdge->m_End.y;
for( int icont2 = 0; icont2 < Area_To_Test->m_Poly->GetNumContours(); icont2++ )
{
int ic_start2 = Area_To_Test->m_Poly->GetContourStart( icont2 );
int ic_end2 = Area_To_Test->m_Poly->GetContourEnd( icont2 );
for( int ic2 = ic_start2; ic2<=ic_end2; ic2++ )
{
int bx1 = Area_To_Test->m_Poly->GetX( ic2 );
int by1 = Area_To_Test->m_Poly->GetY( ic2 );
int bx2, by2;
if( ic2 == ic_end2 )
{
bx2 = Area_To_Test->m_Poly->GetX( ic_start2 );
by2 = Area_To_Test->m_Poly->GetY( ic_start2 );
}
else
{
bx2 = Area_To_Test->m_Poly->GetX( ic2 + 1 );
by2 = Area_To_Test->m_Poly->GetY( ic2 + 1 );
}
int bstyle = Area_To_Test->m_Poly->GetSideStyle( ic2 );
int x, y;
int d = ::GetClearanceBetweenSegments( bx1, by1, bx2, by2, bstyle,
0,
ax1, ay1, ax2, ay2, astyle,
0,
g_DesignSettings.m_ZoneClearence,
&x, &y );
if( d < g_DesignSettings.m_ZoneClearence )
{
// COPPERAREA_COPPERAREA error : edge intersect or too close
m_currentMarker = fillMarker( aEdge, wxPoint( x, y ),
COPPERAREA_CLOSE_TO_COPPERAREA,
m_currentMarker );
return false;
}
}
}
}
return true;
}

View File

@ -1323,56 +1323,6 @@ bool CPolyLine::TestPointInsideContour( int icont, int x, int y )
return FALSE; return FALSE;
} }
// Test for intersection of sides
//
int CPolyLine::TestIntersection( CPolyLine * poly )
{
if( !GetClosed() )
wxASSERT(0);
if( !poly->GetClosed() )
wxASSERT(0);
for( int ic=0; ic<GetNumContours(); ic++ )
{
int istart = GetContourStart(ic);
int iend = GetContourEnd(ic);
for( int is=istart; is<=iend; is++ )
{
int xf, yf;
if( is < GetContourEnd(ic) )
{
xf = GetX(is+1);
yf = GetY(is+1);
}
else
{
xf = GetX(istart);
yf = GetY(istart);
}
for( int ic2=0; ic2<poly->GetNumContours(); ic2++ )
{
int istart2 = poly->GetContourStart(ic2);
int iend2 = poly->GetContourEnd(ic2);
for( int is2=istart2; is2<=iend2; is2++ )
{
int xf2, yf2;
if( is2 < poly->GetContourEnd(ic2) )
{
xf2 = poly->GetX(is2+1);
yf2 = poly->GetY(is2+1);
}
else
{
xf2 = poly->GetX(istart2);
yf2 = poly->GetY(istart2);
}
// test for intersection between side and side2
}
}
}
}
return 0;
}
// copy data from another poly, but don't draw it // copy data from another poly, but don't draw it
// //

View File

@ -93,7 +93,6 @@ public:
bool TestPointInside( int x, int y ); bool TestPointInside( int x, int y );
bool TestPointInsideContour( int icont, int x, int y ); bool TestPointInsideContour( int icont, int x, int y );
bool IsCutoutContour( int icont ); bool IsCutoutContour( int icont );
int TestIntersection( CPolyLine * poly );
void AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num ); void AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num );