Commit 79eca85b authored by dickelbeck's avatar dickelbeck
Browse files

Magnetism

parent c254c13e
Loading
Loading
Loading
Loading
+150 −96
Original line number Original line Diff line number Diff line
@@ -221,10 +221,10 @@ BOARD_ITEM* WinEDA_BasePcbFrame::PcbGeneralLocateAndDisplay( int aHotKeyCode )


/**
/**
 * Function Join
 * Function Join
 * finds the point where b0+x*(b1-b0) intersects with a0+y*(a1-a0).
 * finds the point where line segment (b1,b0) intersects with segment (a1,a0).
 * If that point would be outside of a0-a1, the respective endpoint is used.
 * 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,
 * Join returns the point in "res" and "true" if a suitable point was found,
 * "false" if both lines are parallel.
 * "false" if both lines are parallel or if the length of either segment is zero.
 */
 */
static bool Join( wxPoint* res, wxPoint a0, wxPoint a1, wxPoint b0, wxPoint b1 )
static bool Join( wxPoint* res, wxPoint a0, wxPoint a1, wxPoint b0, wxPoint b1 )
{
{
@@ -236,8 +236,16 @@ static bool Join( wxPoint* res, wxPoint a0, wxPoint a1, wxPoint b0, wxPoint b1 )
    double  denom;
    double  denom;
    double  t;
    double  t;


    // if either segment is zero length
    if( a1.x==a0.x && a1.y==a0.y )
        return false;

    if( b1.x==b0.x && b1.y==b0.y )
        return false;

    a1 -= a0;
    a1 -= a0;
    b1 -= b0;
    b1 -= b0;

    b0 -= a0;
    b0 -= a0;


    denom = (double) b1.y * a1.x - (double) b1.x * a1.y;
    denom = (double) b1.y * a1.x - (double) b1.x * a1.y;
@@ -290,74 +298,102 @@ bool Project( wxPoint* res, wxPoint on_grid, const TRACK* track )
 * "curpos".  If yes, then curpos is adjusted appropriately according to that
 * "curpos".  If yes, then curpos is adjusted appropriately according to that
 * near magnetic item and true is returned.
 * near magnetic item and true is returned.
 * @param curpos The initial position, and what to adjust if a change is needed.
 * @param curpos The initial position, and what to adjust if a change is needed.
 * @return bool - true if the position was adjusted magnetically, else false.
 */
 */
static bool Magnetize( BOARD* m_Pcb, WinEDA_PcbFrame* frame,
static bool Magnetize( BOARD* m_Pcb, WinEDA_PcbFrame* frame,
                       int aCurrentTool, wxSize grid, wxPoint on_grid, wxPoint* curpos )
                       int aCurrentTool, wxSize grid, wxPoint on_grid, wxPoint* curpos )
{
{
    D_PAD*  pad;
    TRACK*  curr = g_CurrentTrackSegment;
    TRACK*  via;
    TRACK*  track;
    int     layer, layer_mask;

    bool    doCheckNet = g_MagneticPadOption != capture_always && Drc_On;
    bool    doCheckNet = g_MagneticPadOption != capture_always && Drc_On;
    bool    doTrack = false;
    bool    doPad = false;
    bool    amMovingVia = false;

    TRACK*      currTrack = g_CurrentTrackSegment;
    BOARD_ITEM* currItem  = frame->GetCurItem();

    // D( printf( "currTrack=%p currItem=%p currTrack->Type()=%d currItem->Type()=%d\n",  currTrack, currItem, currTrack ? currTrack->Type() : 0, currItem ? currItem->Type() : 0 ); )

    if( !currTrack && currItem && currItem->Type()==TYPEVIA && currItem->m_Flags )
    {
        // moving a VIA
        currTrack = (TRACK*) currItem;
        amMovingVia = true;


    if( frame->GetCurItem() != curr )
        return false;   // comment this return out and play with it.
    }
    else if( currItem != currTrack )
    {
    {
        curr = NULL;
        currTrack = NULL;
    }
    }


	bool pad_ok = false; 
	if( g_MagneticPadOption == capture_always )
		pad_ok = true; 


    if( g_MagneticPadOption == capture_always )
        doPad = true;


	bool track_ok = false; 
    if( g_MagneticTrackOption == capture_always )
    if( g_MagneticTrackOption == capture_always )
		track_ok = true; 
        doTrack = true;


	if( aCurrentTool == ID_TRACK_BUTT )
    if( aCurrentTool == ID_TRACK_BUTT || amMovingVia )
    {
    {
        int q = capture_cursor_in_track_tool;
        int q = capture_cursor_in_track_tool;

        if( g_MagneticPadOption == q )
        if( g_MagneticPadOption == q )
			pad_ok = true; 
            doPad = true;

        if( g_MagneticTrackOption == q )
        if( g_MagneticTrackOption == q )
			track_ok = true; 
            doTrack = true;
    }
    }


    if(!pad_ok && !track_ok) //then nothing magnetic to do
    D(printf("doPad=%d doTrack=%d aCurrentTool=%d amMovingVia=%d\n", doPad, doTrack, aCurrentTool, amMovingVia );)
		return false; 

    //  The search precedence order is pads, then tracks/vias


    pad = Locate_Any_Pad( m_Pcb, CURSEUR_OFF_GRILLE, TRUE );
    if( doPad )
    if( pad && pad_ok)
    {
        D_PAD* pad = Locate_Any_Pad( m_Pcb, CURSEUR_OFF_GRILLE, TRUE );
        if( pad )
        {
        {
        if( doCheckNet && curr && curr->GetNet() != pad->GetNet() )
            if( doCheckNet && currTrack && currTrack->GetNet() != pad->GetNet() )
                return false;
                return false;


            *curpos = pad->m_Pos;
            *curpos = pad->m_Pos;
            return true;
            return true;
        }
        }
    }


    layer = ( (PCB_SCREEN*) ActiveScreen )->m_Active_Layer;
    // after pads, only track & via tests remain, skip them if not desired
    if( doTrack )
    {
        int     layer = ( (PCB_SCREEN*) ActiveScreen )->m_Active_Layer;


    via = Locate_Via_Area( m_Pcb, *curpos, layer );
        for( TRACK* via = m_Pcb->m_Track;
    if( via && track_ok) //vias are part of tracks...?
             via && (via = Locate_Via_Area( via, *curpos, layer )) != NULL;
             via = via->Next() )
        {
        {
        if( doCheckNet && curr && curr->GetNet() != via->GetNet() )
            if( via != currTrack )   // a via cannot influence itself
            {
                if( doCheckNet && currTrack && currTrack->GetNet() != via->GetNet() )
                    return false;
                    return false;


                *curpos = via->m_Start;
                *curpos = via->m_Start;
                D(printf("via hit\n");)
                return true;
                return true;
            }
            }
            else
            {
                D( printf( "skipping self\n" ); )
            }
        }


    layer_mask = g_TabOneLayerMask[layer];
        if( !currTrack )

    if( !curr && track_ok)
        {
        {
        track = Locate_Pistes( m_Pcb->m_Track, layer_mask, CURSEUR_OFF_GRILLE );
            int layer_mask = g_TabOneLayerMask[layer];

            TRACK* track = Locate_Pistes( m_Pcb->m_Track, layer_mask, CURSEUR_OFF_GRILLE );
            if( !track || track->Type() != TYPETRACK )
            if( !track || track->Type() != TYPETRACK )
                return false;
                return false;


            D( printf( "Project\n" ); )
            return Project( curpos, on_grid, track );
            return Project( curpos, on_grid, track );
        }
        }


@@ -365,40 +401,41 @@ static bool Magnetize( BOARD* m_Pcb, WinEDA_PcbFrame* frame,
         * In two segment mode, ignore the final segment if it's inside a grid
         * In two segment mode, ignore the final segment if it's inside a grid
         * square.
         * square.
         */
         */
    if( curr && g_TwoSegmentTrackBuild && curr->Back()
        if( !amMovingVia && currTrack && g_TwoSegmentTrackBuild && currTrack->Back()
        && curr->m_Start.x - grid.x < curr->m_End.x
            && currTrack->m_Start.x - grid.x < currTrack->m_End.x
        && curr->m_Start.x + grid.x > curr->m_End.x
            && currTrack->m_Start.x + grid.x > currTrack->m_End.x
        && curr->m_Start.y - grid.y < curr->m_End.y
            && currTrack->m_Start.y - grid.y < currTrack->m_End.y
        && curr->m_Start.y + grid.y > curr->m_End.y )
            && currTrack->m_Start.y + grid.y > currTrack->m_End.y )
        {
        {
        curr = curr->Back();
            currTrack = currTrack->Back();
        }
        }


    for( track = m_Pcb->m_Track;  track && track_ok;  track = track->Next() )

        for( TRACK* track = m_Pcb->m_Track;  track;  track = track->Next() )
        {
        {
            if( track->Type() != TYPETRACK )
            if( track->Type() != TYPETRACK )
                continue;
                continue;


        if( doCheckNet && curr->GetNet() != track->GetNet() )
            if( doCheckNet && currTrack && currTrack->GetNet() != track->GetNet() )
                continue;
                continue;


            if( (g_DesignSettings.m_LayerColor[track->GetLayer()] & ITEM_NOT_SHOW) )
            if( (g_DesignSettings.m_LayerColor[track->GetLayer()] & ITEM_NOT_SHOW) )
                continue;
                continue;


        if( !track->IsOnLayer( layer ) )
            // omit the layer check if moving a via
            if( !amMovingVia && !track->IsOnLayer( layer ) )
                continue;
                continue;


        // @todo, this should be a track overlap test, not a mouse on track test.
        // The former would consider the new track's width.
            if( !track->HitTest( *curpos ) )
            if( !track->HitTest( *curpos ) )
                continue;
                continue;


        if( Join( curpos, track->m_Start, track->m_End, curr->m_Start, curr->m_End ) )
            if( Join( curpos, track->m_Start, track->m_End, currTrack->m_Start, currTrack->m_End ) )
            {
            {
                D(printf( "join currTrack->Type()=%d\n", currTrack->Type() );)
                return true;
                return true;
            }
            }


        if( aCurrentTool == ID_TRACK_BUTT )
            if( aCurrentTool == ID_TRACK_BUTT || amMovingVia )
            {
            {
                // At this point we have a drawing mouse on a track, we are drawing
                // At this point we have a drawing mouse on a track, we are drawing
                // a new track and that new track is parallel to the track the
                // a new track and that new track is parallel to the track the
@@ -410,12 +447,29 @@ static bool Magnetize( BOARD* m_Pcb, WinEDA_PcbFrame* frame,
                double distEnd   = hypot( double( curpos->x - track->m_End.x ),
                double distEnd   = hypot( double( curpos->x - track->m_End.x ),
                                          double( curpos->y - track->m_End.y ));
                                          double( curpos->y - track->m_End.y ));


            if( distStart < distEnd )
                // if track not via, or if its a via dragging but not with its adjacent track
                if( currTrack->Type() != TYPEVIA
                    || ( currTrack->m_Start!=track->m_Start && currTrack->m_Start!=track->m_End ))
                {
                    if( distStart <= currTrack->m_Width/2 )
                    {
                        D(printf("nearest end is start\n");)
                        *curpos = track->m_Start;
                        *curpos = track->m_Start;
            else
                        return true;
                    }

                    if( distEnd <= currTrack->m_Width/2 )
                    {
                        D(printf("nearest end is end\n");)
                        *curpos = track->m_End;
                        *curpos = track->m_End;
                        return true;
                        return true;
                    }
                    }

                    // @todo otherwise confine curpos such that it stays centered
                    // within "track"
                }
            }
        }
    }
    }


    return false;
    return false;
+19 −23
Original line number Original line Diff line number Diff line
@@ -42,51 +42,47 @@ TRACK* Locate_Via( BOARD* Pcb, const wxPoint& pos, int layer )
 *          (TRACK*) adresse de la via
 *          (TRACK*) adresse de la via
 */
 */
{
{
    TRACK* Track;
    TRACK* track;


    for( Track = Pcb->m_Track; Track != NULL; Track = Track->Next() )
    for( track = Pcb->m_Track;  track; track = track->Next() )
    {
    {
        if( Track->Type() != TYPEVIA )
        if( track->Type() != TYPEVIA )
            continue;
            continue;
        if( Track->m_Start != pos )
        if( track->m_Start != pos )
            continue;
            continue;
        if( Track->GetState( BUSY | DELETED ) )
        if( track->GetState( BUSY | DELETED ) )
            continue;
            continue;
        if( layer < 0 )
        if( layer < 0 )
            return Track;
            break;
        if( Track->IsOnLayer( layer ) )
        if( track->IsOnLayer( layer ) )
            return Track;
            break;
    }
    }


    return NULL;
    return track;
}
}




/*******************************************************************/
/*******************************************************************/
TRACK* Locate_Via_Area( BOARD* Pcb, const wxPoint& pos, int layer )
TRACK* Locate_Via_Area( TRACK* aStart, const wxPoint& pos, int layer )
/*******************************************************************/
/*******************************************************************/

/*
 * Like Locate_Via, but finds any via covering the cursor position
 */
{
{
    TRACK* Track;
    TRACK* track;


    for( Track = Pcb->m_Track; Track != NULL; Track = Track->Next() )
    for( track = aStart;   track;  track = track->Next() )
    {
    {
        if( Track->Type() != TYPEVIA )
        if( track->Type() != TYPEVIA )
            continue;
            continue;
        if(!Track->HitTest(pos))
        if( !track->HitTest(pos) )
            continue;
            continue;
        if( Track->GetState( BUSY | DELETED ) )
        if( track->GetState( BUSY | DELETED ) )
            continue;
            continue;
        if( layer < 0 )
        if( layer < 0 )
            return Track;
            break;
        if( Track->IsOnLayer( layer ) )
        if( track->IsOnLayer( layer ) )
            return Track;
            break;
    }
    }


    return NULL;
    return track;
}
}




+9 −1
Original line number Original line Diff line number Diff line
@@ -77,7 +77,15 @@ void Trace_Pads_Only( WinEDA_DrawPanel* panel, wxDC* DC, MODULE* Module, int ox,


TRACK*          Locate_Via( BOARD* Pcb, const wxPoint& pos, int layer = -1 );
TRACK*          Locate_Via( BOARD* Pcb, const wxPoint& pos, int layer = -1 );


TRACK*          Locate_Via_Area( BOARD* Pcb, const wxPoint& pos, int layer = -1 );
/**
 * Function Locate_Via_Area
 * finds the first SEGVIA which covers the given aPos with a matching layer.
 * @param aStart The starting TRACK or SEGVIA in the BOARD's list.
 * @param aPos The wxPoint to HitTest() against.
 * @param aLayer The layer to match, pass -1 for a don't care.
 * @return TRACK* - actually a SEGVIA* if found, else NULL.
 */
TRACK*          Locate_Via_Area( TRACK* aStart, const wxPoint& aPos, int aLayer = -1 );


TRACK*          Fast_Locate_Via( TRACK* start_adr, TRACK* end_adr,
TRACK*          Fast_Locate_Via( TRACK* start_adr, TRACK* end_adr,
                                 const wxPoint& pos, int masquelayer );
                                 const wxPoint& pos, int masquelayer );