void PNS_ROUTER::SyncWorld() { if( !m_board ) { TRACEn( 0, "No board attached, aborting sync." ); return; } ClearWorld(); m_world = new PNS_NODE(); for( MODULE* module = m_board->m_Modules; module; module = module->Next() ) { for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { PNS_ITEM* solid = syncPad( pad ); if( solid ) m_world->Add( solid ); } } for( TRACK* t = m_board->m_Track; t; t = t->Next() ) { KICAD_T type = t->Type(); PNS_ITEM* item = NULL; if( type == PCB_TRACE_T ) item = syncTrack( t ); else if( type == PCB_VIA_T ) item = syncVia( static_cast<VIA*>( t ) ); if( item ) m_world->Add( item ); } // TODO: Create resolvers in ctor, call resolver->SetBoard() in this->SetBoard() and delete it in dtor // TBD: Same remark as with m_sizes.SetMinimumTrackWidth in startRouting() int worstClearance = m_board->GetDesignSettings().GetBiggestClearanceValue(); m_clearanceResolver = new PNS_PCBNEW_CLEARANCE_RESOLVER( this ); m_world->SetClearanceResolver( m_clearanceResolver ); m_world->SetMaxClearance( 4 * worstClearance ); m_pairingResolver = new PCBNEW_PAIRING_RESOLVER( m_board ); m_world->SetPairingResolver( m_pairingResolver ); }
void PNS_ROUTER::SyncWorld() { if( !m_board ) { TRACEn( 0, "No board attached, aborting sync." ); return; } ClearWorld(); m_world = new PNS_NODE(); for( MODULE* module = m_board->m_Modules; module; module = module->Next() ) { for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { PNS_ITEM* solid = syncPad( pad ); if( solid ) m_world->Add( solid ); } } for( TRACK* t = m_board->m_Track; t; t = t->Next() ) { KICAD_T type = t->Type(); PNS_ITEM* item = NULL; if( type == PCB_TRACE_T ) item = syncTrack( t ); else if( type == PCB_VIA_T ) item = syncVia( static_cast<VIA*>( t ) ); if( item ) m_world->Add( item ); } int worstClearance = m_board->GetDesignSettings().GetBiggestClearanceValue(); m_clearanceFunc = new PNS_PCBNEW_CLEARANCE_FUNC( this ); m_world->SetClearanceFunctor( m_clearanceFunc ); m_world->SetMaxClearance( 4 * worstClearance ); }
PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad ) { PNS_LAYERSET layers( 0, MAX_CU_LAYERS - 1 ); // ignore non-copper pads if ( (aPad->GetLayerSet() & LSET::AllCuMask()).none() ) return NULL; switch( aPad->GetAttribute() ) { case PAD_ATTRIB_STANDARD: break; case PAD_ATTRIB_SMD: case PAD_ATTRIB_HOLE_NOT_PLATED: case PAD_ATTRIB_CONN: { LSET lmsk = aPad->GetLayerSet(); bool is_copper = false; for( int i = 0; i < MAX_CU_LAYERS; i++ ) { if( lmsk[i] ) { is_copper = true; if( aPad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED ) layers = PNS_LAYERSET( i ); break; } } if( !is_copper ) return NULL; } break; default: TRACE( 0, "unsupported pad type 0x%x", aPad->GetAttribute() ); return NULL; } PNS_SOLID* solid = new PNS_SOLID; solid->SetLayers( layers ); solid->SetNet( aPad->GetNetCode() ); solid->SetParent( aPad ); wxPoint wx_c = aPad->ShapePos(); wxSize wx_sz = aPad->GetSize(); wxPoint offset = aPad->GetOffset(); VECTOR2I c( wx_c.x, wx_c.y ); VECTOR2I sz( wx_sz.x, wx_sz.y ); RotatePoint( &offset, aPad->GetOrientation() ); solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) ); solid->SetOffset ( VECTOR2I ( offset.x, offset.y ) ); double orient = aPad->GetOrientation() / 10.0; if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) { solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); } else { if( orient == 0.0 || orient == 90.0 || orient == 180.0 || orient == 270.0 ) { if( orient == 90.0 || orient == 270.0 ) sz = VECTOR2I( sz.y, sz.x ); switch( aPad->GetShape() ) { case PAD_SHAPE_OVAL: if( sz.x == sz.y ) solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); else { VECTOR2I delta; if( sz.x > sz.y ) delta = VECTOR2I( ( sz.x - sz.y ) / 2, 0 ); else delta = VECTOR2I( 0, ( sz.y - sz.x ) / 2 ); SHAPE_SEGMENT* shape = new SHAPE_SEGMENT( c - delta, c + delta, std::min( sz.x, sz.y ) ); solid->SetShape( shape ); } break; case PAD_SHAPE_RECT: solid->SetShape( new SHAPE_RECT( c - sz / 2, sz.x, sz.y ) ); break; case PAD_SHAPE_TRAPEZOID: { wxPoint coords[4]; aPad->BuildPadPolygon( coords, wxSize( 0, 0 ), aPad->GetOrientation() ); SHAPE_CONVEX* shape = new SHAPE_CONVEX(); for( int ii = 0; ii < 4; ii++ ) { shape->Append( wx_c + coords[ii] ); } solid->SetShape( shape ); break; } default: TRACEn( 0, "unsupported pad shape" ); delete solid; return NULL; } } else { switch( aPad->GetShape() ) { // PAD_SHAPE_CIRCLE already handled above case PAD_SHAPE_OVAL: if( sz.x == sz.y ) solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); else { wxPoint start; wxPoint end; wxPoint corner; SHAPE_CONVEX* shape = new SHAPE_CONVEX(); int w = aPad->BuildSegmentFromOvalShape( start, end, 0.0, wxSize( 0, 0 ) ); if( start.y == 0 ) corner = wxPoint( start.x, -( w / 2 ) ); else corner = wxPoint( w / 2, start.y ); RotatePoint( &start, aPad->GetOrientation() ); RotatePoint( &corner, aPad->GetOrientation() ); shape->Append( wx_c + corner ); for( int rot = 100; rot <= 1800; rot += 100 ) { wxPoint p( corner ); RotatePoint( &p, start, rot ); shape->Append( wx_c + p ); } if( end.y == 0 ) corner = wxPoint( end.x, w / 2 ); else corner = wxPoint( -( w / 2 ), end.y ); RotatePoint( &end, aPad->GetOrientation() ); RotatePoint( &corner, aPad->GetOrientation() ); shape->Append( wx_c + corner ); for( int rot = 100; rot <= 1800; rot += 100 ) { wxPoint p( corner ); RotatePoint( &p, end, rot ); shape->Append( wx_c + p ); } solid->SetShape( shape ); } break; case PAD_SHAPE_RECT: case PAD_SHAPE_TRAPEZOID: { wxPoint coords[4]; aPad->BuildPadPolygon( coords, wxSize( 0, 0 ), aPad->GetOrientation() ); SHAPE_CONVEX* shape = new SHAPE_CONVEX(); for( int ii = 0; ii < 4; ii++ ) { shape->Append( wx_c + coords[ii] ); } solid->SetShape( shape ); break; } default: TRACEn( 0, "unsupported pad shape" ); delete solid; return NULL; } } } return solid; }