Commit 5427a68a authored by Wayne Stambaugh's avatar Wayne Stambaugh
Browse files

Refactor PCBNew lock point and sorted pad list functions into board object.

parent 1c4d925d
Loading
Loading
Loading
Loading
+138 −0
Original line number Diff line number Diff line
@@ -19,6 +19,19 @@ wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
BOARD_DESIGN_SETTINGS boardDesignSettings;


/**
 * Function SortPadsByXCoord
 * is used to Sort a pad list by x coordinate value.
 */
static int sortPadsByXCoord( const void* pt_ref, const void* pt_comp )
{
    D_PAD* ref  = *(LISTE_PAD*) pt_ref;
    D_PAD* comp = *(LISTE_PAD*) pt_comp;

    return ref->m_Pos.x - comp->m_Pos.x;
}


BOARD::BOARD( EDA_ITEM* parent, PCB_BASE_FRAME* frame ) :
    BOARD_ITEM( (BOARD_ITEM*)parent, TYPE_PCB ),
    m_NetClasses( this )
@@ -1744,6 +1757,15 @@ D_PAD* BOARD::GetPad( LISTE_PAD* aPad, const wxPoint& aPosition, int aLayerMask
}


void BOARD::GetSortedPadListByXCoord( std::vector<D_PAD*>& aVector )
{
    aVector.insert( aVector.end(), m_NetInfo->m_PadsFullList.begin(),
                    m_NetInfo->m_PadsFullList.end() );

    qsort( &aVector[0], GetPadsCount(), sizeof( D_PAD*), sortPadsByXCoord );
}


TRACK* BOARD::GetTrace( TRACK* aTrace, const wxPoint& aPosition, int aLayerMask )
{
    for( TRACK* track = aTrace;   track;  track =  track->Next() )
@@ -2095,6 +2117,122 @@ MODULE* BOARD::GetFootprint( const wxPoint& aPosition, int aActiveLayer,
}


BOARD_ITEM* BOARD::GetLockPoint( const wxPoint& aPosition, int aLayerMask )
{
    for( MODULE* module = m_Modules; module; module = module->Next() )
    {
        D_PAD* pad = module->GetPad( aPosition, aLayerMask );

        if( pad )
            return pad;
    }

    /* No pad has been located so check for a segment of the trace. */
    TRACK* segment = ::GetTrace( m_Track, NULL, aPosition, aLayerMask );

    if( segment == NULL )
        segment = GetTrace( m_Track, aPosition, aLayerMask );

    return segment;
}


TRACK* BOARD::CreateLockPoint( wxPoint& aPosition, TRACK* aSegment, PICKED_ITEMS_LIST* aList )
{
    if( aSegment->m_Start == aPosition || aSegment->m_End == aPosition )
        return NULL;

    /* A via is a good lock point */
    if( aSegment->Type() == TYPE_VIA )
    {
        aPosition = aSegment->m_Start;
        return aSegment;
    }

    // Calculation coordinate of intermediate point relative to the start point of aSegment
     wxPoint delta = aSegment->m_End - aSegment->m_Start;

    // Not yet in use:
#if 0
    int ox, oy, fx, fy;

    if( aRefSegm )
    {
        ox = aRefSegm->m_Start.x - aSegment->m_Start.x;
        oy = aRefSegm->m_Start.y - aSegment->m_Start.y;
        fx = aRefSegm->m_End.x - aSegment->m_Start.x;
        fy = aRefSegm->m_End.y - aSegment->m_Start.y;
    }
#endif

    // calculate coordinates of aPosition relative to aSegment->m_Start
    wxPoint newPoint = aPosition - aSegment->m_Start;

    // newPoint must be on aSegment:
    // Ensure newPoint.y/newPoint.y = delta.y/delta.x
    if( delta.x == 0 )
        newPoint.x = 0;         /* horizontal segment*/
    else
        newPoint.y = wxRound( ( (double)newPoint.x * delta.y ) / delta.x );

    /* Create the intermediate point (that is to say creation of a new
     * segment, beginning at the intermediate point.
     */
    newPoint.x += aSegment->m_Start.x;
    newPoint.y += aSegment->m_Start.y;

    TRACK* newTrack = aSegment->Copy();

    if( aList )
    {
        ITEM_PICKER picker( newTrack, UR_NEW );
        aList->PushItem( picker );
    }


    DLIST<TRACK>* list = (DLIST<TRACK>*)aSegment->GetList();
    wxASSERT( list );
    list->Insert( newTrack, aSegment->Next() );

    if( aList )
    {
        ITEM_PICKER picker( aSegment, UR_CHANGED );
        picker.m_Link = aSegment->Copy();
        aList->PushItem( picker );
    }

    /* Correct pointer at the end of the new segment. */
    newTrack->end = aSegment->end;
    newTrack->SetState( END_ONPAD, aSegment->GetState( END_ONPAD ) );

    /* Set connections info relative to the new point
    */

    /* Old segment now ends at new point. */
    aSegment->m_End = newPoint;
    aSegment->end = newTrack;
    aSegment->SetState( END_ONPAD, OFF );

    /* The new segment begins at the new point. */
    newTrack->m_Start = newPoint;
    newTrack->start = aSegment;
    newTrack->SetState( BEGIN_ONPAD, OFF );

    D_PAD * pad = GetPad( newTrack, START );

    if ( pad )
    {
        newTrack->start = pad;
        newTrack->SetState( BEGIN_ONPAD, ON );
        aSegment->end = pad;
        aSegment->SetState( END_ONPAD, ON );
    }

    aPosition = newPoint;
    return newTrack;
}


#if defined(DEBUG)

void BOARD::Show( int nestLevel, std::ostream& os )
+46 −1
Original line number Diff line number Diff line
@@ -1157,6 +1157,17 @@ public:
     */
    D_PAD* GetPad( LISTE_PAD* aPad, const wxPoint& aPosition, int aLayerMask );

    /**
     * Function GetSortedPadListByXCoord
     * first empties then fills the vector with all pads and sorts them by
     * increasing x coordinate.  The vector only holds pointers to the pads and
     * those pointers are only references to pads which are owned by the BOARD
     * through other links.
     * @param aVector Where to put the pad pointers.
     */
    void GetSortedPadListByXCoord( std::vector<D_PAD*>& aVector );


    /**
     * Function GetTrace
     * find the segment of \a aTrace at \a aPosition on \a aLayer if \a Layer is visible.
@@ -1205,7 +1216,7 @@ public:
     * active layer is returned.  The distance is calculated via manhattan distance from
     * the center of the bounding rectangle to \a aPosition.
     *
     * @param aPosition Flag bits, tuning the search, see pcbnew.h
     * @param aPosition A wxPoint object containing the position to test.
     * @param aActiveLayer Layer to test.
     * @param aVisibleOnly Search only the visible layers if true.
     * @param aIgnoreLocked Ignore locked modules when true.
@@ -1213,6 +1224,40 @@ public:
     */
    MODULE* GetFootprint( const wxPoint& aPosition, int aActiveLayer,
                          bool aVisibleOnly, bool aIgnoreLocked = false );

    /**
     * Function GetLockPoint
     * returns the item at the "attachment" point at the end of a trace at \a aPosition
     * on \a aLayerMask.
     * <p>
     * This may be a PAD or another trace segment.
     * </p>
     *
     * @param aPosition A wxPoint object containing the position to test.
     * @param aLayerMask A layer or layers to mask the hit test.  Use -1 to ignore
     *                   layer mask.
     * @return A pointer to a BOARD_ITEM object if found otherwise NULL.
     */
    BOARD_ITEM* GetLockPoint( const wxPoint& aPosition, int aLayerMask );

    /**
     * Function CreateLockPoint
     * creates an intermediate point on \a aSegment and break it into two segments
     * at \a aPoition.
     * <p>
     * The new segment starts from \a aPosition and ends at the end point of \a
     * aSegement.  The original segment now ends at \a aPosition.
     * </p>
     *
     * @param aPosition A wxPoint object containing the position to test and the new
     *                  segment start position if the return value is not NULL.
     * @param aSegment The trace segment to create the lock point on.
     * @param aList The pick list to add the created items to.
     * @return NULL if no new point was created or a pointer to a TRACK ojbect of the
     *         created segment.  If \a aSegment points to a via the exact value of \a
     *         aPosition and a pointer to the via are returned.
     */
    TRACK* CreateLockPoint( wxPoint& aPosition, TRACK* aSegment, PICKED_ITEMS_LIST* aList );
};

#endif      // #ifndef CLASS_BOARD_H
+1 −22
Original line number Diff line number Diff line
@@ -469,27 +469,6 @@ static void Build_Pads_Info_Connections_By_Tracks( TRACK* pt_start_conn, TRACK*

#define POS_AFF_CHREF 62

/**
 * Function SortPadsByXCoord
 * is used to Sort a pad list by x coordinate value.
 */
static int SortPadsByXCoord( const void* pt_ref, const void* pt_comp )
{
    D_PAD* ref  = *(LISTE_PAD*) pt_ref;
    D_PAD* comp = *(LISTE_PAD*) pt_comp;

    return ref->m_Pos.x - comp->m_Pos.x;
}


void CreateSortedPadListByXCoord( BOARD* aBoard, std::vector<D_PAD*>* aVector )
{
    aVector->insert( aVector->end(), aBoard->m_NetInfo->m_PadsFullList.begin(),
                     aBoard->m_NetInfo->m_PadsFullList.end() );

    qsort( &(*aVector)[0], aBoard->GetPadsCount(), sizeof( D_PAD*), SortPadsByXCoord );
}


void PCB_BASE_FRAME::RecalculateAllTracksNetcode()
{
@@ -523,7 +502,7 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode()
    /**************************************************************/
    /* Pass 1: search the connections between track ends and pads */
    /**************************************************************/
    CreateSortedPadListByXCoord( m_Pcb, &sortedPads );
    m_Pcb->GetSortedPadListByXCoord( sortedPads );

    /* Reset variables and flags used in computation */
    pt_trace = m_Pcb->m_Track;
+20 −14
Original line number Diff line number Diff line
@@ -121,9 +121,7 @@ DRC::~DRC()
}


/*********************************************/
int DRC::Drc( TRACK* aRefSegm, TRACK* aList )
/*********************************************/
{
    updatePointers();

@@ -411,7 +409,7 @@ void DRC::testPad2Pad()
{
    std::vector<D_PAD*> sortedPads;

    CreateSortedPadListByXCoord( m_pcb, &sortedPads );
    m_pcb->GetSortedPadListByXCoord( sortedPads );

    // find the max size of the pads (used to stop the test)
    int max_size = 0;
@@ -420,7 +418,8 @@ void DRC::testPad2Pad()
    {
        D_PAD* pad = sortedPads[i];

        if( pad->m_ShapeMaxRadius > max_size )       // m_ShapeMaxRadius is the radius value of the circle containing the pad
        // m_ShapeMaxRadius is the radius value of the circle containing the pad
        if( pad->m_ShapeMaxRadius > max_size )
            max_size = pad->m_ShapeMaxRadius;
    }

@@ -491,7 +490,7 @@ void DRC::testUnconnected()

void DRC::testZones( bool adoTestFillSegments )
{
    // Test copper areas for valide netcodes
    // Test copper areas for valid netcodes
    // if a netcode is < 0 the netname was not found when reading a netlist
    // if a netcode is == 0 the netname is void, and the zone is not connected.
    // This is allowed, but i am not sure this is a good idea
@@ -558,7 +557,7 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd, in
    MODULE dummymodule( m_pcb );    // Creates a dummy parent
    D_PAD dummypad( &dummymodule );
    dummypad.m_layerMask   |= ALL_CU_LAYERS;  // Ensure the hole is on all copper layers
    dummypad.m_LocalClearance = 1;   /* Use the minimal local clerance value for the dummy pad
    dummypad.m_LocalClearance = 1;   /* Use the minimal local clearance value for the dummy pad
                                      *  the clearance of the active pad will be used
                                      *  as minimum distance to a hole
                                      *  (a value = 0 means use netclass value)
@@ -577,7 +576,7 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd, in
            break;

        // No problem if pads are on different copper layers,
        // but their hole (if any ) can create RDC error because they are on all
        // but their hole (if any ) can create DRC error because they are on all
        // copper layers, so we test them
        if( (pad->m_layerMask & layerMask ) == 0 )
        {
@@ -590,20 +589,24 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd, in
                if( aRefPad->m_DrillShape == PAD_CIRCLE )
                    continue;

                if( pad->m_Orient == aRefPad->m_Orient )                       // for oval holes: must also have the same orientation
                // for oval holes: must also have the same orientation
                if( pad->m_Orient == aRefPad->m_Orient )
                    continue;
            }

            /* Here, we must test clearance between holes and pads
             * dummy pad size and shape is adjusted to pad drill size and shape
             */
            if( pad->m_Drill.x )  // pad under testing has a hole, test this hole against pad reference
            if( pad->m_Drill.x )
            {
                // pad under testing has a hole, test this hole against pad reference
                dummypad.SetPosition( pad->GetPosition() );
                dummypad.m_Size     = pad->m_Drill;
                dummypad.m_PadShape = (pad->m_DrillShape == PAD_OVAL) ? PAD_OVAL : PAD_CIRCLE;
                dummypad.m_Orient   = pad->m_Orient;
                dummypad.ComputeShapeMaxRadius();      // compute the radius of the circle containing this pad

                // compute the radius of the circle containing this pad
                dummypad.ComputeShapeMaxRadius();

                if( !checkClearancePadToPad( aRefPad, &dummypad ) )
                {
@@ -620,7 +623,10 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, LISTE_PAD* aStart, LISTE_PAD* aEnd, in
                dummypad.m_Size     = aRefPad->m_Drill;
                dummypad.m_PadShape = (aRefPad->m_DrillShape == PAD_OVAL) ? PAD_OVAL : PAD_CIRCLE;
                dummypad.m_Orient   = aRefPad->m_Orient;
                dummypad.ComputeShapeMaxRadius();      // compute the radius of the circle containing this pad

                // compute the radius of the circle containing this pad
                dummypad.ComputeShapeMaxRadius();

                if( !checkClearancePadToPad( pad, &dummypad ) )
                {
                    // here we have a drc error on aRefPad!
+1 −1
Original line number Diff line number Diff line
@@ -1001,7 +1001,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
            wxPoint pos   = GetScreen()->GetCrossHairPosition();
            track->Draw( DrawPanel, &dc, GR_XOR );
            PICKED_ITEMS_LIST itemsListPicker;
            TRACK*  newtrack = CreateLockPoint( GetBoard(), pos, track, &itemsListPicker );
            TRACK*  newtrack = GetBoard()->CreateLockPoint( pos, track, &itemsListPicker );
            SaveCopyInUndoList( itemsListPicker, UR_UNSPECIFIED );
            track->Draw( DrawPanel, &dc, GR_XOR );
            newtrack->Draw( DrawPanel, &dc, GR_XOR );
Loading