// Delete null length segments, and intermediate points .. bool TRACKS_CLEANER::clean_segments() { bool modified = false; // Easy things first modified |= delete_null_segments(); // Delete redundant segments, i.e. segments having the same end points and layers for( TRACK *segment = m_Brd->m_Track; segment; segment = segment->Next() ) modified |= remove_duplicates_of_track( segment ); // merge collinear segments: TRACK *nextsegment; for( TRACK *segment = m_Brd->m_Track; segment; segment = nextsegment ) { nextsegment = segment->Next(); if( segment->Type() == PCB_TRACE_T ) { bool merged_this = merge_collinear_of_track( segment ); modified |= merged_this; if( merged_this ) // The current segment was modified, retry to merge it again nextsegment = segment->Next(); } } return modified; }
/* Creates the section "$TRACKS" * This sections give the list of widths (tools) used in tracks and vias * format: * $TRACK * TRACK <name> <width> * $ENDTRACK * * Each tool name is build like this: "TRACK" + track width. * For instance for a width = 120 : name = "TRACK120". */ static void CreateTracksInfoData( FILE* aFile, BOARD* aPcb ) { TRACK* track; int last_width = -1; // Find thickness used for traces // XXX could use the same sorting approach used for pads std::vector <int> trackinfo; unsigned ii; for( track = aPcb->m_Track; track; track = track->Next() ) { if( last_width != track->GetWidth() ) // Find a thickness already used. { for( ii = 0; ii < trackinfo.size(); ii++ ) { if( trackinfo[ii] == track->GetWidth() ) break; } if( ii == trackinfo.size() ) // not found trackinfo.push_back( track->GetWidth() ); last_width = track->GetWidth(); } } for( track = aPcb->m_Zone; track; track = track->Next() ) { if( last_width != track->GetWidth() ) // Find a thickness already used. { for( ii = 0; ii < trackinfo.size(); ii++ ) { if( trackinfo[ii] == track->GetWidth() ) break; } if( ii == trackinfo.size() ) // not found trackinfo.push_back( track->GetWidth() ); last_width = track->GetWidth(); } } // Write data fputs( "$TRACKS\n", aFile ); for( ii = 0; ii < trackinfo.size(); ii++ ) { fprintf( aFile, "TRACK TRACK%d %g\n", trackinfo[ii], trackinfo[ii] / SCALE_FACTOR ); } fputs( "$ENDTRACKS\n\n", aFile ); }
void DRC::testTracks( wxWindow *aActiveWindow, bool aShowProgressBar ) { wxProgressDialog * progressDialog = NULL; const int delta = 500; // This is the number of tests between 2 calls to the // progress bar int count = 0; for( TRACK* segm = m_pcb->m_Track; segm && segm->Next(); segm = segm->Next() ) count++; int deltamax = count/delta; if( aShowProgressBar && deltamax > 3 ) { progressDialog = new wxProgressDialog( _( "Track clearances" ), wxEmptyString, deltamax, aActiveWindow, wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_APP_MODAL | wxPD_ELAPSED_TIME ); progressDialog->Update( 0, wxEmptyString ); } int ii = 0; count = 0; for( TRACK* segm = m_pcb->m_Track; segm && segm->Next(); segm = segm->Next() ) { if ( ii++ > delta ) { ii = 0; count++; if( progressDialog ) { if( !progressDialog->Update( count, wxEmptyString ) ) break; // Aborted by user #ifdef __WXMAC__ // Work around a dialog z-order issue on OS X if( count == deltamax ) aActiveWindow->Raise(); #endif } } if( !doTrackDrc( segm, segm->Next(), true ) ) { wxASSERT( m_currentMarker ); m_pcb->Add( m_currentMarker ); m_mainWindow->GetGalCanvas()->GetView()->Add( m_currentMarker ); m_currentMarker = 0; } } if( progressDialog ) progressDialog->Destroy(); }
void DRC::testTracks( bool aShowProgressBar ) { wxProgressDialog * progressDialog = NULL; const int delta = 500; // This is the number of tests between 2 calls to the // progress bar int count = 0; for( TRACK* segm = m_pcb->m_Track; segm && segm->Next(); segm = segm->Next() ) count++; int deltamax = count/delta; if( aShowProgressBar && deltamax > 3 ) { progressDialog = new wxProgressDialog( _( "Track clearances" ), wxEmptyString, deltamax, m_mainWindow, wxPD_AUTO_HIDE | wxPD_CAN_ABORT ); progressDialog->Update( 0, wxEmptyString ); } int ii = 0; count = 0; for( TRACK* segm = m_pcb->m_Track; segm && segm->Next(); segm = segm->Next() ) { if ( ii++ > delta ) { ii = 0; count++; if( progressDialog ) { if( !progressDialog->Update( count, wxEmptyString ) ) break; // Aborted by user } } if( !doTrackDrc( segm, segm->Next(), true ) ) { wxASSERT( m_currentMarker ); m_pcb->Add( m_currentMarker ); m_mainWindow->GetGalCanvas()->GetView()->Add( m_currentMarker ); m_currentMarker = 0; } } if( progressDialog ) progressDialog->Destroy(); }
TRACK* GetTrack( TRACK* aStartTrace, const TRACK* aEndTrace, const wxPoint& aPosition, LSET aLayerMask ) { for( TRACK* seg = aStartTrace; seg; seg = seg->Next() ) { if( seg->GetState( IS_DELETED | BUSY ) == 0 ) { if( aPosition == seg->GetStart() ) { if( ( aLayerMask & seg->GetLayerSet() ).any() ) return seg; } if( aPosition == seg->GetEnd() ) { if( ( aLayerMask & seg->GetLayerSet() ).any() ) return seg; } } if( seg == aEndTrace ) break; } return NULL; }
bool TRACKS_CLEANER::remove_duplicates_of_track( const TRACK *aTrack ) { bool modified = false; TRACK *nextsegment; for( TRACK *other = aTrack->Next(); other; other = nextsegment ) { nextsegment = other->Next(); // New netcode, break out (can't be there any other) if( aTrack->GetNetCode() != other->GetNetCode() ) break; // Must be of the same type, on the same layer and the endpoints // must be the same (maybe swapped) if( (aTrack->Type() != other->Type()) && (aTrack->GetLayer() != other->GetLayer()) ) { if( ((aTrack->GetStart() == other->GetStart()) && (aTrack->GetEnd() == other->GetEnd())) || ((aTrack->GetStart() == other->GetEnd()) && (aTrack->GetEnd() == other->GetStart()))) { m_Brd->GetRatsnest()->Remove( other ); other->ViewRelease(); other->DeleteStructure(); modified = true; } } } return modified; }
int SELECTION_TOOL::selectConnection( const TOOL_EVENT& aEvent ) { BOARD_CONNECTED_ITEM* item = m_selection.Item<BOARD_CONNECTED_ITEM>( 0 ); int segmentCount; if( item->Type() != PCB_TRACE_T && item->Type() != PCB_VIA_T ) return 0; clearSelection(); TRACK* trackList = getModel<BOARD>()->MarkTrace( static_cast<TRACK*>( item ), &segmentCount, NULL, NULL, true ); if( segmentCount == 0 ) return 0; for( int i = 0; i < segmentCount; ++i ) { select( trackList ); trackList = trackList->Next(); } // Inform other potentially interested tools TOOL_EVENT selectEvent( SelectedEvent ); m_toolMgr->ProcessEvent( selectEvent ); return 0; }
int SELECTION_TOOL::selectConnection( const TOOL_EVENT& aEvent ) { if( !selectCursor( true ) ) return 0; auto item = m_selection.Front(); clearSelection(); if( item->Type() != PCB_TRACE_T && item->Type() != PCB_VIA_T ) return 0; int segmentCount; TRACK* trackList = board()->MarkTrace( static_cast<TRACK*>( item ), &segmentCount, NULL, NULL, true ); if( segmentCount == 0 ) return 0; for( int i = 0; i < segmentCount; ++i ) { select( trackList ); trackList = trackList->Next(); } // Inform other potentially interested tools m_toolMgr->ProcessEvent( SelectedEvent ); return 0; }
TRACK* GetTrack( TRACK* aStartTrace, const TRACK* aEndTrace, const wxPoint& aPosition, LAYER_MSK aLayerMask ) { for( TRACK *PtSegm = aStartTrace; PtSegm != NULL; PtSegm = PtSegm->Next() ) { if( PtSegm->GetState( IS_DELETED | BUSY ) == 0 ) { if( aPosition == PtSegm->GetStart() ) { if( aLayerMask & PtSegm->GetLayerMask() ) return PtSegm; } if( aPosition == PtSegm->GetEnd() ) { if( aLayerMask & PtSegm->GetLayerMask() ) return PtSegm; } } if( PtSegm == aEndTrace ) break; } return NULL; }
static void Show_MoveTrack(WinEDA_DrawPanel * panel, wxDC * DC, bool erase) /*************************************************************************/ /* redessin du contour de la piste lors des deplacements de la souris */ { int ii, dx, dy; TRACK * Track; BASE_SCREEN * screen = panel->GetScreen(); int track_fill_copy = DisplayOpt.DisplayPcbTrackFill; DisplayOpt.DisplayPcbTrackFill = SKETCH ; erase = TRUE; /* efface ancienne position si elle a ete deja dessinee */ if( erase ) { if ( NewTrack ) Trace_Une_Piste(panel, DC, NewTrack,NbPtNewTrack,GR_XOR) ; } /* mise a jour des coordonnees des segments de la piste */ wxPoint Pos = screen->m_Curseur; dx = Pos.x - LastPos.x; dy = Pos.y - LastPos.y; LastPos = Pos; ii = NbPtNewTrack, Track = NewTrack; for( ; ii > 0; ii--, Track = Track->Next() ) { if( Track->m_Flags & STARTPOINT) { Track->m_Start.x += dx; Track->m_Start.y += dy; } if( Track->m_Flags & ENDPOINT) { Track->m_End.x += dx; Track->m_End.y += dy; } } /* dessin de la nouvelle piste */ Trace_Une_Piste(panel, DC, NewTrack,NbPtNewTrack,GR_XOR) ; /* Tracage des segments dragges */ DRAG_SEGM * pt_drag = g_DragSegmentList; for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext) { Track = pt_drag->m_Segm; if ( erase ) Track->Draw(panel, DC, GR_XOR); if( Track->m_Flags & STARTPOINT) { Track->m_Start.x += dx; Track->m_Start.y += dy; } if( Track->m_Flags & ENDPOINT) { Track->m_End.x += dx; Track->m_End.y += dy; } Track->Draw(panel, DC, GR_XOR); } DisplayOpt.DisplayPcbTrackFill = track_fill_copy ; }
void DrawTraces( EDA_DRAW_PANEL* panel, wxDC* DC, TRACK* aTrackList, int nbsegment, GR_DRAWMODE draw_mode ) { // preserve the start of the list for debugging. for( TRACK* track = aTrackList; nbsegment > 0 && track; nbsegment--, track = track->Next() ) { track->Draw( panel, DC, draw_mode ); } }
void PCB_EDIT_FRAME::Swap_Layers( wxCommandEvent& event ) { PCB_LAYER_ID new_layer[PCB_LAYER_ID_COUNT]; DIALOG_SWAP_LAYERS dlg( this, new_layer ); if( dlg.ShowModal() != wxID_OK ) return; BOARD_COMMIT commit( this ); bool hasChanges = false; // Change tracks. for( TRACK* segm = GetBoard()->m_Track; segm; segm = segm->Next() ) { if( segm->Type() == PCB_VIA_T ) { VIA* via = (VIA*) segm; PCB_LAYER_ID top_layer, bottom_layer; if( via->GetViaType() == VIA_THROUGH ) continue; via->LayerPair( &top_layer, &bottom_layer ); if( new_layer[bottom_layer] != bottom_layer || new_layer[top_layer] != top_layer ) { commit.Modify( via ); via->SetLayerPair( new_layer[top_layer], new_layer[bottom_layer] ); GetGalCanvas()->GetView()->Update( via, KIGFX::GEOMETRY ); hasChanges = true; } } else { hasChanges |= processBoardItem( this, commit, segm, new_layer ); } } for( BOARD_ITEM* zone : GetBoard()->Zones() ) { hasChanges |= processBoardItem( this, commit, zone, new_layer ); } for( BOARD_ITEM* drawing : GetBoard()->Drawings() ) { hasChanges |= processBoardItem( this, commit, drawing, new_layer ); } if( hasChanges ) { OnModify(); commit.Push( "Layers moved" ); GetCanvas()->Refresh(); } }
static void export_vrml_tracks( BOARD* pcb ) //{{{ { for( TRACK* track = pcb->m_Track; track != NULL; track = track->Next() ) { if( track->Type() == PCB_VIA_T ) export_vrml_via( pcb, (SEGVIA*) track ); else export_vrml_line( track->GetLayer(), track->GetStart().x, track->GetStart().y, track->GetEnd().x, track->GetEnd().y, track->GetWidth(), 4 ); } }
void PCB_DRAW_PANEL_GAL::DisplayBoard( const BOARD* aBoard ) { m_view->Clear(); // Load zones for( int i = 0; i < aBoard->GetAreaCount(); ++i ) m_view->Add( (KIGFX::VIEW_ITEM*) ( aBoard->GetArea( i ) ) ); // Load drawings for( BOARD_ITEM* drawing = aBoard->m_Drawings; drawing; drawing = drawing->Next() ) m_view->Add( drawing ); // Load tracks for( TRACK* track = aBoard->m_Track; track; track = track->Next() ) m_view->Add( track ); // Load modules and its additional elements for( MODULE* module = aBoard->m_Modules; module; module = module->Next() ) { module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, m_view, _1 ) ); m_view->Add( module ); } // Segzones (equivalent of ZONE_CONTAINER for legacy boards) for( SEGZONE* zone = aBoard->m_Zone; zone; zone = zone->Next() ) m_view->Add( zone ); // Ratsnest if( m_ratsnest ) { m_view->Remove( m_ratsnest ); delete m_ratsnest; } m_ratsnest = new KIGFX::RATSNEST_VIEWITEM( aBoard->GetRatsnest() ); m_view->Add( m_ratsnest ); // Display settings UseColorScheme( aBoard->GetColorsSettings() ); PCB_BASE_FRAME* frame = dynamic_cast<PCB_BASE_FRAME*>( GetParent() ); if( frame ) { SetTopLayer( frame->GetActiveLayer() ); DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*) frame->GetDisplayOptions(); static_cast<KIGFX::PCB_RENDER_SETTINGS*>( m_view->GetPainter()->GetSettings() )->LoadDisplayOptions( displ_opts ); } m_view->RecacheAllItems( true ); }
/* * Test all connections of the board, * and update subnet variable of pads and tracks * TestForActiveLinksInRatsnest must be called after this function * to update active/inactive ratsnest items status */ void PCB_BASE_FRAME::TestConnections() { // Clear the cluster identifier for all pads for( unsigned i = 0; i< m_Pcb->GetPadCount(); ++i ) { D_PAD* pad = m_Pcb->GetPad(i); pad->SetZoneSubNet( 0 ); pad->SetSubNet( 0 ); } m_Pcb->Test_Connections_To_Copper_Areas(); // Test existing connections net by net // note some nets can have no tracks, and pads intersecting // so Build_CurrNet_SubNets_Connections must be called for each net CONNECTIONS connections( m_Pcb ); int last_net_tested = 0; int current_net_code = 0; for( TRACK* track = m_Pcb->m_Track; track; ) { // At this point, track is the first track of a given net current_net_code = track->GetNetCode(); // Get last track of the current net TRACK* lastTrack = track->GetEndNetCode( current_net_code ); if( current_net_code > 0 ) // do not spend time if net code = 0 ( dummy net ) { // Test all previous nets having no tracks for( int net = last_net_tested+1; net < current_net_code; net++ ) connections.Build_CurrNet_SubNets_Connections( NULL, NULL, net ); connections.Build_CurrNet_SubNets_Connections( track, lastTrack, current_net_code ); last_net_tested = current_net_code; } track = lastTrack->Next(); // this is now the first track of the next net } // Test last nets without tracks, if any int netsCount = m_Pcb->GetNetCount(); for( int net = last_net_tested+1; net < netsCount; net++ ) connections.Build_CurrNet_SubNets_Connections( NULL, NULL, net ); Merge_SubNets_Connected_By_CopperAreas( m_Pcb ); return; }
void DRC::testKeepoutAreas() { // Test keepout areas for vias, tracks and pads inside keepout areas for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ ) { ZONE_CONTAINER* area = m_pcb->GetArea( ii ); if( !area->GetIsKeepout() ) continue; for( TRACK* segm = m_pcb->m_Track; segm != NULL; segm = segm->Next() ) { if( segm->Type() == PCB_TRACE_T ) { if( ! area->GetDoNotAllowTracks() ) continue; if( segm->GetLayer() != area->GetLayer() ) continue; if( area->Outline()->Distance( segm->GetStart(), segm->GetEnd(), segm->GetWidth() ) == 0 ) { m_currentMarker = fillMarker( segm, NULL, DRCE_TRACK_INSIDE_KEEPOUT, m_currentMarker ); m_pcb->Add( m_currentMarker ); m_mainWindow->GetGalCanvas()->GetView()->Add( m_currentMarker ); m_currentMarker = 0; } } else if( segm->Type() == PCB_VIA_T ) { if( ! area->GetDoNotAllowVias() ) continue; if( ! ((VIA*)segm)->IsOnLayer( area->GetLayer() ) ) continue; if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 ) { m_currentMarker = fillMarker( segm, NULL, DRCE_VIA_INSIDE_KEEPOUT, m_currentMarker ); m_pcb->Add( m_currentMarker ); m_mainWindow->GetGalCanvas()->GetView()->Add( m_currentMarker ); m_currentMarker = 0; } } } // Test pads: TODO } }
void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aOutlines ) { // convert tracks and vias: for( TRACK* track = m_Track; track != NULL; track = track->Next() ) { if( !track->IsOnLayer( aLayer ) ) continue; track->TransformShapeWithClearanceToPolygon( aOutlines, 0 ); } // convert pads for( MODULE* module = m_Modules; module != NULL; module = module->Next() ) { module->TransformPadsShapesWithClearanceToPolygon( aLayer, aOutlines, 0 ); // Micro-wave modules may have items on copper layers module->TransformGraphicShapesWithClearanceToPolygonSet( aLayer, aOutlines, 0 ); } // convert copper zones for( int ii = 0; ii < GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = GetArea( ii ); PCB_LAYER_ID zonelayer = zone->GetLayer(); if( zonelayer == aLayer ) zone->TransformSolidAreasShapesToPolygonSet( aOutlines ); } // convert graphic items on copper layers (texts) for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) { if( !item->IsOnLayer( aLayer ) ) continue; switch( item->Type() ) { case PCB_LINE_T: ( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon( aOutlines, 0 ); break; case PCB_TEXT_T: ( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet( aOutlines, 0 ); break; default: break; } } }
/* * Delete dangling tracks * Vias: * If a via is only connected to a dangling track, it also will be removed */ bool TRACKS_CLEANER::deleteUnconnectedTracks() { if( m_Brd->m_Track == NULL ) return false; bool modified = false; bool item_erased; do // Iterate when at least one track is deleted { item_erased = false; TRACK* next_track; for( TRACK *track = m_Brd->m_Track; track != NULL; track = next_track ) { next_track = track->Next(); bool flag_erase = false; // Start without a good reason to erase it /* if a track endpoint is not connected to a pad, test if * the endpoint is connected to another track or to a zone. * For via test, an enhancement could be to test if * connected to 2 items on different layers. Currently * a via must be connected to 2 items, that can be on the * same layer */ // Check if there is nothing attached on the start if( !(track->GetState( START_ON_PAD )) ) flag_erase |= testTrackEndpointDangling( track, ENDPOINT_START ); // Check if there is nothing attached on the end if( !(track->GetState( END_ON_PAD )) ) flag_erase |= testTrackEndpointDangling( track, ENDPOINT_END ); if( flag_erase ) { // remove segment from board m_Brd->GetRatsnest()->Remove( track ); track->ViewRelease(); track->DeleteStructure(); /* keep iterating, because a track connected to the deleted track * now perhaps is not connected and should be deleted */ item_erased = true; modified = true; } } } while( item_erased ); return modified; }
void TRACKS_CLEANER::buildTrackConnectionInfo() { BuildTracksCandidatesList( m_Brd->m_Track, NULL); // clear flags and variables used in cleanup for( TRACK * track = m_Brd->m_Track; track; track = track->Next() ) { track->start = NULL; track->end = NULL; track->m_PadsConnected.clear(); track->SetState( START_ON_PAD|END_ON_PAD|BUSY, false ); } // Build connections info tracks to pads SearchTracksConnectedToPads(); for( TRACK * track = m_Brd->m_Track; track; track = track->Next() ) { // Mark track if connected to pads for( unsigned jj = 0; jj < track->m_PadsConnected.size(); jj++ ) { D_PAD * pad = track->m_PadsConnected[jj]; if( pad->HitTest( track->GetStart() ) ) { track->start = pad; track->SetState( START_ON_PAD, true ); } if( pad->HitTest( track->GetEnd() ) ) { track->end = pad; track->SetState( END_ON_PAD, true ); } } } }
void BRDITEMS_PLOTTER::PlotDrillMarks() { /* If small drills marks were requested prepare a clamp value to pass to the helper function */ int small_drill = (GetDrillMarksType() == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE) ? SMALL_DRILL : 0; /* In the filled trace mode drill marks are drawn white-on-black to scrape the underlying pad. This works only for drivers supporting color change, obviously... it means that: - PS, SVG and PDF output is correct (i.e. you have a 'donut' pad) - In HPGL you can't see them - In gerbers you can't see them, too. This is arguably the right thing to do since having drill marks and high speed drill stations is a sure recipe for broken tools and angry manufacturers. If you *really* want them you could start a layer with negative polarity to scrape the film. - In DXF they go into the 'WHITE' layer. This could be useful. */ if( GetMode() == FILLED ) m_plotter->SetColor( WHITE ); for( TRACK *pts = m_board->m_Track; pts != NULL; pts = pts->Next() ) { const VIA* via = dyn_cast<const VIA*>( pts ); if( via ) plotOneDrillMark( PAD_DRILL_CIRCLE, via->GetStart(), wxSize( via->GetDrillValue(), 0 ), wxSize( via->GetWidth(), 0 ), 0, small_drill ); } for( MODULE *Module = m_board->m_Modules; Module != NULL; Module = Module->Next() ) { for( D_PAD *pad = Module->Pads(); pad != NULL; pad = pad->Next() ) { if( pad->GetDrillSize().x == 0 ) continue; plotOneDrillMark( pad->GetDrillShape(), pad->GetPosition(), pad->GetDrillSize(), pad->GetSize(), pad->GetOrientation(), small_drill ); } } if( GetMode() == FILLED ) m_plotter->SetColor( GetColor() ); }
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 ); }
static void export_vrml_tracks( MODEL_VRML& aModel, BOARD* pcb ) { for( TRACK* track = pcb->m_Track; track; track = track->Next() ) { if( track->Type() == PCB_VIA_T ) { export_vrml_via( aModel, pcb, (const VIA*) track ); } else if( track->GetLayer() == B_Cu || track->GetLayer() == F_Cu ) export_vrml_line( aModel, track->GetLayer(), track->GetStart().x * aModel.scale, track->GetStart().y * aModel.scale, track->GetEnd().x * aModel.scale, track->GetEnd().y * aModel.scale, track->GetWidth() * aModel.scale ); } }
TRACK* TRACK::GetBestInsertPoint( BOARD* aPcb ) { TRACK* track; if( Type() == PCB_ZONE_T ) track = aPcb->m_Zone; else track = aPcb->m_Track; for( ; track; track = track->Next() ) { if( GetNetCode() <= track->GetNetCode() ) return track; } return NULL; }
void PNS_KICAD_IFACE::SyncWorld( PNS::NODE *aWorld ) { if( !m_board ) { wxLogTrace( "PNS", "No board attached, aborting sync." ); return; } for( MODULE* module = m_board->m_Modules; module; module = module->Next() ) { for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { std::unique_ptr< PNS::SOLID > solid = syncPad( pad ); if( solid ) aWorld->Add( std::move( solid ) ); } } for( TRACK* t = m_board->m_Track; t; t = t->Next() ) { KICAD_T type = t->Type(); if( type == PCB_TRACE_T ) { std::unique_ptr< PNS::SEGMENT > segment = syncTrack( t ); if( segment ) { aWorld->Add( std::move( segment ) ); } } else if( type == PCB_VIA_T ) { std::unique_ptr< PNS::VIA > via = syncVia( static_cast<VIA*>( t ) ); if( via ) { aWorld->Add( std::move( via ) ); } } } int worstClearance = m_board->GetDesignSettings().GetBiggestClearanceValue(); delete m_ruleResolver; m_ruleResolver = new PNS_PCBNEW_RULE_RESOLVER( m_board, m_router ); aWorld->SetRuleResolver( m_ruleResolver ); aWorld->SetMaxClearance( 4 * worstClearance ); }
void CONNECTIONS::BuildTracksCandidatesList( TRACK* aBegin, TRACK* aEnd) { m_candidates.clear(); m_firstTrack = m_lastTrack = aBegin; unsigned ii = 0; // Count candidates ( i.e. end points ) for( const TRACK* track = aBegin; track; track = track->Next() ) { if( track->Type() == PCB_VIA_T ) ii++; else ii += 2; m_lastTrack = track; if( track == aEnd ) break; } // Build candidate list m_candidates.reserve( ii ); for( TRACK* track = aBegin; track; track = track->Next() ) { CONNECTED_POINT candidate( track, track->GetStart() ); m_candidates.push_back( candidate ); if( track->Type() != PCB_VIA_T ) { CONNECTED_POINT candidate2( track, track->GetEnd()); m_candidates.push_back( candidate2 ); } if( track == aEnd ) break; } // Sort list by increasing X coordinate, // and for increasing Y coordinate when items have the same X coordinate // So candidates to the same location are consecutive in list. sort( m_candidates.begin(), m_candidates.end(), sortConnectedPointByXthenYCoordinates ); }
/* Extract the D356 record from the vias */ static void build_via_testpoints( BOARD *aPcb, std::vector <D356_RECORD>& aRecords ) { wxPoint origin = aPcb->GetAuxOrigin(); // Enumerate all the track segments and keep the vias for( TRACK *track = aPcb->m_Track; track; track = track->Next() ) { if( track->Type() == PCB_VIA_T ) { VIA *via = (VIA*) track; NETINFO_ITEM *net = track->GetNet(); D356_RECORD rk; rk.smd = false; rk.hole = true; if( net ) rk.netname = net->GetNetname(); else rk.netname = wxEmptyString; rk.refdes = wxT("VIA"); rk.pin = wxT(""); rk.midpoint = true; // Vias are always midpoints rk.drill = via->GetDrillValue(); rk.mechanical = false; LAYER_ID top_layer, bottom_layer; via->LayerPair( &top_layer, &bottom_layer ); rk.access = via_access_code( aPcb, top_layer, bottom_layer ); rk.x_location = via->GetPosition().x - origin.x; rk.y_location = origin.y - via->GetPosition().y; rk.x_size = via->GetWidth(); rk.y_size = 0; // Round so height = 0 rk.rotation = 0; rk.soldermask = 3; // XXX always tented? aRecords.push_back( rk ); } } }
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 ); }
// Delete null length track segments bool TRACKS_CLEANER::delete_null_segments() { TRACK *nextsegment; bool modified = false; // Delete null segments for( TRACK *segment = m_Brd->m_Track; segment; segment = nextsegment ) { nextsegment = segment->Next(); if( segment->IsNull() ) // Length segment = 0; delete it { m_Brd->GetRatsnest()->Remove( segment ); segment->ViewRelease(); segment->DeleteStructure(); modified = true; } } return modified; }
int PCBNEW_CONTROL::TrackDisplayMode( TOOL_EVENT& aEvent ) { KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( m_frame->GetGalCanvas()->GetView()->GetPainter() ); KIGFX::PCB_RENDER_SETTINGS* settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*> ( painter->GetSettings() ); // Apply new display options to the GAL canvas DisplayOpt.DisplayPcbTrackFill = !DisplayOpt.DisplayPcbTrackFill; m_frame->m_DisplayPcbTrackFill = DisplayOpt.DisplayPcbTrackFill; settings->LoadDisplayOptions( DisplayOpt ); BOARD* board = getModel<BOARD>( PCB_T ); for( TRACK* track = board->m_Track; track; track = track->Next() ) track->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); setTransitions(); return 0; }
void BOARD::DrawHighLight( EDA_DRAW_PANEL* am_canvas, wxDC* DC, int aNetCode ) { GR_DRAWMODE draw_mode; if( IsHighLightNetON() ) draw_mode = GR_HIGHLIGHT | GR_OR; else draw_mode = GR_AND | GR_HIGHLIGHT; // Redraw ZONE_CONTAINERS BOARD::ZONE_CONTAINERS& zones = m_ZoneDescriptorList; for( BOARD::ZONE_CONTAINERS::iterator zc = zones.begin(); zc!=zones.end(); ++zc ) { if( (*zc)->GetNet() == aNetCode ) { (*zc)->Draw( am_canvas, DC, draw_mode ); } } // Redraw any pads that have aNetCode for( MODULE* module = m_Modules; module; module = module->Next() ) { for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { if( pad->GetNet() == aNetCode ) { pad->Draw( am_canvas, DC, draw_mode ); } } } // Redraw track and vias that have aNetCode for( TRACK* seg = m_Track; seg; seg = seg->Next() ) { if( seg->GetNet() == aNetCode ) { seg->Draw( am_canvas, DC, draw_mode ); } } }