PNS: Merge co-linear segments during placement
This commit is contained in:
parent
4c0aa6db1a
commit
689da3794d
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue