Commit 30932a46 authored by dickelbeck's avatar dickelbeck
Browse files

Werner Almesberger's patches

parent 5977accf
Loading
Loading
Loading
Loading
+2 −4
Original line number Original line Diff line number Diff line
@@ -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
    {
    {
+167 −29
Original line number Original line Diff line number Diff line
@@ -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 )
/*****************************************************************/
/*****************************************************************/
@@ -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;
@@ -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 )
+135 −16
Original line number Original line Diff line number Diff line
@@ -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 );


@@ -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 )
@@ -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:
@@ -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--;
    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 );
@@ -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;


@@ -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;
    }
    }
@@ -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;
}
}




+28 −0
Original line number Original line Diff line number Diff line
@@ -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 )
/********************************************************************/
/********************************************************************/