bool TRACKS_CLEANER::merge_collinear_of_track( TRACK *aSegment ) { bool merged_this = false; // *WHY* doesn't C++ have prec and succ (or ++ --) like PASCAL? for( ENDPOINT_T endpoint = ENDPOINT_START; endpoint <= ENDPOINT_END; endpoint = ENDPOINT_T( endpoint + 1 ) ) { // search for a possible segment connected to the current endpoint of the current one TRACK *other = aSegment->Next(); if( other ) { other = aSegment->GetTrack( other, NULL, endpoint, true, false ); if( other ) { // the two segments must have the same width and the other // cannot be a via if( (aSegment->GetWidth() == other->GetWidth()) && (other->Type() == PCB_TRACE_T) ) { // There can be only one segment connected other->SetState( BUSY, true ); TRACK *yet_another = aSegment->GetTrack( m_Brd->m_Track, NULL, endpoint, true, false ); other->SetState( BUSY, false ); if( !yet_another ) { // Try to merge them TRACK *segDelete = mergeCollinearSegmentIfPossible( aSegment, other, endpoint ); // Merge succesful, the other one has to go away if( segDelete ) { m_Brd->GetRatsnest()->Remove( segDelete ); segDelete->ViewRelease(); segDelete->DeleteStructure(); merged_this = true; } } } } } } return merged_this; }
/** Abort function for drag or move track */ static void Abort_MoveTrack( EDA_DRAW_PANEL* aPanel, wxDC* aDC ) { PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) aPanel->GetParent(); BOARD * pcb = frame->GetBoard(); pcb->HighLightOFF(); pcb->PopHighLight(); frame->SetCurItem( NULL ); aPanel->SetMouseCapture( NULL, NULL ); // Undo move and redraw trace segments. for( unsigned jj=0 ; jj < g_DragSegmentList.size(); jj++ ) { TRACK* track = g_DragSegmentList[jj].m_Track; g_DragSegmentList[jj].RestoreInitialValues(); track->SetState( IN_EDIT, false ); track->ClearFlags(); } // Clear the undo picker list: s_ItemsListPicker.ClearListAndDeleteItems(); EraseDragList(); aPanel->Refresh(); }
/* Cancel move pad command. */ static void Abort_Move_Pad( EDA_DRAW_PANEL* Panel, wxDC* DC ) { D_PAD* pad = s_CurrentSelectedPad; Panel->SetMouseCapture( NULL, NULL ); if( pad == NULL ) return; pad->Draw( Panel, DC, GR_XOR ); pad->ClearFlags(); pad->SetPosition( Pad_OldPos ); pad->Draw( Panel, DC, GR_XOR ); // Pad move in progress: restore origin of dragged tracks, if any. for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { TRACK* Track = g_DragSegmentList[ii].m_Track; Track->Draw( Panel, DC, GR_XOR ); Track->SetState( IN_EDIT, OFF ); g_DragSegmentList[ii].RestoreInitialValues(); Track->Draw( Panel, DC, GR_OR ); } EraseDragList(); s_CurrentSelectedPad = NULL; }
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 PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC ) { TRACK* TrackToStartPoint = NULL; TRACK* TrackToEndPoint = NULL; bool error = false; if( !track ) return; // TODO: Use clenup functions to merge collinear segments if track // is connected to a collinear segment. s_StartSegmentPresent = s_EndSegmentPresent = true; if( ( track->start == NULL ) || ( track->start->Type() == PCB_TRACE_T ) ) TrackToStartPoint = track->GetTrack( GetBoard()->m_Track, NULL, ENDPOINT_START, true, false ); // Test if more than one segment is connected to this point if( TrackToStartPoint ) { TrackToStartPoint->SetState( BUSY, true ); if( ( TrackToStartPoint->Type() == PCB_VIA_T ) || track->GetTrack( GetBoard()->m_Track, NULL, ENDPOINT_START, true, false ) ) error = true; TrackToStartPoint->SetState( BUSY, false ); } if( ( track->end == NULL ) || ( track->end->Type() == PCB_TRACE_T ) ) TrackToEndPoint = track->GetTrack( GetBoard()->m_Track, NULL, ENDPOINT_END, true, false ); // Test if more than one segment is connected to this point if( TrackToEndPoint ) { TrackToEndPoint->SetState( BUSY, true ); if( (TrackToEndPoint->Type() == PCB_VIA_T) || track->GetTrack( GetBoard()->m_Track, NULL, ENDPOINT_END, true, false ) ) error = true; TrackToEndPoint->SetState( BUSY, false ); } if( error ) { DisplayError( this, _( "Unable to drag this segment: too many segments connected" ) ); return; } if( !TrackToStartPoint || ( TrackToStartPoint->Type() != PCB_TRACE_T ) ) s_StartSegmentPresent = false; if( !TrackToEndPoint || ( TrackToEndPoint->Type() != PCB_TRACE_T ) ) s_EndSegmentPresent = false; // Change high light net: the new one will be highlighted GetBoard()->PushHighLight(); if( GetBoard()->IsHighLightNetON() ) HighLight( DC ); EraseDragList(); track->SetFlags( IS_DRAGGED ); if( TrackToStartPoint ) { STATUS_FLAGS flag = STARTPOINT; if( track->GetStart() != TrackToStartPoint->GetStart() ) flag = ENDPOINT; AddSegmentToDragList( flag, TrackToStartPoint ); track->SetFlags( STARTPOINT ); } if( TrackToEndPoint ) { STATUS_FLAGS flag = STARTPOINT; if( track->GetEnd() != TrackToEndPoint->GetStart() ) flag = ENDPOINT; AddSegmentToDragList( flag, TrackToEndPoint ); track->SetFlags( ENDPOINT ); } AddSegmentToDragList( track->GetFlags(), track ); UndrawAndMarkSegmentsToDrag( m_canvas, DC ); PosInit = GetCrossHairPosition(); s_LastPos = GetCrossHairPosition(); m_canvas->SetMouseCapture( Show_Drag_Track_Segment_With_Cte_Slope, Abort_MoveTrack ); GetBoard()->SetHighLightNet( track->GetNetCode() ); GetBoard()->HighLightON(); GetBoard()->DrawHighLight( m_canvas, DC, GetBoard()->GetHighLightNetCode() ); // Prepare the Undo command ITEM_PICKER picker( NULL, UR_CHANGED ); for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { TRACK* draggedtrack = g_DragSegmentList[ii].m_Track; picker.SetItem( draggedtrack); picker.SetLink ( draggedtrack->Clone() ); s_ItemsListPicker.PushItem( picker ); draggedtrack = (TRACK*) picker.GetLink(); draggedtrack->SetStatus( 0 ); draggedtrack->ClearFlags(); } if( !InitialiseDragParameters() ) { DisplayError( this, _( "Unable to drag this segment: two collinear segments" ) ); m_canvas->SetMouseCaptureCallback( NULL ); Abort_MoveTrack( m_canvas, DC ); return; } }
bool PCB_EDIT_FRAME::RemoveMisConnectedTracks() { /* finds all track segments which are mis-connected (to more than one net). * When such a bad segment is found, it is flagged to be removed. * All tracks having at least one flagged segment are removed. */ TRACK* segment; TRACK* other; TRACK* next; int net_code_s, net_code_e; bool isModified = false; for( segment = GetBoard()->m_Track; segment; segment = (TRACK*) segment->Next() ) { segment->SetState( FLAG0, false ); // find the netcode for segment using anything connected to the "start" of "segment" net_code_s = -1; if( segment->start && segment->start->Type()==PCB_PAD_T ) { // get the netcode of the pad to propagate. net_code_s = ((D_PAD*)(segment->start))->GetNetCode(); } else { other = segment->GetTrace( GetBoard()->m_Track, NULL, FLG_START ); if( other ) net_code_s = other->GetNetCode(); } if( net_code_s < 0 ) continue; // the "start" of segment is not connected // find the netcode for segment using anything connected to the "end" of "segment" net_code_e = -1; if( segment->end && segment->end->Type()==PCB_PAD_T ) { net_code_e = ((D_PAD*)(segment->end))->GetNetCode(); } else { other = segment->GetTrace( GetBoard()->m_Track, NULL, FLG_END ); if( other ) net_code_e = other->GetNetCode(); } if( net_code_e < 0 ) continue; // the "end" of segment is not connected // Netcodes do not agree, so mark the segment as "to be removed" if( net_code_s != net_code_e ) { segment->SetState( FLAG0, true ); } } // Remove tracks having a flagged segment for( segment = GetBoard()->m_Track; segment; segment = next ) { next = (TRACK*) segment->Next(); if( segment->GetState( FLAG0 ) ) // Segment is flagged to be removed { segment->SetState( FLAG0, false ); isModified = true; GetBoard()->m_Status_Pcb = 0; Remove_One_Track( NULL, segment ); // the current segment is deleted, // we do not know the next "not yet tested" segment, // so restart to the beginning next = GetBoard()->m_Track; } } return isModified; }
// Delete null length segments, and intermediate points .. bool TRACKS_CLEANER::clean_segments() { bool modified = false; TRACK* segment, * nextsegment; TRACK* other; int flag, no_inc; // Delete null segments for( segment = m_Brd->m_Track; segment; segment = nextsegment ) { nextsegment = segment->Next(); if( segment->IsNull() ) // Length segment = 0; delete it segment->DeleteStructure(); } // Delete redundant segments, i.e. segments having the same end points // and layers for( segment = m_Brd->m_Track; segment; segment = segment->Next() ) { for( other = segment->Next(); other; other = nextsegment ) { nextsegment = other->Next(); bool erase = false; if( segment->Type() != other->Type() ) continue; if( segment->GetLayer() != other->GetLayer() ) continue; if( segment->GetNetCode() != other->GetNetCode() ) break; if( ( segment->GetStart() == other->GetStart() ) && ( segment->GetEnd() == other->GetEnd() ) ) erase = true; if( ( segment->GetStart() == other->GetEnd() ) && ( segment->GetEnd() == other->GetStart() ) ) erase = true; // Delete redundant point if( erase ) { other->DeleteStructure(); modified = true; } } } // merge collinear segments: for( segment = m_Brd->m_Track; segment; segment = nextsegment ) { TRACK* segStart; TRACK* segEnd; TRACK* segDelete; nextsegment = segment->Next(); if( segment->Type() != PCB_TRACE_T ) continue; flag = no_inc = 0; // search for a possible point connected to the START point of the current segment for( segStart = segment->Next(); ; ) { segStart = segment->GetTrace( segStart, NULL, FLG_START ); if( segStart ) { // the two segments must have the same width if( segment->GetWidth() != segStart->GetWidth() ) break; // it cannot be a via if( segStart->Type() != PCB_TRACE_T ) break; // We must have only one segment connected segStart->SetState( BUSY, true ); other = segment->GetTrace( m_Brd->m_Track, NULL, FLG_START ); segStart->SetState( BUSY, false ); if( other == NULL ) flag = 1; // OK break; } break; } if( flag ) // We have the starting point of the segment is connected to an other segment { segDelete = mergeCollinearSegmentIfPossible( segment, segStart, FLG_START ); if( segDelete ) { no_inc = 1; segDelete->DeleteStructure(); modified = true; } } // search for a possible point connected to the END point of the current segment: for( segEnd = segment->Next(); ; ) { segEnd = segment->GetTrace( segEnd, NULL, FLG_END ); if( segEnd ) { if( segment->GetWidth() != segEnd->GetWidth() ) break; if( segEnd->Type() != PCB_TRACE_T ) break; // We must have only one segment connected segEnd->SetState( BUSY, true ); other = segment->GetTrace( m_Brd->m_Track, NULL, FLG_END ); segEnd->SetState( BUSY, false ); if( other == NULL ) flag |= 2; // Ok break; } else { break; } } if( flag & 2 ) // We have the ending point of the segment is connected to an other segment { segDelete = mergeCollinearSegmentIfPossible( segment, segEnd, FLG_END ); if( segDelete ) { no_inc = 1; segDelete->DeleteStructure(); modified = true; } } if( no_inc ) // The current segment was modified, retry to merge it nextsegment = segment->Next(); } return modified; }
/* * 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 = true; while( item_erased ) // Iterate when at least one track is deleted { item_erased = false; TRACK* next_track; for( TRACK * track = m_Brd->m_Track; track ; track = next_track ) { next_track = track->Next(); int flag_erase = 0; //Not connected indicator int type_end = 0; if( track->GetState( START_ON_PAD ) ) type_end |= START_ON_PAD; if( track->GetState( END_ON_PAD ) ) type_end |= END_ON_PAD; // if the track start point is not connected to a pad, // test if this track start point is connected to another track // 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 LAYER_NUM top_layer, bottom_layer; ZONE_CONTAINER* zone; if( (type_end & START_ON_PAD ) == 0 ) { TRACK* other = track->GetTrace( m_Brd->m_Track, NULL, FLG_START ); if( other == NULL ) // Test a connection to zones { if( track->Type() != PCB_VIA_T ) { zone = m_Brd->HitTestForAnyFilledArea( track->GetStart(), track->GetLayer(), track->GetLayer(), track->GetNetCode() ); } else { ((SEGVIA*)track)->LayerPair( &top_layer, &bottom_layer ); zone = m_Brd->HitTestForAnyFilledArea( track->GetStart(), top_layer, bottom_layer, track->GetNetCode() ); } } if( (other == NULL) && (zone == NULL) ) { flag_erase |= 1; } else // segment, via or zone connected to this end { track->start = other; // If a via is connected to this end, // test if this via has a second item connected. // If no, remove it with the current segment if( other && other->Type() == PCB_VIA_T ) { // search for another segment following the via track->SetState( BUSY, true ); SEGVIA* via = (SEGVIA*) other; other = via->GetTrace( m_Brd->m_Track, NULL, FLG_START ); if( other == NULL ) { via->LayerPair( &top_layer, &bottom_layer ); zone = m_Brd->HitTestForAnyFilledArea( via->GetStart(), bottom_layer, top_layer, via->GetNetCode() ); } if( (other == NULL) && (zone == NULL) ) flag_erase |= 2; track->SetState( BUSY, false ); } } } // if track end point is not connected to a pad, // test if this track end point is connected to an other track if( (type_end & END_ON_PAD ) == 0 ) { TRACK* other = track->GetTrace( m_Brd->m_Track, NULL, FLG_END ); if( other == NULL ) // Test a connection to zones { if( track->Type() != PCB_VIA_T ) { zone = m_Brd->HitTestForAnyFilledArea( track->GetEnd(), track->GetLayer(), track->GetLayer(), track->GetNetCode() ); } else { ((SEGVIA*)track)->LayerPair( &top_layer, &bottom_layer ); zone = m_Brd->HitTestForAnyFilledArea( track->GetEnd(), top_layer, bottom_layer, track->GetNetCode() ); } } if ( (other == NULL) && (zone == NULL) ) { flag_erase |= 0x10; } else // segment, via or zone connected to this end { track->end = other; // If a via is connected to this end, test if this via has a second item connected // if no, remove it with the current segment if( other && other->Type() == PCB_VIA_T ) { // search for another segment following the via track->SetState( BUSY, true ); SEGVIA* via = (SEGVIA*) other; other = via->GetTrace( m_Brd->m_Track, NULL, FLG_END ); if( other == NULL ) { via->LayerPair( &top_layer, &bottom_layer ); zone = m_Brd->HitTestForAnyFilledArea( via->GetEnd(), bottom_layer, top_layer, via->GetNetCode() ); } if( (other == NULL) && (zone == NULL) ) flag_erase |= 0x20; track->SetState( BUSY, false ); } } } if( flag_erase ) { // remove segment from board track->DeleteStructure(); // iterate, because a track connected to the deleted track // is now perhaps now not connected and should be deleted item_erased = true; modified = true; } } } return modified; }
/* search connections between tracks and pads and propagate pad net codes to the track * segments. * Pads netcodes are assumed to be up to date. */ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() { // Build the net info list GetBoard()->BuildListOfNets(); // Reset variables and flags used in computation for( TRACK* t = m_Pcb->m_Track; t; t = t->Next() ) { t->m_TracksConnected.clear(); t->m_PadsConnected.clear(); t->start = NULL; t->end = NULL; t->SetState( BUSY | IN_EDIT | BEGIN_ONPAD | END_ONPAD, false ); t->SetZoneSubNet( 0 ); t->SetNetCode( NETINFO_LIST::UNCONNECTED ); } // If no pad, reset pointers and netcode, and do nothing else if( m_Pcb->GetPadCount() == 0 ) return; CONNECTIONS connections( m_Pcb ); connections.BuildPadsList(); connections.BuildTracksCandidatesList(m_Pcb->m_Track); // First pass: build connections between track segments and pads. connections.SearchTracksConnectedToPads(); // For tracks connected to at least one pad, // set the track net code to the pad netcode for( TRACK* t = m_Pcb->m_Track; t; t = t->Next() ) { if( t->m_PadsConnected.size() ) t->SetNetCode( t->m_PadsConnected[0]->GetNetCode() ); } // Pass 2: build connections between track ends for( TRACK* t = m_Pcb->m_Track; t; t = t->Next() ) { connections.SearchConnectedTracks( t ); connections.GetConnectedTracks( t ); } // Propagate net codes from a segment to other connected segments bool new_pass_request = true; // set to true if a track has its netcode changed from 0 // to a known netcode to re-evaluate netcodes // of connected items while( new_pass_request ) { new_pass_request = false; for( TRACK* t = m_Pcb->m_Track; t; t = t->Next() ) { int netcode = t->GetNetCode(); if( netcode == 0 ) { // try to find a connected item having a netcode for( unsigned kk = 0; kk < t->m_TracksConnected.size(); kk++ ) { int altnetcode = t->m_TracksConnected[kk]->GetNetCode(); if( altnetcode ) { new_pass_request = true; netcode = altnetcode; t->SetNetCode(netcode); break; } } } if( netcode ) // this track has a netcode { // propagate this netcode to connected tracks having no netcode for( unsigned kk = 0; kk < t->m_TracksConnected.size(); kk++ ) { int altnetcode = t->m_TracksConnected[kk]->GetNetCode(); if( altnetcode == 0 ) { t->m_TracksConnected[kk]->SetNetCode(netcode); new_pass_request = true; } } } } } // Sort the track list by net codes: RebuildTrackChain( m_Pcb ); }
// Routine to place a moved pad. void PCB_BASE_FRAME::PlacePad( D_PAD* aPad, wxDC* DC ) { int dX, dY; TRACK* Track; if( aPad == NULL ) return; MODULE* module = aPad->GetParent(); ITEM_PICKER picker( NULL, UR_CHANGED ); PICKED_ITEMS_LIST pickList; // Save dragged track segments in undo list for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { Track = g_DragSegmentList[ii].m_Track; // Set the old state if( g_DragSegmentList[ii].m_Pad_Start ) Track->SetStart( Pad_OldPos ); if( g_DragSegmentList[ii].m_Pad_End ) Track->SetEnd( Pad_OldPos ); picker.SetItem( Track ); pickList.PushItem( picker ); } // Save old module and old items values wxPoint pad_curr_position = aPad->GetPosition(); aPad->SetPosition( Pad_OldPos ); if( g_DragSegmentList.size() == 0 ) SaveCopyInUndoList( module, UR_CHANGED ); else { picker.SetItem( module ); pickList.PushItem( picker ); SaveCopyInUndoList( pickList, UR_CHANGED ); } aPad->SetPosition( pad_curr_position ); aPad->Draw( m_canvas, DC, GR_XOR ); // Redraw dragged track segments for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { Track = g_DragSegmentList[ii].m_Track; // Set the new state if( g_DragSegmentList[ii].m_Pad_Start ) Track->SetStart( aPad->GetPosition() ); if( g_DragSegmentList[ii].m_Pad_End ) Track->SetEnd( aPad->GetPosition() ); Track->SetState( IN_EDIT, OFF ); if( DC ) Track->Draw( m_canvas, DC, GR_OR ); } // Compute local coordinates (i.e refer to module position and for module orient = 0) dX = aPad->GetPosition().x - Pad_OldPos.x; dY = aPad->GetPosition().y - Pad_OldPos.y; RotatePoint( &dX, &dY, -module->GetOrientation() ); aPad->SetX0( dX + aPad->GetPos0().x ); aPad->SetY0( dY + aPad->GetPos0().y ); aPad->ClearFlags(); if( DC ) aPad->Draw( m_canvas, DC, GR_OR ); module->CalculateBoundingBox(); module->SetLastEditTime(); EraseDragList(); OnModify(); m_canvas->SetMouseCapture( NULL, NULL ); m_Pcb->m_Status_Pcb &= ~( LISTE_RATSNEST_ITEM_OK | CONNEXION_OK ); }
static void Exit_MoveTrack(WinEDA_DrawFrame * frame, wxDC *DC) /***************************************************************/ /* routine d'annulation de la commande drag, copy ou move track si une piste est en cours de tracage, ou de sortie de l'application EDITRACK. Appel par la touche ESC */ { TRACK * NextS; int ii; /* Effacement du trace en cours */ wxPoint oldpos = frame->GetScreen()->m_Curseur; frame->GetScreen()->m_Curseur = PosInit; frame->GetScreen()->ManageCurseur(frame->DrawPanel, DC, TRUE); frame->GetScreen()->m_Curseur = oldpos; g_HightLigt_Status = FALSE; ( (WinEDA_PcbFrame *)frame)->DrawHightLight( DC, g_HightLigth_NetCode) ; if( NewTrack ) { if (NewTrack->m_Flags & IS_NEW ) { for( ii = 0; ii < NbPtNewTrack; ii++, NewTrack = NextS) { if(NewTrack == NULL) break; NextS = (TRACK*) NewTrack->Pnext; delete NewTrack; } } else /* Move : remise en ancienne position */ { TRACK * Track = NewTrack; int dx = LastPos.x - PosInit.x; int dy = LastPos.y - PosInit.y; for( ii = 0; ii < NbPtNewTrack; ii++, Track = (TRACK*) Track->Pnext) { if( Track == NULL ) break; Track->m_Start.x -= dx; Track->m_Start.y -= dy; Track->m_End.x -= dx; Track->m_End.y -= dy; Track->m_Flags = 0; } Trace_Une_Piste(frame->DrawPanel, DC, NewTrack,NbPtNewTrack,GR_OR); } NewTrack = NULL; } frame->GetScreen()->ManageCurseur = NULL; frame->GetScreen()->ForceCloseManageCurseur = NULL; frame->GetScreen()->m_CurrentItem = NULL; frame->EraseMsgBox(); /* Annulation deplacement et Redessin des segments dragges */ DRAG_SEGM * pt_drag = g_DragSegmentList; for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext) { TRACK * Track = pt_drag->m_Segm; pt_drag->SetInitialValues(); Track->SetState(EDIT,OFF); Track->m_Flags = 0; Track->Draw(frame->DrawPanel, DC, GR_OR); } g_HightLigth_NetCode = Old_HightLigth_NetCode; g_HightLigt_Status = Old_HightLigt_Status; if(g_HightLigt_Status) ( (WinEDA_PcbFrame *)frame)->DrawHightLight( DC, g_HightLigth_NetCode) ; EraseDragListe(); }