From 353d9d7c9e36ded1941911507696735ea419a724 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Thu, 14 Mar 2019 14:35:55 +0100 Subject: [PATCH] Pcbnew, Zone refill: avoid useless refilling, when zone parameters are not modified. Previously, in many cases the selected zone was refilled on exit selection, even if the zone was not modified. This is annoying, because the zone fill can be really time consuming, and cannot be called without a good reason. Now the refilling is made only if a zone parameter is actually modified. --- pcbnew/class_zone.cpp | 16 ++++++++++++++++ pcbnew/class_zone.h | 28 +++++++++++++++++++++++++--- pcbnew/pcb_parser.cpp | 3 +++ pcbnew/tools/point_editor.cpp | 16 +++++++++++++--- pcbnew/zone_filler.cpp | 6 ++++-- pcbnew/zone_filler.h | 7 +++---- 6 files changed, 64 insertions(+), 12 deletions(-) diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 1c459c1119..b2627e37f7 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -68,6 +68,8 @@ ZONE_CONTAINER::ZONE_CONTAINER( BOARD* aBoard ) : SetLocalFlags( 0 ); // flags tempoarry used in zone calculations m_Poly = new SHAPE_POLY_SET(); // Outlines aBoard->GetZoneSettings().ExportSetting( *this ); + + m_needRefill = false; // True only after some edition. } @@ -107,6 +109,8 @@ ZONE_CONTAINER::ZONE_CONTAINER( const ZONE_CONTAINER& aZone ) : SetLayerSet( aZone.GetLayerSet() ); SetLocalFlags( aZone.GetLocalFlags() ); + + SetNeedRefill( aZone.NeedRefill() ); } @@ -220,6 +224,9 @@ void ZONE_CONTAINER::SetLayerSet( LSET aLayerSet ) return; } + if( m_layerSet != aLayerSet ) + SetNeedRefill( true ); + m_layerSet = aLayerSet; // Set the single layer to the first selected layer @@ -641,6 +648,9 @@ int ZONE_CONTAINER::GetThermalReliefCopperBridge( D_PAD* aPad ) const void ZONE_CONTAINER::SetCornerRadius( unsigned int aRadius ) { + if( m_cornerRadius != aRadius ) + SetNeedRefill( true ); + m_cornerRadius = aRadius; } @@ -910,6 +920,8 @@ void ZONE_CONTAINER::MoveEdge( const wxPoint& offset, int aEdge ) m_Poly->Vertex( aEdge ) += VECTOR2I( offset ); m_Poly->Vertex( next_corner ) += VECTOR2I( offset ); Hatch(); + + SetNeedRefill( true ); } } @@ -1013,6 +1025,8 @@ void ZONE_CONTAINER::AddPolygon( std::vector< wxPoint >& aPolygon ) m_Poly->AddOutline( outline ); else m_Poly->AddHole( outline ); + + SetNeedRefill( true ); } @@ -1030,6 +1044,8 @@ bool ZONE_CONTAINER::AppendCorner( wxPoint aPosition, int aHoleIdx, bool aAllowD m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication ); + SetNeedRefill( true ); + return true; } diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index ebcfca1eaf..97968dcb02 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -167,14 +167,17 @@ public: virtual void ViewGetLayers( int aLayers[], int& aCount ) const override; - void SetFillMode( ZONE_FILL_MODE aFillMode ) { m_FillMode = aFillMode; } - ZONE_FILL_MODE GetFillMode() const { return m_FillMode; } + void SetFillMode( ZONE_FILL_MODE aFillMode ) { m_FillMode = aFillMode; } + ZONE_FILL_MODE GetFillMode() const { return m_FillMode; } void SetThermalReliefGap( int aThermalReliefGap ) { m_ThermalReliefGap = aThermalReliefGap; } int GetThermalReliefGap( D_PAD* aPad = NULL ) const; void SetThermalReliefCopperBridge( int aThermalReliefCopperBridge ) { + if( m_ThermalReliefCopperBridge != aThermalReliefCopperBridge ) + SetNeedRefill( true ); + m_ThermalReliefCopperBridge = aThermalReliefCopperBridge; } int GetThermalReliefCopperBridge( D_PAD* aPad = NULL ) const; @@ -185,6 +188,9 @@ public: bool IsFilled() const { return m_IsFilled; } void SetIsFilled( bool isFilled ) { m_IsFilled = isFilled; } + bool NeedRefill() const { return m_needRefill; } + void SetNeedRefill( bool aNeedRefill ) { m_needRefill = aNeedRefill; } + int GetZoneClearance() const { return m_ZoneClearance; } void SetZoneClearance( int aZoneClearance ) { m_ZoneClearance = aZoneClearance; } @@ -192,7 +198,13 @@ public: void SetPadConnection( ZoneConnection aPadConnection ) { m_PadConnection = aPadConnection; } int GetMinThickness() const { return m_ZoneMinThickness; } - void SetMinThickness( int aMinThickness ) { m_ZoneMinThickness = aMinThickness; } + void SetMinThickness( int aMinThickness ) + { + if( m_ZoneMinThickness != aMinThickness ) + SetNeedRefill( true ); + + m_ZoneMinThickness = aMinThickness; + } int GetSelectedCorner() const { @@ -488,6 +500,10 @@ public: // Convert global to relative indices if( m_Poly->GetRelativeIndices( aCornerIndex, &relativeIndices ) ) { + if( m_Poly->Vertex( relativeIndices ).x != new_pos.x || + m_Poly->Vertex( relativeIndices ).y != new_pos.y ) + SetNeedRefill( true ); + m_Poly->Vertex( relativeIndices ).x = new_pos.x; m_Poly->Vertex( relativeIndices ).y = new_pos.y; } @@ -723,6 +739,12 @@ private: /** True when a zone was filled, false after deleting the filled areas. */ bool m_IsFilled; + /** False when a zone was refilled, true after changes in zone params. + * m_needRefill = false does not imply filled areas are up to date, just + * the zone was refilled after edition, and does not need refilling + */ + bool m_needRefill; + ///< Width of the gap in thermal reliefs. int m_ThermalReliefGap; diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index 608b8e193b..483be4c244 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -3347,6 +3347,9 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() } } + // Clear flags used in zone edition: + zone->SetNeedRefill( false ); + return zone.release(); } diff --git a/pcbnew/tools/point_editor.cpp b/pcbnew/tools/point_editor.cpp index bcd0971099..63e532d54e 100644 --- a/pcbnew/tools/point_editor.cpp +++ b/pcbnew/tools/point_editor.cpp @@ -561,7 +561,12 @@ void POINT_EDITOR::updateItem() const SHAPE_POLY_SET& outline = *zone->Outline(); for( int i = 0; i < outline.TotalVertices(); ++i ) + { + if( outline.Vertex( i ) != m_editPoints->Point( i ).GetPosition() ) + zone->SetNeedRefill( true ); + outline.Vertex( i ) = m_editPoints->Point( i ).GetPosition(); + } validatePolygon( outline ); zone->Hatch(); @@ -636,7 +641,7 @@ void POINT_EDITOR::finishItem() { auto zone = static_cast( item ); - if( zone->IsFilled() && m_refill ) + if( zone->IsFilled() && m_refill && zone->NeedRefill() ) { ZONE_FILLER filler( board() ); WX_PROGRESS_REPORTER reporter( getEditFrame(), _( "Refill Zones" ), 4 ); @@ -740,7 +745,7 @@ void POINT_EDITOR::updatePoints() case PCB_ZONE_AREA_T: { - const ZONE_CONTAINER* zone = static_cast( item ); + ZONE_CONTAINER* zone = static_cast( item ); const SHAPE_POLY_SET* outline = zone->Outline(); if( m_editPoints->PointsSize() != (unsigned) outline->TotalVertices() ) @@ -989,7 +994,11 @@ int POINT_EDITOR::addCorner( const TOOL_EVENT& aEvent ) SHAPE_POLY_SET* zoneOutline; if( item->Type() == PCB_ZONE_AREA_T ) - zoneOutline = static_cast( item )->Outline(); + { + ZONE_CONTAINER* zone = static_cast( item ); + zoneOutline = zone->Outline(); + zone->SetNeedRefill( true ); + } else zoneOutline = &( graphicItem->GetPolyShape() ); @@ -1100,6 +1109,7 @@ int POINT_EDITOR::removeCorner( const TOOL_EVENT& aEvent ) { auto zone = static_cast( item ); polygon = zone->Outline(); + zone->SetNeedRefill( true ); } else if( (item->Type() == PCB_MODULE_EDGE_T ) || ( item->Type() == PCB_LINE_T ) ) { diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp index 277c8abf6d..8c37ec6983 100644 --- a/pcbnew/zone_filler.cpp +++ b/pcbnew/zone_filler.cpp @@ -805,7 +805,7 @@ void ZONE_FILLER::computeRawFilledAreas( const ZONE_CONTAINER* aZone, * The solid areas can be more than one on copper layers, and do not have holes * ( holes are linked by overlapping segments to the main outline) */ -bool ZONE_FILLER::fillSingleZone( const ZONE_CONTAINER* aZone, SHAPE_POLY_SET& aRawPolys, +bool ZONE_FILLER::fillSingleZone( ZONE_CONTAINER* aZone, SHAPE_POLY_SET& aRawPolys, SHAPE_POLY_SET& aFinalPolys ) const { SHAPE_POLY_SET smoothedPoly; @@ -829,10 +829,11 @@ bool ZONE_FILLER::fillSingleZone( const ZONE_CONTAINER* aZone, SHAPE_POLY_SET& a aFinalPolys.Fracture( SHAPE_POLY_SET::PM_FAST ); } + aZone->SetNeedRefill( false ); return true; } -bool ZONE_FILLER::fillZoneWithSegments( const ZONE_CONTAINER* aZone, +bool ZONE_FILLER::fillZoneWithSegments( ZONE_CONTAINER* aZone, const SHAPE_POLY_SET& aFilledPolys, ZONE_SEGMENT_FILL& aFillSegs ) const { @@ -891,6 +892,7 @@ bool ZONE_FILLER::fillZoneWithSegments( const ZONE_CONTAINER* aZone, } } + aZone->SetNeedRefill( false ); return success; } diff --git a/pcbnew/zone_filler.h b/pcbnew/zone_filler.h index 19c7efdea7..6298a10abb 100644 --- a/pcbnew/zone_filler.h +++ b/pcbnew/zone_filler.h @@ -77,7 +77,7 @@ private: * a list of SEGZONE items is built, line per line * @return true if success, false on error */ - bool fillZoneWithSegments( const ZONE_CONTAINER* aZone, + bool fillZoneWithSegments( ZONE_CONTAINER* aZone, const SHAPE_POLY_SET& aFilledPolys, ZONE_SEGMENT_FILL& aFillSegs ) const; @@ -111,9 +111,8 @@ private: * by aZone->GetMinThickness() / 2 to be drawn with a outline thickness = aZone->GetMinThickness() * aFinalPolys are polygons that will be drawn on screen and plotted */ - bool fillSingleZone( const ZONE_CONTAINER* aZone, - SHAPE_POLY_SET& aRawPolys, - SHAPE_POLY_SET& aFinalPolys ) const; + bool fillSingleZone( ZONE_CONTAINER* aZone, + SHAPE_POLY_SET& aRawPolys, SHAPE_POLY_SET& aFinalPolys ) const; BOARD* m_board; COMMIT* m_commit;