router: Various bugfixes in length tuning meandering
- When fine-tuning, keep adjust to the original baseline length - Enforce a minimum amplitude based on settings, DP gap and track width - Use binary search to fine-tune amplitude if the length is not trivial - Account for inequalities in balancing - Don't add the meander if adding it with min. amplitude will make the tuning worse - Keep a distance after meandering end to prevent overlaps in DP Fixes https://gitlab.com/kicad/code/kicad/issues/9267 Fixes https://gitlab.com/kicad/code/kicad/issues/1776
This commit is contained in:
parent
0562eaa7b1
commit
90ad4dcc05
|
@ -2,7 +2,7 @@
|
|||
* KiRouter - a push-and-(sometimes-)shove PCB router
|
||||
*
|
||||
* Copyright (C) 2013-2014 CERN
|
||||
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
|
@ -127,6 +127,7 @@ void MEANDERED_LINE::MeanderSegment( const SEG& aBase, bool aSide, int aBaseInde
|
|||
{
|
||||
m.Fit( MT_TURN, aBase, m_last, side );
|
||||
AddMeander( new MEANDER_SHAPE( m ) );
|
||||
side = !side;
|
||||
started = true;
|
||||
}
|
||||
else
|
||||
|
@ -136,8 +137,6 @@ void MEANDERED_LINE::MeanderSegment( const SEG& aBase, bool aSide, int aBaseInde
|
|||
AddMeander( new MEANDER_SHAPE( m ) );
|
||||
turning = false;
|
||||
}
|
||||
|
||||
side = !side;
|
||||
}
|
||||
}
|
||||
else if( !singleSided && started )
|
||||
|
@ -188,12 +187,33 @@ void MEANDERED_LINE::MeanderSegment( const SEG& aBase, bool aSide, int aBaseInde
|
|||
}
|
||||
|
||||
|
||||
int MEANDER_SHAPE::MinAmplitude() const
|
||||
{
|
||||
int minAmplitude = Settings().m_minAmplitude;
|
||||
|
||||
// DP meanders don't really support smaller amplitudes
|
||||
minAmplitude = std::max( minAmplitude, std::abs( m_baselineOffset ) * 2 );
|
||||
|
||||
// The path length won't be correct with very small arcs
|
||||
if( m_placer->MeanderSettings().m_cornerStyle == MEANDER_STYLE_ROUND )
|
||||
minAmplitude = std::max( minAmplitude, m_width + std::abs( m_baselineOffset ) * 2 );
|
||||
|
||||
return minAmplitude;
|
||||
}
|
||||
|
||||
|
||||
int MEANDER_SHAPE::cornerRadius() const
|
||||
{
|
||||
// TODO: fix diff-pair meandering so we can use non-100% radii
|
||||
int rPercent = m_dual ? 100 : Settings().m_cornerRadiusPercentage;
|
||||
|
||||
return (int64_t) spacing() * rPercent / 200;
|
||||
int optCr = (int64_t) spacing() * rPercent / 200;
|
||||
int minCr = std::abs( m_baselineOffset );
|
||||
int maxCr = std::min( m_amplitude / 2, spacing() / 2 );
|
||||
|
||||
int cr = std::clamp( optCr, minCr, maxCr );
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -316,12 +336,14 @@ void MEANDER_SHAPE::uShape( int aSides, int aCorner, int aTop )
|
|||
|
||||
|
||||
SHAPE_LINE_CHAIN MEANDER_SHAPE::genMeanderShape( const VECTOR2D& aP, const VECTOR2D& aDir,
|
||||
bool aSide, MEANDER_TYPE aType, int aAmpl,
|
||||
bool aSide, MEANDER_TYPE aType,
|
||||
int aBaselineOffset )
|
||||
{
|
||||
int cr = cornerRadius();
|
||||
int offset = aBaselineOffset;
|
||||
int spc = spacing();
|
||||
int amplitude = m_amplitude;
|
||||
int targetBaseLen = m_targetBaseLen;
|
||||
|
||||
if( aSide )
|
||||
offset *= -1;
|
||||
|
@ -329,9 +351,9 @@ SHAPE_LINE_CHAIN MEANDER_SHAPE::genMeanderShape( const VECTOR2D& aP, const VECTO
|
|||
VECTOR2D dir_u_b( aDir.Resize( offset ) );
|
||||
VECTOR2D dir_v_b( dir_u_b.Perpendicular() );
|
||||
|
||||
if( 2 * cr > aAmpl )
|
||||
if( 2 * cr > amplitude )
|
||||
{
|
||||
cr = aAmpl / 2;
|
||||
cr = amplitude / 2;
|
||||
}
|
||||
|
||||
if( 2 * cr > spc )
|
||||
|
@ -339,8 +361,19 @@ SHAPE_LINE_CHAIN MEANDER_SHAPE::genMeanderShape( const VECTOR2D& aP, const VECTO
|
|||
cr = spc / 2;
|
||||
}
|
||||
|
||||
if( cr - offset < 0 )
|
||||
{
|
||||
cr = offset;
|
||||
}
|
||||
|
||||
m_meanCornerRadius = cr;
|
||||
|
||||
int sCorner = cr - offset;
|
||||
int uCorner = cr + offset;
|
||||
int startSide = amplitude - 2 * cr + std::abs( offset );
|
||||
int turnSide = amplitude - cr;
|
||||
int top = spc - 2 * cr;
|
||||
|
||||
SHAPE_LINE_CHAIN lc;
|
||||
|
||||
start( &lc, aP + dir_v_b, aDir );
|
||||
|
@ -354,45 +387,62 @@ SHAPE_LINE_CHAIN MEANDER_SHAPE::genMeanderShape( const VECTOR2D& aP, const VECTO
|
|||
}
|
||||
case MT_START:
|
||||
{
|
||||
miter( cr - offset, false );
|
||||
uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
|
||||
forward( std::min( cr - offset, cr + offset ) );
|
||||
if( targetBaseLen )
|
||||
top = std::max( top, targetBaseLen - sCorner - uCorner * 2 + offset );
|
||||
|
||||
miter( sCorner, false );
|
||||
uShape( startSide, uCorner, top );
|
||||
forward( std::min( sCorner, uCorner ) );
|
||||
forward( std::abs( offset ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case MT_FINISH:
|
||||
{
|
||||
if( targetBaseLen )
|
||||
top = std::max( top, targetBaseLen - cr - spc );
|
||||
|
||||
start( &lc, aP - dir_u_b, aDir );
|
||||
turn( -ANGLE_90 );
|
||||
forward( std::min( cr - offset, cr + offset ) );
|
||||
forward( std::min( sCorner, uCorner ) );
|
||||
forward( std::abs( offset ) );
|
||||
uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
|
||||
miter( cr - offset, false );
|
||||
uShape( startSide, uCorner, top );
|
||||
miter( sCorner, false );
|
||||
|
||||
if( targetBaseLen >= spc + cr )
|
||||
lc.Append( aP + dir_v_b + aDir.Resize( targetBaseLen ) );
|
||||
else
|
||||
lc.Append( aP + dir_v_b + aDir.Resize( 2 * spc - cr ) );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MT_TURN:
|
||||
{
|
||||
if( targetBaseLen )
|
||||
top = std::max( top, targetBaseLen - uCorner * 2 + offset * 2 );
|
||||
|
||||
start( &lc, aP - dir_u_b, aDir );
|
||||
turn( -ANGLE_90 );
|
||||
forward( std::abs( offset ) );
|
||||
uShape( aAmpl - cr, cr + offset, spc - 2 * cr );
|
||||
uShape( turnSide, uCorner, top );
|
||||
forward( std::abs( offset ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case MT_SINGLE:
|
||||
{
|
||||
miter( cr - offset, false );
|
||||
uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
|
||||
miter( cr - offset, false );
|
||||
if( targetBaseLen )
|
||||
top = std::max( top, ( targetBaseLen - sCorner * 2 - uCorner * 2 ) / 2 );
|
||||
|
||||
miter( sCorner, false );
|
||||
uShape( startSide, uCorner, top );
|
||||
miter( sCorner, false );
|
||||
lc.Append( aP + dir_v_b + aDir.Resize( 2 * spc ) );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( aSide )
|
||||
|
@ -490,34 +540,27 @@ bool MEANDER_SHAPE::Fit( MEANDER_TYPE aType, const SEG& aSeg, const VECTOR2I& aP
|
|||
}
|
||||
}
|
||||
|
||||
int minAmpl = st.m_minAmplitude;
|
||||
int maxAmpl = st.m_maxAmplitude;
|
||||
|
||||
if( m_dual )
|
||||
{
|
||||
minAmpl = std::max( minAmpl, 2 * std::abs( m_baselineOffset ) );
|
||||
maxAmpl = std::max( maxAmpl, 2 * std::abs( m_baselineOffset ) );
|
||||
}
|
||||
int minAmpl = MinAmplitude();
|
||||
int maxAmpl = std::max( st.m_maxAmplitude, minAmpl );
|
||||
|
||||
for( int ampl = maxAmpl; ampl >= minAmpl; ampl -= st.m_step )
|
||||
{
|
||||
m_amplitude = ampl;
|
||||
|
||||
if( m_dual )
|
||||
{
|
||||
m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl,
|
||||
m_baselineOffset );
|
||||
m_shapes[1] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl,
|
||||
-m_baselineOffset );
|
||||
m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, m_baselineOffset );
|
||||
m_shapes[1] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, -m_baselineOffset );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, 0 );
|
||||
m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, 0 );
|
||||
}
|
||||
|
||||
m_type = aType;
|
||||
m_baseSeg = aSeg;
|
||||
m_p0 = aP;
|
||||
m_side = aSide;
|
||||
m_amplitude = ampl;
|
||||
|
||||
updateBaseSegment();
|
||||
|
||||
|
@ -531,12 +574,12 @@ bool MEANDER_SHAPE::Fit( MEANDER_TYPE aType, const SEG& aSeg, const VECTOR2I& aP
|
|||
|
||||
void MEANDER_SHAPE::Recalculate()
|
||||
{
|
||||
m_shapes[0] = genMeanderShape( m_p0, m_baseSeg.B - m_baseSeg.A, m_side, m_type, m_amplitude,
|
||||
m_shapes[0] = genMeanderShape( m_p0, m_baseSeg.B - m_baseSeg.A, m_side, m_type,
|
||||
m_dual ? m_baselineOffset : 0 );
|
||||
|
||||
if( m_dual )
|
||||
m_shapes[1] = genMeanderShape( m_p0, m_baseSeg.B - m_baseSeg.A, m_side, m_type,
|
||||
m_amplitude, -m_baselineOffset );
|
||||
-m_baselineOffset );
|
||||
|
||||
updateBaseSegment();
|
||||
}
|
||||
|
@ -560,11 +603,12 @@ void MEANDER_SHAPE::MakeEmpty()
|
|||
VECTOR2I dir = m_clippedBaseSeg.B - m_clippedBaseSeg.A;
|
||||
|
||||
m_type = MT_EMPTY;
|
||||
m_amplitude = 0;
|
||||
|
||||
m_shapes[0] = genMeanderShape( m_p0, dir, m_side, m_type, 0, m_dual ? m_baselineOffset : 0 );
|
||||
m_shapes[0] = genMeanderShape( m_p0, dir, m_side, m_type, m_dual ? m_baselineOffset : 0 );
|
||||
|
||||
if( m_dual )
|
||||
m_shapes[1] = genMeanderShape( m_p0, dir, m_side, m_type, 0, -m_baselineOffset );
|
||||
m_shapes[1] = genMeanderShape( m_p0, dir, m_side, m_type, -m_baselineOffset );
|
||||
}
|
||||
|
||||
|
||||
|
@ -654,12 +698,23 @@ int MEANDER_SHAPE::BaselineLength() const
|
|||
}
|
||||
|
||||
|
||||
int MEANDER_SHAPE::MaxTunableLength() const
|
||||
long long int MEANDER_SHAPE::CurrentLength() const
|
||||
{
|
||||
return CLine( 0 ).Length();
|
||||
}
|
||||
|
||||
|
||||
long long int MEANDER_SHAPE::MinTunableLength() const
|
||||
{
|
||||
MEANDER_SHAPE copy = *this;
|
||||
|
||||
copy.SetTargetBaselineLength( BaselineLength() );
|
||||
copy.Resize( copy.MinAmplitude() );
|
||||
|
||||
return copy.CurrentLength();
|
||||
}
|
||||
|
||||
|
||||
void MEANDER_SHAPE::updateBaseSegment( )
|
||||
{
|
||||
if( m_dual )
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* KiRouter - a push-and-(sometimes-)shove PCB router
|
||||
*
|
||||
* Copyright (C) 2013-2015 CERN
|
||||
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
|
@ -129,6 +129,7 @@ public:
|
|||
// Do not leave uninitialized members, and keep static analyzer quiet:
|
||||
m_type = MT_SINGLE;
|
||||
m_amplitude = 0;
|
||||
m_targetBaseLen = 0;
|
||||
m_side = false;
|
||||
m_baseIndex = 0;
|
||||
m_currentTarget = nullptr;
|
||||
|
@ -273,7 +274,17 @@ public:
|
|||
/**
|
||||
* @return the length of the fitted line chain.
|
||||
*/
|
||||
int MaxTunableLength() const;
|
||||
long long int CurrentLength() const;
|
||||
|
||||
/**
|
||||
* @return the minumum tunable length according to settings.
|
||||
*/
|
||||
long long int MinTunableLength() const;
|
||||
|
||||
/**
|
||||
* @return the minumum possible amplitude according to settings.
|
||||
*/
|
||||
int MinAmplitude() const;
|
||||
|
||||
/**
|
||||
* @return the current meandering settings.
|
||||
|
@ -299,6 +310,14 @@ public:
|
|||
m_baselineOffset = aOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the target length of the baseline. When resizing, the meander will try to
|
||||
* fit the baseline length into the specified value.
|
||||
*
|
||||
* @param aLength the minimum baseline length.
|
||||
*/
|
||||
void SetTargetBaselineLength( int aLength ) { m_targetBaseLen = aLength; }
|
||||
|
||||
private:
|
||||
friend class MEANDERED_LINE;
|
||||
|
||||
|
@ -322,7 +341,7 @@ private:
|
|||
|
||||
///< Produce a meander shape of given type.
|
||||
SHAPE_LINE_CHAIN genMeanderShape( const VECTOR2D& aP, const VECTOR2D& aDir, bool aSide,
|
||||
MEANDER_TYPE aType, int aAmpl, int aBaselineOffset = 0 );
|
||||
MEANDER_TYPE aType, int aBaselineOffset = 0 );
|
||||
|
||||
///< Recalculate the clipped baseline after the parameters of the meander have been changed.
|
||||
void updateBaseSegment();
|
||||
|
@ -354,6 +373,9 @@ private:
|
|||
///< Average radius of meander corners (for correction of DP meanders).
|
||||
int m_meanCornerRadius;
|
||||
|
||||
///< Minimum length of the base segment to target when resizing.
|
||||
int m_targetBaseLen;
|
||||
|
||||
///< First point of the meandered line.
|
||||
VECTOR2I m_p0;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* KiRouter - a push-and-(sometimes-)shove PCB router
|
||||
*
|
||||
* Copyright (C) 2013-2015 CERN
|
||||
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
|
@ -27,6 +27,8 @@
|
|||
|
||||
namespace PNS {
|
||||
|
||||
const int LENGTH_TARGET_TOLERANCE = 20;
|
||||
|
||||
MEANDER_PLACER_BASE::MEANDER_PLACER_BASE( ROUTER* aRouter ) :
|
||||
PLACEMENT_ALGO( aRouter )
|
||||
{
|
||||
|
@ -131,32 +133,112 @@ void MEANDER_PLACER_BASE::cutTunedLine( const SHAPE_LINE_CHAIN& aOrigin, const V
|
|||
}
|
||||
|
||||
|
||||
int findAmplitudeBinarySearch( MEANDER_SHAPE& aCopy, int targetLength, int minAmp, int maxAmp )
|
||||
{
|
||||
if( minAmp == maxAmp )
|
||||
return maxAmp;
|
||||
|
||||
aCopy.Resize( minAmp );
|
||||
int minLen = aCopy.CurrentLength();
|
||||
|
||||
aCopy.Resize( maxAmp );
|
||||
int maxLen = aCopy.CurrentLength();
|
||||
|
||||
if( minLen > targetLength )
|
||||
return 0;
|
||||
|
||||
if( maxLen < targetLength )
|
||||
return 0;
|
||||
|
||||
int minError = minLen - targetLength;
|
||||
int maxError = maxLen - targetLength;
|
||||
|
||||
if( std::abs( minError ) < LENGTH_TARGET_TOLERANCE
|
||||
|| std::abs( maxError ) < LENGTH_TARGET_TOLERANCE )
|
||||
{
|
||||
return std::abs( minError ) < std::abs( maxError ) ? minAmp : maxAmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
int left =
|
||||
findAmplitudeBinarySearch( aCopy, targetLength, minAmp, ( minAmp + maxAmp ) / 2 );
|
||||
|
||||
if( left )
|
||||
return left;
|
||||
|
||||
int right =
|
||||
findAmplitudeBinarySearch( aCopy, targetLength, ( minAmp + maxAmp ) / 2, maxAmp );
|
||||
|
||||
if( right )
|
||||
return right;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int findAmplitudeForLength( MEANDER_SHAPE* m, int targetLength, int minAmp, int maxAmp )
|
||||
{
|
||||
MEANDER_SHAPE copy = *m;
|
||||
|
||||
// Try to keep the same baseline length
|
||||
copy.SetTargetBaselineLength( m->BaselineLength() );
|
||||
|
||||
long long initialGuess = m->Amplitude() - ( m->CurrentLength() - targetLength ) / 2;
|
||||
|
||||
if( initialGuess >= minAmp && initialGuess <= maxAmp )
|
||||
{
|
||||
copy.Resize( minAmp );
|
||||
|
||||
if( std::abs( copy.CurrentLength() - targetLength ) < LENGTH_TARGET_TOLERANCE )
|
||||
return initialGuess;
|
||||
}
|
||||
|
||||
// The length is non-trivial, use binary search
|
||||
return findAmplitudeBinarySearch( copy, targetLength, minAmp, maxAmp );
|
||||
}
|
||||
|
||||
|
||||
void MEANDER_PLACER_BASE::tuneLineLength( MEANDERED_LINE& aTuned, long long int aElongation )
|
||||
{
|
||||
long long int remaining = aElongation;
|
||||
bool finished = false;
|
||||
long long int maxElongation = 0;
|
||||
long long int minElongation = 0;
|
||||
bool finished = false;
|
||||
|
||||
for( MEANDER_SHAPE* m : aTuned.Meanders() )
|
||||
{
|
||||
if( m->Type() != MT_CORNER && m->Type() != MT_ARC )
|
||||
{
|
||||
if( remaining >= 0 )
|
||||
remaining -= m->MaxTunableLength() - m->BaselineLength();
|
||||
MEANDER_SHAPE end = *m;
|
||||
MEANDER_TYPE endType;
|
||||
|
||||
if( remaining < 0 )
|
||||
if( m->Type() == MT_START || m->Type() == MT_SINGLE )
|
||||
endType = MT_SINGLE;
|
||||
else
|
||||
endType = MT_FINISH;
|
||||
|
||||
end.SetType( endType );
|
||||
end.Recalculate();
|
||||
|
||||
long long int maxEndElongation = end.CurrentLength() - end.BaselineLength();
|
||||
|
||||
if( maxElongation + maxEndElongation > aElongation )
|
||||
{
|
||||
if( !finished )
|
||||
{
|
||||
MEANDER_TYPE newType;
|
||||
|
||||
if( m->Type() == MT_START || m->Type() == MT_SINGLE )
|
||||
newType = MT_SINGLE;
|
||||
else
|
||||
newType = MT_FINISH;
|
||||
|
||||
m->SetType( newType );
|
||||
m->SetType( endType );
|
||||
m->Recalculate();
|
||||
|
||||
if( endType == MT_SINGLE )
|
||||
{
|
||||
// Check if we need to fit this meander
|
||||
long long int endMinElongation =
|
||||
( m->MinTunableLength() - m->BaselineLength() );
|
||||
|
||||
if( minElongation + endMinElongation >= aElongation )
|
||||
m->MakeEmpty();
|
||||
}
|
||||
|
||||
finished = true;
|
||||
}
|
||||
else
|
||||
|
@ -164,38 +246,52 @@ void MEANDER_PLACER_BASE::tuneLineLength( MEANDERED_LINE& aTuned, long long int
|
|||
m->MakeEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
maxElongation += m->CurrentLength() - m->BaselineLength();
|
||||
minElongation += m->MinTunableLength() - m->BaselineLength();
|
||||
}
|
||||
}
|
||||
|
||||
remaining = aElongation;
|
||||
int meanderCount = 0;
|
||||
long long int remainingElongation = aElongation;
|
||||
int meanderCount = 0;
|
||||
|
||||
for( MEANDER_SHAPE* m : aTuned.Meanders() )
|
||||
{
|
||||
if( m->Type() != MT_CORNER && m->Type() != MT_ARC && m->Type() != MT_EMPTY )
|
||||
{
|
||||
if(remaining >= 0)
|
||||
{
|
||||
remaining -= m->MaxTunableLength() - m->BaselineLength();
|
||||
meanderCount ++;
|
||||
}
|
||||
remainingElongation -= m->CurrentLength() - m->BaselineLength();
|
||||
meanderCount++;
|
||||
}
|
||||
}
|
||||
|
||||
long long int balance = 0;
|
||||
long long int lenReductionLeft = -remainingElongation;
|
||||
int meandersLeft = meanderCount;
|
||||
|
||||
if( meanderCount )
|
||||
balance = -remaining / meanderCount;
|
||||
if( lenReductionLeft < 0 || !meandersLeft )
|
||||
return;
|
||||
|
||||
if( balance >= 0 )
|
||||
for( MEANDER_SHAPE* m : aTuned.Meanders() )
|
||||
{
|
||||
for( MEANDER_SHAPE* m : aTuned.Meanders() )
|
||||
if( m->Type() != MT_CORNER && m->Type() != MT_ARC && m->Type() != MT_EMPTY )
|
||||
{
|
||||
if( m->Type() != MT_CORNER && m->Type() != MT_ARC && m->Type() != MT_EMPTY )
|
||||
{
|
||||
m->Resize( std::max( m->Amplitude() - balance / 2,
|
||||
(long long int) m_settings.m_minAmplitude ) );
|
||||
}
|
||||
long long int lenReductionHere = lenReductionLeft / meandersLeft;
|
||||
long long int initialLen = m->CurrentLength();
|
||||
int minAmpl = m->MinAmplitude();
|
||||
|
||||
int amp = findAmplitudeForLength( m, initialLen - lenReductionHere, minAmpl,
|
||||
m->Amplitude() );
|
||||
|
||||
if( amp < minAmpl )
|
||||
amp = minAmpl;
|
||||
|
||||
m->SetTargetBaselineLength( m->BaselineLength() );
|
||||
m->Resize( amp );
|
||||
|
||||
lenReductionLeft -= initialLen - m->CurrentLength();
|
||||
meandersLeft--;
|
||||
|
||||
if( !meandersLeft )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue