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.") );
@ -83,7 +86,7 @@ wxString DRC_ITEM::ShowCoord( const wxPoint& aPos )
wxString temp; wxString temp;
wxString ret; wxString ret;
ret << wxT("@(") << valeur_param( aPos.x, temp ); ret << wxT("@ (") << valeur_param( aPos.x, temp );
ret << wxT(",") << valeur_param( aPos.y, temp ); ret << wxT(",") << valeur_param( aPos.y, temp );
ret << wxT(")"); ret << wxT(")");

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,27 +45,29 @@ 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 */
int flag; /* flag utilise en trace rastnest et routage auto */ int flag; /* flag utilise en trace rastnest et routage auto */
int m_ModuleStatus; /* For autoplace: flags (LOCKED, AUTOPLACED) */ int m_ModuleStatus; /* For autoplace: flags (LOCKED, AUTOPLACED) */
EDA_Rect m_BoundaryBox; /* position/taille du cadre de reperage (coord locales)*/ EDA_Rect m_BoundaryBox; /* position/taille du cadre de reperage (coord locales)*/
EDA_Rect m_RealBoundaryBox; /* position/taille du module (coord relles) */ EDA_Rect m_RealBoundaryBox; /* position/taille du module (coord relles) */
int m_PadNum; // Nombre total de pads int m_PadNum; // Nombre total de pads
int m_AltPadNum; // en placement auto Nombre de pads actifs pour int m_AltPadNum; // en placement auto Nombre de pads actifs pour
// les calculs // les calculs
int m_CntRot90; // Placement auto: cout ( 0..10 ) de la rotation 90 degre
int m_CntRot180; // Placement auto: cout ( 0..10 ) de la rotation 180 degre
wxSize m_Ext; // marges de "garde": utilise en placement auto.
float m_Surface; // surface du rectangle d'encadrement
unsigned long m_Link; // variable temporaire ( pour editions, ...) int m_CntRot90; // Placement auto: cout ( 0..10 ) de la rotation 90 degre
long m_LastEdit_Time; // Date de la derniere modification du module (gestion de librairies) int m_CntRot180; // Placement auto: cout ( 0..10 ) de la rotation 180 degre
wxSize m_Ext; // marges de "garde": utilise en placement auto.
float m_Surface; // surface du rectangle d'encadrement
wxString m_Doc; // Texte de description du module unsigned long m_Link; // variable temporaire ( pour editions, ...)
wxString m_KeyWord; // Liste des mots cles relatifs au module long m_LastEdit_Time; // Date de la derniere modification du module (gestion de librairies)
wxString m_Doc; // Texte de description du module
wxString m_KeyWord; // Liste des mots cles relatifs au module
public: public:
MODULE( BOARD* parent ); MODULE( BOARD* parent );
@ -77,11 +78,11 @@ public:
MODULE* Next() { return (MODULE*) Pnext; } MODULE* Next() { return (MODULE*) Pnext; }
void Set_Rectangle_Encadrement();/* mise a jour du rect d'encadrement void Set_Rectangle_Encadrement(); /* mise a jour du rect d'encadrement
* en coord locales (orient 0 et origine = pos module) */ * en coord locales (orient 0 et origine = pos module) */
void SetRectangleExinscrit();/* mise a jour du rect d'encadrement void SetRectangleExinscrit(); /* mise a jour du rect d'encadrement
* et de la surface en coord reelles */ * et de la surface en coord reelles */
/** /**
* Function GetPosition * Function GetPosition
@ -94,7 +95,7 @@ public:
return m_Pos; return m_Pos;
} }
// deplacements // deplacements
void SetPosition( const wxPoint& newpos ); void SetPosition( const wxPoint& newpos );
void SetOrientation( int newangle ); void SetOrientation( int newangle );
@ -105,7 +106,7 @@ public:
/** /**
* Function IsLocked * Function IsLocked
* (virtual from BOARD_ITEM ) * (virtual from BOARD_ITEM )
* @returns bool - true if the MODULE is locked, else false * @returns bool - true if the MODULE is locked, else false
*/ */
bool IsLocked() const bool IsLocked() const
@ -129,15 +130,15 @@ public:
/* Reading and writing data on files */ /* Reading and writing data on files */
/** /**
* Function Save * Function Save
* writes the data structures for this object out to a FILE in "*.brd" format. * writes the data structures for this object out to a FILE in "*.brd" format.
* @param aFile The FILE to write to. * @param aFile The FILE to write to.
* @return bool - true if success writing else false. * @return bool - true if success writing else false.
*/ */
bool Save( FILE* aFile ) const; bool Save( FILE* aFile ) const;
int Write_3D_Descr( FILE* File ) const; int Write_3D_Descr( FILE* File ) const;
int ReadDescr( FILE* File, int* LineNum = NULL ); int ReadDescr( FILE* File, int* LineNum = NULL );
int Read_3D_Descr( FILE* File, int* LineNum = NULL ); int Read_3D_Descr( FILE* File, int* LineNum = NULL );
@ -156,10 +157,10 @@ public:
* has knowledge about the frame and how and where to put status information * has knowledge about the frame and how and where to put status information
* about this object into the frame's message panel. * about this object into the frame's message panel.
* @param frame A WinEDA_DrawFrame in which to print status information. * @param frame A WinEDA_DrawFrame in which to print status information.
*/ */
void Display_Infos( WinEDA_DrawFrame* frame ); void Display_Infos( WinEDA_DrawFrame* frame );
/** /**
* Function HitTest * Function HitTest
* tests if the given wxPoint is within the bounds of this object. * tests if the given wxPoint is within the bounds of this object.
@ -168,7 +169,7 @@ public:
*/ */
bool HitTest( const wxPoint& refPos ); bool HitTest( const wxPoint& refPos );
/** /**
* Function HitTest (overlayed) * Function HitTest (overlayed)
* tests if the given EDA_Rect intersect the bounds of this object. * tests if the given EDA_Rect intersect the bounds of this object.
@ -177,7 +178,7 @@ public:
*/ */
bool HitTest( EDA_Rect& refArea ); bool HitTest( EDA_Rect& refArea );
/** /**
* Function GetReference * Function GetReference
* @return wxString - the reference designator text. * @return wxString - the reference designator text.
*/ */
@ -185,8 +186,8 @@ public:
{ {
return m_Reference->m_Text; return m_Reference->m_Text;
} }
/** /**
* Function Visit * Function Visit
* should be re-implemented for each derived class in order to handle * should be re-implemented for each derived class in order to handle
@ -195,15 +196,15 @@ public:
* to do so on lists of such data. * to do so on lists of such data.
* @param inspector An INSPECTOR instance to use in the inspection. * @param inspector An INSPECTOR instance to use in the inspection.
* @param testData Arbitrary data used by the inspector. * @param testData Arbitrary data used by the inspector.
* @param scanTypes Which KICAD_T types are of interest and the order * @param scanTypes Which KICAD_T types are of interest and the order
* is significant too, terminated by EOT. * is significant too, terminated by EOT.
* @return SEARCH_RESULT - SEARCH_QUIT if the Iterator is to stop the scan, * @return SEARCH_RESULT - SEARCH_QUIT if the Iterator is to stop the scan,
* else SCAN_CONTINUE; * else SCAN_CONTINUE;
*/ */
SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData, SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData,
const KICAD_T scanTypes[] ); const KICAD_T scanTypes[] );
/** /**
* Function GetClass * Function GetClass
* returns the class name. * returns the class name.
@ -214,17 +215,17 @@ public:
return wxT( "MODULE" ); return wxT( "MODULE" );
} }
#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.
* @param nestLevel An aid to prettier tree indenting, and is the level * @param nestLevel An aid to prettier tree indenting, and is the level
* of nesting of this object within the overall tree. * of nesting of this object within the overall tree.
* @param os The ostream& to output to. * @param os The ostream& to output to.
*/ */
virtual void Show( int nestLevel, std::ostream& os ); virtual void Show( int nestLevel, std::ostream& os );
#endif #endif
}; };

View File

@ -62,20 +62,9 @@ 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,19 +137,37 @@ 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
* writes the data structures for this object out to a FILE in "*.brd" format. * writes the data structures for this object out to a FILE in "*.brd" format.

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,8 +810,8 @@ 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; {
SetCurItem( NULL ); DrawPanel->m_AutoPAN_Request = FALSE;
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;
EDGE_ZONE* edge = m_Pcb->m_CurrentLimitZone;
EDGE_ZONE* last_edge = m_Pcb->m_CurrentLimitZone;
int layer = edge->GetLayer();
if( m_Pcb->m_CurrentLimitZone ) // 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
*/ */
edge = m_Pcb->m_CurrentLimitZone; /* search first segment outline ( last item of the linked list ) */
edge->m_Flags &= ~(IS_NEW | IS_MOVED); edge = m_Pcb->m_CurrentLimitZone;
while( edge->Next() )
{
edge = edge->Next();
edge->m_Flags &= ~(IS_NEW | IS_MOVED);
}
while( edge && edge->Next() ) wxPoint curr_endpoint = m_Pcb->m_CurrentLimitZone->m_End;
{ m_Pcb->m_CurrentLimitZone->m_End = edge->m_Start;
edge = edge->Next(); edge = m_Pcb->m_CurrentLimitZone;
if( edge->m_Flags & STARTPOINT ) if ( Drc_On && m_drc->Drc( edge ) == BAD_DRC )
break; {
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); edge->m_Flags &= ~(IS_NEW | IS_MOVED);
} Trace_DrawSegmentPcb( DrawPanel, DC, m_Pcb->m_CurrentLimitZone, GR_XOR );
if( edge )
{
edge->m_Flags &= ~(IS_NEW | IS_MOVED);
m_Pcb->m_CurrentLimitZone->m_End = edge->m_Start;
}
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

@ -230,7 +230,7 @@ int BOARD::TestAreaPolygon( ZONE_CONTAINER* CurrArea )
int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
bool bMessageBoxArc, bool bMessageBoxInt, bool bRetainArcs ) bool bMessageBoxArc, bool bMessageBoxInt, bool bRetainArcs )
{ {
CPolyLine* curr_polygon = CurrArea->m_Poly; CPolyLine* curr_polygon = CurrArea->m_Poly;
int test = TestAreaPolygon( CurrArea ); // this sets utility2 flag int test = TestAreaPolygon( CurrArea ); // this sets utility2 flag
if( test == -1 && !bRetainArcs ) if( test == -1 && !bRetainArcs )
@ -248,7 +248,7 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
str += wxT( "Manual correction is recommended." ); str += wxT( "Manual correction is recommended." );
wxMessageBox( str ); wxMessageBox( str );
// bDontShowSelfIntersectionArcsWarning = dlg.bDontShowBoxState; // bDontShowSelfIntersectionArcsWarning = dlg.bDontShowBoxState;
} }
return -1; // arcs intersect with other sides, error return -1; // arcs intersect with other sides, error
} }
@ -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." );
@ -283,7 +284,7 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
int n_poly = CurrArea->m_Poly->NormalizeWithGpc( pa, bRetainArcs ); int n_poly = CurrArea->m_Poly->NormalizeWithGpc( pa, bRetainArcs );
if( n_poly > 1 ) // i.e if clipping has created some polygons, we must add these new copper areas if( n_poly > 1 ) // i.e if clipping has created some polygons, we must add these new copper areas
{ {
ZONE_CONTAINER* NewArea; ZONE_CONTAINER* NewArea;
for( int ip = 1; ip < n_poly; ip++ ) for( int ip = 1; ip < n_poly; ip++ )
{ {
// create new copper area and copy poly into it // create new copper area and copy poly into it
@ -448,94 +449,95 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
if( area_to_test->GetNet() != area2->GetNet() ) if( area_to_test->GetNet() != area2->GetNet() )
continue; continue;
if( area_to_test == area2 ) if( area_to_test == area2 )
continue; continue;
// see if areas are on same layer // see if areas are on same layer
if( area_to_test->GetLayer() != area2->GetLayer() ) if( area_to_test->GetLayer() != area2->GetLayer() )
continue; continue;
CPolyLine* poly2 = area2->m_Poly; CPolyLine* poly2 = area2->m_Poly;
// test bounding rects // test bounding rects
CRect b1 = poly1->GetCornerBounds(); CRect b1 = poly1->GetCornerBounds();
CRect b2 = poly2->GetCornerBounds(); CRect b2 = poly2->GetCornerBounds();
if( b1.bottom > b2.top if( b1.bottom > b2.top
|| b1.top < b2.bottom || b1.top < b2.bottom
|| b1.left > b2.right || b1.left > b2.right
|| b1.right < b2.left ) || b1.right < b2.left )
continue; continue;
// test for intersecting segments // test for intersecting segments
for( int icont1 = 0; icont1<poly1->GetNumContours(); icont1++ ) for( int icont1 = 0; icont1<poly1->GetNumContours(); icont1++ )
{ {
int is1 = poly1->GetContourStart( icont1 ); int is1 = poly1->GetContourStart( icont1 );
int ie1 = poly1->GetContourEnd( icont1 ); int ie1 = poly1->GetContourEnd( icont1 );
for( int ic1 = is1; ic1<=ie1; ic1++ ) for( int ic1 = is1; ic1<=ie1; ic1++ )
{ {
int xi1 = poly1->GetX( ic1 ); int xi1 = poly1->GetX( ic1 );
int yi1 = poly1->GetY( ic1 ); int yi1 = poly1->GetY( ic1 );
int xf1, yf1, style1; int xf1, yf1, style1;
if( ic1 < ie1 ) if( ic1 < ie1 )
{ {
xf1 = poly1->GetX( ic1 + 1 ); xf1 = poly1->GetX( ic1 + 1 );
yf1 = poly1->GetY( ic1 + 1 ); yf1 = poly1->GetY( ic1 + 1 );
} }
else else
{ {
xf1 = poly1->GetX( is1 ); xf1 = poly1->GetX( is1 );
yf1 = poly1->GetY( is1 ); yf1 = poly1->GetY( is1 );
} }
style1 = poly1->GetSideStyle( ic1 ); style1 = poly1->GetSideStyle( ic1 );
for( int icont2 = 0; icont2 < poly2->GetNumContours(); icont2++ ) for( int icont2 = 0; icont2 < poly2->GetNumContours(); icont2++ )
{ {
int is2 = poly2->GetContourStart( icont2 ); int is2 = poly2->GetContourStart( icont2 );
int ie2 = poly2->GetContourEnd( icont2 ); int ie2 = poly2->GetContourEnd( icont2 );
for( int ic2 = is2; ic2<=ie2; ic2++ ) for( int ic2 = is2; ic2<=ie2; ic2++ )
{ {
int xi2 = poly2->GetX( ic2 ); int xi2 = poly2->GetX( ic2 );
int yi2 = poly2->GetY( ic2 ); int yi2 = poly2->GetY( ic2 );
int xf2, yf2, style2; int xf2, yf2, style2;
if( ic2 < ie2 ) if( ic2 < ie2 )
{ {
xf2 = poly2->GetX( ic2 + 1 ); xf2 = poly2->GetX( ic2 + 1 );
yf2 = poly2->GetY( ic2 + 1 ); yf2 = poly2->GetY( ic2 + 1 );
} }
else else
{ {
xf2 = poly2->GetX( is2 ); xf2 = poly2->GetX( is2 );
yf2 = poly2->GetY( is2 ); yf2 = poly2->GetY( is2 );
} }
style2 = poly2->GetSideStyle( ic2 ); style2 = poly2->GetSideStyle( ic2 );
int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, style1, int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, style1,
xi2, yi2, xf2, yf2, style2 ); xi2, yi2, xf2, yf2, style2 );
if( n_int ) if( n_int )
return true; return true;
} }
} }
} }
} }
// 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 );
if( poly1->TestPointInside( x, y ) ) if( poly1->TestPointInside( x, y ) )
{ {
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 y = poly1->GetY( ic1 ); int x = poly1->GetX( ic1 );
if( poly2->TestPointInside( x, y ) ) int y = poly1->GetY( ic1 );
{ if( poly2->TestPointInside( x, y ) )
return true; {
} return true;
} }
*/ } }
}
return false; return false;
} }
@ -636,32 +638,34 @@ 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)
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 );
if( poly1->TestPointInside( x, y ) ) if( poly1->TestPointInside( x, y ) )
{ {
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 y = poly1->GetY( ic1 ); int x = poly1->GetX( ic1 );
if( poly2->TestPointInside( x, y ) ) int y = poly1->GetY( ic1 );
{ if( poly2->TestPointInside( x, y ) )
return 1; {
} return 1;
} }
}
*/ return 0;
} return 0;
}
if( bArcInt ) if( bArcInt )
return 2; return 2;
return 1; return 1;
@ -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
@ -786,48 +790,52 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi
* @param Area_Ref: the given area to compare with other areas * @param Area_Ref: the given area to compare with other areas
* used to remove redundant areas * used to remove redundant areas
*/ */
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
if( Area_Ref->GetLayer() != Area_To_Test->GetLayer() )
continue;
// test if Area_Ref inside Area_To_Test // test for same layer
corners_inside_count = Area_Ref->m_Poly->GetNumCorners(); if( Area_Ref->GetLayer() != Area_To_Test->GetLayer() )
for( int ic = 0; ic < Area_Ref->m_Poly->GetNumCorners(); ic++ ) continue;
{
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 // test if Area_Ref inside Area_To_Test
corners_inside_count = Area_To_Test->m_Poly->GetNumCorners(); corners_inside_count = Area_Ref->m_Poly->GetNumCorners();
for( int ic2 = 0; ic2 < Area_To_Test->m_Poly->GetNumCorners(); ic2++ ) for( int ic = 0; ic < Area_Ref->m_Poly->GetNumCorners(); ic++ )
{ {
int x = Area_To_Test->m_Poly->GetX( ic2 ); int x = Area_Ref->m_Poly->GetX( ic );
int y = Area_To_Test->m_Poly->GetY( ic2 ); int y = Area_Ref->m_Poly->GetY( ic );
if( Area_Ref->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 )
return Area_Ref;
} if( corners_inside_count == 0 )
return Area_Ref;
return NULL;
// 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 #endif
@ -835,14 +843,14 @@ ZONE_CONTAINER* BOARD::Is_Area_Inside_Area( ZONE_CONTAINER* Area_Ref)
* 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:
* Test areas inside other areas * Test areas inside other areas
* Test areas too close * Test areas too close
* @param aArea_To_Examine: area to compare with other areas. if NULL: all areas are compared tp all others * @param aArea_To_Examine: area to compare with other areas. if NULL: all areas are compared tp all others
* @param aCreate_Markers: if true create DRC markers. False: do not creates anything * @param aCreate_Markers: if true create DRC markers. False: do not creates anything
* @return errors count * @return errors count
*/ */
int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_Examine, int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_Examine,
bool aCreate_Markers) bool aCreate_Markers )
{ {
wxString str; wxString str;
long nerrors = 0; long nerrors = 0;
@ -851,19 +859,21 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E
for( int ia = 0; ia < GetAreaCount(); ia++ ) for( int ia = 0; ia < GetAreaCount(); ia++ )
{ {
ZONE_CONTAINER* Area_Ref = GetArea( ia ); ZONE_CONTAINER* Area_Ref = GetArea( ia );
if ( aArea_To_Examine && (aArea_To_Examine != Area_Ref) ) if( aArea_To_Examine && (aArea_To_Examine != Area_Ref) )
continue; continue;
for( int ia2 = 0; ia2 < GetAreaCount(); ia2++ ) for( int ia2 = 0; ia2 < GetAreaCount(); ia2++ )
{ {
ZONE_CONTAINER* Area_To_Test = GetArea( ia2 ); ZONE_CONTAINER* Area_To_Test = GetArea( ia2 );
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
if( Area_Ref->GetNet() == Area_To_Test->GetNet() ) // Test for same net
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
@ -874,20 +884,20 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E
if( Area_To_Test->m_Poly->TestPointInside( x, y ) ) if( Area_To_Test->m_Poly->TestPointInside( x, y ) )
{ {
// COPPERAREA_COPPERAREA error: copper area ref corner inside copper area // COPPERAREA_COPPERAREA error: copper area ref corner inside copper area
if ( aCreate_Markers ) if( aCreate_Markers )
{ {
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_INSIDE_COPPERAREA, wxPoint( x, y ), MARKER* marker = new MARKER( COPPERAREA_INSIDE_COPPERAREA, wxPoint( x, y ),
msg1, wxPoint( x, y ), msg1, wxPoint( x, y ),
msg2, wxPoint( x, y ) ); msg2, wxPoint( x, y ) );
Add( marker ); Add( marker );
} }
nerrors++; nerrors++;
} }
} }
// test for some corners of Area_To_Test inside Area_Ref // test for some corners of Area_To_Test inside Area_Ref
for( int ic2 = 0; ic2 < Area_To_Test->m_Poly->GetNumCorners(); ic2++ ) for( int ic2 = 0; ic2 < Area_To_Test->m_Poly->GetNumCorners(); ic2++ )
{ {
int x = Area_To_Test->m_Poly->GetX( ic2 ); int x = Area_To_Test->m_Poly->GetX( ic2 );
@ -895,15 +905,15 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E
if( Area_Ref->m_Poly->TestPointInside( x, y ) ) if( Area_Ref->m_Poly->TestPointInside( x, y ) )
{ {
// COPPERAREA_COPPERAREA error: copper area corner inside copper area ref // COPPERAREA_COPPERAREA error: copper area corner inside copper area ref
if ( aCreate_Markers ) if( aCreate_Markers )
{ {
wxString msg1 = Area_To_Test->MenuText(this); wxString msg1 = Area_To_Test->MenuText( this );
wxString msg2 = Area_Ref->MenuText(this); wxString msg2 = Area_Ref->MenuText( this );
MARKER* marker = new MARKER( COPPERAREA_INSIDE_COPPERAREA, wxPoint( x, y ), MARKER* marker = new MARKER( COPPERAREA_INSIDE_COPPERAREA, wxPoint( x, y ),
msg1, wxPoint( x, y ), msg1, wxPoint( x, y ),
msg2, wxPoint( x, y ) ); msg2, wxPoint( x, y ) );
Add( marker ); Add( marker );
} }
nerrors++; nerrors++;
} }
} }
@ -950,33 +960,28 @@ 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, 0,
by2, ax1, ay1, ax2,
bstyle, ay2, astyle,
0, 0,
ax1, g_DesignSettings.
ay1, m_TrackClearence,
ax2, &x, &y );
ay2,
astyle,
0,
g_DesignSettings.m_TrackClearence,
&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
if ( aCreate_Markers ) if( aCreate_Markers )
{ {
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,
msg1, wxPoint( x, y ), wxPoint( x, y ),
msg2, wxPoint( x, y ) ); msg1, wxPoint( x, y ),
Add( marker ); msg2, wxPoint( x, y ) );
} Add( marker );
}
nerrors++; nerrors++;
} }
} }
@ -985,7 +990,94 @@ 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 );