diff --git a/change_log.txt b/change_log.txt index 85a7fc628a..ec8f9f5bca 100644 --- a/change_log.txt +++ b/change_log.txt @@ -5,6 +5,13 @@ Started 2007-June-11 Please add newer entries at the top, list the date and your name with email address. +2008-Jan-31 UPDATE Jean-Pierre Charras +================================================================================ ++pcbnew: + remove the old EDGEZONE class. + A ZONE_CONTAINER class is used instead to handle the creation of a new zone outline + + 2008-Jan-29 UPDATE Dick Hollenbeck ================================================================================ +pcbnew: diff --git a/include/base_struct.h b/include/base_struct.h index 2d3453e6c0..8a5d597c89 100644 --- a/include/base_struct.h +++ b/include/base_struct.h @@ -40,7 +40,7 @@ enum KICAD_T { TYPEMIRE, TYPESCREEN, TYPEBLOCK, - TYPEEDGEZONE, + TYPEZONE_UNUSED, TYPEZONE_EDGE_CORNER, TYPEZONE_CONTAINER, diff --git a/include/pcbstruct.h b/include/pcbstruct.h index 5ff641196d..4d99e1899f 100644 --- a/include/pcbstruct.h +++ b/include/pcbstruct.h @@ -109,6 +109,9 @@ #define ECO2_LAYER (1 << ECO2_N) #define EDGE_LAYER (1 << EDGE_N) +#define FIRST_NON_COPPER_LAYER ADHESIVE_N_CU +#define LAST_NON_COPPER_LAYER EDGE_N + // extra bits 0xE0000000 /* masques generaux : */ #define ALL_LAYERS 0x1FFFFFFF diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index 235cde50d3..87f526dada 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -35,7 +35,6 @@ class MODULE; class TRACK; class SEGZONE; class SEGVIA; -class EDGE_ZONE; class D_PAD; class TEXTE_MODULE; class MIREPCB; @@ -268,13 +267,6 @@ public: void Block_Duplicate( wxDC* DC ); - /** - * Function DelLimitesZone - * deletes the limits of a zone. - * @param DC A wxDC to draw onto. - * @param Redraw If true, means redraw the pcb without the zone limits - */ - void DelLimitesZone( wxDC* DC, bool Redraw ); // layerhandling: // (See pcbnew/sel_layer.cpp for description of why null_layer parameter is provided) @@ -487,14 +479,21 @@ public: */ void Delete_Zone_Fill( wxDC* DC, SEGZONE* Track, long aTimestamp = 0 ); - EDGE_ZONE* Del_LastSegmEdgeZone( wxDC* DC ); + + + /** Function Delete_LastCreatedCorner + * Used only while creating a new zone outline + * Remove and delete the current outline segment in progress + * @return 0 if no corner in list, or corner number + */ + int Delete_LastCreatedCorner( wxDC* DC); /** * Function Begin_Zone * initiates a zone edge creation process, * or terminates the current zone edge and creates a new zone edge stub */ - EDGE_ZONE* Begin_Zone( wxDC* DC ); + int Begin_Zone( wxDC* DC ); /** * Function End_Zone diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index 1aa31e6289..3948310940 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -36,7 +36,7 @@ BOARD::BOARD( EDA_BaseStruct* parent, WinEDA_BasePcbFrame* frame ) : m_Pads = NULL; // pointeur liste d'acces aux pads m_Ratsnest = NULL; // pointeur liste rats m_LocalRatsnest = NULL; // pointeur liste rats local - m_CurrentLimitZone = NULL; // pointeur liste des EDEGE_ZONES + m_CurrentZoneContour = NULL; // This ZONE_CONTAINER handle the zone contour cuurently in progress // de determination des contours de zone } @@ -61,9 +61,6 @@ BOARD::~BOARD() m_Zone->DeleteStructList(); m_Zone = 0; - m_CurrentLimitZone->DeleteStructList(); - m_CurrentLimitZone = 0; - MyFree( m_Pads ); m_Pads = 0; @@ -75,6 +72,9 @@ BOARD::~BOARD() DeleteMARKERs(); DeleteZONEOutlines(); + + delete m_CurrentZoneContour; + m_CurrentZoneContour = NULL; } @@ -588,9 +588,7 @@ SEARCH_RESULT BOARD::Visit( INSPECTOR* inspector, const void* testData, ++p; break; - case TYPEEDGEZONE: - result = IterateForward( m_CurrentLimitZone, inspector, testData, p ); - ++p; + case TYPEZONE_UNUSED: // Unused type break; default: // catch EOT or ANY OTHER type here and return. diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 0c0ff0e8d1..a6565a301a 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -45,7 +45,7 @@ public: CHEVELU* m_Ratsnest; // Rastnest list CHEVELU* m_LocalRatsnest; // Rastnest list used while moving a footprint - EDGE_ZONE* m_CurrentLimitZone; /* zone contour currently in progress */ + ZONE_CONTAINER* m_CurrentZoneContour; // zone contour currently in progress BOARD( EDA_BaseStruct* StructFather, WinEDA_BasePcbFrame* frame ); ~BOARD(); diff --git a/pcbnew/class_board_item.cpp b/pcbnew/class_board_item.cpp index 7f7bd4a63a..fc28512721 100644 --- a/pcbnew/class_board_item.cpp +++ b/pcbnew/class_board_item.cpp @@ -89,8 +89,9 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const break; case TYPEEDGEMODULE: + { text << _( "Graphic" ) << wxT( " " ); - const wxChar* cp; + wxString cp; switch( ( (EDGE_MODULE*) item )->m_Shape ) { @@ -126,10 +127,12 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const cp = wxT( "??EDGE??" ); break; } - text << *cp << _( " of " ) + text << cp; + text << wxT( " (" ) << ReturnPcbLayerName( ((EDGE_MODULE*) item )->m_Layer ).Trim() << wxT( ")" ); + text << _( " of " ) << ( (MODULE*) GetParent() )->GetReference(); break; - + } case TYPETRACK: // deleting tracks requires all the information we can get to // disambiguate all the crap under the cursor! @@ -239,8 +242,8 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const ; break; - case TYPEEDGEZONE: - text << _( "Edge Zone" ) << _( " on " ) << ReturnPcbLayerName( item->GetLayer() ).Trim(); // @todo: extend text + case TYPEZONE_UNUSED: + text << wxT( "Unused" ); break; default: @@ -318,8 +321,8 @@ const char** BOARD_ITEM::MenuIcon() const xpm = add_mires_xpm; break; - case TYPEEDGEZONE: - xpm = show_mod_edge_xpm; // @todo: pcb edge xpm + case TYPEZONE_UNUSED: + xpm = 0; // unused break; default: diff --git a/pcbnew/class_edge_mod.cpp b/pcbnew/class_edge_mod.cpp index 9d1e157299..c0d866fb22 100644 --- a/pcbnew/class_edge_mod.cpp +++ b/pcbnew/class_edge_mod.cpp @@ -298,70 +298,9 @@ void EDGE_MODULE::Display_Infos( WinEDA_DrawFrame* frame ) } -#if 0 // replaced by Save() -/*****************************************/ -int EDGE_MODULE::WriteDescr( FILE* File ) -/*****************************************/ - -/* Write one EDGE_MODULE description - * File must be opened. - */ -{ - int NbLigne = 0, ii, * ptr; - - switch( m_Shape ) - { - case S_SEGMENT: - fprintf( File, "DS %d %d %d %d %d %d\n", - m_Start0.x, m_Start0.y, - m_End0.x, m_End0.y, - m_Width, m_Layer ); - NbLigne++; - break; - - case S_CIRCLE: - fprintf( File, "DC %d %d %d %d %d %d\n", - m_Start0.x, m_Start0.y, - m_End0.x, m_End0.y, - m_Width, m_Layer ); - NbLigne++; - break; - - case S_ARC: - fprintf( File, "DA %d %d %d %d %d %d %d\n", - m_Start0.x, m_Start0.y, - m_End0.x, m_End0.y, - m_Angle, - m_Width, m_Layer ); - NbLigne++; - break; - - case S_POLYGON: - fprintf( File, "DP %d %d %d %d %d %d %d\n", - m_Start0.x, m_Start0.y, - m_End0.x, m_End0.y, - m_PolyCount, - m_Width, m_Layer ); - NbLigne++; - for( ii = 0, ptr = m_PolyList; ii < m_PolyCount; ii++ ) - { - fprintf( File, "Dl %d %d\n", - *ptr, *(ptr + 1) ); - NbLigne++; ptr += 2; - } - - break; - - default: - DisplayError( NULL, wxT( "Type Edge Module inconnu" ) ); - break; - } - - return NbLigne; -} -#endif - +/*******************************************/ bool EDGE_MODULE::Save( FILE* aFile ) const +/*******************************************/ { int ret = -1; @@ -514,12 +453,15 @@ int EDGE_MODULE::ReadDescr( char* Line, FILE* File, break; } - // Controle d'epaisseur raisonnable: + // Check for a reasonnable width: if( m_Width <= 1 ) m_Width = 1; if( m_Width > MAX_WIDTH ) m_Width = MAX_WIDTH; + // Check for a reasonnable layer: + if ( (m_Layer < FIRST_NON_COPPER_LAYER) || (m_Layer > LAST_NON_COPPER_LAYER) ) + m_Layer = SILKSCREEN_N_CMP; return error; } diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index c05ef6c5eb..9fec8815b6 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -12,67 +12,6 @@ #include "pcbnew.h" #include "trigo.h" -/**********************/ -/* 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* parent ) : - DRAWSEGMENT( parent, TYPEEDGEZONE ) -{ - m_Width = 2; // a minimum for visibility, while dragging - SetNet(0); -} - - -/* Destructor */ -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 */ @@ -82,48 +21,50 @@ ZONE_CONTAINER::ZONE_CONTAINER( BOARD* parent ) : BOARD_ITEM( parent, TYPEZONE_CONTAINER ) { - m_NetCode = -1; // Net number for fast comparisons - m_CornerSelection = -1; - m_ZoneClearance = 200; // a reasonnable clerance value - m_GridFillValue = 50; // a reasonnable grid used for filling - m_PadOption = THERMAL_PAD; - utility = 0; // flags used in polygon calculations - utility2 = 0; // flags used in polygon calculations - m_Poly = new CPolyLine(); // Outlines - + m_NetCode = -1; // Net number for fast comparisons + m_CornerSelection = -1; + m_ZoneClearance = 200; // a reasonnable clerance value + m_GridFillValue = 50; // a reasonnable grid used for filling + m_PadOption = THERMAL_PAD; + utility = 0; // flags used in polygon calculations + utility2 = 0; // flags used in polygon calculations + m_Poly = new CPolyLine(); // Outlines } ZONE_CONTAINER::~ZONE_CONTAINER() { - delete m_Poly; - m_Poly = NULL; + delete m_Poly; + m_Poly = NULL; } /*******************************************/ void ZONE_CONTAINER::SetNet( int anet_code ) /*******************************************/ + /** - * Set the netcode and the netname + * Set the netcode and the netname * if netcode >= 0, set the netname * if netcode < 0: keep old netname (used to set an necode error flag) */ { - m_NetCode = anet_code; - - if ( anet_code < 0 ) return; - - if ( m_Parent ) - { - EQUIPOT* net = ((BOARD*) m_Parent)->FindNet( anet_code ); - if( net ) - m_Netname = net->m_Netname; - else m_Netname.Empty(); - } - else m_Netname.Empty(); -} + m_NetCode = anet_code; + if( anet_code < 0 ) + return; + + if( m_Parent ) + { + EQUIPOT* net = ( (BOARD*) m_Parent )->FindNet( anet_code ); + if( net ) + m_Netname = net->m_Netname; + else + m_Netname.Empty(); + } + else + m_Netname.Empty(); +} /********************************************/ @@ -133,144 +74,163 @@ bool ZONE_CONTAINER::Save( FILE* aFile ) const if( GetState( DELETED ) ) return true; - unsigned item_pos; - int ret; - unsigned corners_count = m_Poly->corner.size(); - int outline_hatch; + unsigned item_pos; + int ret; + unsigned corners_count = m_Poly->corner.size(); + int outline_hatch; - fprintf( aFile, "$CZONE_OUTLINE\n"); - // Save the outline main info - ret = fprintf( aFile, "ZInfo %8.8lX %d \"%s\"\n", - m_TimeStamp, m_NetCode, - CONV_TO_UTF8(m_Netname) ); - if ( ret < 3 ) return false; - // Save the ouline layer info - ret = fprintf( aFile, "ZLayer %d\n", m_Layer ); - if ( ret < 1 ) return false; - // Save the ouline aux info - switch ( m_Poly->GetHatchStyle() ) - { - default: - case CPolyLine::NO_HATCH: - outline_hatch = 'N'; - break; - case CPolyLine::DIAGONAL_EDGE: - outline_hatch = 'E'; - break; - case CPolyLine::DIAGONAL_FULL: - outline_hatch = 'F'; - break; - } + fprintf( aFile, "$CZONE_OUTLINE\n" ); - ret = fprintf( aFile, "ZAux %d %c\n", corners_count, outline_hatch ); - if ( ret < 2 ) return false; - // Save the corner list - for ( item_pos = 0; item_pos < corners_count; item_pos++ ) - { - ret = fprintf( aFile, "ZCorner %d %d %d \n", + // Save the outline main info + ret = fprintf( aFile, "ZInfo %8.8lX %d \"%s\"\n", + m_TimeStamp, m_NetCode, + CONV_TO_UTF8( m_Netname ) ); + if( ret < 3 ) + return false; + + // Save the ouline layer info + ret = fprintf( aFile, "ZLayer %d\n", m_Layer ); + if( ret < 1 ) + return false; + + // Save the ouline aux info + switch( m_Poly->GetHatchStyle() ) + { + default: + case CPolyLine::NO_HATCH: + outline_hatch = 'N'; + break; + + case CPolyLine::DIAGONAL_EDGE: + outline_hatch = 'E'; + break; + + case CPolyLine::DIAGONAL_FULL: + outline_hatch = 'F'; + break; + } + + ret = fprintf( aFile, "ZAux %d %c\n", corners_count, outline_hatch ); + if( ret < 2 ) + return false; + + // Save the corner list + for( item_pos = 0; item_pos < corners_count; item_pos++ ) + { + ret = fprintf( aFile, "ZCorner %d %d %d \n", m_Poly->corner[item_pos].x, m_Poly->corner[item_pos].y, m_Poly->corner[item_pos].end_contour ); - if ( ret < 3 ) return false; - } - fprintf( aFile, "$endCZONE_OUTLINE\n"); - - return true; + if( ret < 3 ) + return false; + } + + fprintf( aFile, "$endCZONE_OUTLINE\n" ); + + return true; } /**********************************************************/ int ZONE_CONTAINER::ReadDescr( FILE* aFile, int* aLineNum ) /**********************************************************/ + /** Function ReadDescr * @param aFile = opened file * @param aLineNum = pointer on a line number counter (can be NULL or missing) * @return 0 if ok or NULL */ { - char Line[1024], * text; - char netname_buffer[1024]; - int ret; - int n_corner_item = 0; - int outline_hatch = CPolyLine::NO_HATCH; - bool error = false, has_corner = false; + char Line[1024], * text; + char netname_buffer[1024]; + int ret; + int n_corner_item = 0; + int outline_hatch = CPolyLine::NO_HATCH; + bool error = false, has_corner = false; - netname_buffer[0] = 0; + netname_buffer[0] = 0; while( GetLine( aFile, Line, aLineNum, sizeof(Line) - 1 ) != NULL ) { - if( strnicmp(Line, "ZCorner", 7 ) == 0 ) // new corner found + if( strnicmp( Line, "ZCorner", 7 ) == 0 ) // new corner found { - int x = 0, y = 0, flag = 0; - text = Line + 7; - ret = sscanf( text, "%d %d %d", &x, &y, &flag); - if (ret < 3 ) error = true; - else - { - if ( ! has_corner ) - m_Poly->Start( m_Layer, 0, 0, - x, y, - outline_hatch ); - else - m_Poly->AppendCorner( x, y ); - has_corner = true; - if ( flag ) m_Poly->Close(); - } - } - if( strnicmp(Line, "ZInfo", 5 ) == 0 ) // general info found + int x = 0, y = 0, flag = 0; + text = Line + 7; + ret = sscanf( text, "%d %d %d", &x, &y, &flag ); + if( ret < 3 ) + error = true; + else + { + if( !has_corner ) + m_Poly->Start( m_Layer, x, y, outline_hatch ); + else + AppendCorner( wxPoint(x, y) ); + has_corner = true; + if( flag ) + m_Poly->Close(); + } + } + if( strnicmp( Line, "ZInfo", 5 ) == 0 ) // general info found { - int ts = 0, netcode = 0; - text = Line + 5; - ret = sscanf( text, "%X %d %s", &ts, &netcode, netname_buffer); - if (ret < 3 ) error = true; - else - { - m_TimeStamp = ts; - m_NetCode = netcode; - ReadDelimitedText( netname_buffer, netname_buffer, 1024 ); - m_Netname = CONV_FROM_UTF8(netname_buffer); - } - } - if( strnicmp(Line, "ZLayer", 6 ) == 0 ) // layer found + int ts = 0, netcode = 0; + text = Line + 5; + ret = sscanf( text, "%X %d %s", &ts, &netcode, netname_buffer ); + if( ret < 3 ) + error = true; + else + { + m_TimeStamp = ts; + m_NetCode = netcode; + ReadDelimitedText( netname_buffer, netname_buffer, 1024 ); + m_Netname = CONV_FROM_UTF8( netname_buffer ); + } + } + if( strnicmp( Line, "ZLayer", 6 ) == 0 ) // layer found { - int x = 0; - text = Line + 6; - ret = sscanf( text, "%d", &x); - if (ret < 1 ) error = true; - else m_Layer = x; - } - if( strnicmp(Line, "ZAux", 4 ) == 0 ) // aux info found + int x = 0; + text = Line + 6; + ret = sscanf( text, "%d", &x ); + if( ret < 1 ) + error = true; + else + m_Layer = x; + } + if( strnicmp( Line, "ZAux", 4 ) == 0 ) // aux info found { - int x = 0; - char hopt[10]; - text = Line + 4; - ret = sscanf( text, "%d %c", &x, hopt ); - if (ret < 2 ) error = true; - else - { - n_corner_item = x; - switch ( hopt[0] ) - { - case 'n': - case 'N': - outline_hatch = CPolyLine::NO_HATCH; - break; - case 'e': - case 'E': - outline_hatch = CPolyLine::DIAGONAL_EDGE; - break; - case 'f': - case 'F': - outline_hatch = CPolyLine::DIAGONAL_FULL; - break; - } - } - } - if( strnicmp(Line, "$end", 4 ) == 0 ) // end of description + int x = 0; + char hopt[10]; + text = Line + 4; + ret = sscanf( text, "%d %c", &x, hopt ); + if( ret < 2 ) + error = true; + else + { + n_corner_item = x; + + switch( hopt[0] ) + { + case 'n': + case 'N': + outline_hatch = CPolyLine::NO_HATCH; + break; + + case 'e': + case 'E': + outline_hatch = CPolyLine::DIAGONAL_EDGE; + break; + + case 'f': + case 'F': + outline_hatch = CPolyLine::DIAGONAL_FULL; + break; + } + } + } + if( strnicmp( Line, "$end", 4 ) == 0 ) // end of description { - break; - } - } - - return error ? 0 : 1; + break; + } + } + + return error ? 0 : 1; } @@ -285,7 +245,10 @@ void ZONE_CONTAINER::Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& off * @param draw_mode = draw mode: OR, XOR .. */ { - if ( DC == NULL ) return; + if( DC == NULL ) + return; + + wxPoint seg_start, seg_end; int curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer; int color = g_DesignSettings.m_LayerColor[m_Layer]; @@ -315,38 +278,101 @@ void ZONE_CONTAINER::Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& off // draw the lines int i_start_contour = 0; - for( unsigned ic = 0; ic < m_Poly->corner.size(); ic++ ) + for( int ic = 0; ic < GetNumCorners(); ic++ ) { - int xi = m_Poly->corner[ic].x + offset.x; - int yi = m_Poly->corner[ic].y + offset.y; - int xf, yf; - if( m_Poly->corner[ic].end_contour == FALSE && ic < m_Poly->corner.size() - 1 ) + seg_start = GetCornerPosition(ic) + offset; + if( m_Poly->corner[ic].end_contour == FALSE && ic < GetNumCorners() - 1 ) { - xf = m_Poly->corner[ic + 1].x + offset.x; - yf = m_Poly->corner[ic + 1].y + offset.y; + seg_end = GetCornerPosition(ic + 1) + offset; } else { - xf = m_Poly->corner[i_start_contour].x + offset.x; - yf = m_Poly->corner[i_start_contour].y + offset.y; + seg_end = GetCornerPosition(i_start_contour) + offset; i_start_contour = ic + 1; } - GRLine( &panel->m_ClipBox, DC, xi, yi, xf, yf, 0, color ); + GRLine( &panel->m_ClipBox, DC, seg_start.x, seg_start.y, seg_end.x, seg_end.y, 0, color ); } - - // draw hatches + + // draw hatches for( unsigned ic = 0; ic < m_Poly->m_HatchLines.size(); ic++ ) { int xi = m_Poly->m_HatchLines[ic].xi + offset.x; int yi = m_Poly->m_HatchLines[ic].yi + offset.y; int xf = m_Poly->m_HatchLines[ic].xf + offset.x; - int yf =m_Poly->m_HatchLines[ic].yf + offset.y; + int yf = m_Poly->m_HatchLines[ic].yf + offset.y; GRLine( &panel->m_ClipBox, DC, xi, yi, xf, yf, 0, color ); } - } +/**********************************************************************************************/ +void ZONE_CONTAINER::DrawWhileCreateOutline( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode ) +/***********************************************************************************************/ +/** + * Function DrawWhileCreateOutline + * Draws the zone outline when ir is created. + * The moving edges (last segment and the closing edge segment) are in XOR graphic mode, + * old segment in OR graphic mode + * The closing edge has its owm shape + * @param panel = current Draw Panel + * @param DC = current Device Context + * @param draw_mode = draw mode: OR, XOR .. + */ +{ + int current_gr_mode = draw_mode; + bool is_close_segment = false; + wxPoint seg_start, seg_end; + + if( DC == NULL ) + return; + int curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer; + int color = g_DesignSettings.m_LayerColor[m_Layer] & MASKCOLOR; + + if( DisplayOpt.ContrastModeDisplay ) + { + if( !IsOnLayer( curr_layer ) ) + { + color &= ~MASKCOLOR; + color |= DARKDARKGRAY; + } + } + + + // draw the lines + wxPoint start_contour_pos = GetCornerPosition(0); + for( int ic = 0; ic < GetNumCorners(); ic++ ) + { + int xi = GetCornerPosition(ic).x; + int yi = GetCornerPosition(ic).y; + int xf, yf; + if( m_Poly->corner[ic].end_contour == FALSE && ic < GetNumCorners() - 1 ) + { + is_close_segment = false; + xf = GetCornerPosition(ic + 1).x; + yf = GetCornerPosition(ic + 1).y; + if ( (m_Poly->corner[ic + 1].end_contour) || (ic == GetNumCorners() - 2) ) + current_gr_mode = GR_XOR; + else + current_gr_mode = draw_mode; + } + else + { + is_close_segment = true; + current_gr_mode = GR_XOR; + xf = start_contour_pos.x; + yf = start_contour_pos.y; + start_contour_pos = GetCornerPosition(ic + 1); + } + GRSetDrawMode( DC, current_gr_mode ); + if ( is_close_segment ) + GRLine( &panel->m_ClipBox, DC, xi, yi, xf, yf, 0, WHITE ); + else + GRLine( &panel->m_ClipBox, DC, xi, yi, xf, yf, 0, color ); + } +} + + + /** * Function HitTest * tests if the given wxPoint is within the bounds of this object. @@ -375,29 +401,31 @@ bool ZONE_CONTAINER::HitTest( const wxPoint& refPos ) */ int ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos ) { - #define CORNER_MIN_DIST 500 // distance (in internal units) to detect a corner in a zone outline - int dist, min_dist; - unsigned item_pos, lim; - lim = m_Poly->corner.size(); - m_CornerSelection = -1; - - min_dist = CORNER_MIN_DIST; - 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 ) - { - m_CornerSelection = item_pos; - min_dist = dist; - } - } + #define CORNER_MIN_DIST 500 // distance (in internal units) to detect a corner in a zone outline + int dist, min_dist; + unsigned item_pos, lim; + lim = m_Poly->corner.size(); + m_CornerSelection = -1; - if ( m_CornerSelection >= 0 ) - return item_pos; + min_dist = CORNER_MIN_DIST; + 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 ) + { + m_CornerSelection = item_pos; + min_dist = dist; + } + } + + if( m_CornerSelection >= 0 ) + return item_pos; return -1; } + /** * Function HitTestForEdge * tests if the given wxPoint near a corner, or near the segment define by 2 corners. @@ -408,61 +436,63 @@ int ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos ) */ int ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) { - #define EDGE_MIN_DIST 200 // distance (in internal units) to detect a zone outline - int dist, min_dist; - unsigned item_pos, lim; - lim = m_Poly->corner.size(); + #define EDGE_MIN_DIST 200 // distance (in internal units) to detect a zone outline + int dist, min_dist; + unsigned item_pos, lim; + lim = m_Poly->corner.size(); /* Test for an entire segment */ unsigned first_corner_pos = 0, end_segm; - m_CornerSelection = -1; - min_dist = EDGE_MIN_DIST; + m_CornerSelection = -1; + min_dist = EDGE_MIN_DIST; - for ( item_pos = 0; item_pos < lim; item_pos++ ) - { - end_segm = item_pos+1; - /* the last corner of the current outline is tested - * the last segment of the current outline starts at current corner, and ends - * at the first corner of the outline - */ - if( m_Poly->corner[item_pos].end_contour || end_segm >= lim) - { - unsigned tmp = first_corner_pos; - first_corner_pos = end_segm; // first_corner_pos is now the beginning of the next outline - end_segm = tmp; // end_segm is the beginning of the current outline - } + for( item_pos = 0; item_pos < lim; item_pos++ ) + { + end_segm = item_pos + 1; - /* test the dist between segment and ref point */ - dist = (int) GetPointToLineSegmentDistance( refPos.x, - refPos.y, - m_Poly->corner[item_pos].x, - m_Poly->corner[item_pos].y, - m_Poly->corner[end_segm].x, - m_Poly->corner[end_segm].y ); - if( dist <= min_dist ) - { - m_CornerSelection = item_pos; - min_dist = dist; - } - } + /* the last corner of the current outline is tested + * the last segment of the current outline starts at current corner, and ends + * at the first corner of the outline + */ + if( m_Poly->corner[item_pos].end_contour || end_segm >= lim ) + { + unsigned tmp = first_corner_pos; + first_corner_pos = end_segm; // first_corner_pos is now the beginning of the next outline + end_segm = tmp; // end_segm is the beginning of the current outline + } - if ( m_CornerSelection >= 0 ) - return item_pos; + /* test the dist between segment and ref point */ + dist = (int) GetPointToLineSegmentDistance( refPos.x, + refPos.y, + m_Poly->corner[item_pos].x, + m_Poly->corner[item_pos].y, + m_Poly->corner[end_segm].x, + m_Poly->corner[end_segm].y ); + if( dist <= min_dist ) + { + m_CornerSelection = item_pos; + min_dist = dist; + } + } + + if( m_CornerSelection >= 0 ) + return item_pos; return -1; } + /** * Function HitTest (overlayed) * tests if the given EDA_Rect contains the bounds of this object. * @param refArea : the given EDA_Rect * @return bool - true if a hit, else false */ -bool ZONE_CONTAINER::HitTest( EDA_Rect& refArea ) +bool ZONE_CONTAINER::HitTest( EDA_Rect& refArea ) { - bool is_out_of_box = false; + bool is_out_of_box = false; - CRect rect = m_Poly->GetCornerBounds(); + CRect rect = m_Poly->GetCornerBounds(); if( rect.left < refArea.GetX() ) is_out_of_box = true; @@ -476,97 +506,102 @@ bool ZONE_CONTAINER::HitTest( EDA_Rect& refArea ) return is_out_of_box ? false : true; } + /************************************************************/ void ZONE_CONTAINER::Display_Infos( WinEDA_DrawFrame* frame ) /************************************************************/ { wxString msg; int text_pos; - + frame->MsgPanel->EraseMsgBox(); - msg = _( "Zone Outline" ); + msg = _( "Zone Outline" ); - int ncont = m_Poly->GetContour(m_CornerSelection); - if ( ncont ) msg << wxT(" ") << _("(Cutout)"); + int ncont = m_Poly->GetContour( m_CornerSelection ); + if( ncont ) + msg << wxT( " " ) << _( "(Cutout)" ); text_pos = 1; Affiche_1_Parametre( frame, text_pos, _( "Type" ), msg, DARKCYAN ); text_pos += 15; - - if ( GetNet() >= 0 ) - { - EQUIPOT* equipot = ( (WinEDA_PcbFrame*) frame )->m_Pcb->FindNet( GetNet() ); - if( equipot ) - msg = equipot->m_Netname; - else - msg = wxT( "" ); - } - else // a netcode <à is an error - { - msg = wxT( " [" ); - msg << m_Netname + wxT( "]" ); - msg << wxT(" <") << _("Not Found") << wxT(">"); - } + if( GetNet() >= 0 ) + { + EQUIPOT* equipot = ( (WinEDA_PcbFrame*) frame )->m_Pcb->FindNet( GetNet() ); - Affiche_1_Parametre( frame, text_pos, _( "NetName" ), msg, RED ); + if( equipot ) + msg = equipot->m_Netname; + else + msg = wxT( "" ); + } + else // a netcode <à is an error + { + msg = wxT( " [" ); + msg << m_Netname + wxT( "]" ); + msg << wxT( " <" ) << _( "Not Found" ) << wxT( ">" ); + } - /* Display net code : (usefull in test or debug) */ - text_pos += 18; - msg.Printf( wxT( "%d" ), GetNet()); - Affiche_1_Parametre( frame, text_pos, _( "NetCode" ), msg, RED ); + Affiche_1_Parametre( frame, text_pos, _( "NetName" ), msg, RED ); + + /* Display net code : (usefull in test or debug) */ + text_pos += 18; + msg.Printf( wxT( "%d" ), GetNet() ); + Affiche_1_Parametre( frame, text_pos, _( "NetCode" ), msg, RED ); text_pos += 8; - msg = ReturnPcbLayerName( m_Layer ); + msg = ReturnPcbLayerName( m_Layer ); Affiche_1_Parametre( frame, text_pos, _( "Layer" ), msg, BROWN ); text_pos += 8; - msg.Printf( wxT( "%d" ), m_Poly->corner.size() ); + msg.Printf( wxT( "%d" ), m_Poly->corner.size() ); Affiche_1_Parametre( frame, text_pos, _( "Corners" ), msg, BLUE ); text_pos += 8; - msg.Printf( wxT( "%d" ), m_Poly->m_HatchLines.size() ); + msg.Printf( wxT( "%d" ), m_Poly->m_HatchLines.size() ); Affiche_1_Parametre( frame, text_pos, _( "Hatch lines" ), msg, BLUE ); } /* Geometric transformations: */ + /** * Function Move * Move the outlines * @param offset = moving vector */ -void ZONE_CONTAINER::Move(const wxPoint& offset ) +void ZONE_CONTAINER::Move( const wxPoint& offset ) { - for ( unsigned ii = 0; ii < m_Poly->corner.size(); ii++ ) - { - m_Poly->corner[ii].x += offset.x; - m_Poly->corner[ii].y += offset.y; - } - m_Poly->Hatch(); + for( unsigned ii = 0; ii < m_Poly->corner.size(); ii++ ) + { + m_Poly->corner[ii].x += offset.x; + m_Poly->corner[ii].y += offset.y; + } + + m_Poly->Hatch(); } + /** * Function Move * Move the outlines * @param centre = rot centre * @param angle = in 0.1 degree */ -void ZONE_CONTAINER::Rotate( const wxPoint& centre, int angle) +void ZONE_CONTAINER::Rotate( const wxPoint& centre, int angle ) { - for ( unsigned ii = 0; ii < m_Poly->corner.size(); ii++ ) - { - wxPoint pos; - pos.x = m_Poly->corner[ii].x; - pos.y = m_Poly->corner[ii].y; - RotatePoint(&pos, centre, angle ); - m_Poly->corner[ii].x = pos.x; - m_Poly->corner[ii].y = pos.y; - } - - m_Poly->Hatch(); + for( unsigned ii = 0; ii < m_Poly->corner.size(); ii++ ) + { + wxPoint pos; + pos.x = m_Poly->corner[ii].x; + pos.y = m_Poly->corner[ii].y; + RotatePoint( &pos, centre, angle ); + m_Poly->corner[ii].x = pos.x; + m_Poly->corner[ii].y = pos.y; + } + + m_Poly->Hatch(); } @@ -575,15 +610,16 @@ void ZONE_CONTAINER::Rotate( const wxPoint& centre, int angle) * flip the outlines , relative to a given horizontal axis * @param mirror_ref = vertical axis position */ -void ZONE_CONTAINER::Mirror( const wxPoint& mirror_ref) +void ZONE_CONTAINER::Mirror( const wxPoint& mirror_ref ) { - for ( unsigned ii = 0; ii < m_Poly->corner.size(); ii++ ) - { - m_Poly->corner[ii].y -= mirror_ref.y; - m_Poly->corner[ii].y = - m_Poly->corner[ii].y; - m_Poly->corner[ii].y += mirror_ref.y; - } - m_Poly->Hatch(); + for( unsigned ii = 0; ii < m_Poly->corner.size(); ii++ ) + { + m_Poly->corner[ii].y -= mirror_ref.y; + m_Poly->corner[ii].y = -m_Poly->corner[ii].y; + m_Poly->corner[ii].y += mirror_ref.y; + } + + m_Poly->Hatch(); } @@ -591,18 +627,16 @@ void ZONE_CONTAINER::Mirror( const wxPoint& mirror_ref) * copy usefull data from the source. * flags and linked list pointers are NOT copied */ -void ZONE_CONTAINER::Copy( ZONE_CONTAINER * src ) +void ZONE_CONTAINER::Copy( ZONE_CONTAINER* src ) { - m_Parent = src->m_Parent; - m_Layer = src->m_Layer; - SetNet(src->GetNet()); - m_TimeStamp = src->m_TimeStamp; - m_Poly->Copy(src->m_Poly); // copy outlines - m_CornerSelection = -1; // For corner moving, corner index to drag, or -1 if no selection - m_ZoneClearance = src->m_ZoneClearance; // clearance value - m_GridFillValue = src->m_GridFillValue; // Grid used for filling - m_PadOption = src->m_PadOption; - m_Poly->SetHatch(src->m_Poly->GetHatchStyle()); + m_Parent = src->m_Parent; + m_Layer = src->m_Layer; + SetNet( src->GetNet() ); + m_TimeStamp = src->m_TimeStamp; + m_Poly->Copy( src->m_Poly ); // copy outlines + m_CornerSelection = -1; // For corner moving, corner index to drag, or -1 if no selection + m_ZoneClearance = src->m_ZoneClearance; // clearance value + m_GridFillValue = src->m_GridFillValue; // Grid used for filling + m_PadOption = src->m_PadOption; + m_Poly->SetHatch( src->m_Poly->GetHatchStyle() ); } - - diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index 6098c48707..84ea1ba203 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -73,6 +73,19 @@ public: void Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& offset, int draw_mode ); + + /** + * Function DrawWhileCreateOutline + * Draws the zone outline when ir is created. + * The moving edges are in XOR graphic mode, old segment in draw_mode graphic mode (usually GR_OR) + * The closing edge has its owm shape + * @param panel = current Draw Panel + * @param DC = current Device Context + * @param draw_mode = draw mode: OR, XOR .. + */ + void DrawWhileCreateOutline( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode = GR_OR ); + + int GetNet( void ) const { return m_NetCode; @@ -158,73 +171,36 @@ public: { return wxT( "ZONE_CONTAINER" ); } + + /** Acces to m_Poly parameters + */ + + int GetNumCorners(void) + { + return m_Poly->GetNumCorners(); + } + + void RemoveAllContours(void) + { + m_Poly->RemoveAllContours(); + } + + wxPoint GetCornerPosition(int aCornerIndex) + { + return wxPoint(m_Poly->GetX(aCornerIndex), m_Poly->GetY(aCornerIndex)); + } + + void SetCornerPosition(int aCornerIndex, wxPoint new_pos) + { + m_Poly->SetX(aCornerIndex, new_pos.x); + m_Poly->SetY(aCornerIndex, new_pos.y); + } + + void AppendCorner( wxPoint position ) + { + m_Poly->AppendCorner( position.x, position.y ); + } }; -/*******************/ -/* 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 * 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. - * @param aFile The FILE to write to. - * @return bool - true if success writing else false. - */ - bool Save( FILE* aFile ) const; - - /** - * Function GetClass - * returns the class name. - * @return wxString - */ - wxString GetClass() const - { - return wxT( "EDGE_ZONE" ); - } -}; - #endif // #ifndef CLASS_ZONE_H diff --git a/pcbnew/drc.cpp b/pcbnew/drc.cpp index bdf7705552..428047c41e 100644 --- a/pcbnew/drc.cpp +++ b/pcbnew/drc.cpp @@ -157,22 +157,23 @@ int DRC::Drc( TRACK* aRefSegm, TRACK* aList ) } -/*********************************************/ -int DRC::Drc( const EDGE_ZONE* aEdge ) -/*********************************************/ +/**************************************************************/ +int DRC::Drc( ZONE_CONTAINER * aArea, int CornerIndex ) +/*************************************************************/ /** * Function Drc - * tests the current EDGE_ZONE segment and returns the result and displays the error + * tests the outline segment starting at CornerIndex 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. + * @param aEdge The areaparent which contains the corner. + * @param CornerIndex The starting point of the segment to test. * @return int - BAD_DRC (1) if DRC error or OK_DRC (0) if OK */ { updatePointers(); - if( ! doEdgeZoneDrc( aEdge ) ) + if( ! doEdgeZoneDrc( aArea, CornerIndex ) ) { wxASSERT( m_currentMarker ); m_currentMarker->Display_Infos( m_mainWindow ); @@ -461,9 +462,10 @@ MARKER* DRC::fillMarker( ZONE_CONTAINER * aArea, int aErrorCode, MARKER* fillMe return fillMe; } -MARKER* DRC::fillMarker( const EDGE_ZONE * aEdge, const wxPoint & aPos, int aErrorCode, MARKER* fillMe ) + +MARKER* DRC::fillMarker( const ZONE_CONTAINER * aArea, const wxPoint & aPos, int aErrorCode, MARKER* fillMe ) { - wxString textA = aEdge->MenuText( m_pcb ); + wxString textA = aArea->MenuText( m_pcb ); wxPoint posA = aPos; diff --git a/pcbnew/drc_stuff.h b/pcbnew/drc_stuff.h index fbd40eb60b..7945d24646 100644 --- a/pcbnew/drc_stuff.h +++ b/pcbnew/drc_stuff.h @@ -373,7 +373,7 @@ private: * @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 ); + MARKER* fillMarker( const ZONE_CONTAINER * aArea, const wxPoint & aPos, int aErrorCode, MARKER* fillMe ); //---------------------------------------------- @@ -413,14 +413,15 @@ private: /** * Function doEdgeZoneDrc - * tests the current EDGE_ZONE segment: + * tests a segment in ZONE_CONTAINER * aArea: * Test Edge inside other areas * Test Edge too close other areas - * @param aEdge The current segment to test. + * @param aArea The current area. + * @param aCornerIndex The first corner of the segment to test. * @return bool - false if DRC error or true if OK */ - bool doEdgeZoneDrc( const EDGE_ZONE* aEdge ); + bool doEdgeZoneDrc( ZONE_CONTAINER * aArea, int aCornerIndex ); //--------------------------------------------------- @@ -496,14 +497,15 @@ public: /** * Function Drc - * tests the current EDGE_ZONE segment and returns the result and displays the error + * tests the outline segment starting at CornerIndex 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. + * @param aEdge The areaparent which contains the corner. + * @param CornerIndex The starting point of the segment to test. * @return int - BAD_DRC (1) if DRC error or OK_DRC (0) if OK */ - int Drc( const EDGE_ZONE* aEdge ); + int Drc( ZONE_CONTAINER * aArea, int CornerIndex ); /** * Function DrcBlind diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index 7e71e4d457..812a125b67 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -267,7 +267,6 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event ) SetToolID( id, wxCURSOR_PENCIL, _( "Add Zones" ) ); if( !DisplayOpt.DisplayZones ) DisplayInfo( this, _( "Warning: Display Zone is OFF!!!" ) ); - DelLimitesZone( &dc, TRUE ); if( !g_HightLigt_Status && (g_HightLigth_NetCode > 0 ) ) Hight_Light( &dc ); break; @@ -821,7 +820,8 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event ) DrawPanel->MouseToCursorSchema(); if( GetCurItem() && (GetCurItem()->m_Flags & IS_NEW) ) { - SetCurItem( Del_LastSegmEdgeZone( &dc ) ); + if ( Delete_LastCreatedCorner( &dc ) == 0) // No more segment in outline, + SetCurItem(NULL); } break; diff --git a/pcbnew/initpcb.cpp b/pcbnew/initpcb.cpp index fa01148717..5a31ac2fec 100644 --- a/pcbnew/initpcb.cpp +++ b/pcbnew/initpcb.cpp @@ -145,8 +145,6 @@ bool WinEDA_BasePcbFrame::Clear_Pcb( bool query ) m_Pcb->m_Zone = NULL; m_Pcb->m_NbSegmZone = 0; - DelLimitesZone( NULL, FALSE ); - m_Pcb->DeleteMARKERs(); m_Pcb->DeleteZONEOutlines(); @@ -222,7 +220,6 @@ void WinEDA_PcbFrame::Erase_Zones( bool query ) m_Pcb->m_NbSegmZone = 0; } - DelLimitesZone( NULL, FALSE ); m_Pcb->DeleteZONEOutlines(); GetScreen()->SetModify(); diff --git a/pcbnew/onleftclick.cpp b/pcbnew/onleftclick.cpp index 4aca41f09a..b4b697162e 100644 --- a/pcbnew/onleftclick.cpp +++ b/pcbnew/onleftclick.cpp @@ -39,7 +39,10 @@ void WinEDA_PcbFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos ) switch( DrawStruct->Type() ) { case TYPEZONE_CONTAINER: - End_Move_Zone_Corner_Or_Outlines( DC, (ZONE_CONTAINER *) DrawStruct ); + if ( (DrawStruct->m_Flags & IS_NEW) ) + Begin_Zone( DC ); + else + End_Move_Zone_Corner_Or_Outlines( DC, (ZONE_CONTAINER *) DrawStruct ); exit = true; break; @@ -220,13 +223,19 @@ void WinEDA_PcbFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos ) case ID_PCB_ZONES_BUTT: if( (DrawStruct == NULL) || (DrawStruct->m_Flags == 0) ) { - GetScreen()->SetCurItem( DrawStruct = Begin_Zone( DC ) ); + if ( Begin_Zone( DC ) ) + { + DrawStruct = m_Pcb->m_CurrentZoneContour; + GetScreen()->SetCurItem( DrawStruct ); + } } else if( DrawStruct - && (DrawStruct->Type() == TYPEEDGEZONE) + && (DrawStruct->Type() == TYPEZONE_CONTAINER) && (DrawStruct->m_Flags & IS_NEW) ) { - GetScreen()->SetCurItem( DrawStruct = Begin_Zone( DC ) ); + Begin_Zone( DC ); + DrawStruct = m_Pcb->m_CurrentZoneContour; + GetScreen()->SetCurItem( DrawStruct ); } else DisplayError( this, wxT( "Edit: zone internal error" ) ); diff --git a/pcbnew/onrightclick.cpp b/pcbnew/onrightclick.cpp index 4bb0cc4d07..6dccf22e0c 100644 --- a/pcbnew/onrightclick.cpp +++ b/pcbnew/onrightclick.cpp @@ -277,25 +277,23 @@ bool WinEDA_PcbFrame::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu ) case TYPEZONE: // Item used to fill a zone ADD_MENUITEM( aPopMenu, ID_POPUP_PCB_DELETE_ZONE, - _( "Delete Zone" ), delete_xpm ); - break; - - case TYPEEDGEZONE: // Graphic Item used to create a new zone outline - if( flags & IS_NEW ) - { - ADD_MENUITEM( aPopMenu, ID_POPUP_PCB_STOP_CURRENT_EDGE_ZONE, - _( "End edge zone" ), apply_xpm ); - } - ADD_MENUITEM( aPopMenu, ID_POPUP_PCB_DELETE_ZONE_LAST_CREATED_CORNER, - _( "Delete Current Edge" ), delete_xpm ); + _( "Delete Zone Filling" ), delete_xpm ); break; case TYPEZONE_CONTAINER: // Item used to handle a zone area (outlines, holes ...) + if( flags & IS_NEW ) + { + ADD_MENUITEM( aPopMenu, ID_POPUP_PCB_STOP_CURRENT_EDGE_ZONE, + _( "Close Zone Outline" ), apply_xpm ); + ADD_MENUITEM( aPopMenu, ID_POPUP_PCB_DELETE_ZONE_LAST_CREATED_CORNER, + _( "Delete Last Corner" ), delete_xpm ); + } + else createPopUpMenuForZones( (ZONE_CONTAINER*) item, aPopMenu ); break; case TYPETEXTE: - createPopUpMenuForTexts( (TEXTE_PCB*) item, aPopMenu ); + createPopUpMenuForTexts( (TEXTE_PCB*) item, aPopMenu ); break; case TYPETRACK: diff --git a/pcbnew/tracepcb.cpp b/pcbnew/tracepcb.cpp index 1c13331537..1c7af21c8d 100644 --- a/pcbnew/tracepcb.cpp +++ b/pcbnew/tracepcb.cpp @@ -176,18 +176,10 @@ void WinEDA_PcbFrame::Trace_Pcb( wxDC* DC, int mode ) if( g_HightLigt_Status ) DrawHightLight( DC, g_HightLigth_NetCode ); - EDGE_ZONE* segment; - for( segment = m_Pcb->m_CurrentLimitZone; segment; segment = segment->Next() ) - { - if( segment->m_Flags & IS_MOVED ) - continue; - - Trace_DrawSegmentPcb( DrawPanel, DC, segment, mode ); - } - for( unsigned ii = 0; ii < m_Pcb->m_ZoneDescriptorList.size(); ii++ ) + for( unsigned ii = 0; ii < m_Pcb->GetAreaCount(); ii++ ) { - ZONE_CONTAINER* edge_zone = m_Pcb->m_ZoneDescriptorList[ii]; + ZONE_CONTAINER* edge_zone = m_Pcb->GetArea(ii); edge_zone->Draw( DrawPanel, DC, wxPoint(0,0), mode); } diff --git a/pcbnew/zone_filling_algorithm.cpp b/pcbnew/zone_filling_algorithm.cpp index 438bad27fd..55d1592010 100644 --- a/pcbnew/zone_filling_algorithm.cpp +++ b/pcbnew/zone_filling_algorithm.cpp @@ -196,7 +196,12 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose ) if( cells_count == 0 ) { if( verbose ) - DisplayError( frame, _( "No pads or starting point found to fill this zone outline" ) ); + { + msg = _( "No pads or starting point found to fill this zone outline" ); + msg << wxT("\n"); + msg << MenuText( frame->m_Pcb ); + DisplayError( frame, msg ); + } error_level = 2; goto end_of_zone_fill; } diff --git a/pcbnew/zones_by_polygon.cpp b/pcbnew/zones_by_polygon.cpp index d338589ff8..4b4588ac2a 100644 --- a/pcbnew/zones_by_polygon.cpp +++ b/pcbnew/zones_by_polygon.cpp @@ -1,4 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// + // Name: zones_by_polygon.cpp // Licence: GPL License ///////////////////////////////////////////////////////////////////////////// @@ -32,7 +33,7 @@ using namespace std; #include "protos.h" -bool verbose = false; // false if zone outline diags mst not be shown +bool verbose = false; // false if zone outline diags mst not be shown // Outline creation: static void Abort_Zone_Create_Outline( WinEDA_DrawPanel* Panel, wxDC* DC ); @@ -40,7 +41,9 @@ static void Show_New_Zone_Edge_While_Move_Mouse( WinEDA_DrawPanel* panel, wxDC* // Corner moving static void Abort_Zone_Move_Corner_Or_Outlines( WinEDA_DrawPanel* Panel, wxDC* DC ); -static void Show_Zone_Corner_Or_Outline_While_Move_Mouse( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ); +static void Show_Zone_Corner_Or_Outline_While_Move_Mouse( WinEDA_DrawPanel* panel, + wxDC* DC, + bool erase ); /* Local variables */ static bool Zone_45_Only = FALSE; @@ -52,11 +55,11 @@ static wxPoint s_CornerInitialPosition; // Used to abort static bool s_CornerIsNew; // Used to abort a move corner command (if it is a new corner, it must be deleted) static bool s_AddCutoutToCurrentZone; // if true, the next outline will be addes to s_CurrentZone static ZONE_CONTAINER* s_CurrentZone; // if != NULL, these ZONE_CONTAINER params will be used for the next zone -static wxPoint s_CursorLastPosition; // in move zone outline, last cursor position. Used to calculate the move vector +static wxPoint s_CursorLastPosition; // in move zone outline, last cursor position. Used to calculate the move vector // keys used to store net sort option in config file : #define ZONE_NET_OUTLINES_HATCH_OPTION_KEY wxT( "Zone_Ouline_Hatch_Opt" ) -#define ZONE_NET_SORT_OPTION_KEY wxT( "Zone_NetSort_Opt" ) -#define ZONE_NET_FILTER_STRING_KEY wxT( "Zone_Filter_Opt" ) +#define ZONE_NET_SORT_OPTION_KEY wxT( "Zone_NetSort_Opt" ) +#define ZONE_NET_FILTER_STRING_KEY wxT( "Zone_Filter_Opt" ) enum zone_cmd { ZONE_ABORT, @@ -149,31 +152,29 @@ void WinEDA_PcbFrame::Delete_Zone_Fill( wxDC* DC, SEGZONE* aZone, long aTimestam } -/*****************************************************************************/ -EDGE_ZONE* WinEDA_PcbFrame::Del_LastSegmEdgeZone( wxDC* DC) +/*******************************************************/ +int WinEDA_PcbFrame::Delete_LastCreatedCorner( wxDC* DC ) /*****************************************************************************/ -/* Used only while creating a new zone outline +/** Used only while creating a new zone outline * Remove and delete the current outline segment in progress + * @return 0 if no corner in list, or corner number + * if no corner in list, close the outline creation */ { - EDGE_ZONE* segm = m_Pcb->m_CurrentLimitZone; + ZONE_CONTAINER* zone = m_Pcb->m_CurrentZoneContour; - if( segm == NULL ) - return NULL; + if( zone == NULL ) + return 0; - Trace_DrawSegmentPcb( DrawPanel, DC, segm, GR_XOR ); + if( zone->GetNumCorners() == 0 ) + return 0; - m_Pcb->m_CurrentLimitZone = segm->Next(); - delete segm; + zone->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR ); - segm = m_Pcb->m_CurrentLimitZone; - SetCurItem( segm ); - - if( segm ) + if( zone->GetNumCorners() > 1 ) { - segm->Pback = NULL; - segm->m_Flags |= IS_NEW | IS_MOVED; + zone->m_Poly->DeleteCorner( zone->GetNumCorners() - 1 ); if( DrawPanel->ManageCurseur ) DrawPanel->ManageCurseur( DrawPanel, DC, TRUE ); } @@ -182,8 +183,9 @@ EDGE_ZONE* WinEDA_PcbFrame::Del_LastSegmEdgeZone( wxDC* DC) DrawPanel->ManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL; SetCurItem( NULL ); + zone->RemoveAllContours(); } - return segm; + return zone->GetNumCorners(); } @@ -197,14 +199,13 @@ static void Abort_Zone_Create_Outline( WinEDA_DrawPanel* Panel, wxDC* DC ) */ { WinEDA_PcbFrame* pcbframe = (WinEDA_PcbFrame*) Panel->m_Parent; + ZONE_CONTAINER* zone = pcbframe->m_Pcb->m_CurrentZoneContour; - if( pcbframe->m_Pcb->m_CurrentLimitZone ) + if( zone ) { - if( Panel->ManageCurseur ) // trace in progress - { - Panel->ManageCurseur( Panel, DC, 0 ); - } - pcbframe->DelLimitesZone( DC, TRUE ); + zone->DrawWhileCreateOutline( Panel, DC, GR_XOR ); + zone->m_Flags = 0; + zone->RemoveAllContours(); } Panel->ManageCurseur = NULL; @@ -215,36 +216,6 @@ static void Abort_Zone_Create_Outline( WinEDA_DrawPanel* Panel, wxDC* DC ) } -/**************************************************************/ -void WinEDA_BasePcbFrame::DelLimitesZone( wxDC* DC, bool Redraw ) -/**************************************************************/ -{ - EDGE_ZONE* segment; - EDGE_ZONE* next; - - if( m_Pcb->m_CurrentLimitZone == NULL ) - return; - - // erase the old zone outline, one segment at a time - for( segment = m_Pcb->m_CurrentLimitZone; segment; segment = next ) - { - next = segment->Next(); - - if( Redraw && DC ) - { - Trace_DrawSegmentPcb( DrawPanel, DC, segment, GR_OR ); - Trace_DrawSegmentPcb( DrawPanel, DC, segment, GR_XOR ); - } - - delete segment; - } - - m_Pcb->m_CurrentLimitZone = NULL; - - SetCurItem( NULL ); -} - - /*******************************************************************************************************/ void WinEDA_PcbFrame::Start_Move_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_container, int corner_id, bool IsNewCorner ) @@ -257,13 +228,14 @@ void WinEDA_PcbFrame::Start_Move_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_con */ { /* Show the Net */ - if( g_HightLigt_Status && DC) + if( g_HightLigt_Status && DC ) { Hight_Light( DC ); // Remove old hightlight selection } g_HightLigth_NetCode = s_NetcodeSelection = zone_container->GetNet(); - if ( DC ) Hight_Light( DC ); + if( DC ) + Hight_Light( DC ); zone_container->m_Flags = IN_EDIT; DrawPanel->ManageCurseur = Show_Zone_Corner_Or_Outline_While_Move_Mouse; @@ -275,6 +247,7 @@ void WinEDA_PcbFrame::Start_Move_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_con s_CurrentZone = NULL; } + /*******************************************************************************************************/ void WinEDA_PcbFrame::Start_Move_Zone_Outlines( wxDC* DC, ZONE_CONTAINER* zone_container ) /*******************************************************************************************************/ @@ -317,36 +290,38 @@ void WinEDA_PcbFrame::End_Move_Zone_Corner_Or_Outlines( wxDC* DC, ZONE_CONTAINER zone_container->m_Flags = 0; DrawPanel->ManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL; - if ( DC ) - zone_container->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR ); + if( DC ) + zone_container->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR ); GetScreen()->SetModify(); s_AddCutoutToCurrentZone = false; s_CurrentZone = NULL; - SetCurItem( NULL ); // This outine can be deleted when merging outlines + SetCurItem( NULL ); // This outline can be deleted when merging outlines /* Combine zones if possible */ - wxBusyCursor dummy; + wxBusyCursor dummy; - int layer = zone_container->GetLayer(); + int layer = zone_container->GetLayer(); - m_Pcb->RedrawAreasOutlines(DrawPanel, DC, GR_XOR, layer); + m_Pcb->RedrawAreasOutlines( DrawPanel, DC, GR_XOR, layer ); m_Pcb->AreaPolygonModified( zone_container, true, verbose ); - m_Pcb->RedrawAreasOutlines(DrawPanel, DC, GR_OR, layer); - - int ii = m_Pcb->GetAreaIndex(zone_container); // test if zone_container exists - if ( ii < 0 ) zone_container = NULL; // was removed by combining zones - int error_count = m_Pcb->Test_Drc_Areas_Outlines_To_Areas_Outlines(zone_container, true); - if ( error_count ) - { - DisplayError(this, _("Area: DRC outline error")); - } + m_Pcb->RedrawAreasOutlines( DrawPanel, DC, GR_OR, layer ); + + int ii = m_Pcb->GetAreaIndex( zone_container ); // test if zone_container exists + if( ii < 0 ) + zone_container = NULL; // was removed by combining zones + int error_count = m_Pcb->Test_Drc_Areas_Outlines_To_Areas_Outlines( zone_container, true ); + if( error_count ) + { + DisplayError( this, _( "Area: DRC outline error" ) ); + } } /*************************************************************************************/ -void WinEDA_PcbFrame::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER * zone_container ) +void WinEDA_PcbFrame::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_container ) /*************************************************************************************/ + /** * Function End_Move_Zone_Corner * Remove the currently selected corner in a zone outline @@ -355,31 +330,32 @@ void WinEDA_PcbFrame::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER * zone_contai { GetScreen()->SetModify(); - if ( zone_container->m_Poly->GetNumCorners() <= 3 ) - { - zone_container->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR ); - Delete_Zone_Fill( DC, NULL, zone_container->m_TimeStamp ); - m_Pcb->Delete( zone_container ); - return; - } + if( zone_container->m_Poly->GetNumCorners() <= 3 ) + { + zone_container->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR ); + Delete_Zone_Fill( DC, NULL, zone_container->m_TimeStamp ); + m_Pcb->Delete( zone_container ); + return; + } int layer = zone_container->GetLayer(); - m_Pcb->RedrawAreasOutlines(DrawPanel, DC, GR_XOR, layer); + m_Pcb->RedrawAreasOutlines( DrawPanel, DC, GR_XOR, layer ); - zone_container->m_Poly->DeleteCorner(zone_container->m_CornerSelection); - - // modify zones outlines according to the new zone_container shape + zone_container->m_Poly->DeleteCorner( zone_container->m_CornerSelection ); + + // modify zones outlines according to the new zone_container shape m_Pcb->AreaPolygonModified( zone_container, true, verbose ); - m_Pcb->RedrawAreasOutlines(DrawPanel, DC, GR_OR, layer); + m_Pcb->RedrawAreasOutlines( DrawPanel, DC, GR_OR, layer ); - int ii = m_Pcb->GetAreaIndex(zone_container); // test if zone_container exists - if ( ii < 0 ) zone_container = NULL; // zone_container does not exist anymaore, after combining zones - int error_count = m_Pcb->Test_Drc_Areas_Outlines_To_Areas_Outlines(zone_container, true); - if ( error_count ) - { - DisplayError(this, _("Area: DRC outline error")); - } + int ii = m_Pcb->GetAreaIndex( zone_container ); // test if zone_container exists + if( ii < 0 ) + zone_container = NULL; // zone_container does not exist anymaore, after combining zones + int error_count = m_Pcb->Test_Drc_Areas_Outlines_To_Areas_Outlines( zone_container, true ); + if( error_count ) + { + DisplayError( this, _( "Area: DRC outline error" ) ); + } } @@ -397,24 +373,24 @@ void Abort_Zone_Move_Corner_Or_Outlines( WinEDA_DrawPanel* Panel, wxDC* DC ) zone_container->Draw( Panel, DC, wxPoint( 0, 0 ), GR_XOR ); - if ( zone_container->m_Flags == IS_MOVED ) - { - wxPoint offset; - offset = s_CornerInitialPosition - s_CursorLastPosition; - zone_container->Move(offset); - } - else - { - if( s_CornerIsNew ) - { - zone_container->m_Poly->DeleteCorner( zone_container->m_CornerSelection ); - } - else - { - wxPoint pos = s_CornerInitialPosition; - zone_container->m_Poly->MoveCorner( zone_container->m_CornerSelection, pos.x, pos.y ); - } - } + if( zone_container->m_Flags == IS_MOVED ) + { + wxPoint offset; + offset = s_CornerInitialPosition - s_CursorLastPosition; + zone_container->Move( offset ); + } + else + { + if( s_CornerIsNew ) + { + zone_container->m_Poly->DeleteCorner( zone_container->m_CornerSelection ); + } + else + { + wxPoint pos = s_CornerInitialPosition; + zone_container->m_Poly->MoveCorner( zone_container->m_CornerSelection, pos.x, pos.y ); + } + } zone_container->Draw( Panel, DC, wxPoint( 0, 0 ), GR_XOR ); Panel->ManageCurseur = NULL; @@ -436,29 +412,29 @@ void Show_Zone_Corner_Or_Outline_While_Move_Mouse( WinEDA_DrawPanel* Panel, wxDC WinEDA_PcbFrame* pcbframe = (WinEDA_PcbFrame*) Panel->m_Parent; ZONE_CONTAINER* zone_container = (ZONE_CONTAINER*) pcbframe->GetCurItem(); -// if( erase ) /* Undraw edge in old position*/ + if( erase ) /* Undraw edge in old position*/ { - zone_container->Draw( Panel, DC, wxPoint( 0, 0 ), GR_XOR ); + zone_container->Draw( Panel, DC, wxPoint(0,0), GR_XOR ); } wxPoint pos = pcbframe->GetScreen()->m_Curseur; - if( zone_container->m_Flags == IS_MOVED ) - { - wxPoint offset; - offset.x = pos.x - s_CursorLastPosition.x; - offset.y = pos.y - s_CursorLastPosition.y; - zone_container->Move(offset); - s_CursorLastPosition = pos; - } - else - zone_container->m_Poly->MoveCorner( zone_container->m_CornerSelection, pos.x, pos.y ); + if( zone_container->m_Flags == IS_MOVED ) + { + wxPoint offset; + offset.x = pos.x - s_CursorLastPosition.x; + offset.y = pos.y - s_CursorLastPosition.y; + zone_container->Move( offset ); + s_CursorLastPosition = pos; + } + else + zone_container->m_Poly->MoveCorner( zone_container->m_CornerSelection, pos.x, pos.y ); - zone_container->Draw( Panel, DC, wxPoint( 0, 0 ), GR_XOR ); + zone_container->Draw( Panel, DC, wxPoint(0,0), GR_XOR ); } /*************************************************/ -EDGE_ZONE* WinEDA_PcbFrame::Begin_Zone( wxDC* DC ) +int WinEDA_PcbFrame::Begin_Zone( wxDC* DC ) /*************************************************/ /** @@ -467,15 +443,12 @@ EDGE_ZONE* WinEDA_PcbFrame::Begin_Zone( wxDC* DC ) * intermediate segment. */ { - EDGE_ZONE* oldedge; - EDGE_ZONE* newedge = NULL; - // verify if s_CurrentZone exists: - int ii; + int ii; for( ii = 0; ii < m_Pcb->GetAreaCount(); ii++ ) { - if( s_CurrentZone == m_Pcb->GetArea(ii) ) + if( s_CurrentZone == m_Pcb->GetArea( ii ) ) break; } @@ -485,9 +458,12 @@ EDGE_ZONE* WinEDA_PcbFrame::Begin_Zone( wxDC* DC ) s_CurrentZone = NULL; } - oldedge = m_Pcb->m_CurrentLimitZone; + ZONE_CONTAINER* zone; + if( m_Pcb->m_CurrentZoneContour == NULL ) + m_Pcb->m_CurrentZoneContour = new ZONE_CONTAINER( m_Pcb ); - if( m_Pcb->m_CurrentLimitZone == NULL ) /* Start a new contour: init zone params (net and layer) */ + zone = m_Pcb->m_CurrentZoneContour; + if( zone->GetNumCorners() == 0 ) /* Start a new contour: init zone params (net and layer) */ { if( s_CurrentZone == NULL ) { @@ -500,11 +476,11 @@ EDGE_ZONE* WinEDA_PcbFrame::Begin_Zone( wxDC* DC ) DrawPanel->m_IgnoreMouseEvents = FALSE; if( diag == ZONE_ABORT ) - return NULL; - - GetScreen()->m_Active_Layer = s_Zone_Layer; // Set by the dialog frame + return 0; + + GetScreen()->m_Active_Layer = s_Zone_Layer; // Set by the dialog frame } - else /* Start a new contour: init zone params (net and layer) from an existing zone */ + else /* Start a new contour: init zone params (net and layer) from an existing zone */ { GetScreen()->m_Active_Layer = s_Zone_Layer = s_CurrentZone->GetLayer(); s_Zone_Hatching = s_CurrentZone->m_Poly->GetHatchStyle(); @@ -526,65 +502,51 @@ EDGE_ZONE* WinEDA_PcbFrame::Begin_Zone( wxDC* DC ) } // if first segment - if( (m_Pcb->m_CurrentLimitZone == NULL ) /* Initial start of a new outline */ - || (DrawPanel->ManageCurseur == NULL) ) /* reprise d'un trace complementaire */ + if( zone->GetNumCorners() == 0 ) { - newedge = new EDGE_ZONE( m_Pcb ); - 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; - // use the form of SetCurItem() which does not write to the msg panel, - // SCREEN::SetCurItem(), so the DRC error remains on screen. - // WinEDA_PcbFrame::SetCurItem() calls Display_Infos(). - GetScreen()->SetCurItem( NULL ); - DisplayError(this, _("DRC error: this start point is inside or too close an other area")); - return NULL; - } + zone->m_Flags = IS_NEW; + zone->SetLayer( s_Zone_Layer ); + zone->SetNet( s_NetcodeSelection ); + zone->m_TimeStamp = GetTimeStamp(); + zone->m_PadOption = s_Zone_Pad_Options; + zone->m_ZoneClearance = g_DesignSettings.m_ZoneClearence; + zone->m_GridFillValue = g_GridRoutingSize; + zone->m_Poly->Start( s_Zone_Layer, + GetScreen()->m_Curseur.x, GetScreen()->m_Curseur.y, + s_Zone_Hatching ); + zone->AppendCorner( GetScreen()->m_Curseur ); + if( Drc_On && m_drc->Drc( zone, 0 ) == BAD_DRC ) + { + zone->m_Flags = 0; + zone->RemoveAllContours(); - // link into list: - newedge->Pnext = oldedge; - SetCurItem( newedge ); - - if( oldedge ) - oldedge->Pback = newedge; - - m_Pcb->m_CurrentLimitZone = newedge; + // use the form of SetCurItem() which does not write to the msg panel, + // SCREEN::SetCurItem(), so the DRC error remains on screen. + // WinEDA_PcbFrame::SetCurItem() calls Display_Infos(). + GetScreen()->SetCurItem( NULL ); + DisplayError( this, + _( "DRC error: this start point is inside or too close an other area" ) ); + return 0; + } + SetCurItem( zone ); DrawPanel->ManageCurseur = Show_New_Zone_Edge_While_Move_Mouse; DrawPanel->ForceCloseManageCurseur = Abort_Zone_Create_Outline; } // edge in progress: else { - /* edge in progress : the ending point coordinate was set by Show_New_Zone_Edge_While_Move_Mouse */ - if( oldedge->m_Start != oldedge->m_End ) + ii = zone->GetNumCorners() - 1; + + /* edge in progress : the current corner coordinate was set by Show_New_Zone_Edge_While_Move_Mouse */ + if( zone->GetCornerPosition( ii - 1 ) != zone->GetCornerPosition( ii ) ) { - if ( Drc_On && m_drc->Drc( oldedge ) == BAD_DRC ) - { - return oldedge; - } - - oldedge->m_Flags &= ~(IS_NEW | IS_MOVED); - - newedge = new EDGE_ZONE( m_Pcb ); - newedge->m_Flags = IS_NEW | IS_MOVED; - newedge->m_Start = newedge->m_End = oldedge->m_End; - newedge->SetLayer( oldedge->GetLayer() ); - newedge->SetNet( s_NetcodeSelection ); - - // link into list: - newedge->Pnext = oldedge; - oldedge->Pback = newedge; - m_Pcb->m_CurrentLimitZone = newedge; - SetCurItem( newedge ); + if( Drc_On && m_drc->Drc( zone, ii - 1 ) == OK_DRC ) // Ok, we can add a new corner + zone->AppendCorner( GetScreen()->m_Curseur ); } } - return newedge; + return zone->GetNumCorners(); } @@ -600,127 +562,82 @@ bool WinEDA_PcbFrame::End_Zone( wxDC* DC ) * if ok, put it in the main list m_Pcb->m_ZoneDescriptorList (a vector) */ { - 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(); + ZONE_CONTAINER* zone = m_Pcb->m_CurrentZoneContour; - // 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; - } - } + if( zone == NULL ) + return true; - /* 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); - } + // Validate the curren outline: + if( zone->GetNumCorners() <= 2 ) // An outline must have 3 corners or more + { + Abort_Zone_Create_Outline( DrawPanel, DC ); + return true; + } - 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")); + // Validate the current edge: + int icorner = zone->GetNumCorners() - 1; + if( Drc_On && m_drc->Drc( zone, icorner - 1 ) == BAD_DRC ) // we can't validate last edge + return false; + if( Drc_On && m_drc->Drc( zone, icorner ) == BAD_DRC ) // we can't validate the closing edge + { + DisplayError( this, + _( "DRC error: closing this area creates a drc error with an other area" ) ); DrawPanel->MouseToCursorSchema(); - return false; - } + return false; + } - edge->m_Flags &= ~(IS_NEW | IS_MOVED); - Trace_DrawSegmentPcb( DrawPanel, DC, m_Pcb->m_CurrentLimitZone, GR_XOR ); + zone->m_Flags = 0; + + zone->DrawWhileCreateOutline( DrawPanel, DC, GR_XOR ); DrawPanel->ManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL; // Undraw old drawings, because they can have important changes - m_Pcb->RedrawAreasOutlines(DrawPanel, DC, GR_XOR, layer); + int layer = zone->GetLayer(); + m_Pcb->RedrawAreasOutlines( DrawPanel, DC, GR_XOR, layer ); /* Put edges in list */ - ZONE_CONTAINER* new_zone_container; if( s_CurrentZone == NULL ) { - new_zone_container = new ZONE_CONTAINER( m_Pcb ); - new_zone_container->SetLayer( layer ); - new_zone_container->SetNet( g_HightLigth_NetCode ); - new_zone_container->m_TimeStamp = GetTimeStamp(); - - edge = m_Pcb->m_CurrentLimitZone; - new_zone_container->m_Poly->Start( layer, 0, 0, - edge->m_Start.x, edge->m_Start.y, - s_Zone_Hatching ); - edge = edge->Next(); - while( edge ) - { - new_zone_container->m_Poly->AppendCorner( edge->m_Start.x, edge->m_Start.y ); - edge = edge->Next(); - } - - new_zone_container->m_Poly->Close(); // Close the current corner list - new_zone_container->m_Poly->SetHatch( s_Zone_Hatching ); - new_zone_container->m_PadOption = s_Zone_Pad_Options; - new_zone_container->m_ZoneClearance = g_DesignSettings.m_ZoneClearence; - new_zone_container->m_GridFillValue = g_GridRoutingSize; - - m_Pcb->m_ZoneDescriptorList.push_back( new_zone_container ); + zone->m_Poly->Close(); // Close the current corner list + m_Pcb->Add( zone ); + m_Pcb->m_CurrentZoneContour = NULL; } else // Append this outline as a cutout to an existing zone { - new_zone_container = s_CurrentZone; - edge = m_Pcb->m_CurrentLimitZone; - while( edge ) + for( int ii = 0; ii < zone->GetNumCorners(); ii++ ) { - new_zone_container->m_Poly->AppendCorner( edge->m_Start.x, edge->m_Start.y ); - edge = edge->Next(); + s_CurrentZone->AppendCorner( zone->GetCornerPosition( ii ) ); } - new_zone_container->m_Poly->Close(); // Close the current corner list + s_CurrentZone->m_Poly->Close(); // Close the current corner list + zone->RemoveAllContours(); // All corners are copied in s_CurrentZone. Free corner list. + zone = s_CurrentZone; } s_AddCutoutToCurrentZone = false; s_CurrentZone = NULL; - /* Remove the current temporary list */ - DelLimitesZone( DC, TRUE ); - - new_zone_container->m_Flags = 0; GetScreen()->SetCurItem( NULL ); // This outine can be deleted when merging outlines // Combine zones if possible : - m_Pcb->AreaPolygonModified( new_zone_container, true, verbose ); + m_Pcb->AreaPolygonModified( zone, true, verbose ); // Redraw the real edge zone : - m_Pcb->RedrawAreasOutlines(DrawPanel, DC, GR_OR, layer); + m_Pcb->RedrawAreasOutlines( DrawPanel, DC, GR_OR, layer ); - int ii = m_Pcb->GetAreaIndex(new_zone_container); // test if zone_container exists - if ( ii < 0 ) new_zone_container = NULL; // was removed by combining zones - int error_count = m_Pcb->Test_Drc_Areas_Outlines_To_Areas_Outlines(new_zone_container, true); - if ( error_count ) - { - DisplayError(this, _("Area: DRC outline error")); - } + int ii = m_Pcb->GetAreaIndex( zone ); // test if zone_container exists + if( ii < 0 ) + zone = NULL; // was removed by combining zones + int error_count = m_Pcb->Test_Drc_Areas_Outlines_To_Areas_Outlines( zone, true ); + if( error_count ) + { + DisplayError( this, _( "Area: DRC outline error" ) ); + } GetScreen()->SetModify(); - return true; + return true; } @@ -731,41 +648,32 @@ static void Show_New_Zone_Edge_While_Move_Mouse( WinEDA_DrawPanel* panel, wxDC* /* Redraws the edge zone when moving mouse */ { - EDGE_ZONE* edge; - EDGE_ZONE* currentEdge; WinEDA_PcbFrame* pcbframe = (WinEDA_PcbFrame*) panel->m_Parent; + wxPoint c_pos = pcbframe->GetScreen()->m_Curseur; + ZONE_CONTAINER* zone = pcbframe->m_Pcb->m_CurrentZoneContour; - if( pcbframe->m_Pcb->m_CurrentLimitZone == NULL ) + if( zone == NULL ) return; + int icorner = zone->GetNumCorners() - 1; + if( erase ) /* Undraw edge in old position*/ { - edge = pcbframe->m_Pcb->m_CurrentLimitZone; - - // for( ; edge; edge = edge->Next() ) - { - Trace_DrawSegmentPcb( panel, DC, edge, GR_XOR ); - } + zone->DrawWhileCreateOutline( panel, DC ); } /* Redraw the curent edge in its new position */ - currentEdge = pcbframe->m_Pcb->m_CurrentLimitZone; if( Zone_45_Only ) { // calculate the new position as allowed - currentEdge->m_End = pcbframe->GetScreen()->m_Curseur; - Calcule_Coord_Extremite_45( currentEdge->m_Start.x, currentEdge->m_Start.y, - ¤tEdge->m_End.x, ¤tEdge->m_End.y ); - } - else /* all orientations are allowed */ - { - currentEdge->m_End = pcbframe->GetScreen()->m_Curseur; + wxPoint StartPoint = zone->GetCornerPosition( icorner - 1 ); + Calcule_Coord_Extremite_45( StartPoint.x, StartPoint.y, + &c_pos.x, &c_pos.y ); } - // for( ; currentEdge; currentEdge = currentEdge->Next() ) - { - Trace_DrawSegmentPcb( panel, DC, currentEdge, GR_XOR ); - } + zone->SetCornerPosition( icorner, c_pos ); + + zone->DrawWhileCreateOutline( panel, DC ); } @@ -789,10 +697,10 @@ void WinEDA_PcbFrame::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* zone_container if( diag == ZONE_ABORT ) return; - // Undraw old zone outlines + // Undraw old zone outlines for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ ) { - ZONE_CONTAINER* edge_zone = m_Pcb->GetArea(ii); + ZONE_CONTAINER* edge_zone = m_Pcb->GetArea( ii ); edge_zone->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR ); } @@ -810,11 +718,12 @@ void WinEDA_PcbFrame::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* zone_container m_Pcb->AreaPolygonModified( zone_container, true, verbose ); // Redraw the real new zone outlines: - m_Pcb->RedrawAreasOutlines(DrawPanel, DC, GR_OR, -1); + m_Pcb->RedrawAreasOutlines( DrawPanel, DC, GR_OR, -1 ); GetScreen()->SetModify(); } + /************************************************************************************/ void WinEDA_PcbFrame::Delete_Zone_Contour( wxDC* DC, ZONE_CONTAINER* zone_container ) /************************************************************************************/ @@ -829,22 +738,22 @@ void WinEDA_PcbFrame::Delete_Zone_Contour( wxDC* DC, ZONE_CONTAINER* zone_contai * otherwise, the hole is deleted */ { - int ncont = zone_container->m_Poly->GetContour(zone_container->m_CornerSelection); + int ncont = zone_container->m_Poly->GetContour( zone_container->m_CornerSelection ); - if ( DC ) - zone_container->Draw(DrawPanel, DC, wxPoint(0,0), GR_XOR); + if( DC ) + zone_container->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR ); - Delete_Zone_Fill( DC, NULL, zone_container->m_TimeStamp ); // Remove fill segments - - if ( ncont == 0 ) // This is the main outline: remove all - m_Pcb->Delete( zone_container ); + Delete_Zone_Fill( DC, NULL, zone_container->m_TimeStamp ); // Remove fill segments - else - { - zone_container->m_Poly->RemoveContour( ncont ); - if ( DC ) - zone_container->Draw(DrawPanel, DC, wxPoint(0,0), GR_OR); - } + if( ncont == 0 ) // This is the main outline: remove all + m_Pcb->Delete( zone_container ); + + else + { + zone_container->m_Poly->RemoveContour( ncont ); + if( DC ) + zone_container->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR ); + } GetScreen()->SetModify(); } @@ -942,7 +851,7 @@ int WinEDA_PcbFrame::Fill_All_Zones( wxDC* DC, bool verbose ) for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ ) { - zone_container = m_Pcb->GetArea(ii); + zone_container = m_Pcb->GetArea( ii ); error_level = Fill_Zone( NULL, zone_container, verbose ); if( error_level && !verbose ) break; @@ -962,23 +871,23 @@ int WinEDA_PcbFrame::Fill_All_Zones( wxDC* DC, bool verbose ) * Must be called after pad netcodes are calculated * @return : error count */ -int BOARD::SetAreasNetCodesFromNetNames(void) +int BOARD::SetAreasNetCodesFromNetNames( void ) { - int error_count = 0; - - for ( int ii = 0; ii < GetAreaCount(); ii++ ) - { - const EQUIPOT* net = FindNet( GetArea(ii)->m_Netname ); - if ( net ) - { - GetArea(ii)->SetNet(net->GetNet()); - } - else - { - error_count++; - GetArea(ii)->SetNet(-1); //keep Net Name ane set m_NetCode to -1 : error flag - } - } - - return error_count; + int error_count = 0; + + for( int ii = 0; ii < GetAreaCount(); ii++ ) + { + const EQUIPOT* net = FindNet( GetArea( ii )->m_Netname ); + if( net ) + { + GetArea( ii )->SetNet( net->GetNet() ); + } + else + { + error_count++; + GetArea( ii )->SetNet( -1 ); //keep Net Name ane set m_NetCode to -1 : error flag + } + } + + return error_count; } diff --git a/pcbnew/zones_test_and_combine_areas.cpp b/pcbnew/zones_test_and_combine_areas.cpp index ad388e9b8e..5a8c4ce483 100644 --- a/pcbnew/zones_test_and_combine_areas.cpp +++ b/pcbnew/zones_test_and_combine_areas.cpp @@ -65,8 +65,7 @@ ZONE_CONTAINER* BOARD::InsertArea( int netcode, int iarea, int layer, int x, int else m_ZoneDescriptorList.push_back( new_area ); - new_area->m_Poly->Start( layer, 1, 10 * NM_PER_MIL, x, y, - hatch ); + new_area->m_Poly->Start( layer, x, y, hatch ); return new_area; } @@ -744,7 +743,7 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi if( i==0 ) { area_ref->m_Poly->Start( area_ref->GetLayer( - ), 0, 0, x, y, area_ref->m_Poly->GetHatchStyle() ); + ), x, y, area_ref->m_Poly->GetHatchStyle() ); } else area_ref->m_Poly->AppendCorner( x, y ); @@ -997,17 +996,39 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E /** * Function doEdgeZoneDrc - * tests the current EDGE_ZONE segment and returns the result and displays the error - * in the status panel only if one exists. + * tests a segment in ZONE_CONTAINER * aArea: * Test Edge inside other areas * Test Edge too close other areas - * @param aEdge The current segment to test. + * @param aArea The current area. + * @param aCornerIndex The first corner of the segment to test. * @return bool - false if DRC error or true if OK */ -bool DRC::doEdgeZoneDrc( const EDGE_ZONE* aEdge ) +bool DRC::doEdgeZoneDrc( ZONE_CONTAINER * aArea, int aCornerIndex ) { wxString str; + + wxPoint start = aArea->GetCornerPosition(aCornerIndex); + wxPoint end; + // Search the end point of the edge starting at aCornerIndex + if( aArea->m_Poly->corner[aCornerIndex].end_contour == FALSE && + aCornerIndex < (aArea->GetNumCorners() - 1) ) + { + end = aArea->GetCornerPosition(aCornerIndex+1); + } + else // aCornerIndex is the last corner of an outline. + // the corresponding end point of the segment is the first corner of the outline + { + int ii = aCornerIndex-1; + end = aArea->GetCornerPosition(ii); + while ( ii >= 0 ) + { + if ( aArea->m_Poly->corner[ii].end_contour ) + break; + end = aArea->GetCornerPosition(ii); + ii--; + } + } // iterate through all areas for( int ia2 = 0; ia2 < m_pcb->GetAreaCount(); ia2++ ) @@ -1015,20 +1036,20 @@ bool DRC::doEdgeZoneDrc( const EDGE_ZONE* aEdge ) ZONE_CONTAINER* Area_To_Test = m_pcb->GetArea( ia2 ); // test for same layer - if( Area_To_Test->GetLayer() != aEdge->GetLayer() ) + if( Area_To_Test->GetLayer() != aArea->GetLayer() ) continue; // Test for same net - if( (aEdge->GetNet() == Area_To_Test->GetNet()) && (aEdge->GetNet() > 0) ) + if( (aArea->GetNet() == Area_To_Test->GetNet()) && (aArea->GetNet() > 0) ) continue; // test for ending line inside Area_To_Test - int x = aEdge->m_End.x; - int y = aEdge->m_End.y; + int x = end.x; + int y = 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 ), + m_currentMarker = fillMarker( aArea, wxPoint( x, y ), COPPERAREA_INSIDE_COPPERAREA, m_currentMarker ); return false; @@ -1036,10 +1057,10 @@ bool DRC::doEdgeZoneDrc( const EDGE_ZONE* aEdge ) // 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; + int ax1 = start.x; + int ay1 = start.y; + int ax2 = end.x; + int ay2 = end.y; for( int icont2 = 0; icont2 < Area_To_Test->m_Poly->GetNumContours(); icont2++ ) { int ic_start2 = Area_To_Test->m_Poly->GetContourStart( icont2 ); @@ -1070,7 +1091,7 @@ bool DRC::doEdgeZoneDrc( const EDGE_ZONE* aEdge ) if( d < g_DesignSettings.m_ZoneClearence ) { // COPPERAREA_COPPERAREA error : edge intersect or too close - m_currentMarker = fillMarker( aEdge, wxPoint( x, y ), + m_currentMarker = fillMarker( aArea, wxPoint( x, y ), COPPERAREA_CLOSE_TO_COPPERAREA, m_currentMarker ); return false; diff --git a/polygon/PolyLine.cpp b/polygon/PolyLine.cpp index 008e94aba2..8bf41caf79 100644 --- a/polygon/PolyLine.cpp +++ b/polygon/PolyLine.cpp @@ -22,7 +22,7 @@ using namespace std; CPolyLine::CPolyLine() { m_HatchStyle = 0; - m_sel_box = 0; + m_Width = 0; utility = 0; m_gpc_poly = new gpc_polygon; m_gpc_poly->num_contours = 0; @@ -72,7 +72,7 @@ int CPolyLine::NormalizeWithGpc( std::vector * pa, bool bRetainArcs int x = to_int(((m_gpc_poly->contour)[ic].vertex)[i].x); int y = to_int(((m_gpc_poly->contour)[ic].vertex)[i].y); if( i==0 ) - Start( m_layer, m_Width, m_sel_box, x, y, m_HatchStyle ); + Start( m_layer, x, y, m_HatchStyle ); else AppendCorner( x, y, STRAIGHT, FALSE ); } @@ -89,7 +89,7 @@ int CPolyLine::NormalizeWithGpc( std::vector * pa, bool bRetainArcs int x = to_int(((m_gpc_poly->contour)[ic].vertex)[i].x); int y = to_int(((m_gpc_poly->contour)[ic].vertex)[i].y); if( i==0 ) - poly->Start( m_layer, m_Width, m_sel_box, x, y, m_HatchStyle ); + poly->Start( m_layer, x, y, m_HatchStyle ); else poly->AppendCorner( x, y, STRAIGHT, FALSE ); } @@ -199,10 +199,7 @@ void CPolyLine::ClipPhpPolygon( int php_op, CPolyLine * poly ) do { vertex * v = p->getFirst(); - Start( m_layer, m_Width, m_sel_box, - to_int(v->X()*DENOM), - to_int(v->Y()*DENOM), - m_HatchStyle ); + Start( m_layer, to_int(v->X()*DENOM), to_int(v->Y()*DENOM), m_HatchStyle ); do { vertex * n = v->Next(); @@ -606,12 +603,9 @@ int CPolyLine::RestoreArcs( std::vector * arc_array, std::vectorStart( 0, 0, 0, x-dx, y, 0 ); + poly->Start( 0, x-dx, y, 0 ); poly->AppendCorner( x, y+dy, ARC_CW, 0 ); poly->AppendCorner( x+dx, y, ARC_CW, 0 ); poly->AppendCorner( x, y-dy, ARC_CW, 0 ); diff --git a/polygon/PolyLine.h b/polygon/PolyLine.h index 1b21a59832..ce7c6b96a5 100644 --- a/polygon/PolyLine.h +++ b/polygon/PolyLine.h @@ -69,8 +69,7 @@ public: ~CPolyLine(); // functions for modifying polyline - void Start( int layer, int w, int sel_box, int x, int y, - int hatch ); + void Start( int layer, int x, int y, int hatch ); void AppendCorner( int x, int y, int style = STRAIGHT, bool bDraw=TRUE ); void InsertCorner( int ic, int x, int y ); void DeleteCorner( int ic, bool bDraw=TRUE ); @@ -138,8 +137,7 @@ public: private: int m_layer; // layer to draw on - int m_Width; // line width - int m_sel_box; // corner selection box width/2 + int m_Width; // lines width when drawing. Provided but not really used int utility; public: std::vector corner; // array of points for corners