Loading CHANGELOG.txt +11 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,17 @@ Started 2007-June-11 Please add newer entries at the top, list the date and your name with email address. 2009-Jan-15 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr> ================================================================================ ++Pcbnew: Added: patch from Rok Markovic (rok@kanardia.eu) to remove unused stubs in thermal pads Modified: print boards when printing in color mode layers on one sheet: now printed in OR mode like drawings on screen Also in SVG mode, but OR mode seems not work inSVG mode. 2009-Jan-11 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr> ================================================================================ ++Pcbnew: Loading pcbnew/class_pad_draw_functions.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -328,7 +328,7 @@ void D_PAD::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, const wxPoin { blackpenstate = GetGRForceBlackPenState(); GRForceBlackPen( false ); color = WHITE; color = g_DrawBgColor; } else color = BLACK; // or DARKGRAY; Loading pcbnew/class_track.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -629,6 +629,9 @@ void TRACK::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, const wxPoin m_End.x, m_End.y, m_Width, color ); } if( g_IsPrinting ) return; // Show clearance for tracks, not for zone segments if( ShowClearance( this ) ) { Loading @@ -643,7 +646,7 @@ void TRACK::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, const wxPoin * - only tracks with a length > 10 * thickness are eligible * and, of course, if we are not printing the board */ if( Type() == TYPE_ZONE || g_IsPrinting ) if( Type() == TYPE_ZONE ) return; #define THRESHOLD 10 Loading pcbnew/print_board_functions.cpp +29 −14 Original line number Diff line number Diff line Loading @@ -51,7 +51,21 @@ void WinEDA_DrawPanel::PrintPage( wxDC* aDC, bool aPrint_Sheet_Ref, int aPrintMa m_PrintIsMirrored = aPrintMirrorMode; if( ( g_DrawBgColor == BLACK ) && (GetGRForceBlackPenState( ) == false) ) { // One can use the OR mode in this case, and we draw a black background to draw board in OR mode, like on screen // But because black background are very expensive to draw, we draw in black only the minimun area. drawmode = GR_OR; EDA_Rect rect = frame->GetBoard()->m_BoundaryBox; rect.Inflate( 2000, 2000 ); // Margin in 1/10000 inch around the board to draw the black background. GRSetDrawMode( aDC, GR_COPY ); // draw in black the minimum page area: GRFilledRect( &m_ClipBox, aDC, rect.GetX(), rect.GetY(), rect.GetEnd().x, rect.GetEnd().y, g_DrawBgColor, g_DrawBgColor ); } /* Print the pcb graphic items (texts, ...) */ GRSetDrawMode( aDC, drawmode ); for( BOARD_ITEM* item = Pcb->m_Drawings; item; item = item->Next() ) { switch( item->Type() ) Loading Loading @@ -106,35 +120,36 @@ void WinEDA_DrawPanel::PrintPage( wxDC* aDC, bool aPrint_Sheet_Ref, int aPrintMa Print_Module( this, aDC, Module, drawmode, aPrintMaskLayer ); } /* Print via holes in white color*/ /* Draw filled areas (i.e. zones) */ for( int ii = 0; ii < Pcb->GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = Pcb->GetArea(ii); if( ( aPrintMaskLayer & (1 << zone->GetLayer()) ) == 0 ) continue; zone->DrawFilledArea( this, aDC, drawmode ); } /* Print via holes in bg color: Not sure it is good for buried or blind vias */ pt_piste = Pcb->m_Track; int rayon = g_DesignSettings.m_ViaDrill / 2; int color = WHITE; int color = g_DrawBgColor; bool blackpenstate = GetGRForceBlackPenState( ); GRForceBlackPen( false ); GRSetDrawMode( aDC, GR_COPY ); for( ; pt_piste != NULL; pt_piste = pt_piste->Next() ) { if( ( aPrintMaskLayer & pt_piste->ReturnMaskLayer() ) == 0 ) continue; if( pt_piste->Type() == TYPE_VIA ) /* VIA rencontree */ { GRSetDrawMode( aDC, drawmode ); int rayon = g_DesignSettings.m_ViaDrill / 2; GRFilledCircle( &m_ClipBox, aDC, pt_piste->m_Start.x, pt_piste->m_Start.y, rayon, 0, color, color ); } } GRForceBlackPen( blackpenstate ); /* Draw filled areas (i.e. zones) */ for( int ii = 0; ii < Pcb->GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = Pcb->GetArea(ii); if( ( aPrintMaskLayer & (1 << zone->GetLayer()) ) == 0 ) continue; zone->DrawFilledArea( this, aDC, drawmode ); } if( aPrint_Sheet_Ref ) m_Parent->TraceWorkSheet( aDC, GetScreen(), g_PlotLine_Width ); Loading pcbnew/zones_convert_brd_items_to_polygons.cpp +126 −0 Original line number Diff line number Diff line Loading @@ -295,6 +295,132 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) delete booleng; } // Now we remove all unused thermal stubs. #define REMOVE_UNUSED_THERMAL_STUBS // Can be commented to skip unused thermal stubs calculations #ifdef REMOVE_UNUSED_THERMAL_STUBS // first compute endindex for TestPointInsidePolygon unsigned int indexstart = 0, indexend; for( indexend = 0; indexend < m_FilledPolysList.size(); indexend++ ) { if( m_FilledPolysList[indexend].end_contour ) // end of a filled sub-area found { break; } } /* Second, Add the main (corrected) polygon (i.e. the filled area using only one outline) * in GroupA in Bool_Engine to do a BOOL_A_SUB_B operation * All areas to remove will be put in GroupB in Bool_Engine */ booleng = new Bool_Engine(); ArmBoolEng( booleng, true ); /* Add the main corrected polygon (i.e. the filled area using only one outline) * in GroupA in Bool_Engine */ CopyPolygonsFromFilledPolysListToBoolengine( booleng, GROUP_A ); /* * Test and add polygons to remove thermal stubs. */ for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) { for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->Next() ) { // check if( pad->IsOnLayer( GetLayer() ) && pad->GetNet() == GetNet() && m_PadOption == THERMAL_PAD ) { item_boundingbox = pad->GetBoundingBox(); item_boundingbox.Inflate( m_ThermalReliefGapValue, m_ThermalReliefGapValue ); if( !(item_boundingbox.Intersects( zone_boundingbox )) ) continue; // test point int dx = (pad->m_Size.x / 2) + m_ThermalReliefGapValue; int dy = (pad->m_Size.y / 2) + m_ThermalReliefGapValue; // compute north, south, west and east points for zone connection. wxPoint ptTest[4]; ptTest[0] = wxPoint(0, dy+m_ZoneMinThickness/2); ptTest[1] = wxPoint(0, -(dy+m_ZoneMinThickness/2)); ptTest[2] = wxPoint( dx+m_ZoneMinThickness/2, 0); ptTest[3] = wxPoint(-(dx+m_ZoneMinThickness/2), 0); // This is CIRCLE pad tweak (for circle pads the thermal stubs are at 45 deg) float fAngle = 0.0; if ( pad->m_PadShape == PAD_CIRCLE) fAngle = 450.0; // Test all sides for (int i=0; i<4; i++) { // rotate point RotatePoint( &ptTest[i], pad->m_Orient + fAngle ); // translate point ptTest[i] += pad->ReturnShapePos(); if ( TestPointInsidePolygon( m_FilledPolysList, indexstart, indexend, ptTest[i].x, ptTest[i].y ) == false) { // polygon buffer std::vector<wxPoint> corners_buffer; // polygons are rectangles with width of copper bridge value const int iDTRC = m_ThermalReliefCopperBridgeValue / 2; switch (i) { case 0: corners_buffer.push_back( wxPoint( -iDTRC, dy) ); corners_buffer.push_back( wxPoint( +iDTRC, dy) ); corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, iDTRC ) ); break; case 1: corners_buffer.push_back( wxPoint( -iDTRC, -dy ) ); corners_buffer.push_back( wxPoint( +iDTRC, -dy ) ); corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) ); break; case 2: corners_buffer.push_back( wxPoint( dx, -iDTRC ) ); corners_buffer.push_back( wxPoint( dx, iDTRC ) ); corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) ); corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) ); break; case 3: corners_buffer.push_back( wxPoint( -dx, -iDTRC ) ); corners_buffer.push_back( wxPoint( -dx, iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) ); break; } // add computed polygon to group_B if( booleng->StartPolygonAdd( GROUP_B ) ) { for( unsigned ic = 0; ic < corners_buffer.size(); ic++ ) { wxPoint cpos = corners_buffer[ic]; RotatePoint( &cpos, pad->m_Orient + fAngle ); // Rotate according to module orientation cpos += pad->ReturnShapePos(); // Shift origin to position booleng->AddPoint( cpos.x, cpos.y ); } booleng->EndPolygonAdd(); } } } } } } /* compute copper areas */ booleng->Do_Operation( BOOL_A_SUB_B ); /* put these areas in m_FilledPolysList */ m_FilledPolysList.clear(); CopyPolygonsFromBoolengineToFilledPolysList( booleng ); delete booleng; #endif // Remove insulated islands: if( GetNet() > 0 ) Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb ); Loading Loading
CHANGELOG.txt +11 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,17 @@ Started 2007-June-11 Please add newer entries at the top, list the date and your name with email address. 2009-Jan-15 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr> ================================================================================ ++Pcbnew: Added: patch from Rok Markovic (rok@kanardia.eu) to remove unused stubs in thermal pads Modified: print boards when printing in color mode layers on one sheet: now printed in OR mode like drawings on screen Also in SVG mode, but OR mode seems not work inSVG mode. 2009-Jan-11 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr> ================================================================================ ++Pcbnew: Loading
pcbnew/class_pad_draw_functions.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -328,7 +328,7 @@ void D_PAD::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, const wxPoin { blackpenstate = GetGRForceBlackPenState(); GRForceBlackPen( false ); color = WHITE; color = g_DrawBgColor; } else color = BLACK; // or DARKGRAY; Loading
pcbnew/class_track.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -629,6 +629,9 @@ void TRACK::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, const wxPoin m_End.x, m_End.y, m_Width, color ); } if( g_IsPrinting ) return; // Show clearance for tracks, not for zone segments if( ShowClearance( this ) ) { Loading @@ -643,7 +646,7 @@ void TRACK::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, const wxPoin * - only tracks with a length > 10 * thickness are eligible * and, of course, if we are not printing the board */ if( Type() == TYPE_ZONE || g_IsPrinting ) if( Type() == TYPE_ZONE ) return; #define THRESHOLD 10 Loading
pcbnew/print_board_functions.cpp +29 −14 Original line number Diff line number Diff line Loading @@ -51,7 +51,21 @@ void WinEDA_DrawPanel::PrintPage( wxDC* aDC, bool aPrint_Sheet_Ref, int aPrintMa m_PrintIsMirrored = aPrintMirrorMode; if( ( g_DrawBgColor == BLACK ) && (GetGRForceBlackPenState( ) == false) ) { // One can use the OR mode in this case, and we draw a black background to draw board in OR mode, like on screen // But because black background are very expensive to draw, we draw in black only the minimun area. drawmode = GR_OR; EDA_Rect rect = frame->GetBoard()->m_BoundaryBox; rect.Inflate( 2000, 2000 ); // Margin in 1/10000 inch around the board to draw the black background. GRSetDrawMode( aDC, GR_COPY ); // draw in black the minimum page area: GRFilledRect( &m_ClipBox, aDC, rect.GetX(), rect.GetY(), rect.GetEnd().x, rect.GetEnd().y, g_DrawBgColor, g_DrawBgColor ); } /* Print the pcb graphic items (texts, ...) */ GRSetDrawMode( aDC, drawmode ); for( BOARD_ITEM* item = Pcb->m_Drawings; item; item = item->Next() ) { switch( item->Type() ) Loading Loading @@ -106,35 +120,36 @@ void WinEDA_DrawPanel::PrintPage( wxDC* aDC, bool aPrint_Sheet_Ref, int aPrintMa Print_Module( this, aDC, Module, drawmode, aPrintMaskLayer ); } /* Print via holes in white color*/ /* Draw filled areas (i.e. zones) */ for( int ii = 0; ii < Pcb->GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = Pcb->GetArea(ii); if( ( aPrintMaskLayer & (1 << zone->GetLayer()) ) == 0 ) continue; zone->DrawFilledArea( this, aDC, drawmode ); } /* Print via holes in bg color: Not sure it is good for buried or blind vias */ pt_piste = Pcb->m_Track; int rayon = g_DesignSettings.m_ViaDrill / 2; int color = WHITE; int color = g_DrawBgColor; bool blackpenstate = GetGRForceBlackPenState( ); GRForceBlackPen( false ); GRSetDrawMode( aDC, GR_COPY ); for( ; pt_piste != NULL; pt_piste = pt_piste->Next() ) { if( ( aPrintMaskLayer & pt_piste->ReturnMaskLayer() ) == 0 ) continue; if( pt_piste->Type() == TYPE_VIA ) /* VIA rencontree */ { GRSetDrawMode( aDC, drawmode ); int rayon = g_DesignSettings.m_ViaDrill / 2; GRFilledCircle( &m_ClipBox, aDC, pt_piste->m_Start.x, pt_piste->m_Start.y, rayon, 0, color, color ); } } GRForceBlackPen( blackpenstate ); /* Draw filled areas (i.e. zones) */ for( int ii = 0; ii < Pcb->GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = Pcb->GetArea(ii); if( ( aPrintMaskLayer & (1 << zone->GetLayer()) ) == 0 ) continue; zone->DrawFilledArea( this, aDC, drawmode ); } if( aPrint_Sheet_Ref ) m_Parent->TraceWorkSheet( aDC, GetScreen(), g_PlotLine_Width ); Loading
pcbnew/zones_convert_brd_items_to_polygons.cpp +126 −0 Original line number Diff line number Diff line Loading @@ -295,6 +295,132 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) delete booleng; } // Now we remove all unused thermal stubs. #define REMOVE_UNUSED_THERMAL_STUBS // Can be commented to skip unused thermal stubs calculations #ifdef REMOVE_UNUSED_THERMAL_STUBS // first compute endindex for TestPointInsidePolygon unsigned int indexstart = 0, indexend; for( indexend = 0; indexend < m_FilledPolysList.size(); indexend++ ) { if( m_FilledPolysList[indexend].end_contour ) // end of a filled sub-area found { break; } } /* Second, Add the main (corrected) polygon (i.e. the filled area using only one outline) * in GroupA in Bool_Engine to do a BOOL_A_SUB_B operation * All areas to remove will be put in GroupB in Bool_Engine */ booleng = new Bool_Engine(); ArmBoolEng( booleng, true ); /* Add the main corrected polygon (i.e. the filled area using only one outline) * in GroupA in Bool_Engine */ CopyPolygonsFromFilledPolysListToBoolengine( booleng, GROUP_A ); /* * Test and add polygons to remove thermal stubs. */ for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) { for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->Next() ) { // check if( pad->IsOnLayer( GetLayer() ) && pad->GetNet() == GetNet() && m_PadOption == THERMAL_PAD ) { item_boundingbox = pad->GetBoundingBox(); item_boundingbox.Inflate( m_ThermalReliefGapValue, m_ThermalReliefGapValue ); if( !(item_boundingbox.Intersects( zone_boundingbox )) ) continue; // test point int dx = (pad->m_Size.x / 2) + m_ThermalReliefGapValue; int dy = (pad->m_Size.y / 2) + m_ThermalReliefGapValue; // compute north, south, west and east points for zone connection. wxPoint ptTest[4]; ptTest[0] = wxPoint(0, dy+m_ZoneMinThickness/2); ptTest[1] = wxPoint(0, -(dy+m_ZoneMinThickness/2)); ptTest[2] = wxPoint( dx+m_ZoneMinThickness/2, 0); ptTest[3] = wxPoint(-(dx+m_ZoneMinThickness/2), 0); // This is CIRCLE pad tweak (for circle pads the thermal stubs are at 45 deg) float fAngle = 0.0; if ( pad->m_PadShape == PAD_CIRCLE) fAngle = 450.0; // Test all sides for (int i=0; i<4; i++) { // rotate point RotatePoint( &ptTest[i], pad->m_Orient + fAngle ); // translate point ptTest[i] += pad->ReturnShapePos(); if ( TestPointInsidePolygon( m_FilledPolysList, indexstart, indexend, ptTest[i].x, ptTest[i].y ) == false) { // polygon buffer std::vector<wxPoint> corners_buffer; // polygons are rectangles with width of copper bridge value const int iDTRC = m_ThermalReliefCopperBridgeValue / 2; switch (i) { case 0: corners_buffer.push_back( wxPoint( -iDTRC, dy) ); corners_buffer.push_back( wxPoint( +iDTRC, dy) ); corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, iDTRC ) ); break; case 1: corners_buffer.push_back( wxPoint( -iDTRC, -dy ) ); corners_buffer.push_back( wxPoint( +iDTRC, -dy ) ); corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) ); break; case 2: corners_buffer.push_back( wxPoint( dx, -iDTRC ) ); corners_buffer.push_back( wxPoint( dx, iDTRC ) ); corners_buffer.push_back( wxPoint( +iDTRC, iDTRC ) ); corners_buffer.push_back( wxPoint( +iDTRC, -iDTRC ) ); break; case 3: corners_buffer.push_back( wxPoint( -dx, -iDTRC ) ); corners_buffer.push_back( wxPoint( -dx, iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, iDTRC ) ); corners_buffer.push_back( wxPoint( -iDTRC, -iDTRC ) ); break; } // add computed polygon to group_B if( booleng->StartPolygonAdd( GROUP_B ) ) { for( unsigned ic = 0; ic < corners_buffer.size(); ic++ ) { wxPoint cpos = corners_buffer[ic]; RotatePoint( &cpos, pad->m_Orient + fAngle ); // Rotate according to module orientation cpos += pad->ReturnShapePos(); // Shift origin to position booleng->AddPoint( cpos.x, cpos.y ); } booleng->EndPolygonAdd(); } } } } } } /* compute copper areas */ booleng->Do_Operation( BOOL_A_SUB_B ); /* put these areas in m_FilledPolysList */ m_FilledPolysList.clear(); CopyPolygonsFromBoolengineToFilledPolysList( booleng ); delete booleng; #endif // Remove insulated islands: if( GetNet() > 0 ) Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb ); Loading