Loading pcbnew/class_track.cpp +2 −4 Original line number Original line Diff line number Diff line Loading @@ -890,10 +890,8 @@ bool TRACK::HitTest( const wxPoint& ref_pos ) if( Type() == TYPEVIA ) /* VIA rencontree */ if( Type() == TYPEVIA ) /* VIA rencontree */ { { if( (abs( spot_cX ) <= l_piste ) && (abs( spot_cY ) <=l_piste) ) return (int64_t) spot_cX*spot_cX + (int64_t) spot_cY*spot_cY <= return true; (int64_t) l_piste*l_piste; else return false; } } else else { { Loading pcbnew/controle.cpp +167 −29 Original line number Original line Diff line number Diff line Loading @@ -219,6 +219,152 @@ BOARD_ITEM* WinEDA_BasePcbFrame::PcbGeneralLocateAndDisplay( int aHotKeyCode ) } } /* * "Join" finds the point where b0+x*(b1-b0) intersects with a0+y*(a1-a0). * If that point would be outside of a0-a1, the respective endpoint is used. * Join returns the point in "res" and "true" if a suitable point was found, * "false" if both lines are parallel. */ static bool Join( wxPoint& res, wxPoint a0, wxPoint a1, wxPoint b0, wxPoint b1 ) { int64_t denom; double t; a1 -= a0; b1 -= b0; b0 -= a0; denom = (int64_t) b1.y*a1.x - (int64_t) b1.x*a1.y; if (!denom) return false; // parallel t = ((int64_t) b1.y*b0.x - (int64_t) b1.x*b0.y)/(double) denom; t = min( max( t, 0.0 ), 1.0 ); res.x = (int) round(a0.x+t*a1.x); res.y = (int) round(a0.y+t*a1.y); return true; } /* * "Project" finds the projection of a grid point on a track. This is the point * from where we want to draw new orthogonal tracks when starting on a track. */ bool Project( wxPoint& res, wxPoint on_grid, const TRACK* track ) { wxPoint vec; double t; if( track->m_Start == track->m_End ) return false; vec = track->m_End-track->m_Start; t = (int64_t) (on_grid.x-track->m_Start.x)*vec.x + (int64_t) (on_grid.y-track->m_Start.y)*vec.y; t /= (int64_t) vec.x*vec.x + (int64_t) vec.y*vec.y; t = min( max( t, 0.0 ), 1.0 ); res.x = (int) round( track->m_Start.x + t*vec.x ); res.y = (int) round( track->m_Start.y + t*vec.y ); return true; } static bool Magnetize( BOARD* m_Pcb, WinEDA_PcbFrame* frame, int m_ID_current_state, wxSize grid, wxPoint on_grid, wxPoint& curpos ) { const D_PAD* pad; const TRACK* curr = NULL; const TRACK* via, * track; int layer, layer_mask; bool sometimes = g_MagneticPadOption != capture_always && Drc_On; curr = g_CurrentTrackSegment; if( frame->GetCurItem() != curr ) curr = NULL; switch( g_MagneticPadOption ) { case capture_cursor_in_track_tool: if( m_ID_current_state != ID_TRACK_BUTT ) return false; break; case capture_always: break; case no_effect: default: return false; } pad = Locate_Any_Pad( m_Pcb, CURSEUR_OFF_GRILLE, TRUE ); if( pad ) { if( curr && curr->GetNet() != pad->GetNet() && sometimes ) return false; curpos = pad->m_Pos; return true; } layer = ( (PCB_SCREEN*) ActiveScreen )->m_Active_Layer; via = Locate_Via_Area( m_Pcb, curpos, layer ); if( via ) { if( curr && curr->GetNet() != via->GetNet() && sometimes ) return false; curpos = via->m_Start; return true; } layer_mask = g_TabOneLayerMask[layer]; if( !curr ) { track = Locate_Pistes( m_Pcb->m_Track, layer_mask, CURSEUR_OFF_GRILLE ); if( !track || track->Type() != TYPETRACK ) return false; return Project( curpos, on_grid, track ); } /* * In two segment mode, ignore the final segment if it's inside a grid * square. */ if( g_TwoSegmentTrackBuild && curr->Pback && curr->m_Start.x - grid.x < curr->m_End.x && curr->m_Start.x + grid.x > curr->m_End.x && curr->m_Start.y - grid.y < curr->m_End.y && curr->m_Start.y + grid.y > curr->m_End.y ) curr = curr->Back(); track = Locate_Pistes( m_Pcb->m_Track, layer_mask, CURSEUR_OFF_GRILLE ); for( ; track; track = track->Next() ) { if( track->Type() != TYPETRACK ) continue; if( curr->GetNet() != track->GetNet() && sometimes ) continue; if( Join( curpos, track->m_Start, track->m_End, curr->m_Start, curr->m_End ) ) return true; } return false; } /****************************************************************/ /****************************************************************/ void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse ) void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse ) /*****************************************************************/ /*****************************************************************/ Loading Loading @@ -341,7 +487,6 @@ void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse ) * But if the tool DELETE is active the cursor is left off grid * But if the tool DELETE is active the cursor is left off grid * this is better to reach items to delete off grid * this is better to reach items to delete off grid */ */ D_PAD* pad; bool keep_on_grid = TRUE; bool keep_on_grid = TRUE; if( m_ID_current_state == ID_PCB_DELETE_ITEM_BUTT ) if( m_ID_current_state == ID_PCB_DELETE_ITEM_BUTT ) keep_on_grid = FALSE; keep_on_grid = FALSE; Loading @@ -354,34 +499,27 @@ void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse ) if( DrawStruct && DrawStruct->m_Flags ) if( DrawStruct && DrawStruct->m_Flags ) keep_on_grid = TRUE; keep_on_grid = TRUE; switch( g_MagneticPadOption ) if (keep_on_grid) { { wxPoint on_grid = curpos; case capture_cursor_in_track_tool: case capture_always: pad = Locate_Any_Pad( m_Pcb, CURSEUR_OFF_GRILLE, TRUE ); if( (m_ID_current_state != ID_TRACK_BUTT ) && (g_MagneticPadOption == capture_cursor_in_track_tool) ) pad = NULL; if( keep_on_grid ) PutOnGrid(&on_grid); { if (Magnetize(m_Pcb, (WinEDA_PcbFrame *) this, m_ID_current_state, if( pad ) // Put cursor on the pad GetScreen()->GetGrid(), on_grid, curpos)) GetScreen()->m_Curseur = curpos = pad->m_Pos; GetScreen()->m_Curseur = curpos; else else { // Put cursor on grid extern TRACK *LocateIntrusion(TRACK *start, int net, int width); PutOnGrid( &GetScreen()->m_Curseur ); } break; case no_effect: default: // If we are not in delete function, put cursor on grid /* if( keep_on_grid ) * If there's an intrusion and DRC is active, we pass the cursor { * "as is", and let ShowNewTrackWhenMovingCursor figure our what to PutOnGrid( &GetScreen()->m_Curseur ); * do. */ if (!Drc_On || !g_CurrentTrackSegment || g_CurrentTrackSegment != this->GetCurItem() || !LocateIntrusion(m_Pcb->m_Track, g_CurrentTrackSegment->GetNet(), g_CurrentTrackSegment->m_Width)) GetScreen()->m_Curseur = on_grid; } } break; } } if( oldpos != GetScreen()->m_Curseur ) if( oldpos != GetScreen()->m_Curseur ) Loading pcbnew/editrack.cpp +135 −16 Original line number Original line Diff line number Diff line Loading @@ -18,7 +18,7 @@ static void Exit_Editrack( WinEDA_DrawPanel* panel, wxDC* DC ); static void Exit_Editrack( WinEDA_DrawPanel* panel, wxDC* DC ); void ShowNewTrackWhenMovingCursor( WinEDA_DrawPanel* panel, void ShowNewTrackWhenMovingCursor( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ); wxDC* DC, bool erase ); static void ComputeBreakPoint( TRACK* track, int n ); static void ComputeBreakPoint( TRACK* track, int n, wxPoint end ); static TRACK* DeleteNullTrackSegments( BOARD* pcb, TRACK* track, int* segmcount ); static TRACK* DeleteNullTrackSegments( BOARD* pcb, TRACK* track, int* segmcount ); static void EnsureEndTrackOnPad( D_PAD* Pad ); static void EnsureEndTrackOnPad( D_PAD* Pad ); Loading Loading @@ -493,6 +493,120 @@ void WinEDA_PcbFrame::End_Route( TRACK* track, wxDC* DC ) SetCurItem( NULL ); SetCurItem( NULL ); } } /* * PushTrack detecs if the mouse is pointing into a conflicting track. * In this case, it tries to push the new track out of the conflicting track's * clearance zone. This gives us a cheap mechanism for drawing tracks that * tightly follow others, independent of grid settings. * * KNOWN BUGS: * - we do the same sort of search and calculation up to three times: * 1) we search for magnetic hits (in controle.cpp) * 2) we check if there's a DRC violation in the making (also controle.cpp) * 3) we try to fix the DRC violation (here) * - if we have a magnetic hit and a DRC violation at the same time, we choose * the magnetic hit instead of solving the violation * - should locate conflicting tracks also when we're crossing over them * - we obviously shouldn't access functions through "extern" or have #includes * in the middle of the file */ #include "trigo.h" extern bool Project(wxPoint &res, wxPoint on_grid, const TRACK *track); TRACK *LocateIntrusion(TRACK *start, int net, int width) { int layer = ((PCB_SCREEN *) ActiveScreen)->m_Active_Layer; int layer_mask = g_TabOneLayerMask[layer]; wxPoint ref = ActiveScreen->RefPos(1); TRACK *track, *found = NULL; for (track = start; track; track = track->Next()) { int dist; wxPoint pos, vec; int64_t tmp; /* Locate_Pistes */ if (track->GetState(BUSY | DELETED)) continue; if (!(g_TabOneLayerMask[track->GetLayer()] & layer_mask)) continue; if (track->GetNet() == net) continue; if (track->Type() == TYPEVIA) continue; /* TRACK::HitTest */ dist = width/2 + track->m_Width/2 + g_DesignSettings.m_TrackClearence; pos = ref-track->m_Start; vec = track->m_End-track->m_Start; if (!DistanceTest(dist, vec.x, vec.y, pos.x, pos.y)) continue; found = track; /* prefer intrusions from the side, not the end */ tmp = (int64_t) pos.x*vec.x + (int64_t) pos.y*vec.y; if (tmp >= 0 && tmp <= (int64_t) vec.x*vec.x + (int64_t) vec.y*vec.y) break; } return found; } static void PushTrack(WinEDA_DrawPanel *panel) { BOARD *pcb = ((WinEDA_BasePcbFrame *) (panel->m_Parent))->m_Pcb; wxPoint cursor = ActiveScreen->m_Curseur; wxPoint cv, vec, n; TRACK *track = g_CurrentTrackSegment; TRACK *other; int64_t det; int dist; double f; other = LocateIntrusion(pcb->m_Track, track->GetNet(), track->m_Width); /* are we currently pointing into a conflicting trace ? */ if (!other) return; if (other->GetNet() == track->GetNet()) return; cv = cursor-other->m_Start; vec = other->m_End-other->m_Start; det = (int64_t) cv.x*vec.y - (int64_t) cv.y*vec.x; /* cursor is right at the center of the old track */ if (!det) return; dist = (track->m_Width+1)/2 + (other->m_Width+1)/2 + g_DesignSettings.m_TrackClearence+2; /* * DRC wants >, so +1. * We may have a quantization error of 1/sqrt(2), so +1 again. */ /* Vector "n" is perpendicular to "other", pointing towards the cursor. */ if (det > 0) { n.x = vec.y; n.y = -vec.x; } else { n.x = -vec.y; n.y = vec.x; } f = dist/hypot(n.x, n.y); n.x = (int) round(f*n.x); n.y = (int) round(f*n.y); Project(track->m_End, cursor, other); track->m_End += n; } /****************************************************************************/ /****************************************************************************/ void ShowNewTrackWhenMovingCursor( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) void ShowNewTrackWhenMovingCursor( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) Loading Loading @@ -538,8 +652,13 @@ void ShowNewTrackWhenMovingCursor( WinEDA_DrawPanel* panel, wxDC* DC, bool erase if( Track_45_Only ) if( Track_45_Only ) { { if( g_TwoSegmentTrackBuild ) if( g_TwoSegmentTrackBuild ) { ComputeBreakPoint( g_CurrentTrackSegment, g_TrackSegmentCount ); g_CurrentTrackSegment->m_End = ActiveScreen->m_Curseur; if (Drc_On) PushTrack(panel); ComputeBreakPoint( g_CurrentTrackSegment, g_TrackSegmentCount, g_CurrentTrackSegment->m_End); } else else { { /* Calcul de l'extremite de la piste pour orientations permises: /* Calcul de l'extremite de la piste pour orientations permises: Loading Loading @@ -625,7 +744,7 @@ void Calcule_Coord_Extremite_45( int ox, int oy, int* fx, int* fy ) /********************************************************/ /********************************************************/ void ComputeBreakPoint( TRACK* track, int SegmentCount ) void ComputeBreakPoint( TRACK* track, int SegmentCount, wxPoint end ) /********************************************************/ /********************************************************/ /** /** Loading @@ -646,8 +765,8 @@ void ComputeBreakPoint( TRACK* track, int SegmentCount ) SegmentCount--; SegmentCount--; if( track ) if( track ) { { iDx = ActiveScreen->m_Curseur.x - track->m_Start.x; iDx = end.x - track->m_Start.x; iDy = ActiveScreen->m_Curseur.y - track->m_Start.y; iDy = end.y - track->m_Start.y; iDx = abs( iDx ); iDx = abs( iDx ); iDy = abs( iDy ); iDy = abs( iDy ); Loading Loading @@ -680,10 +799,10 @@ void ComputeBreakPoint( TRACK* track, int SegmentCount ) break; break; case 0: case 0: if( (ActiveScreen->m_Curseur.x - track->m_Start.x) < 0 ) if( (end.x - track->m_Start.x) < 0 ) track->m_End.x = ActiveScreen->m_Curseur.x + iDy; track->m_End.x = end.x + iDy; else else track->m_End.x = ActiveScreen->m_Curseur.x - iDy; track->m_End.x = end.x - iDy; track->m_End.y = track->m_Start.y; track->m_End.y = track->m_Start.y; break; break; Loading @@ -691,19 +810,19 @@ void ComputeBreakPoint( TRACK* track, int SegmentCount ) iDx = MIN( iDx, iDy ); iDx = MIN( iDx, iDy ); iDy = iDx; iDy = iDx; /* recalcul des signes de deltax et deltay */ /* recalcul des signes de deltax et deltay */ if( (ActiveScreen->m_Curseur.x - track->m_Start.x) < 0 ) if( (end.x - track->m_Start.x) < 0 ) iDx = -iDx; iDx = -iDx; if( (ActiveScreen->m_Curseur.y - track->m_Start.y) < 0 ) if( (end.y - track->m_Start.y) < 0 ) iDy = -iDy; iDy = -iDy; track->m_End.x = track->m_Start.x + iDx; track->m_End.x = track->m_Start.x + iDx; track->m_End.y = track->m_Start.y + iDy; track->m_End.y = track->m_Start.y + iDy; break; break; case 90: case 90: if( (ActiveScreen->m_Curseur.y - track->m_Start.y) < 0 ) if( (end.y - track->m_Start.y) < 0 ) track->m_End.y = ActiveScreen->m_Curseur.y + iDx; track->m_End.y = end.y + iDx; else else track->m_End.y = ActiveScreen->m_Curseur.y - iDx; track->m_End.y = end.y - iDx; track->m_End.x = track->m_Start.x; track->m_End.x = track->m_Start.x; break; break; } } Loading @@ -711,10 +830,10 @@ void ComputeBreakPoint( TRACK* track, int SegmentCount ) if( track ) if( track ) { { if( track->IsNull() ) if( track->IsNull() ) track->m_End = ActiveScreen->m_Curseur; track->m_End = end; NewTrack->m_Start = track->m_End; NewTrack->m_Start = track->m_End; } } NewTrack->m_End = ActiveScreen->m_Curseur; NewTrack->m_End = end; } } Loading pcbnew/locate.cpp +28 −0 Original line number Original line Diff line number Diff line Loading @@ -111,6 +111,34 @@ TRACK* Locate_Via( BOARD* Pcb, const wxPoint& pos, int layer ) } } /*******************************************************************/ TRACK* Locate_Via_Area( BOARD* Pcb, const wxPoint& pos, int layer ) /*******************************************************************/ /* * Like Locate_Via, but finds any via covering the cursor position */ { TRACK* Track; for( Track = Pcb->m_Track; Track != NULL; Track = Track->Next() ) { if( Track->Type() != TYPEVIA ) continue; if(!Track->HitTest(pos)) continue; if( Track->GetState( BUSY | DELETED ) ) continue; if( layer < 0 ) return Track; if( Track->IsOnLayer( layer ) ) return Track; } return NULL; } /********************************************************************/ /********************************************************************/ D_PAD* Locate_Pad_Connecte( BOARD* Pcb, TRACK* ptr_piste, int extr ) D_PAD* Locate_Pad_Connecte( BOARD* Pcb, TRACK* ptr_piste, int extr ) /********************************************************************/ /********************************************************************/ Loading Loading
pcbnew/class_track.cpp +2 −4 Original line number Original line Diff line number Diff line Loading @@ -890,10 +890,8 @@ bool TRACK::HitTest( const wxPoint& ref_pos ) if( Type() == TYPEVIA ) /* VIA rencontree */ if( Type() == TYPEVIA ) /* VIA rencontree */ { { if( (abs( spot_cX ) <= l_piste ) && (abs( spot_cY ) <=l_piste) ) return (int64_t) spot_cX*spot_cX + (int64_t) spot_cY*spot_cY <= return true; (int64_t) l_piste*l_piste; else return false; } } else else { { Loading
pcbnew/controle.cpp +167 −29 Original line number Original line Diff line number Diff line Loading @@ -219,6 +219,152 @@ BOARD_ITEM* WinEDA_BasePcbFrame::PcbGeneralLocateAndDisplay( int aHotKeyCode ) } } /* * "Join" finds the point where b0+x*(b1-b0) intersects with a0+y*(a1-a0). * If that point would be outside of a0-a1, the respective endpoint is used. * Join returns the point in "res" and "true" if a suitable point was found, * "false" if both lines are parallel. */ static bool Join( wxPoint& res, wxPoint a0, wxPoint a1, wxPoint b0, wxPoint b1 ) { int64_t denom; double t; a1 -= a0; b1 -= b0; b0 -= a0; denom = (int64_t) b1.y*a1.x - (int64_t) b1.x*a1.y; if (!denom) return false; // parallel t = ((int64_t) b1.y*b0.x - (int64_t) b1.x*b0.y)/(double) denom; t = min( max( t, 0.0 ), 1.0 ); res.x = (int) round(a0.x+t*a1.x); res.y = (int) round(a0.y+t*a1.y); return true; } /* * "Project" finds the projection of a grid point on a track. This is the point * from where we want to draw new orthogonal tracks when starting on a track. */ bool Project( wxPoint& res, wxPoint on_grid, const TRACK* track ) { wxPoint vec; double t; if( track->m_Start == track->m_End ) return false; vec = track->m_End-track->m_Start; t = (int64_t) (on_grid.x-track->m_Start.x)*vec.x + (int64_t) (on_grid.y-track->m_Start.y)*vec.y; t /= (int64_t) vec.x*vec.x + (int64_t) vec.y*vec.y; t = min( max( t, 0.0 ), 1.0 ); res.x = (int) round( track->m_Start.x + t*vec.x ); res.y = (int) round( track->m_Start.y + t*vec.y ); return true; } static bool Magnetize( BOARD* m_Pcb, WinEDA_PcbFrame* frame, int m_ID_current_state, wxSize grid, wxPoint on_grid, wxPoint& curpos ) { const D_PAD* pad; const TRACK* curr = NULL; const TRACK* via, * track; int layer, layer_mask; bool sometimes = g_MagneticPadOption != capture_always && Drc_On; curr = g_CurrentTrackSegment; if( frame->GetCurItem() != curr ) curr = NULL; switch( g_MagneticPadOption ) { case capture_cursor_in_track_tool: if( m_ID_current_state != ID_TRACK_BUTT ) return false; break; case capture_always: break; case no_effect: default: return false; } pad = Locate_Any_Pad( m_Pcb, CURSEUR_OFF_GRILLE, TRUE ); if( pad ) { if( curr && curr->GetNet() != pad->GetNet() && sometimes ) return false; curpos = pad->m_Pos; return true; } layer = ( (PCB_SCREEN*) ActiveScreen )->m_Active_Layer; via = Locate_Via_Area( m_Pcb, curpos, layer ); if( via ) { if( curr && curr->GetNet() != via->GetNet() && sometimes ) return false; curpos = via->m_Start; return true; } layer_mask = g_TabOneLayerMask[layer]; if( !curr ) { track = Locate_Pistes( m_Pcb->m_Track, layer_mask, CURSEUR_OFF_GRILLE ); if( !track || track->Type() != TYPETRACK ) return false; return Project( curpos, on_grid, track ); } /* * In two segment mode, ignore the final segment if it's inside a grid * square. */ if( g_TwoSegmentTrackBuild && curr->Pback && curr->m_Start.x - grid.x < curr->m_End.x && curr->m_Start.x + grid.x > curr->m_End.x && curr->m_Start.y - grid.y < curr->m_End.y && curr->m_Start.y + grid.y > curr->m_End.y ) curr = curr->Back(); track = Locate_Pistes( m_Pcb->m_Track, layer_mask, CURSEUR_OFF_GRILLE ); for( ; track; track = track->Next() ) { if( track->Type() != TYPETRACK ) continue; if( curr->GetNet() != track->GetNet() && sometimes ) continue; if( Join( curpos, track->m_Start, track->m_End, curr->m_Start, curr->m_End ) ) return true; } return false; } /****************************************************************/ /****************************************************************/ void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse ) void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse ) /*****************************************************************/ /*****************************************************************/ Loading Loading @@ -341,7 +487,6 @@ void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse ) * But if the tool DELETE is active the cursor is left off grid * But if the tool DELETE is active the cursor is left off grid * this is better to reach items to delete off grid * this is better to reach items to delete off grid */ */ D_PAD* pad; bool keep_on_grid = TRUE; bool keep_on_grid = TRUE; if( m_ID_current_state == ID_PCB_DELETE_ITEM_BUTT ) if( m_ID_current_state == ID_PCB_DELETE_ITEM_BUTT ) keep_on_grid = FALSE; keep_on_grid = FALSE; Loading @@ -354,34 +499,27 @@ void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse ) if( DrawStruct && DrawStruct->m_Flags ) if( DrawStruct && DrawStruct->m_Flags ) keep_on_grid = TRUE; keep_on_grid = TRUE; switch( g_MagneticPadOption ) if (keep_on_grid) { { wxPoint on_grid = curpos; case capture_cursor_in_track_tool: case capture_always: pad = Locate_Any_Pad( m_Pcb, CURSEUR_OFF_GRILLE, TRUE ); if( (m_ID_current_state != ID_TRACK_BUTT ) && (g_MagneticPadOption == capture_cursor_in_track_tool) ) pad = NULL; if( keep_on_grid ) PutOnGrid(&on_grid); { if (Magnetize(m_Pcb, (WinEDA_PcbFrame *) this, m_ID_current_state, if( pad ) // Put cursor on the pad GetScreen()->GetGrid(), on_grid, curpos)) GetScreen()->m_Curseur = curpos = pad->m_Pos; GetScreen()->m_Curseur = curpos; else else { // Put cursor on grid extern TRACK *LocateIntrusion(TRACK *start, int net, int width); PutOnGrid( &GetScreen()->m_Curseur ); } break; case no_effect: default: // If we are not in delete function, put cursor on grid /* if( keep_on_grid ) * If there's an intrusion and DRC is active, we pass the cursor { * "as is", and let ShowNewTrackWhenMovingCursor figure our what to PutOnGrid( &GetScreen()->m_Curseur ); * do. */ if (!Drc_On || !g_CurrentTrackSegment || g_CurrentTrackSegment != this->GetCurItem() || !LocateIntrusion(m_Pcb->m_Track, g_CurrentTrackSegment->GetNet(), g_CurrentTrackSegment->m_Width)) GetScreen()->m_Curseur = on_grid; } } break; } } if( oldpos != GetScreen()->m_Curseur ) if( oldpos != GetScreen()->m_Curseur ) Loading
pcbnew/editrack.cpp +135 −16 Original line number Original line Diff line number Diff line Loading @@ -18,7 +18,7 @@ static void Exit_Editrack( WinEDA_DrawPanel* panel, wxDC* DC ); static void Exit_Editrack( WinEDA_DrawPanel* panel, wxDC* DC ); void ShowNewTrackWhenMovingCursor( WinEDA_DrawPanel* panel, void ShowNewTrackWhenMovingCursor( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ); wxDC* DC, bool erase ); static void ComputeBreakPoint( TRACK* track, int n ); static void ComputeBreakPoint( TRACK* track, int n, wxPoint end ); static TRACK* DeleteNullTrackSegments( BOARD* pcb, TRACK* track, int* segmcount ); static TRACK* DeleteNullTrackSegments( BOARD* pcb, TRACK* track, int* segmcount ); static void EnsureEndTrackOnPad( D_PAD* Pad ); static void EnsureEndTrackOnPad( D_PAD* Pad ); Loading Loading @@ -493,6 +493,120 @@ void WinEDA_PcbFrame::End_Route( TRACK* track, wxDC* DC ) SetCurItem( NULL ); SetCurItem( NULL ); } } /* * PushTrack detecs if the mouse is pointing into a conflicting track. * In this case, it tries to push the new track out of the conflicting track's * clearance zone. This gives us a cheap mechanism for drawing tracks that * tightly follow others, independent of grid settings. * * KNOWN BUGS: * - we do the same sort of search and calculation up to three times: * 1) we search for magnetic hits (in controle.cpp) * 2) we check if there's a DRC violation in the making (also controle.cpp) * 3) we try to fix the DRC violation (here) * - if we have a magnetic hit and a DRC violation at the same time, we choose * the magnetic hit instead of solving the violation * - should locate conflicting tracks also when we're crossing over them * - we obviously shouldn't access functions through "extern" or have #includes * in the middle of the file */ #include "trigo.h" extern bool Project(wxPoint &res, wxPoint on_grid, const TRACK *track); TRACK *LocateIntrusion(TRACK *start, int net, int width) { int layer = ((PCB_SCREEN *) ActiveScreen)->m_Active_Layer; int layer_mask = g_TabOneLayerMask[layer]; wxPoint ref = ActiveScreen->RefPos(1); TRACK *track, *found = NULL; for (track = start; track; track = track->Next()) { int dist; wxPoint pos, vec; int64_t tmp; /* Locate_Pistes */ if (track->GetState(BUSY | DELETED)) continue; if (!(g_TabOneLayerMask[track->GetLayer()] & layer_mask)) continue; if (track->GetNet() == net) continue; if (track->Type() == TYPEVIA) continue; /* TRACK::HitTest */ dist = width/2 + track->m_Width/2 + g_DesignSettings.m_TrackClearence; pos = ref-track->m_Start; vec = track->m_End-track->m_Start; if (!DistanceTest(dist, vec.x, vec.y, pos.x, pos.y)) continue; found = track; /* prefer intrusions from the side, not the end */ tmp = (int64_t) pos.x*vec.x + (int64_t) pos.y*vec.y; if (tmp >= 0 && tmp <= (int64_t) vec.x*vec.x + (int64_t) vec.y*vec.y) break; } return found; } static void PushTrack(WinEDA_DrawPanel *panel) { BOARD *pcb = ((WinEDA_BasePcbFrame *) (panel->m_Parent))->m_Pcb; wxPoint cursor = ActiveScreen->m_Curseur; wxPoint cv, vec, n; TRACK *track = g_CurrentTrackSegment; TRACK *other; int64_t det; int dist; double f; other = LocateIntrusion(pcb->m_Track, track->GetNet(), track->m_Width); /* are we currently pointing into a conflicting trace ? */ if (!other) return; if (other->GetNet() == track->GetNet()) return; cv = cursor-other->m_Start; vec = other->m_End-other->m_Start; det = (int64_t) cv.x*vec.y - (int64_t) cv.y*vec.x; /* cursor is right at the center of the old track */ if (!det) return; dist = (track->m_Width+1)/2 + (other->m_Width+1)/2 + g_DesignSettings.m_TrackClearence+2; /* * DRC wants >, so +1. * We may have a quantization error of 1/sqrt(2), so +1 again. */ /* Vector "n" is perpendicular to "other", pointing towards the cursor. */ if (det > 0) { n.x = vec.y; n.y = -vec.x; } else { n.x = -vec.y; n.y = vec.x; } f = dist/hypot(n.x, n.y); n.x = (int) round(f*n.x); n.y = (int) round(f*n.y); Project(track->m_End, cursor, other); track->m_End += n; } /****************************************************************************/ /****************************************************************************/ void ShowNewTrackWhenMovingCursor( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) void ShowNewTrackWhenMovingCursor( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) Loading Loading @@ -538,8 +652,13 @@ void ShowNewTrackWhenMovingCursor( WinEDA_DrawPanel* panel, wxDC* DC, bool erase if( Track_45_Only ) if( Track_45_Only ) { { if( g_TwoSegmentTrackBuild ) if( g_TwoSegmentTrackBuild ) { ComputeBreakPoint( g_CurrentTrackSegment, g_TrackSegmentCount ); g_CurrentTrackSegment->m_End = ActiveScreen->m_Curseur; if (Drc_On) PushTrack(panel); ComputeBreakPoint( g_CurrentTrackSegment, g_TrackSegmentCount, g_CurrentTrackSegment->m_End); } else else { { /* Calcul de l'extremite de la piste pour orientations permises: /* Calcul de l'extremite de la piste pour orientations permises: Loading Loading @@ -625,7 +744,7 @@ void Calcule_Coord_Extremite_45( int ox, int oy, int* fx, int* fy ) /********************************************************/ /********************************************************/ void ComputeBreakPoint( TRACK* track, int SegmentCount ) void ComputeBreakPoint( TRACK* track, int SegmentCount, wxPoint end ) /********************************************************/ /********************************************************/ /** /** Loading @@ -646,8 +765,8 @@ void ComputeBreakPoint( TRACK* track, int SegmentCount ) SegmentCount--; SegmentCount--; if( track ) if( track ) { { iDx = ActiveScreen->m_Curseur.x - track->m_Start.x; iDx = end.x - track->m_Start.x; iDy = ActiveScreen->m_Curseur.y - track->m_Start.y; iDy = end.y - track->m_Start.y; iDx = abs( iDx ); iDx = abs( iDx ); iDy = abs( iDy ); iDy = abs( iDy ); Loading Loading @@ -680,10 +799,10 @@ void ComputeBreakPoint( TRACK* track, int SegmentCount ) break; break; case 0: case 0: if( (ActiveScreen->m_Curseur.x - track->m_Start.x) < 0 ) if( (end.x - track->m_Start.x) < 0 ) track->m_End.x = ActiveScreen->m_Curseur.x + iDy; track->m_End.x = end.x + iDy; else else track->m_End.x = ActiveScreen->m_Curseur.x - iDy; track->m_End.x = end.x - iDy; track->m_End.y = track->m_Start.y; track->m_End.y = track->m_Start.y; break; break; Loading @@ -691,19 +810,19 @@ void ComputeBreakPoint( TRACK* track, int SegmentCount ) iDx = MIN( iDx, iDy ); iDx = MIN( iDx, iDy ); iDy = iDx; iDy = iDx; /* recalcul des signes de deltax et deltay */ /* recalcul des signes de deltax et deltay */ if( (ActiveScreen->m_Curseur.x - track->m_Start.x) < 0 ) if( (end.x - track->m_Start.x) < 0 ) iDx = -iDx; iDx = -iDx; if( (ActiveScreen->m_Curseur.y - track->m_Start.y) < 0 ) if( (end.y - track->m_Start.y) < 0 ) iDy = -iDy; iDy = -iDy; track->m_End.x = track->m_Start.x + iDx; track->m_End.x = track->m_Start.x + iDx; track->m_End.y = track->m_Start.y + iDy; track->m_End.y = track->m_Start.y + iDy; break; break; case 90: case 90: if( (ActiveScreen->m_Curseur.y - track->m_Start.y) < 0 ) if( (end.y - track->m_Start.y) < 0 ) track->m_End.y = ActiveScreen->m_Curseur.y + iDx; track->m_End.y = end.y + iDx; else else track->m_End.y = ActiveScreen->m_Curseur.y - iDx; track->m_End.y = end.y - iDx; track->m_End.x = track->m_Start.x; track->m_End.x = track->m_Start.x; break; break; } } Loading @@ -711,10 +830,10 @@ void ComputeBreakPoint( TRACK* track, int SegmentCount ) if( track ) if( track ) { { if( track->IsNull() ) if( track->IsNull() ) track->m_End = ActiveScreen->m_Curseur; track->m_End = end; NewTrack->m_Start = track->m_End; NewTrack->m_Start = track->m_End; } } NewTrack->m_End = ActiveScreen->m_Curseur; NewTrack->m_End = end; } } Loading
pcbnew/locate.cpp +28 −0 Original line number Original line Diff line number Diff line Loading @@ -111,6 +111,34 @@ TRACK* Locate_Via( BOARD* Pcb, const wxPoint& pos, int layer ) } } /*******************************************************************/ TRACK* Locate_Via_Area( BOARD* Pcb, const wxPoint& pos, int layer ) /*******************************************************************/ /* * Like Locate_Via, but finds any via covering the cursor position */ { TRACK* Track; for( Track = Pcb->m_Track; Track != NULL; Track = Track->Next() ) { if( Track->Type() != TYPEVIA ) continue; if(!Track->HitTest(pos)) continue; if( Track->GetState( BUSY | DELETED ) ) continue; if( layer < 0 ) return Track; if( Track->IsOnLayer( layer ) ) return Track; } return NULL; } /********************************************************************/ /********************************************************************/ D_PAD* Locate_Pad_Connecte( BOARD* Pcb, TRACK* ptr_piste, int extr ) D_PAD* Locate_Pad_Connecte( BOARD* Pcb, TRACK* ptr_piste, int extr ) /********************************************************************/ /********************************************************************/ Loading