Commit 30932a46 authored by dickelbeck's avatar dickelbeck

Werner Almesberger's patches

parent 5977accf
......@@ -890,10 +890,8 @@ bool TRACK::HitTest( const wxPoint& ref_pos )
if( Type() == TYPEVIA ) /* VIA rencontree */
{
if( (abs( spot_cX ) <= l_piste ) && (abs( spot_cY ) <=l_piste) )
return true;
else
return false;
return (int64_t) spot_cX*spot_cX + (int64_t) spot_cY*spot_cY <=
(int64_t) l_piste*l_piste;
}
else
{
......
......@@ -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 )
/*****************************************************************/
......@@ -232,7 +378,7 @@ void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse )
// Save the board after the time out :
int CurrentTime = time( NULL );
if( !GetScreen()->IsModify() || GetScreen()->IsSave() )
{
/* If no change, reset the time out */
......@@ -262,7 +408,7 @@ void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse )
delta.x = (int) round( (double) GetScreen()->GetGrid().x / zoom );
delta.y = (int) round( (double) GetScreen()->GetGrid().y / zoom );
if( delta.x <= 0 )
delta.x = 1;
if( delta.y <= 0 )
......@@ -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
* this is better to reach items to delete off grid
*/
D_PAD* pad;
bool keep_on_grid = TRUE;
if( m_ID_current_state == ID_PCB_DELETE_ITEM_BUTT )
keep_on_grid = FALSE;
......@@ -354,34 +499,27 @@ void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse )
if( DrawStruct && DrawStruct->m_Flags )
keep_on_grid = TRUE;
switch( g_MagneticPadOption )
{
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 )
{
if( pad ) // Put cursor on the pad
GetScreen()->m_Curseur = curpos = pad->m_Pos;
else
// Put cursor on grid
PutOnGrid( &GetScreen()->m_Curseur );
}
break;
if (keep_on_grid) {
wxPoint on_grid = curpos;
case no_effect:
default:
PutOnGrid(&on_grid);
if (Magnetize(m_Pcb, (WinEDA_PcbFrame *) this, m_ID_current_state,
GetScreen()->GetGrid(), on_grid, curpos))
GetScreen()->m_Curseur = curpos;
else {
extern TRACK *LocateIntrusion(TRACK *start, int net, int width);
// If we are not in delete function, put cursor on grid
if( keep_on_grid )
{
PutOnGrid( &GetScreen()->m_Curseur );
}
break;
/*
* If there's an intrusion and DRC is active, we pass the cursor
* "as is", and let ShowNewTrackWhenMovingCursor figure our what to
* 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;
}
}
if( oldpos != GetScreen()->m_Curseur )
......
......@@ -18,7 +18,7 @@
static void Exit_Editrack( WinEDA_DrawPanel* panel, wxDC* DC );
void ShowNewTrackWhenMovingCursor( WinEDA_DrawPanel* panel,
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 void EnsureEndTrackOnPad( D_PAD* Pad );
......@@ -493,6 +493,120 @@ void WinEDA_PcbFrame::End_Route( TRACK* track, wxDC* DC )
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 )
......@@ -538,8 +652,13 @@ void ShowNewTrackWhenMovingCursor( WinEDA_DrawPanel* panel, wxDC* DC, bool erase
if( Track_45_Only )
{
if( g_TwoSegmentTrackBuild )
ComputeBreakPoint( g_CurrentTrackSegment, g_TrackSegmentCount );
if( g_TwoSegmentTrackBuild ) {
g_CurrentTrackSegment->m_End = ActiveScreen->m_Curseur;
if (Drc_On)
PushTrack(panel);
ComputeBreakPoint( g_CurrentTrackSegment, g_TrackSegmentCount,
g_CurrentTrackSegment->m_End);
}
else
{
/* Calcul de l'extremite de la piste pour orientations permises:
......@@ -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 )
/********************************************************/
/**
......@@ -646,8 +765,8 @@ void ComputeBreakPoint( TRACK* track, int SegmentCount )
SegmentCount--;
if( track )
{
iDx = ActiveScreen->m_Curseur.x - track->m_Start.x;
iDy = ActiveScreen->m_Curseur.y - track->m_Start.y;
iDx = end.x - track->m_Start.x;
iDy = end.y - track->m_Start.y;
iDx = abs( iDx );
iDy = abs( iDy );
......@@ -680,10 +799,10 @@ void ComputeBreakPoint( TRACK* track, int SegmentCount )
break;
case 0:
if( (ActiveScreen->m_Curseur.x - track->m_Start.x) < 0 )
track->m_End.x = ActiveScreen->m_Curseur.x + iDy;
if( (end.x - track->m_Start.x) < 0 )
track->m_End.x = end.x + iDy;
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;
break;
......@@ -691,19 +810,19 @@ void ComputeBreakPoint( TRACK* track, int SegmentCount )
iDx = MIN( iDx, iDy );
iDy = iDx;
/* 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;
if( (ActiveScreen->m_Curseur.y - track->m_Start.y) < 0 )
if( (end.y - track->m_Start.y) < 0 )
iDy = -iDy;
track->m_End.x = track->m_Start.x + iDx;
track->m_End.y = track->m_Start.y + iDy;
break;
case 90:
if( (ActiveScreen->m_Curseur.y - track->m_Start.y) < 0 )
track->m_End.y = ActiveScreen->m_Curseur.y + iDx;
if( (end.y - track->m_Start.y) < 0 )
track->m_End.y = end.y + iDx;
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;
break;
}
......@@ -711,10 +830,10 @@ void ComputeBreakPoint( TRACK* track, int SegmentCount )
if( track )
{
if( track->IsNull() )
track->m_End = ActiveScreen->m_Curseur;
track->m_End = end;
NewTrack->m_Start = track->m_End;
}
NewTrack->m_End = ActiveScreen->m_Curseur;
NewTrack->m_End = end;
}
......
......@@ -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 )
/********************************************************************/
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment