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;