diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 02531370a4..5b84ec9543 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -531,6 +531,7 @@ set( PCB_COMMON_SRCS ${CMAKE_SOURCE_DIR}/pcbnew/board_commit.cpp ${CMAKE_SOURCE_DIR}/pcbnew/board_connected_item.cpp ${CMAKE_SOURCE_DIR}/pcbnew/board_design_settings.cpp + ${CMAKE_SOURCE_DIR}/pcbnew/teardrop/teardrop_parameters.cpp #needed by board_design_settings.cpp ${CMAKE_SOURCE_DIR}/pcbnew/board.cpp ${CMAKE_SOURCE_DIR}/pcbnew/board_item.cpp ${CMAKE_SOURCE_DIR}/pcbnew/pcb_dimension.cpp diff --git a/include/board_design_settings.h b/include/board_design_settings.h index e9f0a90af5..fd9240c759 100644 --- a/include/board_design_settings.h +++ b/include/board_design_settings.h @@ -34,6 +34,7 @@ #include #include #include +#include #define DEFAULT_SILK_LINE_WIDTH 0.12 @@ -231,6 +232,11 @@ public: BOARD_STACKUP& GetStackupDescriptor() { return m_stackup; } const BOARD_STACKUP& GetStackupDescriptor() const { return m_stackup; } + TEARDROP_PARAMETERS_LIST* GetTeadropParamsList() + { + return &m_TeardropParamsList; + } + SEVERITY GetSeverity( int aDRCErrorCode ); /** @@ -662,6 +668,11 @@ public: std::vector m_ViasDimensionsList; std::vector m_DiffPairDimensionsList; + /** The parameters of teardrops for the different teardrop targets (via/pad, track end) + * 3 set of parameters always exist: for round shapes, for rect shapes, for track ends + */ + TEARDROP_PARAMETERS_LIST m_TeardropParamsList; + bool m_MicroViasAllowed; ///< true to allow micro vias bool m_BlindBuriedViaAllowed; ///< true to allow blind/buried vias VIATYPE m_CurrentViaType; ///< (VIA_BLIND_BURIED, VIA_THROUGH, VIA_MICROVIA) diff --git a/pcbnew/board_design_settings.cpp b/pcbnew/board_design_settings.cpp index 5e54d06cfa..866e00605e 100644 --- a/pcbnew/board_design_settings.cpp +++ b/pcbnew/board_design_settings.cpp @@ -448,6 +448,110 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std: }, {} ) ); + // Handle options for teardrops (targets and some others): + m_params.emplace_back( new PARAM_LAMBDA( "teardrop_options", + [&]() -> nlohmann::json + { + nlohmann::json js = nlohmann::json::array(); + nlohmann::json entry = {}; + + entry["td_onviapad"] = m_TeardropParamsList.m_TargetViasPads; + entry["td_onpadsmd"] = m_TeardropParamsList.m_TargetPadsWithNoHole; + entry["td_ontrackend"] = m_TeardropParamsList.m_TargetTrack2Track; + entry["td_onroundshapesonly"] = m_TeardropParamsList.m_UseRoundShapesOnly; + entry["td_allow_use_two_tracks"] = m_TeardropParamsList.m_AllowUseTwoTracks; + entry["td_curve_segcount"] = m_TeardropParamsList.m_CurveSegCount; + + js.push_back( entry ); + + return js; + }, + [&]( const nlohmann::json& aObj ) + { + if( !aObj.is_array() ) + return; + + for( const nlohmann::json& entry : aObj ) + { + if( entry.empty() || !entry.is_object() ) + continue; + + if( !entry.contains( "td_onviapad" ) + || !entry.contains( "td_onpadsmd" ) + || !entry.contains( "td_ontrackend" ) + || !entry.contains( "td_onroundshapesonly" ) + || !entry.contains( "td_allow_use_two_tracks" ) + || !entry.contains( "td_curve_segcount" ) + ) + continue; + + m_TeardropParamsList.m_TargetViasPads = entry["td_onviapad"].get(); + m_TeardropParamsList.m_TargetPadsWithNoHole = entry["td_onpadsmd"].get(); + m_TeardropParamsList.m_TargetTrack2Track = entry["td_ontrackend"].get(); + m_TeardropParamsList.m_UseRoundShapesOnly = entry["td_onroundshapesonly"].get(); + m_TeardropParamsList.m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get(); + m_TeardropParamsList.m_CurveSegCount = entry["td_curve_segcount"].get(); + } + }, + {} ) ); + + // Handle parameters (sizes, shape) for each type of teardrop: + m_params.emplace_back( new PARAM_LAMBDA( "teardrop_parameters", + [&]() -> nlohmann::json + { + nlohmann::json js = nlohmann::json::array(); + + for( int ii = 0; ii < m_TeardropParamsList.GetParametersCount(); ii++ ) + { + nlohmann::json entry = {}; + TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)ii ); + + entry["td_target_name"] = GetTeardropTargetCanonicalName( (TARGET_TD)ii ); + entry["td_maxlen"] = Iu2Millimeter( td_prm->m_TdMaxLen ); + entry["td_maxheight"] = Iu2Millimeter( td_prm->m_TdMaxHeight ); + entry["td_length_ratio"] = td_prm->m_LengthRatio; + entry["td_height_ratio"] = td_prm->m_HeightRatio; + entry["td_curve_segcount"] = td_prm->m_CurveSegCount; + + js.push_back( entry ); + } + + return js; + }, + [&]( const nlohmann::json& aObj ) + { + if( !aObj.is_array() ) + return; + + for( const nlohmann::json& entry : aObj ) + { + if( entry.empty() || !entry.is_object() ) + continue; + + if( !entry.contains( "td_target_name" ) + || !entry.contains( "td_maxlen" ) + || !entry.contains( "td_maxheight" ) + || !entry.contains( "td_length_ratio" ) + || !entry.contains( "td_height_ratio" ) + || !entry.contains( "td_curve_segcount" ) + ) + continue; + + int idx = GetTeardropTargetTypeFromCanonicalName( entry["td_target_name"].get() ); + + if( idx >= 0 && idx < 3 ) + { + TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)idx ); + td_prm->m_TdMaxLen = Millimeter2iu( entry["td_maxlen"].get() ); + td_prm->m_TdMaxHeight = Millimeter2iu( entry["td_maxheight"].get() ); + td_prm->m_LengthRatio = entry["td_length_ratio"].get(); + td_prm->m_HeightRatio = entry["td_height_ratio"].get(); + td_prm->m_CurveSegCount = entry["td_curve_segcount"].get(); + } + } + }, + {} ) ); + m_params.emplace_back( new PARAM_SCALED( "defaults.silk_line_width", &m_LineThickness[LAYER_CLASS_SILK], Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) ); diff --git a/pcbnew/teardrop/dialog_teardrop.cpp b/pcbnew/teardrop/dialog_teardrop.cpp index 657451540a..49d1448402 100644 --- a/pcbnew/teardrop/dialog_teardrop.cpp +++ b/pcbnew/teardrop/dialog_teardrop.cpp @@ -43,6 +43,7 @@ class TEARDROP_DIALOG: public TEARDROP_DIALOG_BASE public: TEARDROP_DIALOG( PCB_EDIT_FRAME* aParent ): TEARDROP_DIALOG_BASE( aParent ), + m_brdSettings( nullptr ), m_frame( aParent ), m_teardropMaxLenSettingRound( aParent,m_stMaxLenRound, m_tcTdMaxLenRound, nullptr ), m_teardropMaxHeightSettingRound( aParent, m_stTdMaxSizeRound, m_tcMaxHeightRound, m_stLenUnitRound ), @@ -56,30 +57,37 @@ public: m_bitmapTdRectangularInfo->SetBitmap( KiBitmap( BITMAPS::teardrop_rect_sizes ) ); m_bitmapTdTrackInfo->SetBitmap( KiBitmap( BITMAPS::teardrop_track_sizes ) ); - m_cbSmdSimilarPads->SetValue( m_includeNotPTH ); - m_cbRoundShapesOnly->SetValue( m_roundShapesOnly ); - m_rbShapeRound->SetSelection( m_curveOptionRoundShapes ); - m_rbShapeRect->SetSelection( m_curveOptionRectShapes ); - m_rbShapeTrack->SetSelection( m_curveOptionTrackShapes ); - m_cbOptUseNextTrack->SetValue( m_canUseTwoTracks ); - m_spPointCount->SetValue( m_curveSegCount ); - m_cbTrack2Track->SetValue( m_track2Track ); - m_cbPadVia->SetValue( m_includeViasAndPTH ); + m_brdSettings = &m_frame->GetBoard()->GetBoard()->GetDesignSettings(); + TEARDROP_PARAMETERS_LIST* prmsList = m_brdSettings->GetTeadropParamsList(); - m_teardropMaxLenSettingRound.SetValue( m_teardropMaxLenPrmRound ); - m_teardropMaxHeightSettingRound.SetValue( m_teardropMaxSizePrmRound ); - m_spTeardropLenPercentRound->SetValue( m_teardropLenPrmRound ); - m_spTeardropSizePercentRound->SetValue( m_teardropSizePrmRound ); + m_cbPadVia->SetValue( prmsList->m_TargetViasPads ); + m_cbSmdSimilarPads->SetValue( prmsList->m_TargetPadsWithNoHole ); + m_cbRoundShapesOnly->SetValue( prmsList->m_UseRoundShapesOnly ); + m_cbTrack2Track->SetValue( prmsList->m_TargetTrack2Track ); - m_teardropMaxLenSettingRect.SetValue( m_teardropMaxLenPrmRect ); - m_teardropMaxHeightSettingRect.SetValue( m_teardropMaxSizePrmRect ); - m_spTeardropLenPercentRect->SetValue( m_teardropLenPrmRect ); - m_spTeardropSizePercentRect->SetValue( m_teardropSizePrmRect ); + m_cbOptUseNextTrack->SetValue( prmsList->m_AllowUseTwoTracks ); + m_spPointCount->SetValue( prmsList->m_CurveSegCount ); - m_teardropMaxLenSettingTrack.SetValue( m_teardropMaxLenPrmTrack ); - m_teardropMaxHeightSettingTrack.SetValue( m_teardropMaxSizePrmTrack ); - m_spTeardropLenPercentTrack->SetValue( m_teardropLenPrmTrack ); - m_spTeardropSizePercentTrack->SetValue( m_teardropSizePrmTrack ); + TEARDROP_PARAMETERS* prms = prmsList->GetParameters( TARGET_ROUND ); + m_teardropMaxLenSettingRound.SetValue( prms->m_TdMaxLen ); + m_teardropMaxHeightSettingRound.SetValue( prms->m_TdMaxHeight ); + m_spTeardropLenPercentRound->SetValue( prms->m_LengthRatio*100 ); + m_spTeardropSizePercentRound->SetValue( prms->m_HeightRatio*100 ); + m_rbShapeRound->SetSelection( prms->IsCurved() ); + + prms = prmsList->GetParameters( TARGET_RECT ); + m_teardropMaxLenSettingRect.SetValue( prms->m_TdMaxLen ); + m_teardropMaxHeightSettingRect.SetValue( prms->m_TdMaxHeight ); + m_spTeardropLenPercentRect->SetValue( prms->m_LengthRatio*100 ); + m_spTeardropSizePercentRect->SetValue(prms->m_HeightRatio*100 ); + m_rbShapeRect->SetSelection( prms->IsCurved() ); + + prms = prmsList->GetParameters( TARGET_TRACK ); + m_teardropMaxLenSettingTrack.SetValue(prms->m_TdMaxLen ); + m_teardropMaxHeightSettingTrack.SetValue( prms->m_TdMaxHeight ); + m_spTeardropLenPercentTrack->SetValue( prms->m_LengthRatio*100 ); + m_spTeardropSizePercentTrack->SetValue( prms->m_HeightRatio*100 ); + m_rbShapeTrack->SetSelection( prms->IsCurved() ); // recalculate sizers, now the bitmap is initialized finishDialogSettings(); @@ -87,30 +95,37 @@ public: ~TEARDROP_DIALOG() { - m_teardropLenPrmRound = m_spTeardropLenPercentRound->GetValue(); - m_teardropSizePrmRound = m_spTeardropSizePercentRound->GetValue(); - m_teardropMaxLenPrmRound = m_teardropMaxLenSettingRound.GetValue(); - m_teardropMaxSizePrmRound = m_teardropMaxHeightSettingRound.GetValue(); + int shape_seg_count = GetCurvePointCount(); + TEARDROP_PARAMETERS_LIST* prmsList = m_brdSettings->GetTeadropParamsList(); - m_teardropLenPrmRect = m_spTeardropLenPercentRect->GetValue(); - m_teardropSizePrmRect = m_spTeardropSizePercentRect->GetValue(); - m_teardropMaxLenPrmRect = m_teardropMaxLenSettingRect.GetValue(); - m_teardropMaxSizePrmRect = m_teardropMaxHeightSettingRect.GetValue(); + prmsList->m_TargetViasPads = m_cbPadVia->GetValue(); + prmsList->m_TargetPadsWithNoHole = m_cbSmdSimilarPads->GetValue(); + prmsList->m_UseRoundShapesOnly = m_cbRoundShapesOnly->GetValue(); + prmsList->m_TargetTrack2Track = m_cbTrack2Track->GetValue(); - m_teardropLenPrmTrack = m_spTeardropLenPercentTrack->GetValue(); - m_teardropSizePrmTrack = m_spTeardropSizePercentTrack->GetValue(); - m_teardropMaxLenPrmTrack = m_teardropMaxLenSettingTrack.GetValue(); - m_teardropMaxSizePrmTrack = m_teardropMaxHeightSettingTrack.GetValue(); + prmsList->m_AllowUseTwoTracks = m_cbOptUseNextTrack->GetValue(); + prmsList->m_CurveSegCount = m_spPointCount->GetValue(); - m_roundShapesOnly = m_cbRoundShapesOnly->GetValue(); - m_includeNotPTH = m_cbSmdSimilarPads->GetValue(); - m_curveOptionRoundShapes = m_rbShapeRound->GetSelection(); - m_curveOptionRectShapes = m_rbShapeRect->GetSelection(); - m_curveOptionTrackShapes = m_rbShapeTrack->GetSelection(); - m_canUseTwoTracks = m_cbOptUseNextTrack->GetValue(); - m_curveSegCount = m_spPointCount->GetValue(); - m_track2Track = m_cbTrack2Track->GetValue(); - m_includeViasAndPTH = m_cbPadVia->GetValue(); + TEARDROP_PARAMETERS* prms = prmsList->GetParameters( TARGET_ROUND ); + prms->m_LengthRatio = GetTeardropLenPercentRound(); + prms->m_HeightRatio = GetTeardropSizePercentRound(); + prms->m_TdMaxLen = m_teardropMaxLenSettingRound.GetValue(); + prms->m_TdMaxHeight = m_teardropMaxHeightSettingRound.GetValue(); + prms->m_CurveSegCount = (CurvedShapeOption() & CURVED_OPTION_ROUND) ? shape_seg_count : 0; + + prms = prmsList->GetParameters( TARGET_RECT ); + prms->m_LengthRatio = GetTeardropLenPercentRect(); + prms->m_HeightRatio = GetTeardropSizePercentRect(); + prms->m_TdMaxLen = m_teardropMaxLenSettingRect.GetValue(); + prms->m_TdMaxHeight = m_teardropMaxHeightSettingRect.GetValue(); + prms->m_CurveSegCount = (CurvedShapeOption() & CURVED_OPTION_RECT) ? shape_seg_count : 0; + + prms = prmsList->GetParameters( TARGET_TRACK ); + prms->m_LengthRatio = GetTeardropLenPercentTrack(); + prms->m_HeightRatio = GetTeardropSizePercentTrack(); + prms->m_TdMaxLen = m_teardropMaxLenSettingTrack.GetValue(); + prms->m_TdMaxHeight = m_teardropMaxHeightSettingTrack.GetValue(); + prms->m_CurveSegCount = (CurvedShapeOption() & CURVED_OPTION_TRACK) ? shape_seg_count : 0; } int CurvedShapeOption() @@ -158,6 +173,7 @@ public: bool TeardropOnTracks() { return m_cbTrack2Track->GetValue(); } private: + BOARD_DESIGN_SETTINGS* m_brdSettings; PCB_EDIT_FRAME* m_frame; UNIT_BINDER m_teardropMaxLenSettingRound; UNIT_BINDER m_teardropMaxHeightSettingRound; @@ -165,61 +181,8 @@ private: UNIT_BINDER m_teardropMaxHeightSettingRect; UNIT_BINDER m_teardropMaxLenSettingTrack; UNIT_BINDER m_teardropMaxHeightSettingTrack; - - // Used to store settings during a session: - static double m_teardropLenPrmRound; - static double m_teardropSizePrmRound; - static int m_teardropMaxLenPrmRound; - static int m_teardropMaxSizePrmRound; - - static double m_teardropLenPrmRect; - static double m_teardropSizePrmRect; - static int m_teardropMaxLenPrmRect; - static int m_teardropMaxSizePrmRect; - - static double m_teardropLenPrmTrack; - static double m_teardropSizePrmTrack; - static int m_teardropMaxLenPrmTrack; - static int m_teardropMaxSizePrmTrack; - - static bool m_includeNotPTH; - static bool m_roundShapesOnly; - static int m_curveOptionRoundShapes; - static int m_curveOptionRectShapes; - static int m_curveOptionTrackShapes; - static bool m_canUseTwoTracks; - static int m_curveSegCount; - static bool m_track2Track; - static bool m_includeViasAndPTH; - }; -// Store settings during a session: -double TEARDROP_DIALOG::m_teardropLenPrmRound = 50; -double TEARDROP_DIALOG::m_teardropSizePrmRound = 100; -int TEARDROP_DIALOG::m_teardropMaxLenPrmRound = Millimeter2iu( 1.0 ); -int TEARDROP_DIALOG::m_teardropMaxSizePrmRound = Millimeter2iu( 2.0 ); - -double TEARDROP_DIALOG::m_teardropLenPrmRect = 50; -double TEARDROP_DIALOG::m_teardropSizePrmRect = 100; -int TEARDROP_DIALOG::m_teardropMaxLenPrmRect = Millimeter2iu( 1.0 ); -int TEARDROP_DIALOG::m_teardropMaxSizePrmRect = Millimeter2iu( 2.0 ); - -double TEARDROP_DIALOG::m_teardropLenPrmTrack = 100; -double TEARDROP_DIALOG::m_teardropSizePrmTrack = 100; -int TEARDROP_DIALOG::m_teardropMaxLenPrmTrack = Millimeter2iu( 2.0 ); -int TEARDROP_DIALOG::m_teardropMaxSizePrmTrack = Millimeter2iu( 2.0 ); - -bool TEARDROP_DIALOG::m_includeNotPTH = true; -bool TEARDROP_DIALOG::m_roundShapesOnly = false; -int TEARDROP_DIALOG::m_curveOptionRoundShapes = 0; -int TEARDROP_DIALOG::m_curveOptionRectShapes = 0; -int TEARDROP_DIALOG::m_curveOptionTrackShapes = 0; -bool TEARDROP_DIALOG::m_canUseTwoTracks = true; -int TEARDROP_DIALOG::m_curveSegCount = 5; -bool TEARDROP_DIALOG::m_track2Track = true; -bool TEARDROP_DIALOG::m_includeViasAndPTH = true; - void PCB_EDIT_FRAME::OnRunTeardropTool( wxCommandEvent& event ) { diff --git a/pcbnew/teardrop/teardrop.cpp b/pcbnew/teardrop/teardrop.cpp index a9f54ce4a6..854b7b60fc 100644 --- a/pcbnew/teardrop/teardrop.cpp +++ b/pcbnew/teardrop/teardrop.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2021 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -156,8 +156,8 @@ int TEARDROP_MANAGER::SetTeardrops( BOARD_COMMIT* aCommitter, // Ensure a teardrop shape can be built: // The track width must be < teardrop height - if( track->GetWidth() >= currParams->m_tdMaxHeight - || track->GetWidth() >= viapad.m_Width * currParams->m_heightRatio ) + if( track->GetWidth() >= currParams->m_TdMaxHeight + || track->GetWidth() >= viapad.m_Width * currParams->m_HeightRatio ) continue; // Skip case where pad/via and the track is within a copper zone with the same net diff --git a/pcbnew/teardrop/teardrop_parameters.cpp b/pcbnew/teardrop/teardrop_parameters.cpp new file mode 100644 index 0000000000..4b0a39250c --- /dev/null +++ b/pcbnew/teardrop/teardrop_parameters.cpp @@ -0,0 +1,62 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2021 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "teardrop_parameters.h" + +#define TARGET_NAME_ROUND "td_round_shape" +#define TARGET_NAME_RECT "td_rect_shape" +#define TARGET_NAME_TRACK "td_track_end" + +std::string GetTeardropTargetCanonicalName( TARGET_TD aTdType ) +{ + // return the canonical name of the target aTdType + std::string name; + + switch( aTdType ) + { + case TARGET_ROUND: name = TARGET_NAME_ROUND; break; + case TARGET_RECT: name = TARGET_NAME_RECT; break; + case TARGET_TRACK: name = TARGET_NAME_TRACK; break; + default: break; + } + + return name; +} + + +TARGET_TD GetTeardropTargetTypeFromCanonicalName( const std::string& aTargetName ) +{ + // return the target type from the canonical name + + if( aTargetName == TARGET_NAME_ROUND ) + return TARGET_ROUND; + + if( aTargetName == TARGET_NAME_RECT ) + return TARGET_RECT; + + if( aTargetName == TARGET_NAME_TRACK ) + return TARGET_TRACK; + + return TARGET_UNKNOWN; +} diff --git a/pcbnew/teardrop/teardrop_parameters.h b/pcbnew/teardrop/teardrop_parameters.h index d36c3a6c58..98c592488e 100644 --- a/pcbnew/teardrop/teardrop_parameters.h +++ b/pcbnew/teardrop/teardrop_parameters.h @@ -25,9 +25,14 @@ #ifndef TEARDROP_PARAMS_H #define TEARDROP_PARAMS_H +#include +#include +#include + // IDs for targets when creating teardrops enum TARGET_TD { + TARGET_UNKNOWN = -1, TARGET_ROUND = 0, TARGET_RECT = 1, TARGET_TRACK = 2, @@ -41,16 +46,14 @@ enum TARGET_TD */ class TEARDROP_PARAMETERS { - friend class TEARDROP_MANAGER; - friend class TEARDROP_PARAMETERS_LIST; - public: - TEARDROP_PARAMETERS(): - m_tdMaxLen( Millimeter2iu( 1.0 ) ), - m_tdMaxHeight( Millimeter2iu( 2.0 ) ), - m_lengthRatio( 0.5), - m_heightRatio( 1.0 ), - m_curveSegCount( 0 ) + TEARDROP_PARAMETERS( TARGET_TD aTdType ): + m_TdType( aTdType ), + m_TdMaxLen( Millimeter2iu( 1.0 ) ), + m_TdMaxHeight( Millimeter2iu( 2.0 ) ), + m_LengthRatio( 0.5), + m_HeightRatio( 1.0 ), + m_CurveSegCount( 0 ) { } @@ -60,8 +63,8 @@ public: */ void SetTeardropMaxSize( int aMaxLen, int aMaxHeight ) { - m_tdMaxLen = aMaxLen; - m_tdMaxHeight = aMaxHeight; + m_TdMaxLen = aMaxLen; + m_TdMaxHeight = aMaxHeight; } /** @@ -71,8 +74,8 @@ public: */ void SetTeardropSizeRatio( double aLenghtRatio = 0.5, double aHeightRatio = 1.0 ) { - m_lengthRatio = aLenghtRatio; - m_heightRatio = aHeightRatio; + m_LengthRatio = aLenghtRatio; + m_HeightRatio = aHeightRatio; } /** @@ -81,23 +84,24 @@ public: */ void SetTeardropCurvedPrm( int aCurveSegCount = 0 ) { - m_curveSegCount = aCurveSegCount; + m_CurveSegCount = aCurveSegCount; } - bool IsCurved() const { return m_curveSegCount > 2; } + bool IsCurved() const { return m_CurveSegCount > 2; } -protected: +public: + TARGET_TD m_TdType; /// the type of target for these parameters /// max allowed length for teardrops in IU. <= 0 to disable - int m_tdMaxLen; + int m_TdMaxLen; /// max allowed height for teardrops in IU. <= 0 to disable - int m_tdMaxHeight; + int m_TdMaxHeight; /// The length of a teardrop as ratio between length and size of pad/via - double m_lengthRatio; + double m_LengthRatio; /// The height of a teardrop as ratio between height and size of pad/via - double m_heightRatio; + double m_HeightRatio; /// number of segments to build the curved sides of a teardrop area /// must be > 2. for values <= 2 a straight line is used - int m_curveSegCount; + int m_CurveSegCount; }; @@ -111,11 +115,33 @@ class TEARDROP_PARAMETERS_LIST std::vector m_params_list; public: - TEARDROP_PARAMETERS_LIST() + /// True to create teardrops for vias and pads with holes + bool m_TargetViasPads; + /// True to create teardrops for pads without holes (SMD and others + bool m_TargetPadsWithNoHole; + /// True to create teardrops at the end of a track connected to the end of + /// another track having a different width + bool m_TargetTrack2Track; + /// True to create teardrops for round shapes only + bool m_UseRoundShapesOnly; + /// True to create teardrops using 2 track segments if the first in too small + bool m_AllowUseTwoTracks; + /// the number of segments to apprximate a curve (Bezier curve) in a teardrop + /// Must be > 2, otherwise a line is used + int m_CurveSegCount; + +public: + TEARDROP_PARAMETERS_LIST() : + m_TargetViasPads( true ), + m_TargetPadsWithNoHole( true ), + m_TargetTrack2Track( false ), + m_UseRoundShapesOnly( false ), + m_AllowUseTwoTracks( true ), + m_CurveSegCount( 5 ) { - m_params_list.emplace_back( ); // parameters for TARGET_ROUND - m_params_list.emplace_back( ); // parameters for TARGET_RECT - m_params_list.emplace_back( ); // parameters for TARGET_TRACK + m_params_list.emplace_back( TARGET_ROUND ); // parameters for TARGET_ROUND + m_params_list.emplace_back( TARGET_RECT ); // parameters for TARGET_RECT + m_params_list.emplace_back( TARGET_TRACK ); // parameters for TARGET_TRACK } /** @@ -136,4 +162,16 @@ public: }; +/** + * @return the canonical name of a target type of a TEARDROP_PARAMETERS + * @param aTdType is the target type + */ +std::string GetTeardropTargetCanonicalName( TARGET_TD aTdType ); + +/** + * @return the target type from a canonical name of a TEARDROP_PARAMETERS + * @param aTargetName is the canonical name + */ +TARGET_TD GetTeardropTargetTypeFromCanonicalName( const std::string& aTargetName ); + #endif // ifndef TEARDROP_PARAMS_H diff --git a/pcbnew/teardrop/teardrop_utils.cpp b/pcbnew/teardrop/teardrop_utils.cpp index 3e849bbac4..33155a8030 100644 --- a/pcbnew/teardrop/teardrop_utils.cpp +++ b/pcbnew/teardrop/teardrop_utils.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2021 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -263,14 +263,14 @@ void TEARDROP_MANAGER::computeCurvedForRoundShape( TEARDROP_PARAMETERS* aCurrPar // A and B are points on the track ( pts[0] and pts[1] ) // C and E are points on the aViaPad ( pts[2] and pts[4] ) // D is the aViaPad centre ( pts[3] ) - double Vpercent = aCurrParams->m_heightRatio; + double Vpercent = aCurrParams->m_HeightRatio; int td_height = aViaPad.m_Width * Vpercent; // First, calculate a aVpercent equivalent to the td_height clamped by aTdMaxHeight // We cannot use the initial aVpercent because it gives bad shape with points // on aViaPad calculated for a clamped aViaPad size - if( aCurrParams->m_tdMaxHeight > 0 && aCurrParams->m_tdMaxHeight < td_height ) - Vpercent *= (double)aCurrParams->m_tdMaxHeight / td_height; + if( aCurrParams->m_TdMaxHeight > 0 && aCurrParams->m_TdMaxHeight < td_height ) + Vpercent *= (double)aCurrParams->m_TdMaxHeight / td_height; int radius = aViaPad.m_Width / 2; double minVpercent = double( aTrackHalfWidth ) / radius; @@ -290,9 +290,9 @@ void TEARDROP_MANAGER::computeCurvedForRoundShape( TEARDROP_PARAMETERS* aCurrPar VECTOR2I tangentA = VECTOR2I( pts[0].x - aTrackDir.x * biasAE, pts[0].y - aTrackDir.y * biasAE ); std::vector curve_pts; - curve_pts.reserve( aCurrParams->m_curveSegCount ); + curve_pts.reserve( aCurrParams->m_CurveSegCount ); BEZIER_POLY( pts[1], tangentB, tangentC, pts[2] ).GetPoly( curve_pts, 0, - aCurrParams->m_curveSegCount ); + aCurrParams->m_CurveSegCount ); for( VECTOR2I& corner: curve_pts ) aPoly.push_back( corner ); @@ -301,7 +301,7 @@ void TEARDROP_MANAGER::computeCurvedForRoundShape( TEARDROP_PARAMETERS* aCurrPar curve_pts.clear(); BEZIER_POLY( pts[4], tangentE, tangentA, pts[0] ).GetPoly( curve_pts, 0, - aCurrParams->m_curveSegCount ); + aCurrParams->m_CurveSegCount ); for( VECTOR2I& corner: curve_pts ) aPoly.push_back( corner ); @@ -328,7 +328,7 @@ void TEARDROP_MANAGER::computeCurvedForRectShape( TEARDROP_PARAMETERS* aCurrPar VECTOR2I side2( aPts[4] - aPts[0] ); // vector from track to via std::vector curve_pts; - curve_pts.reserve( aCurrParams->m_curveSegCount ); + curve_pts.reserve( aCurrParams->m_CurveSegCount ); // Note: This side is from track to via VECTOR2I ctrl1 = ( aPts[1] + aPts[1] + aPts[2] ) / 3; @@ -360,7 +360,7 @@ void TEARDROP_MANAGER::computeCurvedForRectShape( TEARDROP_PARAMETERS* aCurrPar ctrl2.y += bias.y; BEZIER_POLY( aPts[1], ctrl1, ctrl2, aPts[2] ).GetPoly( curve_pts, 0, - aCurrParams->m_curveSegCount ); + aCurrParams->m_CurveSegCount ); for( VECTOR2I& corner: curve_pts ) aPoly.push_back( corner ); @@ -388,7 +388,7 @@ void TEARDROP_MANAGER::computeCurvedForRectShape( TEARDROP_PARAMETERS* aCurrPar ctrl2.y += bias.y; BEZIER_POLY( aPts[4], ctrl1, ctrl2, aPts[0] ).GetPoly( curve_pts, 0, - aCurrParams->m_curveSegCount ); + aCurrParams->m_CurveSegCount ); for( VECTOR2I& corner: curve_pts ) aPoly.push_back( corner ); @@ -410,17 +410,17 @@ bool TEARDROP_MANAGER::ComputePointsOnPadVia( TEARDROP_PARAMETERS* aCurrParams, // For rectangular (and similar) shapes, the preferred_height is calculated from the min // dim of the rectangle = aViaPad.m_Width - int preferred_height = aViaPad.m_Width * aCurrParams->m_heightRatio; + int preferred_height = aViaPad.m_Width * aCurrParams->m_HeightRatio; // force_clip_shape = true to force the via/pad polygon to be clipped to follow // contraints // Clipping is also needed for rectangular shapes, because the teardrop shape is // restricted to a polygonal area smaller than the pad area (the teardrop height // use the smaller value of X and Y sizes). - bool force_clip_shape = aCurrParams->m_heightRatio < 1.0; + bool force_clip_shape = aCurrParams->m_HeightRatio < 1.0; // To find the anchor points on via/pad shape, we build the polygonal shape, and clip the polygon - // to the max size (preferred_height or m_tdMaxHeight) by a rectangle centered on the + // to the max size (preferred_height or m_TdMaxHeight) by a rectangle centered on the // axis of the expected teardrop shape. // (only reduce the size of polygonal shape does not give good anchor points) if( aViaPad.m_IsRound ) @@ -433,18 +433,18 @@ bool TEARDROP_MANAGER::ComputePointsOnPadVia( TEARDROP_PARAMETERS* aCurrParams, wxASSERT( pad ); force_clip_shape = true; - preferred_height = aViaPad.m_Width * aCurrParams->m_heightRatio; + preferred_height = aViaPad.m_Width * aCurrParams->m_HeightRatio; pad->TransformShapeWithClearanceToPolygon( c_buffer, aTrack->GetLayer(), 0, ARC_LOW_DEF, ERROR_INSIDE ); } - // Clip the pad/via shape to match the m_tdMaxHeight constraint, and for + // Clip the pad/via shape to match the m_TdMaxHeight constraint, and for // not rounded pad, clip the shape at the aViaPad.m_Width, i.e. the value // of the smallest value between size.x and size.y values. - if( force_clip_shape || ( aCurrParams->m_tdMaxHeight > 0 - && aCurrParams->m_tdMaxHeight < preferred_height ) ) + if( force_clip_shape || ( aCurrParams->m_TdMaxHeight > 0 + && aCurrParams->m_TdMaxHeight < preferred_height ) ) { - int halfsize = std::min( aCurrParams->m_tdMaxHeight, preferred_height )/2; + int halfsize = std::min( aCurrParams->m_TdMaxHeight, preferred_height )/2; // teardrop_axis is the line from anchor point on the track and the end point // of the teardrop in the pad/via @@ -457,7 +457,7 @@ bool TEARDROP_MANAGER::ComputePointsOnPadVia( TEARDROP_PARAMETERS* aCurrParams, // Build the constraint polygon: a rectangle with // length = dist between the point on track and the pad/via pos - // height = m_tdMaxHeight or aViaPad.m_Width + // height = m_TdMaxHeight or aViaPad.m_Width SHAPE_POLY_SET clipping_rect; clipping_rect.NewOutline(); @@ -592,10 +592,10 @@ bool TEARDROP_MANAGER::findAnchorPointsOnTrack( TEARDROP_PARAMETERS* aCurrParams int radius = aViaPad.m_Width / 2; // Requested length of the teardrop: - int targetLength = aViaPad.m_Width * aCurrParams->m_lengthRatio; + int targetLength = aViaPad.m_Width * aCurrParams->m_LengthRatio; - if( aCurrParams->m_tdMaxLen > 0 ) - targetLength = std::min( aCurrParams->m_tdMaxLen, targetLength ); + if( aCurrParams->m_TdMaxLen > 0 ) + targetLength = std::min( aCurrParams->m_TdMaxLen, targetLength ); int actualTdLen; // The actual teardrop length, limited by the available track length @@ -738,10 +738,10 @@ bool TEARDROP_MANAGER::computeTeardropPolygonPoints( TEARDROP_PARAMETERS* aCurrP } else { - int td_height = aViaPad.m_Width * aCurrParams->m_heightRatio; + int td_height = aViaPad.m_Width * aCurrParams->m_HeightRatio; - if( aCurrParams->m_tdMaxHeight > 0 && aCurrParams->m_tdMaxHeight < td_height ) - td_height = aCurrParams->m_tdMaxHeight; + if( aCurrParams->m_TdMaxHeight > 0 && aCurrParams->m_TdMaxHeight < td_height ) + td_height = aCurrParams->m_TdMaxHeight; computeCurvedForRectShape( aCurrParams, aCorners, td_height, track_halfwidth, aViaPad, pts );