Loading CHANGELOG.txt +11 −0 Original line number Original line 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 Please add newer entries at the top, list the date and your name with email address. 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> 2009-Jan-11 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr> ================================================================================ ================================================================================ ++Pcbnew: ++Pcbnew: Loading pcbnew/class_pad_draw_functions.cpp +1 −1 Original line number Original line 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(); blackpenstate = GetGRForceBlackPenState(); GRForceBlackPen( false ); GRForceBlackPen( false ); color = WHITE; color = g_DrawBgColor; } } else else color = BLACK; // or DARKGRAY; color = BLACK; // or DARKGRAY; Loading pcbnew/class_track.cpp +4 −1 Original line number Original line 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 ); m_End.x, m_End.y, m_Width, color ); } } if( g_IsPrinting ) return; // Show clearance for tracks, not for zone segments // Show clearance for tracks, not for zone segments if( ShowClearance( this ) ) 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 * - only tracks with a length > 10 * thickness are eligible * and, of course, if we are not printing the board * and, of course, if we are not printing the board */ */ if( Type() == TYPE_ZONE || g_IsPrinting ) if( Type() == TYPE_ZONE ) return; return; #define THRESHOLD 10 #define THRESHOLD 10 Loading pcbnew/print_board_functions.cpp +29 −14 Original line number Original line 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; 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, ...) */ /* Print the pcb graphic items (texts, ...) */ GRSetDrawMode( aDC, drawmode ); for( BOARD_ITEM* item = Pcb->m_Drawings; item; item = item->Next() ) for( BOARD_ITEM* item = Pcb->m_Drawings; item; item = item->Next() ) { { switch( item->Type() ) 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_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; pt_piste = Pcb->m_Track; int rayon = g_DesignSettings.m_ViaDrill / 2; int color = g_DrawBgColor; int color = WHITE; bool blackpenstate = GetGRForceBlackPenState( ); bool blackpenstate = GetGRForceBlackPenState( ); GRForceBlackPen( false ); GRForceBlackPen( false ); GRSetDrawMode( aDC, GR_COPY ); for( ; pt_piste != NULL; pt_piste = pt_piste->Next() ) for( ; pt_piste != NULL; pt_piste = pt_piste->Next() ) { { if( ( aPrintMaskLayer & pt_piste->ReturnMaskLayer() ) == 0 ) if( ( aPrintMaskLayer & pt_piste->ReturnMaskLayer() ) == 0 ) continue; continue; if( pt_piste->Type() == TYPE_VIA ) /* VIA rencontree */ 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, GRFilledCircle( &m_ClipBox, aDC, pt_piste->m_Start.x, pt_piste->m_Start.y, rayon, 0, color, color ); rayon, 0, color, color ); } } } } GRForceBlackPen( blackpenstate ); 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 ) if( aPrint_Sheet_Ref ) m_Parent->TraceWorkSheet( aDC, GetScreen(), g_PlotLine_Width ); m_Parent->TraceWorkSheet( aDC, GetScreen(), g_PlotLine_Width ); Loading pcbnew/zones_convert_brd_items_to_polygons.cpp +126 −0 Original line number Original line Diff line number Diff line Loading @@ -295,6 +295,132 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) delete booleng; 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: // Remove insulated islands: if( GetNet() > 0 ) if( GetNet() > 0 ) Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb ); Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb ); Loading Loading
CHANGELOG.txt +11 −0 Original line number Original line 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 Please add newer entries at the top, list the date and your name with email address. 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> 2009-Jan-11 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr> ================================================================================ ================================================================================ ++Pcbnew: ++Pcbnew: Loading
pcbnew/class_pad_draw_functions.cpp +1 −1 Original line number Original line 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(); blackpenstate = GetGRForceBlackPenState(); GRForceBlackPen( false ); GRForceBlackPen( false ); color = WHITE; color = g_DrawBgColor; } } else else color = BLACK; // or DARKGRAY; color = BLACK; // or DARKGRAY; Loading
pcbnew/class_track.cpp +4 −1 Original line number Original line 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 ); m_End.x, m_End.y, m_Width, color ); } } if( g_IsPrinting ) return; // Show clearance for tracks, not for zone segments // Show clearance for tracks, not for zone segments if( ShowClearance( this ) ) 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 * - only tracks with a length > 10 * thickness are eligible * and, of course, if we are not printing the board * and, of course, if we are not printing the board */ */ if( Type() == TYPE_ZONE || g_IsPrinting ) if( Type() == TYPE_ZONE ) return; return; #define THRESHOLD 10 #define THRESHOLD 10 Loading
pcbnew/print_board_functions.cpp +29 −14 Original line number Original line 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; 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, ...) */ /* Print the pcb graphic items (texts, ...) */ GRSetDrawMode( aDC, drawmode ); for( BOARD_ITEM* item = Pcb->m_Drawings; item; item = item->Next() ) for( BOARD_ITEM* item = Pcb->m_Drawings; item; item = item->Next() ) { { switch( item->Type() ) 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_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; pt_piste = Pcb->m_Track; int rayon = g_DesignSettings.m_ViaDrill / 2; int color = g_DrawBgColor; int color = WHITE; bool blackpenstate = GetGRForceBlackPenState( ); bool blackpenstate = GetGRForceBlackPenState( ); GRForceBlackPen( false ); GRForceBlackPen( false ); GRSetDrawMode( aDC, GR_COPY ); for( ; pt_piste != NULL; pt_piste = pt_piste->Next() ) for( ; pt_piste != NULL; pt_piste = pt_piste->Next() ) { { if( ( aPrintMaskLayer & pt_piste->ReturnMaskLayer() ) == 0 ) if( ( aPrintMaskLayer & pt_piste->ReturnMaskLayer() ) == 0 ) continue; continue; if( pt_piste->Type() == TYPE_VIA ) /* VIA rencontree */ 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, GRFilledCircle( &m_ClipBox, aDC, pt_piste->m_Start.x, pt_piste->m_Start.y, rayon, 0, color, color ); rayon, 0, color, color ); } } } } GRForceBlackPen( blackpenstate ); 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 ) if( aPrint_Sheet_Ref ) m_Parent->TraceWorkSheet( aDC, GetScreen(), g_PlotLine_Width ); m_Parent->TraceWorkSheet( aDC, GetScreen(), g_PlotLine_Width ); Loading
pcbnew/zones_convert_brd_items_to_polygons.cpp +126 −0 Original line number Original line Diff line number Diff line Loading @@ -295,6 +295,132 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) delete booleng; 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: // Remove insulated islands: if( GetNet() > 0 ) if( GetNet() > 0 ) Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb ); Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb ); Loading