From bcf7990bf9b7674d5d807e52f53d67f5806a8767 Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Mon, 15 Aug 2016 17:16:49 +0200 Subject: [PATCH] P&S: support for 45-degree style length tuning meanders --- .../dialog_pns_length_tuning_settings.cpp | 6 +- pcbnew/router/pns_meander.cpp | 93 ++++++++++++------- pcbnew/router/pns_meander.h | 22 ++--- 3 files changed, 73 insertions(+), 48 deletions(-) diff --git a/pcbnew/dialogs/dialog_pns_length_tuning_settings.cpp b/pcbnew/dialogs/dialog_pns_length_tuning_settings.cpp index 0ba8f11572..6ec2534eb0 100644 --- a/pcbnew/dialogs/dialog_pns_length_tuning_settings.cpp +++ b/pcbnew/dialogs/dialog_pns_length_tuning_settings.cpp @@ -34,7 +34,7 @@ DIALOG_PNS_LENGTH_TUNING_SETTINGS::DIALOG_PNS_LENGTH_TUNING_SETTINGS( wxWindow* m_settings( aSettings ), m_mode( aMode ) { - m_miterStyle->Enable( false ); + m_miterStyle->Enable( true ); m_radiusText->Enable( aMode != PNS_MODE_TUNE_DIFF_PAIR ); //m_minAmpl.Enable ( aMode != PNS_MODE_TUNE_DIFF_PAIR_SKEW ); @@ -44,7 +44,7 @@ DIALOG_PNS_LENGTH_TUNING_SETTINGS::DIALOG_PNS_LENGTH_TUNING_SETTINGS( wxWindow* m_spacing.SetValue( m_settings.m_spacing ); m_radiusText->SetValue( wxString::Format( wxT( "%i" ), m_settings.m_cornerRadiusPercentage ) ); - m_miterStyle->SetSelection( m_settings.m_cornerType == PNS_MEANDER_SETTINGS::ROUND ? 1 : 0 ); + m_miterStyle->SetSelection( m_settings.m_cornerStyle == MEANDER_STYLE_ROUND ? 1 : 0 ); switch( aMode ) { @@ -97,7 +97,7 @@ void DIALOG_PNS_LENGTH_TUNING_SETTINGS::OnOkClick( wxCommandEvent& aEvent ) if( m_settings.m_maxAmplitude < m_settings.m_minAmplitude ) m_settings.m_maxAmplitude = m_settings.m_minAmplitude; - m_settings.m_cornerType = m_miterStyle->GetSelection() ? PNS_MEANDER_SETTINGS::CHAMFER : PNS_MEANDER_SETTINGS::ROUND; + m_settings.m_cornerStyle = m_miterStyle->GetSelection() ? MEANDER_STYLE_ROUND : MEANDER_STYLE_CHAMFER; EndModal( wxID_OK ); } diff --git a/pcbnew/router/pns_meander.cpp b/pcbnew/router/pns_meander.cpp index 3529e9b33c..65589aea9b 100644 --- a/pcbnew/router/pns_meander.cpp +++ b/pcbnew/router/pns_meander.cpp @@ -28,6 +28,7 @@ #include "pns_meander.h" #include "pns_meander_placer_base.h" #include "pns_router.h" +#include "pns_debug_decorator.h" const PNS_MEANDER_SETTINGS& PNS_MEANDER_SHAPE::Settings() const { @@ -163,9 +164,7 @@ void PNS_MEANDERED_LINE::MeanderSegment( const SEG& aBase, int aBaseIndex ) int PNS_MEANDER_SHAPE::cornerRadius() const { - int cr = (int64_t) spacing() * Settings().m_cornerRadiusPercentage / 200; - - return cr; + return (int64_t) spacing() * Settings().m_cornerRadiusPercentage / 200; } @@ -181,7 +180,7 @@ int PNS_MEANDER_SHAPE::spacing( ) const } -SHAPE_LINE_CHAIN PNS_MEANDER_SHAPE::circleQuad( VECTOR2D aP, VECTOR2D aDir, bool aSide ) +SHAPE_LINE_CHAIN PNS_MEANDER_SHAPE::makeMiterShape( VECTOR2D aP, VECTOR2D aDir, bool aSide ) { SHAPE_LINE_CHAIN lc; @@ -193,32 +192,57 @@ SHAPE_LINE_CHAIN PNS_MEANDER_SHAPE::circleQuad( VECTOR2D aP, VECTOR2D aDir, bool VECTOR2D dir_u( aDir ); VECTOR2D dir_v( aDir.Perpendicular( ) ); - - const int ArcSegments = Settings().m_cornerArcSegments; - - double radius = (double) aDir.EuclideanNorm(); - double angleStep = M_PI / 2.0 / (double) ArcSegments; - - double correction = 12.0 * radius * ( 1.0 - cos( angleStep / 2.0 ) ); - - if( !m_dual ) - correction = 0.0; - else if( radius < m_meanCornerRadius ) - correction = 0.0; - VECTOR2D p = aP; lc.Append( ( int ) p.x, ( int ) p.y ); - VECTOR2D dir_uu = dir_u.Resize( radius - correction ); - VECTOR2D dir_vv = dir_v.Resize( radius - correction ); - VECTOR2D shift = dir_u.Resize( correction ); - - for( int i = ArcSegments - 1; i >= 0; i-- ) + PNS_DEBUG_DECORATOR *dbg = PNS_ROUTER::GetInstance()->GetInterface()->GetDebugDecorator(); + // fixme: refactor + switch (m_placer->MeanderSettings().m_cornerStyle) { - double alpha = (double) i / (double) ( ArcSegments - 1 ) * M_PI / 2.0; - p = aP + shift + dir_uu * cos( alpha ) + dir_vv * ( aSide ? -1.0 : 1.0 ) * ( 1.0 - sin( alpha ) ); + case MEANDER_STYLE_ROUND: + { + const int ArcSegments = Settings().m_cornerArcSegments; + + double radius = (double) aDir.EuclideanNorm(); + double angleStep = M_PI / 2.0 / (double) ArcSegments; + + double correction = 12.0 * radius * ( 1.0 - cos( angleStep / 2.0 ) ); + + if( !m_dual ) + correction = 0.0; + else if( radius < m_meanCornerRadius ) + correction = 0.0; + + VECTOR2D dir_uu = dir_u.Resize( radius - correction ); + VECTOR2D dir_vv = dir_v.Resize( radius - correction ); + + VECTOR2D shift = dir_u.Resize( correction ); + + for( int i = ArcSegments - 1; i >= 0; i-- ) + { + double alpha = (double) i / (double) ( ArcSegments - 1 ) * M_PI / 2.0; + p = aP + shift + dir_uu * cos( alpha ) + dir_vv * ( aSide ? -1.0 : 1.0 ) * ( 1.0 - sin( alpha ) ); + lc.Append( ( int ) p.x, ( int ) p.y ); + } + } + break; + case MEANDER_STYLE_CHAMFER: + { + double radius = (double) aDir.EuclideanNorm(); + double correction = 0; + if( m_dual && radius > m_meanCornerRadius ) + correction = (double)(m_baselineOffset * 2) * tan ( 22.5 * M_PI / 180.0 ); + + VECTOR2D dir_cu = dir_u.Resize( correction ); + VECTOR2D dir_cv = dir_v.Resize( correction ); + + p = aP - dir_cu; lc.Append( ( int ) p.x, ( int ) p.y ); + p = aP + dir_u + (dir_v + dir_cv) * ( aSide ? -1.0 : 1.0 ); + lc.Append( ( int ) p.x, ( int ) p.y ); + break; + } } p = aP + dir_u + dir_v * ( aSide ? -1.0 : 1.0 ); @@ -270,7 +294,7 @@ void PNS_MEANDER_SHAPE::turn( int aAngle ) } -void PNS_MEANDER_SHAPE::arc( int aRadius, bool aSide ) +void PNS_MEANDER_SHAPE::miter( int aRadius, bool aSide ) { if( aRadius <= 0 ) { @@ -279,20 +303,21 @@ void PNS_MEANDER_SHAPE::arc( int aRadius, bool aSide ) } VECTOR2D dir = m_currentDir.Resize( (double) aRadius ); - SHAPE_LINE_CHAIN arc = circleQuad( m_currentPos, dir, aSide ); - m_currentPos = arc.CPoint( -1 ); + SHAPE_LINE_CHAIN lc = makeMiterShape( m_currentPos, dir, aSide ); + + m_currentPos = lc.CPoint( -1 ); m_currentDir = dir.Rotate( aSide ? -M_PI / 2.0 : M_PI / 2.0 ); - m_currentTarget->Append ( arc ); + m_currentTarget->Append ( lc ); } void PNS_MEANDER_SHAPE::uShape( int aSides, int aCorner, int aTop ) { forward( aSides ); - arc( aCorner, true ); + miter( aCorner, true ); forward( aTop ); - arc( aCorner, true ); + miter( aCorner, true ); forward( aSides ); } @@ -336,7 +361,7 @@ SHAPE_LINE_CHAIN PNS_MEANDER_SHAPE::genMeanderShape( VECTOR2D aP, VECTOR2D aDir, } case MT_START: { - arc( cr - offset, false ); + miter( cr - offset, false ); uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr ); forward( std::min( cr - offset, cr + offset ) ); forward( std::abs( offset ) ); @@ -351,7 +376,7 @@ SHAPE_LINE_CHAIN PNS_MEANDER_SHAPE::genMeanderShape( VECTOR2D aP, VECTOR2D aDir, forward( std::min( cr - offset, cr + offset ) ); forward( std::abs( offset ) ); uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr ); - arc( cr - offset, false ); + miter( cr - offset, false ); break; } @@ -367,9 +392,9 @@ SHAPE_LINE_CHAIN PNS_MEANDER_SHAPE::genMeanderShape( VECTOR2D aP, VECTOR2D aDir, case MT_SINGLE: { - arc( cr - offset, false ); + miter( cr - offset, false ); uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr ); - arc( cr - offset, false ); + miter( cr - offset, false ); lc.Append( aP + dir_v_b + aDir.Resize ( 2 * st.m_spacing ) ); break; } diff --git a/pcbnew/router/pns_meander.h b/pcbnew/router/pns_meander.h index 5d1ae511be..53cfc3380f 100644 --- a/pcbnew/router/pns_meander.h +++ b/pcbnew/router/pns_meander.h @@ -40,6 +40,12 @@ enum PNS_MEANDER_TYPE { MT_EMPTY // no meander (straight line) }; +///> meander corner shape +enum PNS_MEANDER_STYLE { + MEANDER_STYLE_ROUND = 1, // rounded (90 degree arc) + MEANDER_STYLE_CHAMFER // chamfered (45 degree segment) +}; + /** * Class PNS_MEANDER_SETTINGS * @@ -49,12 +55,6 @@ class PNS_MEANDER_SETTINGS { public: - ///> meander corner shape - enum CornerType { - ROUND = 1, // rounded (90 degree arc) - CHAMFER // chamfered (45 degree segment) - }; - PNS_MEANDER_SETTINGS() { m_minAmplitude = 100000; @@ -63,7 +63,7 @@ public: m_spacing = 600000; m_targetLength = 100000000; m_targetSkew = 0; - m_cornerType = ROUND; + m_cornerStyle = MEANDER_STYLE_ROUND; m_cornerRadiusPercentage = 100; m_lengthTolerance = 100000; m_cornerArcSegments = 8; @@ -80,7 +80,7 @@ public: ///> desired length of the tuned line/diff pair int m_targetLength; ///> type of corners for the meandered line - CornerType m_cornerType; + PNS_MEANDER_STYLE m_cornerStyle; ///> rounding percentage (0 - 100) int m_cornerRadiusPercentage; ///> allowable tuning error @@ -325,13 +325,13 @@ private: void forward( int aLength ); ///> turns the turtle by aAngle void turn( int aAngle ); - ///> tells the turtle to draw an arc of given radius and turn direction - void arc( int aRadius, bool aSide ); + ///> tells the turtle to draw a mitered corner of given radius and turn direction + void miter( int aRadius, bool aSide ); ///> tells the turtle to draw an U-like shape void uShape( int aSides, int aCorner, int aTop ); ///> generates a 90-degree circular arc - SHAPE_LINE_CHAIN circleQuad( VECTOR2D aP, VECTOR2D aDir, bool aSide ); + SHAPE_LINE_CHAIN makeMiterShape( VECTOR2D aP, VECTOR2D aDir, bool aSide ); ///> reflects a point onto other side of a given segment VECTOR2I reflect( VECTOR2I aP, const SEG& aLine );