PNS: Merge co-linear segments during placement

This commit is contained in:
Jon Evans 2020-12-29 21:14:14 -05:00
parent 4c0aa6db1a
commit 689da3794d
3 changed files with 53 additions and 18 deletions

View File

@ -1147,6 +1147,13 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
if( !l.SegmentCount() )
{
// Do a final optimization to the stored state
NODE::ITEM_VECTOR removed, added;
m_lastNode->GetUpdatedItems( removed, added );
if( !added.empty() && added.back()->Kind() == ITEM::SEGMENT_T )
simplifyNewLine( m_lastNode, static_cast<SEGMENT*>( added.back() ) );
// Nothing to commit if we have an empty line
if( !pl.EndsWithVia() )
return false;
@ -1181,6 +1188,7 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
else
lastV = std::max( 1, l.SegmentCount() - 1 );
SEGMENT seg;
SEGMENT* lastSeg = nullptr;
int lastArc = -1;
@ -1190,13 +1198,12 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
if( arcIndex < 0 )
{
const SEG& s = pl.CSegment( i );
auto seg = std::make_unique<SEGMENT>( s, m_currentNet );
seg->SetWidth( pl.Width() );
seg->SetLayer( m_currentLayer );
seg = SEGMENT( pl.CSegment( i ), m_currentNet );
seg.SetWidth( pl.Width() );
seg.SetLayer( m_currentLayer );
if( !m_lastNode->Add( std::move( seg ) ) )
lastSeg = nullptr;
if( m_lastNode->Add( std::make_unique<SEGMENT>( seg ) ) )
lastSeg = &seg;
}
else
{
@ -1242,10 +1249,12 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
if ( m_shove )
m_shove->AddLockedSpringbackNode( m_currentNode );
DIRECTION_45 lastSegDir = pl.EndsWithVia() ? DIRECTION_45::UNDEFINED : d_last;
m_postureSolver.Clear();
m_postureSolver.SetTolerance( m_head.Width() );
m_postureSolver.AddTrailPoint( m_currentStart );
m_postureSolver.SetDefaultDirections( m_initial_direction, d_last );
m_postureSolver.SetDefaultDirections( m_initial_direction, lastSegDir );
m_placementCorrect = true;
}
@ -1364,11 +1373,14 @@ void LINE_PLACER::removeLoops( NODE* aNode, LINE& aLatest )
void LINE_PLACER::simplifyNewLine( NODE* aNode, SEGMENT* aLatest )
{
LINE l = aNode->AssembleLine( aLatest );
bool optimized = OPTIMIZER::Optimize( &l, OPTIMIZER::MERGE_COLINEAR, aNode );
SHAPE_LINE_CHAIN simplified( l.CLine() );
simplified.Simplify();
if( simplified.PointCount() != l.PointCount() )
if( optimized || simplified.PointCount() != l.PointCount() )
{
aNode->Remove( l );
l.SetShape( simplified );
@ -1602,10 +1614,10 @@ void POSTURE_SOLVER::AddTrailPoint( const VECTOR2I& aP )
DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
{
// Tuning factor for how good the "fit" of the trail must be to the posture
const double areaRatioThreshold = 1.5;
const double areaRatioThreshold = 1.3;
// Tuning factor to minimize flutter
const double areaRatioEpsilon = 0.3;
const double areaRatioEpsilon = 0.25;
// Minimum distance factor of the trail before the min area test is used to lock the solver
const double minAreaCutoffDistanceFactor = 6;

View File

@ -598,6 +598,25 @@ bool OPTIMIZER::mergeFull( LINE* aLine )
}
bool OPTIMIZER::mergeColinear( LINE* aLine )
{
SHAPE_LINE_CHAIN& line = aLine->Line();
int nSegs = line.SegmentCount();
for( int segIdx = 0; segIdx < line.SegmentCount() - 1; ++segIdx )
{
SEG s1 = line.CSegment( segIdx );
SEG s2 = line.CSegment( segIdx + 1 );
if( s1.Collinear( s2 ) )
line.Replace( segIdx, segIdx + 1, s1.A );
}
return line.SegmentCount() < nSegs;
}
bool OPTIMIZER::Optimize( LINE* aLine, LINE* aResult )
{
if( !aResult )
@ -636,6 +655,9 @@ bool OPTIMIZER::Optimize( LINE* aLine, LINE* aResult )
if( m_effortLevel & MERGE_OBTUSE )
rv |= mergeObtuse( aResult );
if( m_effortLevel & MERGE_COLINEAR )
rv |= mergeColinear( aResult );
if( m_effortLevel & SMART_PADS )
rv |= runSmartPads( aResult );

View File

@ -97,14 +97,14 @@ class OPTIMIZER
public:
enum OptimizationEffort
{
MERGE_SEGMENTS = 0x01,
SMART_PADS = 0x02,
MERGE_OBTUSE = 0x04,
FANOUT_CLEANUP = 0x08,
MERGE_SEGMENTS = 0x01, ///< Reduce corner cost iteratively
SMART_PADS = 0x02, ///< Reroute pad exits
MERGE_OBTUSE = 0x04, ///< Reduce corner cost by merging obtuse segments
FANOUT_CLEANUP = 0x08, ///< Simplify pad-pad and pad-via connections if possible
KEEP_TOPOLOGY = 0x10,
PRESERVE_VERTEX = 0x20,
RESTRICT_VERTEX_RANGE = 0x40
RESTRICT_VERTEX_RANGE = 0x40,
MERGE_COLINEAR = 0x80 ///< Merge co-linear segments
};
OPTIMIZER( NODE* aWorld );
@ -172,6 +172,7 @@ private:
bool mergeObtuse( LINE* aLine );
bool mergeFull( LINE* aLine );
bool mergeColinear( LINE* aLine );
bool removeUglyCorners( LINE* aLine );
bool runSmartPads( LINE* aLine );
bool mergeStep( LINE* aLine, SHAPE_LINE_CHAIN& aCurrentLine, int step );