From 4195d71fa2dba49d88be29f552a9902036182cfc Mon Sep 17 00:00:00 2001 From: CHARRAS Date: Thu, 24 Jan 2008 19:51:13 +0000 Subject: [PATCH] Bugs about fill zones and block delete removed --- change_log.txt | 8 +++ pcbnew/autorout.cpp | 24 ++++++--- pcbnew/block.cpp | 6 +++ pcbnew/class_zone.cpp | 24 ++++++--- pcbnew/dialog_zones_by_polygon.cpp | 13 +++-- pcbnew/dialog_zones_by_polygon.pjd | 3 +- pcbnew/makefile.g95 | 2 +- pcbnew/makefile.include | 5 +- pcbnew/zone_filling_algorithm.cpp | 82 ++++++++++++++++++------------ 9 files changed, 114 insertions(+), 53 deletions(-) diff --git a/change_log.txt b/change_log.txt index aeb52d3a78..d474e4fd14 100644 --- a/change_log.txt +++ b/change_log.txt @@ -4,6 +4,14 @@ Started 2007-June-11 Please add newer entries at the top, list the date and your name with email address. + +2008-Jan-24 UPDATE Jean-Pierre Charras +================================================================================ ++pcbnew: + Bugs about fill zones removed (not all, of course). + Fixed an old bug in block delete (could crashes pcbnew after deleting footprints). + + 2008-Jan-23 UPDATE Dick Hollenbeck ================================================================================ +pcbnew: diff --git a/pcbnew/autorout.cpp b/pcbnew/autorout.cpp index b1ed0ccbb3..289f2ea0ff 100644 --- a/pcbnew/autorout.cpp +++ b/pcbnew/autorout.cpp @@ -203,31 +203,41 @@ void DisplayBoard( WinEDA_DrawPanel* panel, wxDC* DC ) int dcell0, dcell1 = 0, color; int maxi; - maxi = ( /*ActiveScreen->Lim_XD - 20*/ 500) / Ncols; + maxi = 600 / Ncols; maxi = (maxi * 3 ) / 4; if( !maxi ) maxi = 1; + GRSetDrawMode( DC, GR_COPY ); for( col = 0; col < Ncols; col++ ) { for( row = 0; row < Nrows; row++ ) { color = 0; - dcell0 = GetCell( row, col, BOTTOM ); if( dcell0 & HOLE ) + dcell0 = GetCell( row, col, BOTTOM ); + if( dcell0 & HOLE ) color = GREEN; - if( Nb_Sides ) - dcell1 = GetCell( row, col, TOP ); +// if( Nb_Sides ) +// dcell1 = GetCell( row, col, TOP ); if( dcell1 & HOLE ) color |= RED; - dcell0 |= dcell1; +// dcell0 |= dcell1; if( !color && (dcell0 & VIA_IMPOSSIBLE) ) color = BLUE; - if( color ) + if( dcell0 & CELL_is_EDGE ) + color = YELLOW; + else if( dcell0 & CELL_is_ZONE ) + color = YELLOW; + + #define DRAW_OFFSET_X -20 + #define DRAW_OFFSET_Y 20 +// if( color ) { for( i = 0; i < maxi; i++ ) for( j = 0; j < maxi; j++ ) GRSPutPixel( &panel->m_ClipBox, DC, - (col * maxi) + i + 10, (row * maxi) + 60 + j, color ); + (col * maxi) + i + DRAW_OFFSET_X, + (row * maxi) + j + DRAW_OFFSET_Y, color ); } } diff --git a/pcbnew/block.cpp b/pcbnew/block.cpp index 7c36ebbf95..6b9a91467f 100644 --- a/pcbnew/block.cpp +++ b/pcbnew/block.cpp @@ -579,6 +579,12 @@ void WinEDA_BasePcbFrame::Block_Delete( wxDC* DC ) DrawPanel->Refresh( TRUE ); if( g_Show_Ratsnest ) Compile_Ratsnest( DC, TRUE ); + else + { + m_Pcb->m_Status_Pcb = 0; /* we need (later) a full ratnest computation */ + build_liste_pads(); + } + } diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 69d44ea646..a15572021e 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -367,6 +367,7 @@ 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. + * Choose the nearest corner * "near" means CORNER_MIN_DIST_IN_PIXELS pixels * @return -1 if none, corner index in .corner * @param refPos : A wxPoint to test @@ -374,27 +375,32 @@ 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; + 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 <= CORNER_MIN_DIST ) + if( dist <= min_dist ) { m_CornerSelection = item_pos; - return 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. + * choose the nearest segment * "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 @@ -402,13 +408,14 @@ 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; + 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; for ( item_pos = 0; item_pos < lim; item_pos++ ) { @@ -431,13 +438,16 @@ 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 <= EDGE_MIN_DIST ) + if( dist <= min_dist ) { m_CornerSelection = item_pos; - return item_pos; + min_dist = dist; } } + if ( m_CornerSelection >= 0 ) + return item_pos; + return -1; } diff --git a/pcbnew/dialog_zones_by_polygon.cpp b/pcbnew/dialog_zones_by_polygon.cpp index be70009436..2fbc45612e 100644 --- a/pcbnew/dialog_zones_by_polygon.cpp +++ b/pcbnew/dialog_zones_by_polygon.cpp @@ -136,7 +136,7 @@ void WinEDA_ZoneFrame::CreateControls() SetFont( *g_DialogFont ); ////@begin WinEDA_ZoneFrame content construction - // Generated by DialogBlocks, 06/01/2008 15:03:35 (unregistered) + // Generated by DialogBlocks, 24/01/2008 11:39:58 (unregistered) WinEDA_ZoneFrame* itemDialog1 = this; @@ -153,6 +153,7 @@ void WinEDA_ZoneFrame::CreateControls() m_GridCtrlStrings.Add(_("0.00000")); m_GridCtrlStrings.Add(_("0.00000")); m_GridCtrlStrings.Add(_("0.00000")); + m_GridCtrlStrings.Add(_("0.00000")); m_GridCtrl = new wxRadioBox( itemDialog1, ID_RADIOBOX_GRID_SELECTION, _("Grid Size for Filling:"), wxDefaultPosition, wxDefaultSize, m_GridCtrlStrings, 1, wxRA_SPECIFY_COLS ); m_GridCtrl->SetSelection(0); itemBoxSizer4->Add(m_GridCtrl, 0, wxGROW|wxALL, 5); @@ -260,7 +261,7 @@ void WinEDA_ZoneFrame::CreateControls() if( Zone_45_Only ) m_OrientEdgesOpt->SetSelection( 1 ); - static const int GridList[3] = { 50, 100, 250 }; + static const int GridList[4] = { 25, 50, 100, 250 }; int selection = 0; for( unsigned ii = 0; ii < (unsigned) m_GridCtrl->GetCount(); ii++ ) @@ -473,15 +474,19 @@ bool WinEDA_ZoneFrame::AcceptOptions(bool aPromptForErrors) switch( m_GridCtrl->GetSelection() ) { case 0: - g_GridRoutingSize = 50; + g_GridRoutingSize = 25; break; case 1: - g_GridRoutingSize = 100; + g_GridRoutingSize = 50; break; default: case 2: + g_GridRoutingSize = 100; + break; + + case 3: g_GridRoutingSize = 250; break; } diff --git a/pcbnew/dialog_zones_by_polygon.pjd b/pcbnew/dialog_zones_by_polygon.pjd index 7123586e36..f408d14f17 100644 --- a/pcbnew/dialog_zones_by_polygon.pjd +++ b/pcbnew/dialog_zones_by_polygon.pjd @@ -248,6 +248,7 @@ 0 1 0 + 0 1 0 0 @@ -368,7 +369,7 @@ "m_GridCtrl" "Grid Size for Filling:" 1 - "0.00000|0.00000|0.00000" + "0.00000|0.00000|0.00000|0.00000" 0 "" "" diff --git a/pcbnew/makefile.g95 b/pcbnew/makefile.g95 index e694adbb03..2ed69a3515 100644 --- a/pcbnew/makefile.g95 +++ b/pcbnew/makefile.g95 @@ -1,7 +1,7 @@ #makefile for pcbnew, Windows WXDIR = $(WXWIN) - +BOOST_LIB = /f/boost/boost_1_34_1 TARGET=pcbnew include ../libs.win diff --git a/pcbnew/makefile.include b/pcbnew/makefile.include index 6a71e17640..49d53f8b8c 100644 --- a/pcbnew/makefile.include +++ b/pcbnew/makefile.include @@ -1,6 +1,7 @@ + EXTRALIBS = ../common/common.a ../polygon/lib_polygon.a EXTRACPPFLAGS += -DPCBNEW -fno-strict-aliasing -I./ -Ibitmaps -I../include -I../share\ - -I../pcbnew -I../3d-viewer -I../polygon + -I../pcbnew -I../3d-viewer -I../polygon -I$(BOOST_LIB) #COMMON = pcbnew.h struct.h class_pad.h class_module.h class_text_mod.h \ # class_edge_mod.h class_equipot.h @@ -10,9 +11,11 @@ LIBVIEWER3D = ../3d-viewer/3d-viewer.a ZONE_FILES = zones_by_polygon.o #ZONE_FILES = zones.o +SPECCTRA_TOOLS = specctra.o specctra_export.o dsn.o OBJECTS= $(TARGET).o classpcb.o\ $(ZONE_FILES)\ + $(SPECCTRA_TOOLS)\ zones_test_and_combine_areas.o\ zone_filling_algorithm.o\ lay2plot.o\ diff --git a/pcbnew/zone_filling_algorithm.cpp b/pcbnew/zone_filling_algorithm.cpp index 354d58e097..f1bc8fbbe4 100644 --- a/pcbnew/zone_filling_algorithm.cpp +++ b/pcbnew/zone_filling_algorithm.cpp @@ -17,7 +17,7 @@ static void Genere_Segments_Zone( WinEDA_PcbFrame* frame, wxDC* DC, int net_code, int layer ); /* Local variables */ -static bool Zone_Debug = FALSE; +static bool Zone_Debug = false; static unsigned long s_TimeStamp; /* Time stamp common to all segments relative to the new created zone */ /*****************************************************************************/ @@ -42,7 +42,13 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose ) wxString msg; BOARD* Pcb = frame->m_Pcb; - g_DesignSettings.m_TrackClearence = g_DesignSettings.m_ZoneClearence; + // Set the g_DesignSettings.m_TrackClearence (used to fill board map) to the max of m_TrackClearence and m_ZoneClearence + g_DesignSettings.m_TrackClearence = max ( g_DesignSettings.m_TrackClearence, g_DesignSettings.m_ZoneClearence); + + // In order to avoid ends of segments used to fill the zone, and to the clearence the radius of ends + // which is g_GridRoutingSize/2 + g_DesignSettings.m_TrackClearence += g_GridRoutingSize/2; + g_HightLigth_NetCode = m_NetCode; s_TimeStamp = m_TimeStamp; @@ -50,8 +56,8 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose ) // Delete the old filling, if any : frame->Delete_Zone_Fill( DC, NULL, m_TimeStamp ); - // calculate the fixed step of the routing matrix as 5 mils or more - E_scale = g_GridRoutingSize / 50; + // calculate the fixed step of the routing matrix as 25 mils or more + E_scale = g_GridRoutingSize / 25; if( g_GridRoutingSize < 1 ) g_GridRoutingSize = 1; @@ -59,8 +65,6 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose ) // calculate the Ncols and Nrows, size of the routing matrix ComputeMatriceSize( frame, g_GridRoutingSize ); - // Determine the cell pointed to by the mouse - // create the routing matrix in autorout.h's eda_global BOARDHEAD Board Nb_Sides = ONE_SIDE; if( Board.InitBoard() < 0 ) @@ -88,6 +92,11 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose ) g_DesignSettings.m_CurrentTrackWidth = g_GridRoutingSize; + // trace the pcb edges (pcb contour) into the routing matrix + Route_Layer_BOTTOM = Route_Layer_TOP = EDGE_N; + PlaceCells( Pcb, -1, 0 ); + Route_Layer_BOTTOM = Route_Layer_TOP = m_Layer; + /* Create the starting point for the zone: * The starting point and all the tracks are suitable "starting points" */ TRACK* pt_segm = Pcb->m_Track; @@ -96,20 +105,14 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose ) if( g_HightLigth_NetCode != pt_segm->GetNet() ) continue; - if( pt_segm->GetLayer() != m_Layer ) + if( ! pt_segm->IsOnLayer( m_Layer ) ) continue; - if( pt_segm->Type() != TYPETRACK ) - continue; +// if( pt_segm->Type() != TYPETRACK ) +// continue; TraceSegmentPcb( Pcb, pt_segm, CELL_is_FRIEND, 0, WRITE_CELL ); } - - // trace the pcb edges (pcb contour) into the routing matrix - Route_Layer_BOTTOM = Route_Layer_TOP = EDGE_N; - PlaceCells( Pcb, -1, 0 ); - Route_Layer_BOTTOM = Route_Layer_TOP = m_Layer; - // trace the zone edges into the routing matrix int i_start_contour = 0; for( unsigned ic = 0; ic < m_Poly->corner.size(); ic++ ) @@ -136,16 +139,21 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose ) int cells_count = 0; for( ii = 0, pad = frame->m_Pcb->m_Pads; ii < frame->m_Pcb->m_NbPads; ii++, pad++ ) { - wxPoint pos; - if( m_Poly->TestPointInside( (*pad)->m_Pos.x, (*pad)->m_Pos.y ) ) + if ( ! (*pad)->IsOnLayer( GetLayer() ) ) continue; + if ( (*pad)->GetNet() != GetNet() ) continue; + wxPoint pos = (*pad)->m_Pos; + if( m_Poly->TestPointInside( pos.x, pos.y ) ) { - ZoneStartFill.x = ( (*pad)->m_Pos.x - Pcb->m_BoundaryBox.m_Pos.x + - (g_GridRoutingSize / 2) ) / g_GridRoutingSize; + pos -= Pcb->m_BoundaryBox.m_Pos; + ZoneStartFill.x = ( pos.x + (g_GridRoutingSize / 2) ) / g_GridRoutingSize; - ZoneStartFill.y = ( (*pad)->m_Pos.y - Pcb->m_BoundaryBox.m_Pos.y + - (g_GridRoutingSize / 2) ) / g_GridRoutingSize; - OrCell( ZoneStartFill.y, ZoneStartFill.x, BOTTOM, CELL_is_ZONE ); - cells_count++; + ZoneStartFill.y = ( pos.y + (g_GridRoutingSize / 2) ) / g_GridRoutingSize; + BoardCell cell = GetCell( ZoneStartFill.y, ZoneStartFill.x, BOTTOM ); + if ( (cell & CELL_is_EDGE) == 0 ) + { + OrCell( ZoneStartFill.y, ZoneStartFill.x, BOTTOM, CELL_is_ZONE ); + cells_count++; + } } } @@ -180,6 +188,10 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose ) } } + if( Zone_Debug && DC ) + { + DisplayBoard( frame->DrawPanel, DC ); + } // now, all the cell candidates are marked // place all the obstacles into the matrix, such as (pads, tracks, vias, @@ -218,20 +230,21 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose ) * (could be deleted by PlaceCells()) : */ for( ii = 0, pad = frame->m_Pcb->m_Pads; ii < frame->m_Pcb->m_NbPads; ii++, pad++ ) { - wxPoint pos; - if( m_Poly->TestPointInside( (*pad)->m_Pos.x, (*pad)->m_Pos.y ) ) + if ( ! (*pad)->IsOnLayer( GetLayer() ) ) continue; + if ( (*pad)->GetNet() != GetNet() ) continue; + wxPoint pos = (*pad)->m_Pos; + if( m_Poly->TestPointInside( pos.x, pos.y ) ) { - ZoneStartFill.x = ( (*pad)->m_Pos.x - Pcb->m_BoundaryBox.m_Pos.x + - (g_GridRoutingSize / 2) ) / g_GridRoutingSize; + pos -= Pcb->m_BoundaryBox.m_Pos; + ZoneStartFill.x = ( pos.x + (g_GridRoutingSize / 2) ) / g_GridRoutingSize; - ZoneStartFill.y = ( (*pad)->m_Pos.y - Pcb->m_BoundaryBox.m_Pos.y + - (g_GridRoutingSize / 2) ) / g_GridRoutingSize; - OrCell( ZoneStartFill.y, ZoneStartFill.x, BOTTOM, CELL_is_ZONE ); + ZoneStartFill.y = ( pos.y + (g_GridRoutingSize / 2) ) / g_GridRoutingSize; + BoardCell cell = GetCell( ZoneStartFill.y, ZoneStartFill.x, BOTTOM ); + if ( (cell & CELL_is_EDGE) == 0 ) + OrCell( ZoneStartFill.y, ZoneStartFill.x, BOTTOM, CELL_is_ZONE ); } } - if( Zone_Debug && DC ) - DisplayBoard( frame->DrawPanel, DC ); /* Filling the cells of the matrix (this is the zone building)*/ ii = 1; jj = 1; @@ -242,6 +255,11 @@ int ZONE_CONTAINER::Fill_Zone( WinEDA_PcbFrame* frame, wxDC* DC, bool verbose ) ii = Propagation( frame ); } + if( Zone_Debug && DC ) + { + DisplayBoard( frame->DrawPanel, DC ); + } + // replace obstacles into the matrix(pads) if( m_PadOption == THERMAL_PAD ) PlaceCells( Pcb, g_HightLigth_NetCode, FORCE_PADS );