Cleanup (and a minor performance improvement).

This commit is contained in:
Jeff Young 2021-01-04 22:31:57 +00:00
parent 597a74af9a
commit d24b034cbc
4 changed files with 199 additions and 251 deletions

View File

@ -368,18 +368,19 @@ bool LINE_PLACER::mergeHead()
VECTOR2I closestProjectedPoint( const SHAPE_LINE_CHAIN& line, const VECTOR2I& p ) VECTOR2I closestProjectedPoint( const SHAPE_LINE_CHAIN& line, const VECTOR2I& p )
{ {
int min_dist = INT_MAX; // Keep distances squared for performance
VECTOR2I closest; SEG::ecoord min_dist_sq = VECTOR2I::ECOORD_MAX;
VECTOR2I closest;
for(int i = 0; i < line.SegmentCount(); i++ ) for( int i = 0; i < line.SegmentCount(); i++ )
{ {
const auto& s = line.CSegment(i); const SEG& s = line.CSegment(i);
auto a = s.NearestPoint( p ); VECTOR2I a = s.NearestPoint( p );
auto d = (a - p).EuclideanNorm(); int d_sq = (a - p).SquaredEuclideanNorm();
if( d < min_dist ) if( d_sq < min_dist_sq )
{ {
min_dist = d; min_dist_sq = d_sq;
closest = a; closest = a;
} }
} }
@ -407,14 +408,14 @@ bool LINE_PLACER::rhWalkOnly( const VECTOR2I& aP, LINE& aNewHead )
WALKAROUND::RESULT wr = walkaround.Route( initTrack ); WALKAROUND::RESULT wr = walkaround.Route( initTrack );
//WALKAROUND::WALKAROUND_STATUS wf = walkaround.Route( initTrack, walkFull, false ); //WALKAROUND::WALKAROUND_STATUS wf = walkaround.Route( initTrack, walkFull, false );
auto l_cw = wr.lineCw.CLine(); SHAPE_LINE_CHAIN l_cw = wr.lineCw.CLine();
auto l_ccw = wr.lineCcw.CLine(); SHAPE_LINE_CHAIN l_ccw = wr.lineCcw.CLine();
if( wr.statusCcw == WALKAROUND::ALMOST_DONE || wr.statusCw == WALKAROUND::ALMOST_DONE ) if( wr.statusCcw == WALKAROUND::ALMOST_DONE || wr.statusCw == WALKAROUND::ALMOST_DONE )
{ {
auto p_cw = closestProjectedPoint( l_cw, aP ); VECTOR2I p_cw = closestProjectedPoint( l_cw, aP );
auto p_ccw = closestProjectedPoint( l_ccw, aP ); VECTOR2I p_ccw = closestProjectedPoint( l_ccw, aP );
int idx_cw = l_cw.Split( p_cw ); int idx_cw = l_cw.Split( p_cw );
int idx_ccw = l_ccw.Split( p_ccw ); int idx_ccw = l_ccw.Split( p_ccw );
@ -1097,7 +1098,7 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
if( arcIndex == lastArc ) if( arcIndex == lastArc )
continue; continue;
auto arc = std::make_unique<ARC>( l.Arc( arcIndex ), m_currentNet ); std::unique_ptr<ARC> arc = std::make_unique<ARC>( l.Arc( arcIndex ), m_currentNet );
arc->SetWidth( pl.Width() ); arc->SetWidth( pl.Width() );
arc->SetLayer( m_currentLayer ); arc->SetLayer( m_currentLayer );
m_lastNode->Add( std::move( arc ) ); m_lastNode->Add( std::move( arc ) );
@ -1481,7 +1482,7 @@ void POSTURE_SOLVER::AddTrailPoint( const VECTOR2I& aP )
for( int i = 0; i < m_trail.SegmentCount() - 1; i++ ) for( int i = 0; i < m_trail.SegmentCount() - 1; i++ )
{ {
const auto& s_trail = m_trail.CSegment( i ); const SEG& s_trail = m_trail.CSegment( i );
if( s_trail.Distance( s_new ) <= m_tolerance ) if( s_trail.Distance( s_new ) <= m_tolerance )
{ {
@ -1495,9 +1496,7 @@ void POSTURE_SOLVER::AddTrailPoint( const VECTOR2I& aP )
m_trail.Simplify(); m_trail.Simplify();
auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator(); ROUTER::GetInstance()->GetInterface()->GetDebugDecorator()->AddLine( m_trail, 5, 100000 );
dbg->AddLine( m_trail, 5, 100000 );
} }
@ -1526,13 +1525,11 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
return m_direction; return m_direction;
} }
auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator(); DEBUG_DECORATOR* dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
VECTOR2I p0 = m_trail.CPoint( 0 );
auto p0 = m_trail.CPoint( 0 ); double refLength = SEG( p0, aP ).Length();
double refLength = SEG( p0, aP ).Length();
SHAPE_LINE_CHAIN straight( DIRECTION_45().BuildInitialTrace( p0, aP, false, false ) ); SHAPE_LINE_CHAIN straight( DIRECTION_45().BuildInitialTrace( p0, aP, false, false ) );
straight.SetClosed( true ); straight.SetClosed( true );
straight.Append( m_trail.Reverse() ); straight.Append( m_trail.Reverse() );
straight.Simplify(); straight.Simplify();

View File

@ -51,23 +51,12 @@ int COST_ESTIMATOR::CornerCost( const SEG& aA, const SEG& aB )
switch( dir_a.Angle( dir_b ) ) switch( dir_a.Angle( dir_b ) )
{ {
case DIRECTION_45::ANG_OBTUSE: case DIRECTION_45::ANG_OBTUSE: return 10;
return 10; case DIRECTION_45::ANG_STRAIGHT: return 5;
case DIRECTION_45::ANG_ACUTE: return 50;
case DIRECTION_45::ANG_STRAIGHT: case DIRECTION_45::ANG_RIGHT: return 30;
return 5; case DIRECTION_45::ANG_HALF_FULL: return 60;
default: return 100;
case DIRECTION_45::ANG_ACUTE:
return 50;
case DIRECTION_45::ANG_RIGHT:
return 30;
case DIRECTION_45::ANG_HALF_FULL:
return 60;
default:
return 100;
} }
} }
@ -112,9 +101,8 @@ void COST_ESTIMATOR::Replace( const LINE& aOldLine, const LINE& aNewLine )
} }
bool COST_ESTIMATOR::IsBetter( const COST_ESTIMATOR& aOther, bool COST_ESTIMATOR::IsBetter( const COST_ESTIMATOR& aOther, double aLengthTolerance,
double aLengthTolerance, double aCornerTolerance ) const
double aCornerTolerance ) const
{ {
if( aOther.m_cornerCost < m_cornerCost && aOther.m_lengthCost < m_lengthCost ) if( aOther.m_cornerCost < m_cornerCost && aOther.m_lengthCost < m_lengthCost )
return true; return true;
@ -133,8 +121,7 @@ bool COST_ESTIMATOR::IsBetter( const COST_ESTIMATOR& aOther,
OPTIMIZER::OPTIMIZER( NODE* aWorld ) : OPTIMIZER::OPTIMIZER( NODE* aWorld ) :
m_world( aWorld ), m_world( aWorld ),
m_collisionKindMask( ITEM::ANY_T ), m_collisionKindMask( ITEM::ANY_T ),
m_effortLevel( MERGE_SEGMENTS ), m_effortLevel( MERGE_SEGMENTS )
m_keepPostures( false )
{ {
} }
@ -208,12 +195,6 @@ void OPTIMIZER::CacheRemove( ITEM* aItem )
} }
void OPTIMIZER::CacheStaticItem( ITEM* aItem )
{
cacheAdd( aItem, true );
}
void OPTIMIZER::ClearCache( bool aStaticOnly ) void OPTIMIZER::ClearCache( bool aStaticOnly )
{ {
if( !aStaticOnly ) if( !aStaticOnly )
@ -223,7 +204,7 @@ void OPTIMIZER::ClearCache( bool aStaticOnly )
return; return;
} }
for( CachedItemTags::iterator i = m_cacheTags.begin(); i!= m_cacheTags.end(); ++i ) for( auto i = m_cacheTags.begin(); i!= m_cacheTags.end(); ++i )
{ {
if( i->second.m_isStatic ) if( i->second.m_isStatic )
{ {
@ -234,65 +215,30 @@ void OPTIMIZER::ClearCache( bool aStaticOnly )
} }
bool ANGLE_CONSTRAINT_45::Check( int aVertex1, int aVertex2, const LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement ) bool AREA_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine,
const SHAPE_LINE_CHAIN& aCurrentPath,
const SHAPE_LINE_CHAIN& aReplacement )
{ {
auto dir_orig0 = DIRECTION_45( aOriginLine->CSegment( aVertex1 ) ); const VECTOR2I& p1 = aOriginLine->CPoint( aVertex1 );
auto dir_orig1 = DIRECTION_45( aOriginLine->CSegment( aVertex2 - 1) ); const VECTOR2I& p2 = aOriginLine->CPoint( aVertex2 );
if( aVertex1 == 0 ) bool p1_in = m_allowedArea.Contains( p1 );
{ bool p2_in = m_allowedArea.Contains( p2 );
if( ( dir_orig0.Mask() & m_entryDirectionMask ) == 0 )
return false; // disallowed entry angle
}
if( aVertex2 == aOriginLine->SegmentCount() - 1 )
{
if( ( dir_orig1.Mask() & m_exitDirectionMask ) == 0 )
return false; // disallowed exit ngle
}
/*auto ang_rep0 = DIRECTION_45( aReplacement.CSegment(0) ).Angle( dir_orig0 );
auto ang_rep1 = DIRECTION_45( aReplacement.CSegment(-1) ).Angle( dir_orig1 );*/
return true;
}
bool AREA_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement )
{
auto p1 = aOriginLine->CPoint( aVertex1 );
auto p2 = aOriginLine->CPoint( aVertex2 );
auto p1_in = m_allowedArea.Contains( p1 );
auto p2_in = m_allowedArea.Contains( p2 );
return p1_in || p2_in; return p1_in || p2_in;
} }
class JOINT_CACHE
{
public:
JOINT_CACHE( NODE *aWorld, int aLayer, int aMaxJoints );
bool CheckInside( const VECTOR2I& aPos ) const; bool PRESERVE_VERTEX_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine,
const SHAPE_LINE_CHAIN& aCurrentPath,
private: const SHAPE_LINE_CHAIN& aReplacement )
struct ENTRY {
JOINT* joint;
int score;
};
};
bool PRESERVE_VERTEX_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement )
{ {
bool cv = false; bool cv = false;
for( int i = aVertex1; i < aVertex2; i++ ) for( int i = aVertex1; i < aVertex2; i++ )
{ {
int dist = aCurrentPath.CSegment(i).Distance( m_v ); SEG::ecoord dist = aCurrentPath.CSegment(i).SquaredDistance( m_v );
if ( dist <= 1 ) if ( dist <= 1 )
{ {
cv = true; cv = true;
@ -300,26 +246,24 @@ bool PRESERVE_VERTEX_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE*
} }
} }
if(!cv) if( !cv )
{
return true; return true;
}
for( int i = 0; i < aReplacement.SegmentCount(); i++ ) for( int i = 0; i < aReplacement.SegmentCount(); i++ )
{ {
int dist = aReplacement.CSegment(i).Distance( m_v ); SEG::ecoord dist = aReplacement.CSegment(i).SquaredDistance( m_v );
if ( dist <= 1 ) if ( dist <= 1 )
{
return true; return true;
}
} }
return false; return false;
} }
bool RESTRICT_VERTEX_RANGE_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement ) bool RESTRICT_VERTEX_RANGE_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine,
const SHAPE_LINE_CHAIN& aCurrentPath,
const SHAPE_LINE_CHAIN& aReplacement )
{ {
return true; return true;
} }
@ -335,18 +279,17 @@ static bool pointInside2( const SHAPE_LINE_CHAIN& aL, const VECTOR2I& aP )
int result = 0; int result = 0;
size_t cnt = aL.PointCount(); size_t cnt = aL.PointCount();
auto ip = aL.CPoint( 0 ); VECTOR2I ip = aL.CPoint( 0 );
for( size_t i = 1; i <= cnt; ++i ) for( size_t i = 1; i <= cnt; ++i )
{ {
auto ipNext = (i == cnt ? aL.CPoint( 0 ) : aL.CPoint( i )); VECTOR2I ipNext = (i == cnt ? aL.CPoint( 0 ) : aL.CPoint( i ));
if( ipNext.y == aP.y ) if( ipNext.y == aP.y )
{ {
if( (ipNext.x ==aP.x) || ( ip.y ==aP.y if( (ipNext.x ==aP.x) || ( ip.y == aP.y && ( (ipNext.x >aP.x) == (ip.x <aP.x) ) ) )
&& ( (ipNext.x >aP.x) == (ip.x <aP.x) ) ) )
return -1; return -1;
} }
if( (ip.y <aP.y) != (ipNext.y <aP.y) ) if( (ip.y <aP.y) != (ipNext.y <aP.y) )
{ {
@ -391,15 +334,17 @@ static bool pointInside2( const SHAPE_LINE_CHAIN& aL, const VECTOR2I& aP )
} }
bool KEEP_TOPOLOGY_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement ) bool KEEP_TOPOLOGY_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine,
{ const SHAPE_LINE_CHAIN& aCurrentPath,
const SHAPE_LINE_CHAIN& aReplacement )
{
SHAPE_LINE_CHAIN encPoly = aOriginLine->CLine().Slice( aVertex1, aVertex2 ); SHAPE_LINE_CHAIN encPoly = aOriginLine->CLine().Slice( aVertex1, aVertex2 );
// fixme: this is a remarkably shitty implementation... // fixme: this is a remarkably shitty implementation...
encPoly.Append( aReplacement.Reverse() ); encPoly.Append( aReplacement.Reverse() );
encPoly.SetClosed( true ); encPoly.SetClosed( true );
auto bb = encPoly.BBox(); BOX2I bb = encPoly.BBox();
std::vector<JOINT*> joints; std::vector<JOINT*> joints;
int cnt = m_world->QueryJoints( bb, joints, aOriginLine->Layers(), ITEM::SOLID_T ); int cnt = m_world->QueryJoints( bb, joints, aOriginLine->Layers(), ITEM::SOLID_T );
@ -407,7 +352,7 @@ bool KEEP_TOPOLOGY_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aO
if( !cnt ) if( !cnt )
return true; return true;
for( auto j : joints ) for( JOINT* j : joints )
{ {
if( j->Net() == aOriginLine->Net() ) if( j->Net() == aOriginLine->Net() )
continue; continue;
@ -435,6 +380,7 @@ bool KEEP_TOPOLOGY_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aO
return true; return true;
} }
bool OPTIMIZER::checkColliding( ITEM* aItem, bool aUpdateCache ) bool OPTIMIZER::checkColliding( ITEM* aItem, bool aUpdateCache )
{ {
CACHE_VISITOR v( aItem, m_world, m_collisionKindMask ); CACHE_VISITOR v( aItem, m_world, m_collisionKindMask );
@ -442,26 +388,30 @@ bool OPTIMIZER::checkColliding( ITEM* aItem, bool aUpdateCache )
return static_cast<bool>( m_world->CheckColliding( aItem ) ); return static_cast<bool>( m_world->CheckColliding( aItem ) );
} }
void OPTIMIZER::ClearConstraints() void OPTIMIZER::ClearConstraints()
{ {
for( auto c : m_constraints) for( OPT_CONSTRAINT* c : m_constraints )
delete c; delete c;
m_constraints.clear(); m_constraints.clear();
} }
void OPTIMIZER::AddConstraint ( OPT_CONSTRAINT *aConstraint ) void OPTIMIZER::AddConstraint ( OPT_CONSTRAINT *aConstraint )
{ {
m_constraints.push_back(aConstraint); m_constraints.push_back( aConstraint );
} }
bool OPTIMIZER::checkConstraints( int aVertex1, int aVertex2, LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement )
bool OPTIMIZER::checkConstraints( int aVertex1, int aVertex2, LINE* aOriginLine,
const SHAPE_LINE_CHAIN& aCurrentPath,
const SHAPE_LINE_CHAIN& aReplacement )
{ {
for( auto c: m_constraints) for( OPT_CONSTRAINT* c : m_constraints )
{ {
if( !c->Check( aVertex1, aVertex2, aOriginLine, aCurrentPath, aReplacement ) ) if( !c->Check( aVertex1, aVertex2, aOriginLine, aCurrentPath, aReplacement ) )
{
return false; return false;
}
} }
return true; return true;
@ -618,15 +568,15 @@ bool OPTIMIZER::mergeColinear( LINE* aLine )
bool OPTIMIZER::Optimize( LINE* aLine, LINE* aResult ) bool OPTIMIZER::Optimize( LINE* aLine, LINE* aResult )
{ {
if( !aResult ) if( !aResult )
{
aResult = aLine; aResult = aLine;
}
else else
{ {
*aResult = *aLine; *aResult = *aLine;
aResult->ClearLinks(); aResult->ClearLinks();
} }
m_keepPostures = false;
bool rv = false; bool rv = false;
if( m_effortLevel & PRESERVE_VERTEX ) if( m_effortLevel & PRESERVE_VERTEX )
@ -637,7 +587,8 @@ bool OPTIMIZER::Optimize( LINE* aLine, LINE* aResult )
if( m_effortLevel & RESTRICT_VERTEX_RANGE ) if( m_effortLevel & RESTRICT_VERTEX_RANGE )
{ {
auto c = new RESTRICT_VERTEX_RANGE_CONSTRAINT( m_world, m_restrictedVertexRange.first, m_restrictedVertexRange.second ); auto c = new RESTRICT_VERTEX_RANGE_CONSTRAINT( m_world, m_restrictedVertexRange.first,
m_restrictedVertexRange.second );
AddConstraint( c ); AddConstraint( c );
} }
@ -730,17 +681,18 @@ bool OPTIMIZER::mergeStep( LINE* aLine, SHAPE_LINE_CHAIN& aCurrentPath, int step
} }
OPTIMIZER::BREAKOUT_LIST OPTIMIZER::circleBreakouts( int aWidth, OPTIMIZER::BREAKOUT_LIST OPTIMIZER::circleBreakouts( int aWidth, const SHAPE* aShape,
const SHAPE* aShape, bool aPermitDiagonal ) const bool aPermitDiagonal ) const
{ {
BREAKOUT_LIST breakouts; BREAKOUT_LIST breakouts;
for( int angle = 0; angle < 360; angle += 45 ) for( int angle = 0; angle < 360; angle += 45 )
{ {
const SHAPE_CIRCLE* cir = static_cast<const SHAPE_CIRCLE*>( aShape ); const SHAPE_CIRCLE* cir = static_cast<const SHAPE_CIRCLE*>( aShape );
SHAPE_LINE_CHAIN l; SHAPE_LINE_CHAIN l;
VECTOR2I p0 = cir->GetCenter(); VECTOR2I p0 = cir->GetCenter();
VECTOR2I v0( cir->GetRadius() * M_SQRT2, 0 ); VECTOR2I v0( cir->GetRadius() * M_SQRT2, 0 );
l.Append( p0 ); l.Append( p0 );
l.Append( p0 + v0.Rotate( angle * M_PI / 180.0 ) ); l.Append( p0 + v0.Rotate( angle * M_PI / 180.0 ) );
breakouts.push_back( l ); breakouts.push_back( l );
@ -750,8 +702,8 @@ OPTIMIZER::BREAKOUT_LIST OPTIMIZER::circleBreakouts( int aWidth,
} }
OPTIMIZER::BREAKOUT_LIST OPTIMIZER::customBreakouts( int aWidth, OPTIMIZER::BREAKOUT_LIST OPTIMIZER::customBreakouts( int aWidth, const ITEM* aItem,
const ITEM* aItem, bool aPermitDiagonal ) const bool aPermitDiagonal ) const
{ {
BREAKOUT_LIST breakouts; BREAKOUT_LIST breakouts;
const SHAPE_SIMPLE* convex = static_cast<const SHAPE_SIMPLE*>( aItem->Shape() ); const SHAPE_SIMPLE* convex = static_cast<const SHAPE_SIMPLE*>( aItem->Shape() );
@ -792,8 +744,8 @@ OPTIMIZER::BREAKOUT_LIST OPTIMIZER::customBreakouts( int aWidth,
} }
OPTIMIZER::BREAKOUT_LIST OPTIMIZER::rectBreakouts( int aWidth, OPTIMIZER::BREAKOUT_LIST OPTIMIZER::rectBreakouts( int aWidth, const SHAPE* aShape,
const SHAPE* aShape, bool aPermitDiagonal ) const bool aPermitDiagonal ) const
{ {
const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>(aShape); const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>(aShape);
VECTOR2I s = rect->GetSize(); VECTOR2I s = rect->GetSize();
@ -847,8 +799,8 @@ OPTIMIZER::BREAKOUT_LIST OPTIMIZER::rectBreakouts( int aWidth,
} }
OPTIMIZER::BREAKOUT_LIST OPTIMIZER::computeBreakouts( int aWidth, OPTIMIZER::BREAKOUT_LIST OPTIMIZER::computeBreakouts( int aWidth, const ITEM* aItem,
const ITEM* aItem, bool aPermitDiagonal ) const bool aPermitDiagonal ) const
{ {
switch( aItem->Kind() ) switch( aItem->Kind() )
{ {
@ -943,10 +895,12 @@ int OPTIMIZER::smartPadsSingle( LINE* aLine, ITEM* aPad, bool aEnd, int aEndVert
// If the line is contained inside the pad, don't optimize // If the line is contained inside the pad, don't optimize
if( solid && solid->Shape() && !solid->Shape()->Collide( if( solid && solid->Shape() && !solid->Shape()->Collide(
SEG( line.CPoint( 0 ), line.CPoint( p ) ), aLine->Width() / 2 ) ) SEG( line.CPoint( 0 ), line.CPoint( p ) ), aLine->Width() / 2 ) )
{
continue; continue;
}
for( SHAPE_LINE_CHAIN & breakout : breakouts ) { for( SHAPE_LINE_CHAIN & breakout : breakouts )
{
for( int diag = 0; diag < 2; diag++ ) for( int diag = 0; diag < 2; diag++ )
{ {
SHAPE_LINE_CHAIN v; SHAPE_LINE_CHAIN v;
@ -1125,15 +1079,17 @@ bool OPTIMIZER::fanoutCleanup( LINE* aLine )
} }
int findCoupledVertices( const VECTOR2I& aVertex, const SEG& aOrigSeg, const SHAPE_LINE_CHAIN& aCoupled, DIFF_PAIR* aPair, int* aIndices ) int findCoupledVertices( const VECTOR2I& aVertex, const SEG& aOrigSeg,
const SHAPE_LINE_CHAIN& aCoupled, DIFF_PAIR* aPair, int* aIndices )
{ {
int count = 0; int count = 0;
for ( int i = 0; i < aCoupled.SegmentCount(); i++ )
for( int i = 0; i < aCoupled.SegmentCount(); i++ )
{ {
SEG s = aCoupled.CSegment( i ); SEG s = aCoupled.CSegment( i );
VECTOR2I projOverCoupled = s.LineProject ( aVertex ); VECTOR2I projOverCoupled = s.LineProject ( aVertex );
if( s.ApproxParallel ( aOrigSeg ) ) if( s.ApproxParallel( aOrigSeg ) )
{ {
int64_t dist = int64_t{(( projOverCoupled - aVertex ).EuclideanNorm())} - aPair->Width(); int64_t dist = int64_t{(( projOverCoupled - aVertex ).EuclideanNorm())} - aPair->Width();
@ -1149,7 +1105,8 @@ int findCoupledVertices( const VECTOR2I& aVertex, const SEG& aOrigSeg, const SHA
} }
bool verifyDpBypass( NODE* aNode, DIFF_PAIR* aPair, bool aRefIsP, const SHAPE_LINE_CHAIN& aNewRef, const SHAPE_LINE_CHAIN& aNewCoupled ) bool verifyDpBypass( NODE* aNode, DIFF_PAIR* aPair, bool aRefIsP, const SHAPE_LINE_CHAIN& aNewRef,
const SHAPE_LINE_CHAIN& aNewCoupled )
{ {
LINE refLine ( aRefIsP ? aPair->PLine() : aPair->NLine(), aNewRef ); LINE refLine ( aRefIsP ? aPair->PLine() : aPair->NLine(), aNewRef );
LINE coupledLine ( aRefIsP ? aPair->NLine() : aPair->PLine(), aNewCoupled ); LINE coupledLine ( aRefIsP ? aPair->NLine() : aPair->PLine(), aNewCoupled );
@ -1167,17 +1124,19 @@ bool verifyDpBypass( NODE* aNode, DIFF_PAIR* aPair, bool aRefIsP, const SHAPE_LI
} }
bool coupledBypass( NODE* aNode, DIFF_PAIR* aPair, bool aRefIsP, const SHAPE_LINE_CHAIN& aRef, const SHAPE_LINE_CHAIN& aRefBypass, const SHAPE_LINE_CHAIN& aCoupled, SHAPE_LINE_CHAIN& aNewCoupled ) bool coupledBypass( NODE* aNode, DIFF_PAIR* aPair, bool aRefIsP, const SHAPE_LINE_CHAIN& aRef,
const SHAPE_LINE_CHAIN& aRefBypass, const SHAPE_LINE_CHAIN& aCoupled,
SHAPE_LINE_CHAIN& aNewCoupled )
{ {
int vStartIdx[1024]; // fixme: possible overflow int vStartIdx[1024]; // fixme: possible overflow
int nStarts = findCoupledVertices( aRefBypass.CPoint( 0 ), aRefBypass.CSegment( 0 ),
aCoupled, aPair, vStartIdx );
DIRECTION_45 dir( aRefBypass.CSegment( 0 ) );
int nStarts = findCoupledVertices( aRefBypass.CPoint( 0 ), aRefBypass.CSegment( 0 ), aCoupled, aPair, vStartIdx ); int64_t bestLength = -1;
DIRECTION_45 dir( aRefBypass.CSegment( 0 ) ); bool found = false;
int64_t bestLength = -1;
bool found = false;
SHAPE_LINE_CHAIN bestBypass; SHAPE_LINE_CHAIN bestBypass;
int si, ei; int si, ei;
for( int i=0; i< nStarts; i++ ) for( int i=0; i< nStarts; i++ )
{ {
@ -1188,7 +1147,8 @@ bool coupledBypass( NODE* aNode, DIFF_PAIR* aPair, bool aRefIsP, const SHAPE_LIN
if( delta > 1 ) if( delta > 1 )
{ {
const VECTOR2I& vs = aCoupled.CPoint( vStartIdx[i] ); const VECTOR2I& vs = aCoupled.CPoint( vStartIdx[i] );
SHAPE_LINE_CHAIN bypass = dir.BuildInitialTrace( vs, aCoupled.CPoint(j), dir.IsDiagonal() ); SHAPE_LINE_CHAIN bypass = dir.BuildInitialTrace( vs, aCoupled.CPoint(j),
dir.IsDiagonal() );
int64_t coupledLength = aPair->CoupledLength( aRef, bypass ); int64_t coupledLength = aPair->CoupledLength( aRef, bypass );
@ -1202,7 +1162,8 @@ bool coupledBypass( NODE* aNode, DIFF_PAIR* aPair, bool aRefIsP, const SHAPE_LIN
else else
newCoupled.Replace( ei, si, bypass.Reverse() ); newCoupled.Replace( ei, si, bypass.Reverse() );
if(coupledLength > bestLength && verifyDpBypass( aNode, aPair, aRefIsP, aRef, newCoupled) ) if( coupledLength > bestLength && verifyDpBypass( aNode, aPair, aRefIsP, aRef,
newCoupled) )
{ {
bestBypass = newCoupled; bestBypass = newCoupled;
bestLength = coupledLength; bestLength = coupledLength;
@ -1260,7 +1221,7 @@ bool OPTIMIZER::mergeDpStep( DIFF_PAIR* aPair, bool aTryP, int step )
deltaUni = aPair->CoupledLength ( newRef, coupledPath ) - clenPre + budget; deltaUni = aPair->CoupledLength ( newRef, coupledPath ) - clenPre + budget;
if ( coupledBypass( m_world, aPair, aTryP, newRef, bypass, coupledPath, newCoup ) ) if( coupledBypass( m_world, aPair, aTryP, newRef, bypass, coupledPath, newCoup ) )
{ {
deltaCoupled = aPair->CoupledLength( newRef, newCoup ) - clenPre + budget; deltaCoupled = aPair->CoupledLength( newRef, newCoup ) - clenPre + budget;
@ -1273,7 +1234,7 @@ bool OPTIMIZER::mergeDpStep( DIFF_PAIR* aPair, bool aTryP, int step )
return true; return true;
} }
} }
else if( deltaUni >= 0 && verifyDpBypass ( m_world, aPair, aTryP, newRef, coupledPath ) ) else if( deltaUni >= 0 && verifyDpBypass( m_world, aPair, aTryP, newRef, coupledPath ) )
{ {
newRef.Simplify(); newRef.Simplify();
coupledPath.Simplify(); coupledPath.Simplify();
@ -1336,6 +1297,7 @@ bool OPTIMIZER::Optimize( DIFF_PAIR* aPair )
return mergeDpSegments( aPair ); return mergeDpSegments( aPair );
} }
static int64_t shovedArea( const SHAPE_LINE_CHAIN& aOld, const SHAPE_LINE_CHAIN& aNew ) static int64_t shovedArea( const SHAPE_LINE_CHAIN& aOld, const SHAPE_LINE_CHAIN& aNew )
{ {
int64_t area = 0; int64_t area = 0;
@ -1347,16 +1309,18 @@ static int64_t shovedArea( const SHAPE_LINE_CHAIN& aOld, const SHAPE_LINE_CHAIN&
{ {
int i_next = (i + 1 == total ? 0 : i + 1); int i_next = (i + 1 == total ? 0 : i + 1);
const VECTOR2I &v0 = ( i < oc ? aOld.CPoint(i) : aNew.CPoint( nc - 1 - (i - oc) ) ); const VECTOR2I &v0 = i < oc ? aOld.CPoint(i)
const VECTOR2I &v1 = ( i_next < oc ? aOld.CPoint ( i_next ) : aNew.CPoint( nc - 1 - (i_next - oc) ) ); : aNew.CPoint( nc - 1 - (i - oc) );
const VECTOR2I &v1 = i_next < oc ? aOld.CPoint ( i_next )
: aNew.CPoint( nc - 1 - (i_next - oc) );
area += -(int64_t) v0.y * v1.x + (int64_t) v0.x * v1.y; area += -(int64_t) v0.y * v1.x + (int64_t) v0.x * v1.y;
} }
return std::abs(area / 2); return std::abs(area / 2);
} }
bool tightenSegment( bool dir, NODE *aNode, const LINE& cur, bool tightenSegment( bool dir, NODE *aNode, const LINE& cur, const SHAPE_LINE_CHAIN& in,
const SHAPE_LINE_CHAIN& in, SHAPE_LINE_CHAIN& out ) SHAPE_LINE_CHAIN& out )
{ {
SEG a = in.CSegment(0); SEG a = in.CSegment(0);
SEG center = in.CSegment(1); SEG center = in.CSegment(1);
@ -1380,10 +1344,10 @@ bool tightenSegment( bool dir, NODE *aNode, const LINE& cur,
return false; return false;
{ {
//auto rC = *a.IntersectLines( b );
// dbg->AddSegment ( SEG( center.A, rC ), 1 );
// dbg->AddSegment ( SEG( center.B, rC ), 2 );
/* /*
auto rC = *a.IntersectLines( b );
dbg->AddSegment ( SEG( center.A, rC ), 1 );
dbg->AddSegment ( SEG( center.B, rC ), 2 );
auto perp = dirCenter.Left().Left(); auto perp = dirCenter.Left().Left();
SEG sperp ( center.A, center.A + perp.ToVector() ); SEG sperp ( center.A, center.A + perp.ToVector() );
@ -1399,15 +1363,14 @@ bool tightenSegment( bool dir, NODE *aNode, const LINE& cur,
dbg->AddSegment ( SEG( vpc, vp ), 5 ); dbg->AddSegment ( SEG( vpc, vp ), 5 );
guide = SEG ( vpc, vp );*/ guide = SEG ( vpc, vp );
*/
} }
int da = a.Length(); int da = a.Length();
int db = b.Length(); int db = b.Length();
if ( da < db ) if( da < db )
guide = a; guide = a;
else else
guide = b; guide = b;
@ -1419,9 +1382,9 @@ bool tightenSegment( bool dir, NODE *aNode, const LINE& cur,
int current = step; int current = step;
SHAPE_LINE_CHAIN snew; SHAPE_LINE_CHAIN snew;
while (step > 1) while( step > 1 )
{ {
LINE l ( cur ); LINE l( cur );
snew.Clear(); snew.Clear();
snew.Append( a.A ); snew.Append( a.A );
@ -1432,14 +1395,13 @@ bool tightenSegment( bool dir, NODE *aNode, const LINE& cur,
step /= 2; step /= 2;
l.SetShape(snew); l.SetShape(snew);
if( aNode->CheckColliding(&l) ) if( aNode->CheckColliding(&l) )
{
current -= step; current -= step;
} else if ( current + step >= initial ) { else if ( current + step >= initial )
current = initial; current = initial;
} else { else
current += step; current += step;
}
//dbg->AddSegment ( SEG( center.A , a.LineProject( center.A + gr ) ), 3 ); //dbg->AddSegment ( SEG( center.A , a.LineProject( center.A + gr ) ), 3 );
@ -1477,6 +1439,7 @@ void Tighten( NODE *aNode, const SHAPE_LINE_CHAIN& aOldLine, const LINE& aNewLin
SHAPE_LINE_CHAIN l_in, l_out; SHAPE_LINE_CHAIN l_in, l_out;
l_in = current.Slice(i, i+3); l_in = current.Slice(i, i+3);
for( int dir = 0; dir < 1; dir++) for( int dir = 0; dir < 1; dir++)
{ {
if( tightenSegment( dir ? true : false, aNode, aNewLine, l_in, l_out ) ) if( tightenSegment( dir ? true : false, aNode, aNewLine, l_in, l_out ) )
@ -1487,15 +1450,12 @@ void Tighten( NODE *aNode, const SHAPE_LINE_CHAIN& aOldLine, const LINE& aNewLin
auto prevArea = std::abs(shovedArea( aOldLine, current )); auto prevArea = std::abs(shovedArea( aOldLine, current ));
if( optArea < prevArea ) if( optArea < prevArea )
{
current = opt; current = opt;
}
break; break;
} }
} }
} }
} }
aOptimized = LINE(aNewLine, current); aOptimized = LINE(aNewLine, current);

View File

@ -111,14 +111,14 @@ public:
~OPTIMIZER(); ~OPTIMIZER();
///> a quick shortcut to optmize a line without creating and setting up an optimizer ///> a quick shortcut to optmize a line without creating and setting up an optimizer
static bool Optimize( LINE* aLine, int aEffortLevel, NODE* aWorld, const VECTOR2I aV = VECTOR2I(0, 0) ); static bool Optimize( LINE* aLine, int aEffortLevel, NODE* aWorld,
const VECTOR2I aV = VECTOR2I(0, 0) );
bool Optimize( LINE* aLine, LINE* aResult = NULL ); bool Optimize( LINE* aLine, LINE* aResult = NULL );
bool Optimize( DIFF_PAIR* aPair ); bool Optimize( DIFF_PAIR* aPair );
void SetWorld( NODE* aNode ) { m_world = aNode; } void SetWorld( NODE* aNode ) { m_world = aNode; }
void CacheStaticItem( ITEM* aItem );
void CacheRemove( ITEM* aItem ); void CacheRemove( ITEM* aItem );
void ClearCache( bool aStaticOnly = false ); void ClearCache( bool aStaticOnly = false );
@ -132,7 +132,6 @@ public:
m_effortLevel = aEffort; m_effortLevel = aEffort;
} }
void SetPreserveVertex( const VECTOR2I& aV ) void SetPreserveVertex( const VECTOR2I& aV )
{ {
m_preservedVertex = aV; m_preservedVertex = aV;
@ -154,9 +153,6 @@ public:
void ClearConstraints(); void ClearConstraints();
void AddConstraint ( OPT_CONSTRAINT *aConstraint ); void AddConstraint ( OPT_CONSTRAINT *aConstraint );
bool extractPadGrids( std::vector<JOINT*>& aPadJoints );
void BuildPadGrids();
private: private:
static const int MaxCachedItems = 256; static const int MaxCachedItems = 256;
@ -173,7 +169,6 @@ private:
bool mergeObtuse( LINE* aLine ); bool mergeObtuse( LINE* aLine );
bool mergeFull( LINE* aLine ); bool mergeFull( LINE* aLine );
bool mergeColinear( LINE* aLine ); bool mergeColinear( LINE* aLine );
bool removeUglyCorners( LINE* aLine );
bool runSmartPads( LINE* aLine ); bool runSmartPads( LINE* aLine );
bool mergeStep( LINE* aLine, SHAPE_LINE_CHAIN& aCurrentLine, int step ); bool mergeStep( LINE* aLine, SHAPE_LINE_CHAIN& aCurrentLine, int step );
bool fanoutCleanup( LINE * aLine ); bool fanoutCleanup( LINE * aLine );
@ -186,13 +181,12 @@ private:
void cacheAdd( ITEM* aItem, bool aIsStatic ); void cacheAdd( ITEM* aItem, bool aIsStatic );
void removeCachedSegments( LINE* aLine, int aStartVertex = 0, int aEndVertex = -1 ); void removeCachedSegments( LINE* aLine, int aStartVertex = 0, int aEndVertex = -1 );
bool checkConstraints( int aVertex1, int aVertex2, LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement ); bool checkConstraints( int aVertex1, int aVertex2, LINE* aOriginLine,
const SHAPE_LINE_CHAIN& aCurrentPath,
const SHAPE_LINE_CHAIN& aReplacement );
BREAKOUT_LIST circleBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const; BREAKOUT_LIST circleBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
BREAKOUT_LIST rectBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const; BREAKOUT_LIST rectBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
BREAKOUT_LIST ovalBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
BREAKOUT_LIST customBreakouts( int aWidth, const ITEM* aItem, bool aPermitDiagonal ) const; BREAKOUT_LIST customBreakouts( int aWidth, const ITEM* aItem, bool aPermitDiagonal ) const;
BREAKOUT_LIST computeBreakouts( int aWidth, const ITEM* aItem, bool aPermitDiagonal ) const; BREAKOUT_LIST computeBreakouts( int aWidth, const ITEM* aItem, bool aPermitDiagonal ) const;
@ -200,20 +194,18 @@ private:
ITEM* findPadOrVia( int aLayer, int aNet, const VECTOR2I& aP ) const; ITEM* findPadOrVia( int aLayer, int aNet, const VECTOR2I& aP ) const;
SHAPE_INDEX_LIST<ITEM*> m_cache; private:
SHAPE_INDEX_LIST<ITEM*> m_cache;
std::vector<OPT_CONSTRAINT*> m_constraints;
std::unordered_map<ITEM*, CACHED_ITEM> m_cacheTags;
std::vector<OPT_CONSTRAINT*> m_constraints; NODE* m_world;
typedef std::unordered_map<ITEM*, CACHED_ITEM> CachedItemTags; int m_collisionKindMask;
CachedItemTags m_cacheTags; int m_effortLevel;
NODE* m_world;
int m_collisionKindMask;
int m_effortLevel;
bool m_keepPostures;
VECTOR2I m_preservedVertex;
VECTOR2I m_preservedVertex;
std::pair<int, int> m_restrictedVertexRange; std::pair<int, int> m_restrictedVertexRange;
BOX2I m_restrictArea; BOX2I m_restrictArea;
}; };
class OPT_CONSTRAINT class OPT_CONSTRAINT
@ -221,87 +213,76 @@ class OPT_CONSTRAINT
public: public:
OPT_CONSTRAINT( NODE* aWorld ) : OPT_CONSTRAINT( NODE* aWorld ) :
m_world( aWorld ) m_world( aWorld )
{
m_priority = 0;
};
virtual ~OPT_CONSTRAINT() {};
virtual bool Check( int aVertex1, int aVertex2, const LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement ) = 0;
int GetPriority() const
{ {
return m_priority; m_priority = 0;
} };
void SetPriority( int aPriority ) virtual ~OPT_CONSTRAINT()
{ {
m_priority = aPriority; };
}
virtual bool Check( int aVertex1, int aVertex2, const LINE* aOriginLine,
const SHAPE_LINE_CHAIN& aCurrentPath,
const SHAPE_LINE_CHAIN& aReplacement ) = 0;
int GetPriority() const { return m_priority; }
void SetPriority( int aPriority ) { m_priority = aPriority; }
protected: protected:
NODE* m_world; NODE* m_world;
int m_priority; int m_priority;
}; };
class ANGLE_CONSTRAINT_45: public OPT_CONSTRAINT
{
public:
ANGLE_CONSTRAINT_45( NODE* aWorld, int aEntryDirectionMask = -1, int aExitDirectionMask = -1 ) :
OPT_CONSTRAINT( aWorld ),
m_entryDirectionMask( aEntryDirectionMask ),
m_exitDirectionMask( aExitDirectionMask )
{
}
virtual ~ANGLE_CONSTRAINT_45() {};
virtual bool Check( int aVertex1, int aVertex2, const LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement ) override;
private:
int m_entryDirectionMask;
int m_exitDirectionMask;
};
class AREA_CONSTRAINT : public OPT_CONSTRAINT class AREA_CONSTRAINT : public OPT_CONSTRAINT
{ {
public: public:
AREA_CONSTRAINT( NODE* aWorld, const BOX2I& aAllowedArea ) : AREA_CONSTRAINT( NODE* aWorld, const BOX2I& aAllowedArea ) :
OPT_CONSTRAINT( aWorld ), OPT_CONSTRAINT( aWorld ),
m_allowedArea ( aAllowedArea ) {}; m_allowedArea ( aAllowedArea )
{
};
virtual bool Check( int aVertex1, int aVertex2, const LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement ) override; bool Check( int aVertex1, int aVertex2, const LINE* aOriginLine,
const SHAPE_LINE_CHAIN& aCurrentPath,
const SHAPE_LINE_CHAIN& aReplacement ) override;
private: private:
BOX2I m_allowedArea; BOX2I m_allowedArea;
}; };
class KEEP_TOPOLOGY_CONSTRAINT: public OPT_CONSTRAINT class KEEP_TOPOLOGY_CONSTRAINT: public OPT_CONSTRAINT
{ {
public: public:
KEEP_TOPOLOGY_CONSTRAINT( NODE* aWorld ) : KEEP_TOPOLOGY_CONSTRAINT( NODE* aWorld ) :
OPT_CONSTRAINT( aWorld ) OPT_CONSTRAINT( aWorld )
{}; {
};
virtual bool Check( int aVertex1, int aVertex2, const LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement ) override; bool Check( int aVertex1, int aVertex2, const LINE* aOriginLine,
const SHAPE_LINE_CHAIN& aCurrentPath,
const SHAPE_LINE_CHAIN& aReplacement ) override;
}; };
class PRESERVE_VERTEX_CONSTRAINT: public OPT_CONSTRAINT class PRESERVE_VERTEX_CONSTRAINT: public OPT_CONSTRAINT
{ {
public: public:
PRESERVE_VERTEX_CONSTRAINT( NODE* aWorld, const VECTOR2I& aV ) : PRESERVE_VERTEX_CONSTRAINT( NODE* aWorld, const VECTOR2I& aV ) :
OPT_CONSTRAINT( aWorld ), OPT_CONSTRAINT( aWorld ),
m_v( aV ) m_v( aV )
{}; {
};
virtual bool Check( int aVertex1, int aVertex2, const LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement ) override; bool Check( int aVertex1, int aVertex2, const LINE* aOriginLine,
const SHAPE_LINE_CHAIN& aCurrentPath,
const SHAPE_LINE_CHAIN& aReplacement ) override;
private: private:
VECTOR2I m_v; VECTOR2I m_v;
}; };
class RESTRICT_VERTEX_RANGE_CONSTRAINT: public OPT_CONSTRAINT class RESTRICT_VERTEX_RANGE_CONSTRAINT: public OPT_CONSTRAINT
{ {
public: public:
@ -309,11 +290,13 @@ public:
OPT_CONSTRAINT( aWorld ), OPT_CONSTRAINT( aWorld ),
m_start( aStart ), m_start( aStart ),
m_end( aEnd ) m_end( aEnd )
{}; {
};
virtual bool Check( int aVertex1, int aVertex2, const LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement ) override; virtual bool Check( int aVertex1, int aVertex2, const LINE* aOriginLine,
const SHAPE_LINE_CHAIN& aCurrentPath,
const SHAPE_LINE_CHAIN& aReplacement ) override;
private: private:
int m_start; int m_start;
int m_end; int m_end;
}; };

View File

@ -34,7 +34,8 @@
namespace PNS { namespace PNS {
static const SHAPE_LINE_CHAIN buildHullForPrimitiveShape( const SHAPE* aShape, int aClearance, int aWalkaroundThickness ) static const SHAPE_LINE_CHAIN buildHullForPrimitiveShape( const SHAPE* aShape, int aClearance,
int aWalkaroundThickness )
{ {
int cl = aClearance + ( aWalkaroundThickness + 1 )/ 2; int cl = aClearance + ( aWalkaroundThickness + 1 )/ 2;
@ -43,15 +44,20 @@ static const SHAPE_LINE_CHAIN buildHullForPrimitiveShape( const SHAPE* aShape, i
case SH_RECT: case SH_RECT:
{ {
const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>( aShape ); const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>( aShape );
return OctagonalHull( rect->GetPosition(), rect->GetSize(), cl + 1, 0.2 * cl ); return OctagonalHull( rect->GetPosition(),
rect->GetSize(),
cl + 1,
0.2 * cl );
} }
case SH_CIRCLE: case SH_CIRCLE:
{ {
const SHAPE_CIRCLE* circle = static_cast<const SHAPE_CIRCLE*>( aShape ); const SHAPE_CIRCLE* circle = static_cast<const SHAPE_CIRCLE*>( aShape );
int r = circle->GetRadius(); int r = circle->GetRadius();
return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ), return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ),
cl + 1, 0.52 * ( r + cl ) ); VECTOR2I( 2 * r, 2 * r ),
cl + 1,
0.52 * ( r + cl ) );
} }
case SH_SEGMENT: case SH_SEGMENT:
@ -91,12 +97,13 @@ const SHAPE_LINE_CHAIN SOLID::Hull( int aClearance, int aWalkaroundThickness, in
if ( cmpnd->Shapes().size() == 1 ) if ( cmpnd->Shapes().size() == 1 )
{ {
return buildHullForPrimitiveShape( cmpnd->Shapes()[0], aClearance, aWalkaroundThickness ); return buildHullForPrimitiveShape( cmpnd->Shapes()[0], aClearance,
aWalkaroundThickness );
} }
else else
{ {
// fixme - shouldn't happen but one day we should move TransformShapeWithClearanceToPolygon() // fixme - shouldn't happen but one day we should move
// to the Geometry Library // TransformShapeWithClearanceToPolygon() to the Geometry Library
return SHAPE_LINE_CHAIN(); return SHAPE_LINE_CHAIN();
} }
} }
@ -118,12 +125,13 @@ const SHAPE_LINE_CHAIN SOLID::HoleHull( int aClearance, int aWalkaroundThickness
if ( cmpnd->Shapes().size() == 1 ) if ( cmpnd->Shapes().size() == 1 )
{ {
return buildHullForPrimitiveShape( cmpnd->Shapes()[0], aClearance, aWalkaroundThickness ); return buildHullForPrimitiveShape( cmpnd->Shapes()[0], aClearance,
aWalkaroundThickness );
} }
else else
{ {
// fixme - shouldn't happen but one day we should move TransformShapeWithClearanceToPolygon() // fixme - shouldn't happen but one day we should move
// to the Geometry Library // TransformShapeWithClearanceToPolygon() to the Geometry Library
return SHAPE_LINE_CHAIN(); return SHAPE_LINE_CHAIN();
} }
} }