From 6873a7531315df98254fe429c84414eeeff7c4d9 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Fri, 25 Apr 2025 09:36:17 +0100 Subject: [PATCH] Solder masks for teardrops on tracks with solder masks. Also moves teardrops away from the zone UI: they are now always filled and their borders never drawn. Fixes https://gitlab.com/kicad/code/kicad/-/issues/20744 --- pcbnew/pcb_painter.cpp | 3 ++ pcbnew/teardrop/teardrop.cpp | 63 ++++++++++++++++++++++++++++++++++-- pcbnew/teardrop/teardrop.h | 3 ++ 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index e02db4f83e..c97f2dfab8 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -2738,6 +2738,9 @@ void PCB_PAINTER::draw( const ZONE* aZone, int aLayer ) std::deque corners; ZONE_DISPLAY_MODE displayMode = m_pcbSettings.m_ZoneDisplayMode; + if( aZone->IsTeardropArea() ) + displayMode = ZONE_DISPLAY_MODE::SHOW_FILLED; + // Draw the outline if( !IsZoneFillLayer( aLayer ) ) { diff --git a/pcbnew/teardrop/teardrop.cpp b/pcbnew/teardrop/teardrop.cpp index 66a9b1943e..5299968208 100644 --- a/pcbnew/teardrop/teardrop.cpp +++ b/pcbnew/teardrop/teardrop.cpp @@ -73,8 +73,7 @@ ZONE* TEARDROP_MANAGER::createTeardrop( TEARDROP_VARIANT aTeardropVariant, teardrop->SetPadConnection( ZONE_CONNECTION::FULL ); teardrop->SetIsFilled( false ); teardrop->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::NEVER ); - teardrop->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL, - pcbIUScale.mmToIU( 0.1 ), true ); + teardrop->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::INVISIBLE_BORDER, 0, false ); SHAPE_POLY_SET* outline = teardrop->Outline(); outline->NewOutline(); @@ -94,6 +93,45 @@ ZONE* TEARDROP_MANAGER::createTeardrop( TEARDROP_VARIANT aTeardropVariant, } +ZONE* TEARDROP_MANAGER::createTeardropMask( TEARDROP_VARIANT aTeardropVariant, + std::vector& aPoints, PCB_TRACK* aTrack ) const +{ + ZONE* teardrop = new ZONE( m_board ); + + teardrop->SetTeardropAreaType( aTeardropVariant == TD_TYPE_PADVIA ? TEARDROP_TYPE::TD_VIAPAD + : TEARDROP_TYPE::TD_TRACKEND ); + teardrop->SetLayer( aTrack->GetLayer() == F_Cu ? F_Mask : B_Mask ); + teardrop->SetMinThickness( pcbIUScale.mmToIU( 0.0254 ) ); // The minimum zone thickness + teardrop->SetIsFilled( false ); + teardrop->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::NEVER ); + teardrop->SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE::INVISIBLE_BORDER, 0, false ); + + SHAPE_POLY_SET* outline = teardrop->Outline(); + outline->NewOutline(); + + for( const VECTOR2I& pt: aPoints ) + outline->Append( pt.x, pt.y ); + + if( int expansion = aTrack->GetSolderMaskExpansion() ) + { + // The zone-min-thickness deflate/reinflate is going to round corners, so it's more + // efficient to allow acute corners on the solder mask expansion here, and delegate the + // rounding to the deflate/reinflate. + teardrop->SetMinThickness( std::max( teardrop->GetMinThickness(), expansion ) ); + + outline->Inflate( expansion, CORNER_STRATEGY::ALLOW_ACUTE_CORNERS, + m_board->GetDesignSettings().m_MaxError ); + } + + // Until we know better (ie: pay for a potentially very expensive zone refill), the teardrop + // fill is the same as its outline. + teardrop->SetFilledPolysList( teardrop->GetLayer(), *teardrop->Outline() ); + teardrop->SetIsFilled( true ); + + return teardrop; +} + + void TEARDROP_MANAGER::RemoveTeardrops( BOARD_COMMIT& aCommit, const std::vector* dirtyPadsAndVias, const std::set* dirtyTracks ) @@ -217,6 +255,13 @@ void TEARDROP_MANAGER::UpdateTeardrops( BOARD_COMMIT& aCommit, m_createdTdList.push_back( new_teardrop ); aCommit.Added( new_teardrop ); + + if( track->HasSolderMask() && ( track->GetLayer() == F_Cu || track->GetLayer() == B_Cu ) ) + { + ZONE* new_teardrop_mask = createTeardropMask( TD_TYPE_PADVIA, points, track ); + m_board->Add( new_teardrop_mask, ADD_MODE::BULK_INSERT ); + aCommit.Added( new_teardrop_mask ); + } } } @@ -253,6 +298,13 @@ void TEARDROP_MANAGER::UpdateTeardrops( BOARD_COMMIT& aCommit, m_createdTdList.push_back( new_teardrop ); aCommit.Added( new_teardrop ); + + if( track->HasSolderMask() && ( track->GetLayer() == F_Cu || track->GetLayer() == B_Cu ) ) + { + ZONE* new_teardrop_mask = createTeardropMask( TD_TYPE_PADVIA, points, track ); + m_board->Add( new_teardrop_mask, ADD_MODE::BULK_INSERT ); + aCommit.Added( new_teardrop_mask ); + } } } } @@ -428,6 +480,13 @@ void TEARDROP_MANAGER::AddTeardropsOnTracks( BOARD_COMMIT& aCommit, m_createdTdList.push_back( new_teardrop ); aCommit.Added( new_teardrop ); + + if( track->HasSolderMask() && ( track->GetLayer() == F_Cu || track->GetLayer() == B_Cu ) ) + { + ZONE* new_teardrop_mask = createTeardropMask( TD_TYPE_TRACKEND, points, track ); + m_board->Add( new_teardrop_mask, ADD_MODE::BULK_INSERT ); + aCommit.Added( new_teardrop_mask ); + } } } } diff --git a/pcbnew/teardrop/teardrop.h b/pcbnew/teardrop/teardrop.h index cebd9c6cab..2979069169 100644 --- a/pcbnew/teardrop/teardrop.h +++ b/pcbnew/teardrop/teardrop.h @@ -205,6 +205,9 @@ private: ZONE* createTeardrop( TEARDROP_VARIANT aTeardropVariant, std::vector& aPoints, PCB_TRACK* aTrack ) const; + ZONE* createTeardropMask( TEARDROP_VARIANT aTeardropVariant, + std::vector& aPoints, PCB_TRACK* aTrack ) const; + /** * Set priority of created teardrops. smaller have bigger priority */