From 9dac8534c1afd01076279816bd75bc4a0fe8b97f Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Tue, 27 Aug 2019 13:32:00 +0200 Subject: [PATCH] Pcbnew: seriously speedup calculation time when plotting large filled areas. --- pcbnew/dialogs/dialog_plot.cpp | 6 ++++-- pcbnew/plot_board_layers.cpp | 15 ++++++++++++--- pcbnew/plot_brditems_plotter.cpp | 21 +++++++++++++-------- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/pcbnew/dialogs/dialog_plot.cpp b/pcbnew/dialogs/dialog_plot.cpp index e3bd53a0a6..5f1c97fa74 100644 --- a/pcbnew/dialogs/dialog_plot.cpp +++ b/pcbnew/dialogs/dialog_plot.cpp @@ -851,14 +851,16 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event ) plotter->EndPlot(); delete plotter; - msg.Printf( _( "Plot file \"%s\" created." ), GetChars( fn.GetFullPath() ) ); + msg.Printf( _( "Plot file \"%s\" created." ), fn.GetFullPath() ); reporter.Report( msg, REPORTER::RPT_ACTION ); } else { - msg.Printf( _( "Unable to create file \"%s\"." ), GetChars( fn.GetFullPath() ) ); + msg.Printf( _( "Unable to create file \"%s\"." ), fn.GetFullPath() ); reporter.Report( msg, REPORTER::RPT_ERROR ); } + + wxSafeYield(); // displays report message. } if( m_plotOpts.GetFormat() == PLOT_FORMAT_GERBER && m_plotOpts.GetCreateGerberJobFile() ) diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index bb5df56afe..ed46a72aa8 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -573,6 +573,9 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter, plotted.insert( zone ); SHAPE_POLY_SET aggregateArea = zone->GetFilledPolysList(); + bool needFracture = false; // If 2 or more filled areas are combined, resulting + // aggregateArea will be simplified and fractured + // (Long calculation time) for( ZONE_CONTAINER* candidate : aBoard->Zones() ) { @@ -586,7 +589,7 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter, // having compatible settings for drawings: // use or not outline thickness, and if using outline thickness, // having the same thickness - // becuase after merging only one outline thickness is used + // because after merging only one outline thickness is used if( candidate->GetFilledPolysUseThickness() != zone->GetFilledPolysUseThickness() ) // Should not happens, because usually the same option is used for filling continue; @@ -596,10 +599,16 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter, continue; plotted.insert( candidate ); - aggregateArea.BooleanAdd( candidate->GetFilledPolysList(), SHAPE_POLY_SET::PM_FAST ); + aggregateArea.Append( candidate->GetFilledPolysList() ); + needFracture = true; + } + + if( needFracture ) + { + aggregateArea.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); + aggregateArea.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); } - aggregateArea.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); itemplotter.PlotFilledAreas( zone, aggregateArea ); } aPlotter->EndBlock( NULL ); diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index cf7718ba17..4e0f82c858 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -653,8 +653,7 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( ZONE_CONTAINER* aZone, SHAPE_POLY_SET& p } // We need a buffer to store corners coordinates: - static std::vector< wxPoint > cornerList; - cornerList.clear(); + std::vector< wxPoint > cornerList; m_plotter->SetColor( getColor( aZone->GetLayer() ) ); @@ -666,12 +665,20 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( ZONE_CONTAINER* aZone, SHAPE_POLY_SET& p */ int outline_thickness = aZone->GetFilledPolysUseThickness() ? aZone->GetMinThickness() : 0; - for( auto ic = polysList.CIterate(); ic; ++ic ) + for( int idx = 0; idx < polysList.OutlineCount(); ++idx ) { - wxPoint pos( ic->x, ic->y ); - cornerList.push_back( pos ); + SHAPE_LINE_CHAIN& outline = polysList.Outline( idx ); - if( ic.IsEndContour() ) // Plot the current filled area outline + cornerList.clear(); + cornerList.reserve( outline.PointCount() ); + + for( int ic = 0; ic < outline.PointCount(); ++ic ) + { + VECTOR2I& point = outline.Point( ic ); + cornerList.emplace_back( wxPoint( point.x, point.y ) ); + } + + if( cornerList.size() ) // Plot the current filled area outline { // First, close the outline if( cornerList[0] != cornerList[cornerList.size() - 1] ) @@ -696,8 +703,6 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( ZONE_CONTAINER* aZone, SHAPE_POLY_SET& p m_plotter->SetCurrentLineWidth( -1 ); } - - cornerList.clear(); } } }