From e9b3322fc0ba97b4a00bbc782f59746b3abf62f4 Mon Sep 17 00:00:00 2001 From: CHARRAS Date: Sun, 20 Jan 2008 19:55:22 +0000 Subject: [PATCH] On line DRC when creating a zone outline --- change_log.txt | 6 + include/wxPcbStruct.h | 5 +- pcbnew/class_drawsegment.h | 2 +- pcbnew/class_drc_item.cpp | 7 +- pcbnew/class_module.h | 89 ++--- pcbnew/class_track.cpp | 33 +- pcbnew/class_zone.cpp | 61 ++- pcbnew/class_zone.h | 26 +- pcbnew/drc.cpp | 80 +++- pcbnew/drc_stuff.h | 39 +- pcbnew/edit.cpp | 4 +- pcbnew/onleftclick.cpp | 8 +- pcbnew/zones_by_polygon.cpp | 117 ++++-- pcbnew/zones_test_and_combine_areas.cpp | 492 ++++++++++++++---------- polygon/PolyLine.cpp | 50 --- polygon/PolyLine.h | 1 - 16 files changed, 634 insertions(+), 386 deletions(-) diff --git a/change_log.txt b/change_log.txt index 571ac42418..da1d4413af 100644 --- a/change_log.txt +++ b/change_log.txt @@ -4,6 +4,12 @@ Started 2007-June-11 Please add newer entries at the top, list the date and your name with email address. +2008-Jan-20 UPDATE Jean-Pierre Charras +================================================================================ ++pcbnew: + On line DRC when creating a zone outline. + Needs more work to display errors DRC. + 2008-Jan-18 UPDATE Jean-Pierre Charras ================================================================================ diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index 5041f1204d..1c845b4126 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -491,10 +491,11 @@ public: /** * Function End_Zone - * terminates the zone edge creation process + * terminates (if no DRC error ) the zone edge creation process * @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() * Calculate the zone filling for the outline zone_container diff --git a/pcbnew/class_drawsegment.h b/pcbnew/class_drawsegment.h index 3669d08e59..6957cd9d1d 100644 --- a/pcbnew/class_drawsegment.h +++ b/pcbnew/class_drawsegment.h @@ -56,7 +56,7 @@ public: * Is virtual from EDA_BaseStruct. * @param frame A WinEDA_BasePcbFrame in which to print status information. */ - void Display_Infos( WinEDA_DrawFrame* frame ); + virtual void Display_Infos( WinEDA_DrawFrame* frame ); /** diff --git a/pcbnew/class_drc_item.cpp b/pcbnew/class_drc_item.cpp index 21f9f0bb12..856bd8e522 100644 --- a/pcbnew/class_drc_item.cpp +++ b/pcbnew/class_drc_item.cpp @@ -70,7 +70,10 @@ wxString DRC_ITEM::GetErrorText() const case COPPERAREA_INSIDE_COPPERAREA: return wxString( _("Copper area inside copper area")); 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: return wxString( wxT("PROGRAM BUG, PLEASE LEAVE THE ROOM.") ); @@ -83,7 +86,7 @@ wxString DRC_ITEM::ShowCoord( const wxPoint& aPos ) wxString temp; 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(")"); diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 545956ecf9..f46236cd02 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -37,7 +37,6 @@ enum Mod_Attribut /* Attributs d'un module */ class MODULE : public BOARD_ITEM { - public: wxPoint m_Pos; // Real coord on board 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_Value; // texte valeur du composant (74LS00, 22K..) 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_Orient; /* orientation en 1/10 degres */ - int flag; /* flag utilise en trace rastnest et routage auto */ - int m_ModuleStatus; /* For autoplace: flags (LOCKED, AUTOPLACED) */ - EDA_Rect m_BoundaryBox; /* position/taille du cadre de reperage (coord locales)*/ - EDA_Rect m_RealBoundaryBox; /* position/taille du module (coord relles) */ - int m_PadNum; // Nombre total de pads - int m_AltPadNum; // en placement auto Nombre de pads actifs pour + int m_Attributs; /* Flags bits a bit ( voir enum Mod_Attribut ) */ + int m_Orient; /* orientation en 1/10 degres */ + int flag; /* flag utilise en trace rastnest et routage auto */ + int m_ModuleStatus; /* For autoplace: flags (LOCKED, AUTOPLACED) */ + EDA_Rect m_BoundaryBox; /* position/taille du cadre de reperage (coord locales)*/ + EDA_Rect m_RealBoundaryBox; /* position/taille du module (coord relles) */ + int m_PadNum; // Nombre total de pads + int m_AltPadNum; // en placement auto Nombre de pads actifs pour // 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, ...) - long m_LastEdit_Time; // Date de la derniere modification du module (gestion de librairies) + 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 - wxString m_Doc; // Texte de description du module - wxString m_KeyWord; // Liste des mots cles relatifs au module + unsigned long m_Link; // variable temporaire ( pour editions, ...) + 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: MODULE( BOARD* parent ); @@ -77,11 +78,11 @@ public: MODULE* Next() { return (MODULE*) Pnext; } - void Set_Rectangle_Encadrement();/* mise a jour du rect d'encadrement - * en coord locales (orient 0 et origine = pos module) */ + void Set_Rectangle_Encadrement(); /* mise a jour du rect d'encadrement + * en coord locales (orient 0 et origine = pos module) */ - void SetRectangleExinscrit();/* mise a jour du rect d'encadrement - * et de la surface en coord reelles */ + void SetRectangleExinscrit(); /* mise a jour du rect d'encadrement + * et de la surface en coord reelles */ /** * Function GetPosition @@ -94,7 +95,7 @@ public: return m_Pos; } - + // deplacements void SetPosition( const wxPoint& newpos ); void SetOrientation( int newangle ); @@ -105,7 +106,7 @@ public: /** * Function IsLocked - * (virtual from BOARD_ITEM ) + * (virtual from BOARD_ITEM ) * @returns bool - true if the MODULE is locked, else false */ bool IsLocked() const @@ -129,15 +130,15 @@ public: /* Reading and writing data on files */ - + /** * Function Save * writes the data structures for this object out to a FILE in "*.brd" format. * @param aFile The FILE to write to. * @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 ReadDescr( 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 * about this object into the frame's message panel. * @param frame A WinEDA_DrawFrame in which to print status information. - */ + */ void Display_Infos( WinEDA_DrawFrame* frame ); - + /** * Function HitTest * tests if the given wxPoint is within the bounds of this object. @@ -168,7 +169,7 @@ public: */ bool HitTest( const wxPoint& refPos ); - + /** * Function HitTest (overlayed) * tests if the given EDA_Rect intersect the bounds of this object. @@ -177,7 +178,7 @@ public: */ bool HitTest( EDA_Rect& refArea ); - /** + /** * Function GetReference * @return wxString - the reference designator text. */ @@ -185,8 +186,8 @@ public: { return m_Reference->m_Text; } - - + + /** * Function Visit * 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. * @param inspector An INSPECTOR instance to use in the inspection. * @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. * @return SEARCH_RESULT - SEARCH_QUIT if the Iterator is to stop the scan, * else SCAN_CONTINUE; */ - SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData, - const KICAD_T scanTypes[] ); - - + SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData, + const KICAD_T scanTypes[] ); + + /** * Function GetClass * returns the class name. @@ -214,17 +215,17 @@ public: return wxT( "MODULE" ); } - - #if defined(DEBUG) - /** + + #if defined (DEBUG) + + /** * Function Show * 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. * @param os The ostream& to output to. */ virtual void Show( int nestLevel, std::ostream& os ); #endif - }; diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index 0f6ab00317..4a124931b3 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -62,20 +62,9 @@ wxString TRACK::ShowWidth() /***************************/ { 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 ); -#endif - 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 , 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; } diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 47982e7b6f..69d44ea646 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -15,12 +15,17 @@ /**********************/ /* 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 */ -EDGE_ZONE::EDGE_ZONE( BOARD_ITEM* parent ) : +EDGE_ZONE::EDGE_ZONE( BOARD* parent ) : DRAWSEGMENT( parent, TYPEEDGEZONE ) { 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 /****************************************/ +/* edge_zone is a temporary item only used when creating a zone area. +* it will not saved in file +*/ { 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 */ @@ -330,26 +367,22 @@ bool ZONE_CONTAINER::HitTest( const wxPoint& refPos ) /** * Function HitTestForCorner * 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 * @param refPos : A wxPoint to test */ 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; unsigned item_pos, lim; lim = m_Poly->corner.size(); 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++ ) { 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; return item_pos; @@ -362,21 +395,17 @@ int ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos ) /** * Function HitTestForEdge * 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 * @param refPos : A wxPoint to test */ 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; unsigned item_pos, lim; 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 */ unsigned first_corner_pos = 0, end_segm; m_CornerSelection = -1; @@ -402,7 +431,7 @@ int ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) m_Poly->corner[item_pos].y, m_Poly->corner[end_segm].x, m_Poly->corner[end_segm].y ); - if( dist <= min_dist ) + if( dist <= EDGE_MIN_DIST ) { m_CornerSelection = item_pos; return item_pos; diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index cdb092b108..2a4445de0c 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -62,7 +62,7 @@ public: void Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& offset, int draw_mode ); - int GetNet( void ) { return m_NetCode; } + int GetNet( void ) const { return m_NetCode; } void SetNet( int anet_code ); /** * Function HitTest @@ -137,19 +137,37 @@ public: /*******************/ /* 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 { +private: + int m_NetCode; + public: - EDGE_ZONE( BOARD_ITEM* StructFather ); - EDGE_ZONE( const EDGE_ZONE& edgezone ); + EDGE_ZONE( BOARD * StructFather ); + ~EDGE_ZONE(); EDGE_ZONE* Next() { return (EDGE_ZONE*) Pnext; } 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 * writes the data structures for this object out to a FILE in "*.brd" format. diff --git a/pcbnew/drc.cpp b/pcbnew/drc.cpp index 6e5d1e10b6..bdf7705552 100644 --- a/pcbnew/drc.cpp +++ b/pcbnew/drc.cpp @@ -139,9 +139,9 @@ DRC::~DRC() delete m_unconnected[i]; } -/***********************************************************************/ +/*********************************************/ int DRC::Drc( TRACK* aRefSegm, TRACK* aList ) -/***********************************************************************/ +/*********************************************/ { 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() { // someone should have cleared the two lists before calling this. @@ -169,8 +196,7 @@ void DRC::RunTests() testTracks(); // test zone clearances to other zones, pads, tracks, and vias - if( m_doZonesTest ) - testZones(); + testZones(m_doZonesTest); // find and gather unconnected pads. 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 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() ) ++m_pcb->m_NbSegmZone; */ - + if ( ! adoTestFillSegments ) return; for( zoneSeg = m_pcb->m_Zone; zoneSeg && zoneSeg->Next(); zoneSeg=zoneSeg->Next() ) { // 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; } +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 ) diff --git a/pcbnew/drc_stuff.h b/pcbnew/drc_stuff.h index bc25c874cf..fbd40eb60b 100644 --- a/pcbnew/drc_stuff.h +++ b/pcbnew/drc_stuff.h @@ -57,6 +57,7 @@ #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_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 @@ -358,6 +359,21 @@ private: 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 ); //---------------------------------------------- @@ -367,7 +383,7 @@ private: void testUnconnected(); - void testZones(); + void testZones(bool adoTestFillSegments); //---------------------------------------------- @@ -395,6 +411,17 @@ private: 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 ); + //--------------------------------------------------- /** @@ -467,6 +494,16 @@ public: */ 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 diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index 730d967f93..3f65e8423d 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -810,8 +810,8 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event ) DrawPanel->MouseToCursorSchema(); if( GetCurItem() && (GetCurItem()->m_Flags & IS_NEW) ) { - End_Zone( &dc ); - SetCurItem( NULL ); + if ( End_Zone( &dc ) ) + SetCurItem( NULL ); } break; diff --git a/pcbnew/onleftclick.cpp b/pcbnew/onleftclick.cpp index b1cc7c70a2..b9004f054f 100644 --- a/pcbnew/onleftclick.cpp +++ b/pcbnew/onleftclick.cpp @@ -406,9 +406,11 @@ void WinEDA_PcbFrame::OnLeftDClick( wxDC* DC, const wxPoint& MousePos ) break; case ID_PCB_ZONES_BUTT: - End_Zone( DC ); - DrawPanel->m_AutoPAN_Request = FALSE; - SetCurItem( NULL ); + if ( End_Zone( DC ) ) + { + DrawPanel->m_AutoPAN_Request = FALSE; + SetCurItem( NULL ); + } break; case ID_LINE_COMMENT_BUTT: diff --git a/pcbnew/zones_by_polygon.cpp b/pcbnew/zones_by_polygon.cpp index f4335397eb..94621b9b96 100644 --- a/pcbnew/zones_by_polygon.cpp +++ b/pcbnew/zones_by_polygon.cpp @@ -197,7 +197,7 @@ static void Abort_Zone_Create_Outline( WinEDA_DrawPanel* Panel, wxDC* DC ) /** * 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; @@ -235,7 +235,10 @@ void WinEDA_BasePcbFrame::DelLimitesZone( wxDC* DC, bool Redraw ) next = segment->Next(); if( Redraw && DC ) + { + Trace_DrawSegmentPcb( DrawPanel, DC, segment, GR_OR ); Trace_DrawSegmentPcb( DrawPanel, DC, segment, GR_XOR ); + } 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); - // 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 ); if ( DC ) { @@ -506,7 +509,7 @@ EDGE_ZONE* WinEDA_PcbFrame::Begin_Zone( wxDC* DC ) 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_CurrentZone = NULL; @@ -560,6 +563,14 @@ EDGE_ZONE* WinEDA_PcbFrame::Begin_Zone( wxDC* DC ) newedge->m_Flags = IS_NEW | STARTPOINT | IS_MOVED; newedge->m_Start = newedge->m_End = GetScreen()->m_Curseur; 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: 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 */ 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); - newedge = new EDGE_ZONE( oldedge ); + newedge = new EDGE_ZONE( m_Pcb ); newedge->m_Flags = IS_NEW | IS_MOVED; 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: 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 * Terminates a zone outline creation - * Close the current zone outline considered as a polygon - * put it in the main list m_Pcb->m_ZoneDescriptorList (a vector) + * terminates (if no DRC error ) the zone edge creation process + * @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) */ { - EDGE_ZONE* edge; - int layer = GetScreen()->m_Active_Layer; + if( m_Pcb->m_CurrentLimitZone == NULL ) return true; + + EDGE_ZONE* edge = m_Pcb->m_CurrentLimitZone; + EDGE_ZONE* last_edge = m_Pcb->m_CurrentLimitZone; + int layer = edge->GetLayer(); - if( m_Pcb->m_CurrentLimitZone ) - { - Begin_Zone( DC ); + // Validate the current edge: + if ( edge->m_Start != edge->m_End ) + { + 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. - * Use it to close the polygon by setting its ending point coordinate = start point of first segment - */ - edge = m_Pcb->m_CurrentLimitZone; - edge->m_Flags &= ~(IS_NEW | IS_MOVED); + /* 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 + */ + /* search first segment outline ( last item of the linked list ) */ + edge = m_Pcb->m_CurrentLimitZone; + while( edge->Next() ) + { + edge = edge->Next(); + edge->m_Flags &= ~(IS_NEW | IS_MOVED); + } - while( edge && edge->Next() ) - { - edge = edge->Next(); - if( edge->m_Flags & STARTPOINT ) - break; + wxPoint curr_endpoint = m_Pcb->m_CurrentLimitZone->m_End; + 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); - } - - 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 ); - } + edge->m_Flags &= ~(IS_NEW | IS_MOVED); + Trace_DrawSegmentPcb( DrawPanel, DC, m_Pcb->m_CurrentLimitZone, GR_XOR ); DrawPanel->ManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL; @@ -642,9 +680,9 @@ void WinEDA_PcbFrame::End_Zone( wxDC* DC ) // Undraw old drawings, because they can have important changes for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ ) { - ZONE_CONTAINER* edge_zone = m_Pcb->GetArea(ii); - if( layer == edge_zone->GetLayer() ) - edge_zone->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR ); + ZONE_CONTAINER* area = m_Pcb->GetArea(ii); + if( layer == area->GetLayer() ) + area->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR ); } /* Put edges in list */ @@ -717,6 +755,7 @@ void WinEDA_PcbFrame::End_Zone( wxDC* DC ) } 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 */ currentEdge = pcbframe->m_Pcb->m_CurrentLimitZone; if( Zone_45_Only ) diff --git a/pcbnew/zones_test_and_combine_areas.cpp b/pcbnew/zones_test_and_combine_areas.cpp index b685477d1b..ad388e9b8e 100644 --- a/pcbnew/zones_test_and_combine_areas.cpp +++ b/pcbnew/zones_test_and_combine_areas.cpp @@ -230,7 +230,7 @@ int BOARD::TestAreaPolygon( ZONE_CONTAINER* CurrArea ) int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, 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 if( test == -1 && !bRetainArcs ) @@ -248,7 +248,7 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, str += wxT( "Manual correction is recommended." ); wxMessageBox( str ); -// bDontShowSelfIntersectionArcsWarning = dlg.bDontShowBoxState; +// bDontShowSelfIntersectionArcsWarning = dlg.bDontShowBoxState; } return -1; // arcs intersect with other sides, error } @@ -265,7 +265,8 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, if( bMessageBoxInt && bDontShowSelfIntersectionWarning == false ) { 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() ); str += wxT( "This may result in splitting the area.\n" ); 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 ); 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++ ) { // 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() ) continue; if( area_to_test == area2 ) - continue; + continue; - // see if areas are on same layer - if( area_to_test->GetLayer() != area2->GetLayer() ) - continue; + // see if areas are on same layer + if( area_to_test->GetLayer() != area2->GetLayer() ) + continue; - CPolyLine* poly2 = area2->m_Poly; + CPolyLine* poly2 = area2->m_Poly; - // test bounding rects - CRect b1 = poly1->GetCornerBounds(); - CRect b2 = poly2->GetCornerBounds(); - if( b1.bottom > b2.top - || b1.top < b2.bottom - || b1.left > b2.right - || b1.right < b2.left ) - continue; + // test bounding rects + CRect b1 = poly1->GetCornerBounds(); + CRect b2 = poly2->GetCornerBounds(); + if( b1.bottom > b2.top + || b1.top < b2.bottom + || b1.left > b2.right + || b1.right < b2.left ) + continue; - // test for intersecting segments - for( int icont1 = 0; icont1GetNumContours(); icont1++ ) - { - int is1 = poly1->GetContourStart( icont1 ); - int ie1 = poly1->GetContourEnd( icont1 ); - for( int ic1 = is1; ic1<=ie1; ic1++ ) - { - int xi1 = poly1->GetX( ic1 ); - int yi1 = poly1->GetY( ic1 ); - int xf1, yf1, style1; - if( ic1 < ie1 ) - { - xf1 = poly1->GetX( ic1 + 1 ); - yf1 = poly1->GetY( ic1 + 1 ); - } - else - { - xf1 = poly1->GetX( is1 ); - yf1 = poly1->GetY( is1 ); - } - style1 = poly1->GetSideStyle( ic1 ); - for( int icont2 = 0; icont2 < poly2->GetNumContours(); icont2++ ) - { - int is2 = poly2->GetContourStart( icont2 ); - int ie2 = poly2->GetContourEnd( icont2 ); - for( int ic2 = is2; ic2<=ie2; ic2++ ) - { - int xi2 = poly2->GetX( ic2 ); - int yi2 = poly2->GetY( ic2 ); - int xf2, yf2, style2; - if( ic2 < ie2 ) - { - xf2 = poly2->GetX( ic2 + 1 ); - yf2 = poly2->GetY( ic2 + 1 ); - } - else - { - xf2 = poly2->GetX( is2 ); - yf2 = poly2->GetY( is2 ); - } - style2 = poly2->GetSideStyle( ic2 ); - int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, style1, - xi2, yi2, xf2, yf2, style2 ); - if( n_int ) - return true; - } - } - } - } - - // 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) -/* for( int ic2 = 0; ic2 < poly2->GetNumCorners(); ic2++ ) - { - int x = poly2->GetX( ic2 ); - int y = poly2->GetY( ic2 ); - if( poly1->TestPointInside( x, y ) ) - { - return true; - } - } - for( int ic1 = 0; ic1 < poly1->GetNumCorners(); ic1++ ) - { - int x = poly1->GetX( ic1 ); - int y = poly1->GetY( ic1 ); - if( poly2->TestPointInside( x, y ) ) - { - return true; - } - } -*/ } + // test for intersecting segments + for( int icont1 = 0; icont1GetNumContours(); icont1++ ) + { + int is1 = poly1->GetContourStart( icont1 ); + int ie1 = poly1->GetContourEnd( icont1 ); + for( int ic1 = is1; ic1<=ie1; ic1++ ) + { + int xi1 = poly1->GetX( ic1 ); + int yi1 = poly1->GetY( ic1 ); + int xf1, yf1, style1; + if( ic1 < ie1 ) + { + xf1 = poly1->GetX( ic1 + 1 ); + yf1 = poly1->GetY( ic1 + 1 ); + } + else + { + xf1 = poly1->GetX( is1 ); + yf1 = poly1->GetY( is1 ); + } + style1 = poly1->GetSideStyle( ic1 ); + for( int icont2 = 0; icont2 < poly2->GetNumContours(); icont2++ ) + { + int is2 = poly2->GetContourStart( icont2 ); + int ie2 = poly2->GetContourEnd( icont2 ); + for( int ic2 = is2; ic2<=ie2; ic2++ ) + { + int xi2 = poly2->GetX( ic2 ); + int yi2 = poly2->GetY( ic2 ); + int xf2, yf2, style2; + if( ic2 < ie2 ) + { + xf2 = poly2->GetX( ic2 + 1 ); + yf2 = poly2->GetY( ic2 + 1 ); + } + else + { + xf2 = poly2->GetX( is2 ); + yf2 = poly2->GetY( is2 ); + } + style2 = poly2->GetSideStyle( ic2 ); + int n_int = FindSegmentIntersections( xi1, yi1, xf1, yf1, style1, + xi2, yi2, xf2, yf2, style2 ); + if( n_int ) + return true; + } + } + } + } + + // 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) + for( int ic2 = 0; ic2 < poly2->GetNumCorners(); ic2++ ) + { + int x = poly2->GetX( ic2 ); + int y = poly2->GetY( ic2 ); + if( poly1->TestPointInside( x, y ) ) + { + return true; + } + } + + for( int ic1 = 0; ic1 < poly1->GetNumCorners(); ic1++ ) + { + int x = poly1->GetX( ic1 ); + int y = poly1->GetY( ic1 ); + if( poly2->TestPointInside( x, y ) ) + { + return true; + } + } + } return false; } @@ -636,32 +638,34 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ } 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 - // test a corner inside an outline (only one corner is enought) - for( int ic2 = 0; ic2 < poly2->GetNumCorners(); ic2++ ) - { - int x = poly2->GetX( ic2 ); - int y = poly2->GetY( ic2 ); - if( poly1->TestPointInside( x, y ) ) - { - return 1; - } - } - for( int ic1 = 0; ic1 < poly1->GetNumCorners(); ic1++ ) - { - int x = poly1->GetX( ic1 ); - int y = poly1->GetY( ic1 ); - if( poly2->TestPointInside( x, y ) ) - { - return 1; - } - } - -*/ return 0; - } + // 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) + for( int ic2 = 0; ic2 < poly2->GetNumCorners(); ic2++ ) + { + int x = poly2->GetX( ic2 ); + int y = poly2->GetY( ic2 ); + if( poly1->TestPointInside( x, y ) ) + { + return 1; + } + } + + for( int ic1 = 0; ic1 < poly1->GetNumCorners(); ic1++ ) + { + int x = poly1->GetX( ic1 ); + int y = poly1->GetY( ic1 ); + if( poly2->TestPointInside( x, y ) ) + { + return 1; + } + } + + return 0; + } if( bArcInt ) return 2; 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 * 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 * 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++ ) - { - ZONE_CONTAINER* Area_To_Test = GetArea( ia ); + for( int ia = 0; ia < GetAreaCount(); ia++ ) + { + ZONE_CONTAINER* Area_To_Test = GetArea( ia ); - if( Area_Ref == Area_To_Test ) - continue; - // test for same layer - if( Area_Ref->GetLayer() != Area_To_Test->GetLayer() ) - continue; + if( Area_Ref == Area_To_Test ) + continue; - // test if Area_Ref inside Area_To_Test - corners_inside_count = Area_Ref->m_Poly->GetNumCorners(); - for( int ic = 0; ic < Area_Ref->m_Poly->GetNumCorners(); ic++ ) - { - int x = Area_Ref->m_Poly->GetX( ic ); - int y = Area_Ref->m_Poly->GetY( ic ); - if( Area_To_Test->m_Poly->TestPointInside( x, y ) ) - corners_inside_count--; - } - if ( corners_inside_count == 0 ) - return Area_Ref; + // test for same layer + if( Area_Ref->GetLayer() != Area_To_Test->GetLayer() ) + continue; - // 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; + // test if Area_Ref inside Area_To_Test + corners_inside_count = Area_Ref->m_Poly->GetNumCorners(); + for( int ic = 0; ic < Area_Ref->m_Poly->GetNumCorners(); ic++ ) + { + int x = Area_Ref->m_Poly->GetX( ic ); + int y = Area_Ref->m_Poly->GetY( ic ); + if( Area_To_Test->m_Poly->TestPointInside( x, y ) ) + corners_inside_count--; + } - } - - return NULL; + if( corners_inside_count == 0 ) + return Area_Ref; + + // test if Area_To_Test inside Area_Ref + corners_inside_count = Area_To_Test->m_Poly->GetNumCorners(); + for( int ic2 = 0; ic2 < Area_To_Test->m_Poly->GetNumCorners(); ic2++ ) + { + int x = Area_To_Test->m_Poly->GetX( ic2 ); + int y = Area_To_Test->m_Poly->GetY( ic2 ); + if( Area_Ref->m_Poly->TestPointInside( x, y ) ) + corners_inside_count--; + } + + if( corners_inside_count == 0 ) + return Area_Ref; + } + + return NULL; } + + #endif @@ -835,14 +843,14 @@ ZONE_CONTAINER* BOARD::Is_Area_Inside_Area( ZONE_CONTAINER* Area_Ref) * Function Test_Drc_Areas_Outlines_To_Areas_Outlines * Test Areas outlines for DRC: * 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 aCreate_Markers: if true create DRC markers. False: do not creates anything * @return errors count */ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_Examine, - bool aCreate_Markers) + bool aCreate_Markers ) { wxString str; 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++ ) { ZONE_CONTAINER* Area_Ref = GetArea( ia ); - if ( aArea_To_Examine && (aArea_To_Examine != Area_Ref) ) - continue; + if( aArea_To_Examine && (aArea_To_Examine != Area_Ref) ) + continue; for( int ia2 = 0; ia2 < GetAreaCount(); ia2++ ) { ZONE_CONTAINER* Area_To_Test = GetArea( ia2 ); if( Area_Ref == Area_To_Test ) continue; + // test for same layer if( Area_Ref->GetLayer() != Area_To_Test->GetLayer() ) continue; - // Test for same net - if( Area_Ref->GetNet() == Area_To_Test->GetNet() ) + + // Test for same net + if( Area_Ref->GetNet() == Area_To_Test->GetNet() && Area_Ref->GetNet() > 0 ) continue; // 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 ) ) { // COPPERAREA_COPPERAREA error: copper area ref corner inside copper area - if ( aCreate_Markers ) - { - wxString msg1 = Area_Ref->MenuText(this); - wxString msg2 = Area_To_Test->MenuText(this); - MARKER* marker = new MARKER( COPPERAREA_INSIDE_COPPERAREA, wxPoint( x, y ), - msg1, wxPoint( x, y ), - msg2, wxPoint( x, y ) ); - Add( marker ); - } + if( aCreate_Markers ) + { + wxString msg1 = Area_Ref->MenuText( this ); + wxString msg2 = Area_To_Test->MenuText( this ); + MARKER* marker = new MARKER( COPPERAREA_INSIDE_COPPERAREA, wxPoint( x, y ), + msg1, wxPoint( x, y ), + msg2, wxPoint( x, y ) ); + Add( marker ); + } nerrors++; } } - // test for some corners of Area_To_Test inside Area_Ref + // test for some corners of Area_To_Test inside Area_Ref for( int ic2 = 0; ic2 < Area_To_Test->m_Poly->GetNumCorners(); 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 ) ) { // COPPERAREA_COPPERAREA error: copper area corner inside copper area ref - if ( aCreate_Markers ) - { - wxString msg1 = Area_To_Test->MenuText(this); - wxString msg2 = Area_Ref->MenuText(this); - MARKER* marker = new MARKER( COPPERAREA_INSIDE_COPPERAREA, wxPoint( x, y ), - msg1, wxPoint( x, y ), - msg2, wxPoint( x, y ) ); - Add( marker ); - } + if( aCreate_Markers ) + { + wxString msg1 = Area_To_Test->MenuText( this ); + wxString msg2 = Area_Ref->MenuText( this ); + MARKER* marker = new MARKER( COPPERAREA_INSIDE_COPPERAREA, wxPoint( x, y ), + msg1, wxPoint( x, y ), + msg2, wxPoint( x, y ) ); + Add( marker ); + } 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 x, y; - int d = ::GetClearanceBetweenSegments( bx1, - by1, - bx2, - by2, - bstyle, - 0, - ax1, - ay1, - ax2, - ay2, - astyle, - 0, - g_DesignSettings.m_TrackClearence, - &x, - &y ); + int d = ::GetClearanceBetweenSegments( + bx1, by1, bx2, by2, bstyle, + 0, + ax1, ay1, ax2, + ay2, astyle, + 0, + g_DesignSettings. + m_TrackClearence, + &x, &y ); if( d < g_DesignSettings.m_TrackClearence ) { // COPPERAREA_COPPERAREA error : intersect or too close - if ( aCreate_Markers ) - { - wxString msg1 = Area_Ref->MenuText(this); - wxString msg2 = Area_To_Test->MenuText(this); - MARKER* marker = new MARKER( COPPERAREA_CLOSE_TO_COPPERAREA, wxPoint( x, y ), - msg1, wxPoint( x, y ), - msg2, wxPoint( x, y ) ); - Add( marker ); - } + if( aCreate_Markers ) + { + wxString msg1 = Area_Ref->MenuText( this ); + wxString msg2 = Area_To_Test->MenuText( this ); + MARKER* marker = new MARKER( COPPERAREA_CLOSE_TO_COPPERAREA, + wxPoint( x, y ), + msg1, wxPoint( x, y ), + msg2, wxPoint( x, y ) ); + Add( marker ); + } 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; +} diff --git a/polygon/PolyLine.cpp b/polygon/PolyLine.cpp index 4d595a64d2..31fc1d7ae2 100644 --- a/polygon/PolyLine.cpp +++ b/polygon/PolyLine.cpp @@ -1323,56 +1323,6 @@ bool CPolyLine::TestPointInsideContour( int icont, int x, int y ) 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; icGetNumContours(); 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 // diff --git a/polygon/PolyLine.h b/polygon/PolyLine.h index 8eeac368a6..1b21a59832 100644 --- a/polygon/PolyLine.h +++ b/polygon/PolyLine.h @@ -93,7 +93,6 @@ public: bool TestPointInside( int x, int y ); bool TestPointInsideContour( int icont, int x, int y ); bool IsCutoutContour( int icont ); - int TestIntersection( CPolyLine * poly ); void AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num );