int SELECTION_TOOL::selectConnection( const TOOL_EVENT& aEvent )
{
    BOARD_CONNECTED_ITEM* item = m_selection.Item<BOARD_CONNECTED_ITEM>( 0 );
    int segmentCount;

    if( item->Type() != PCB_TRACE_T && item->Type() != PCB_VIA_T )
        return 0;

    clearSelection();
    TRACK* trackList = getModel<BOARD>()->MarkTrace( static_cast<TRACK*>( item ), &segmentCount,
                                                        NULL, NULL, true );

    if( segmentCount == 0 )
        return 0;

    for( int i = 0; i < segmentCount; ++i )
    {
        select( trackList );
        trackList = trackList->Next();
    }

    // Inform other potentially interested tools
    TOOL_EVENT selectEvent( SelectedEvent );
    m_toolMgr->ProcessEvent( selectEvent );

    return 0;
}
Exemplo n.º 2
0
int PNS_PCBNEW_CLEARANCE_RESOLVER::localPadClearance( const PNS_ITEM* aItem ) const
{
    BOARD_CONNECTED_ITEM *parent = aItem->Parent<BOARD_CONNECTED_ITEM>();
    if( !parent || parent->Type() != PCB_PAD_T )
        return 0;

    const D_PAD* pad = static_cast<D_PAD*>( parent );
    return pad->GetLocalClearance();
}
Exemplo n.º 3
0
/*
 * This function starts a new track segment.
 * If a new track segment is in progress, ends this current new segment,
 * and created a new one.
 */
TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC )
{
    TRACK*      TrackOnStartPoint = NULL;
    int         layerMask = GetLayerMask( GetScreen()->m_Active_Layer );
    BOARD_CONNECTED_ITEM* LockPoint;
    wxPoint     pos = GetScreen()->GetCrossHairPosition();

    if( aTrack == NULL )  // Starting a new track segment
    {
        m_canvas->SetMouseCapture( ShowNewTrackWhenMovingCursor, Abort_Create_Track );

        // Prepare the undo command info
        s_ItemsListPicker.ClearListAndDeleteItems();  // Should not be necessary, but...

        GetBoard()->PushHighLight();

        // erase old highlight
        if( GetBoard()->IsHighLightNetON() )
            HighLight( aDC );

        g_CurrentTrackList.PushBack( new TRACK( GetBoard() ) );
        g_CurrentTrackSegment->SetFlags( IS_NEW );

        GetBoard()->SetHighLightNet( 0 );

        // Search for a starting point of the new track, a track or pad
        LockPoint = GetBoard()->GetLockPoint( pos, layerMask );

        D_PAD* pad = NULL;
        if( LockPoint ) // An item (pad or track) is found
        {
            if( LockPoint->Type() == PCB_PAD_T )
            {
                pad = (D_PAD*) LockPoint;

                // A pad is found: put the starting point on pad center
                pos = pad->GetPosition();
                GetBoard()->SetHighLightNet( pad->GetNet() );
            }
            else // A track segment is found
            {
                TrackOnStartPoint    = (TRACK*) LockPoint;
                GetBoard()->SetHighLightNet( TrackOnStartPoint->GetNet() );
                GetBoard()->CreateLockPoint( pos, TrackOnStartPoint, &s_ItemsListPicker );
            }
        }
        else
        {
            // Not a starting point, but a filled zone area can exist. This is also a
            // good starting point.
            ZONE_CONTAINER* zone;
            zone = GetBoard()->HitTestForAnyFilledArea( pos, GetScreen()-> m_Active_Layer );

            if( zone )
                GetBoard()->SetHighLightNet( zone->GetNet() );
        }

        D( g_CurrentTrackList.VerifyListIntegrity() );

        BuildAirWiresTargetsList( LockPoint, wxPoint( 0, 0 ), true );

        D( g_CurrentTrackList.VerifyListIntegrity() );

        GetBoard()->HighLightON();
        GetBoard()->DrawHighLight( m_canvas, aDC, GetBoard()->GetHighLightNetCode() );

        // Display info about track Net class, and init track and vias sizes:
        g_CurrentTrackSegment->SetNet( GetBoard()->GetHighLightNetCode() );
        GetBoard()->SetCurrentNetClass( g_CurrentTrackSegment->GetNetClassName() );

        g_CurrentTrackSegment->SetLayer( GetScreen()->m_Active_Layer );
        g_CurrentTrackSegment->SetWidth( GetBoard()->GetCurrentTrackWidth() );

        if( GetBoard()->GetDesignSettings().m_UseConnectedTrackWidth )
        {
            if( TrackOnStartPoint && TrackOnStartPoint->Type() == PCB_TRACE_T )
                g_CurrentTrackSegment->SetWidth( TrackOnStartPoint->GetWidth());
        }

        g_CurrentTrackSegment->SetStart( pos );
        g_CurrentTrackSegment->SetEnd( pos );

        if( pad )
        {
            g_CurrentTrackSegment->m_PadsConnected.push_back( pad );
            // Useful to display track length, if the pad has a die length:
            g_CurrentTrackSegment->SetState( BEGIN_ONPAD, ON );
            g_CurrentTrackSegment->start = pad;
        }

        if( g_TwoSegmentTrackBuild )
        {
            // Create 2nd segment
            g_CurrentTrackList.PushBack( (TRACK*)g_CurrentTrackSegment->Clone() );

            D( g_CurrentTrackList.VerifyListIntegrity(); );

            g_CurrentTrackSegment->start = g_FirstTrackSegment;
            g_FirstTrackSegment->end     = g_CurrentTrackSegment;

            g_FirstTrackSegment->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
        }
/**
 * Function Test_Connection_To_Copper_Areas
 * init .m_ZoneSubnet parameter in tracks and pads according to the connections to areas found
 * @param aNetcode = netcode to analyse. if -1, analyse all nets
 */
void BOARD::Test_Connections_To_Copper_Areas( int aNetcode )
{
    // list of pads and tracks candidates on this layer and on this net.
    // It is static to avoid multiple memory realloc.
    static std::vector <BOARD_CONNECTED_ITEM*> candidates;

    // clear .m_ZoneSubnet parameter for pads
    for( MODULE* module = m_Modules;  module;  module = module->Next() )
    {
        for( D_PAD* pad = module->Pads();  pad;  pad = pad->Next() )
            if( aNetcode < 0 || aNetcode == pad->GetNetCode() )
                pad->SetZoneSubNet( 0 );
    }

    // clear .m_ZoneSubnet parameter for tracks and vias
    for( TRACK* track = m_Track;  track;  track = track->Next() )
    {
        if( aNetcode < 0 || aNetcode == track->GetNetCode() )
            track->SetZoneSubNet( 0 );
    }

    // examine all zones, net by net:
    int subnet = 0;

    // Build zones candidates list
    std::vector<ZONE_CONTAINER*> zones_candidates;

    zones_candidates.reserve( GetAreaCount() );

    for( int index = 0; index < GetAreaCount(); index++ )
    {
        ZONE_CONTAINER* zone = GetArea( index );

        if( !zone->IsOnCopperLayer() )
            continue;

        if( aNetcode >= 0 &&  aNetcode != zone->GetNetCode() )
            continue;

        if( zone->GetFilledPolysList().GetCornersCount() == 0 )
            continue;

        zones_candidates.push_back( zone );
    }

    // sort them by netcode then vertices count.
    // For a given net, examine the smaller zones first slightly speed up calculation
    // (25% faster)
    // this is only noticeable with very large boards and depends on board zones topology
    // This is due to the fact some items are connected by small zones ares,
    // before examining large zones areas and these items are not tested after a connection is found
    sort( zones_candidates.begin(), zones_candidates.end(), sort_areas );

    int oldnetcode = -1;
    for( unsigned idx = 0; idx < zones_candidates.size(); idx++ )
    {
        ZONE_CONTAINER* zone = zones_candidates[idx];

        int netcode = zone->GetNetCode();

        // Build a list of candidates connected to the net:
        // At this point, layers are not considered, because areas on different layers can
        // be connected by a via or a pad.
        // (because zones are sorted by netcode, there is made only once per net)
        NETINFO_ITEM* net = FindNet( netcode );

        wxASSERT( net );
        if( net == NULL )
            continue;

        if( oldnetcode != netcode )
        {
            oldnetcode = netcode;
            candidates.clear();

            // Build the list of pads candidates connected to the net:
            candidates.reserve( net->m_PadInNetList.size() );

            for( unsigned ii = 0; ii < net->m_PadInNetList.size(); ii++ )
                candidates.push_back( net->m_PadInNetList[ii] );

            // Build the list of track candidates connected to the net:
            TRACK* track = m_Track.GetFirst()->GetStartNetCode( netcode );

            for( ; track; track = track->Next() )
            {
                if( track->GetNetCode() != netcode )
                    break;

                candidates.push_back( track );
            }
        }

        // test if a candidate is inside a filled area of this zone
        unsigned indexstart = 0, indexend;
        const CPOLYGONS_LIST& polysList = zone->GetFilledPolysList();

        for( indexend = 0; indexend < polysList.GetCornersCount(); indexend++ )
        {
            // end of a filled sub-area found
            if( polysList.IsEndContour( indexend ) )
            {
                subnet++;
                EDA_RECT bbox = zone->CalculateSubAreaBoundaryBox( indexstart, indexend );

                for( unsigned ic = 0; ic < candidates.size(); ic++ )
                {
                    // test if this area is connected to a board item:
                    BOARD_CONNECTED_ITEM* item = candidates[ic];

                    if( item->GetZoneSubNet() == subnet )   // Already merged
                        continue;

                   if( !item->IsOnLayer( zone->GetLayer() ) )
                        continue;

                    wxPoint pos1, pos2;

                    if( item->Type() == PCB_PAD_T )
                    {
                        // For pads we use the shape position instead of
                        // the pad position, because the zones are connected
                        // to the center of the shape, not the pad position
                        // (this is important for pads with thermal relief)
                        pos1 = pos2 = ( (D_PAD*) item )->ShapePos();
                    }
                    else if( item->Type() == PCB_VIA_T )
                    {
                        const VIA *via = static_cast<const VIA*>( item );
                        pos1 = via->GetStart();
                        pos2 = pos1;
                    }
                    else if( item->Type() == PCB_TRACE_T )
                    {
                        const TRACK *trk = static_cast<const TRACK*>( item );
                        pos1 = trk->GetStart();
                        pos2 = trk->GetEnd();
                    }
                    else
                    {
                        continue;
                    }

                    bool connected = false;

                    if( bbox.Contains( pos1 ) )
                    {
                        if( TestPointInsidePolygon( polysList, indexstart,
                                                    indexend, pos1.x, pos1.y ) )
                            connected = true;
                    }
                    if( !connected && (pos1 != pos2 ) )
                    {
                        if( bbox.Contains( pos2 ) )
                        {
                            if( TestPointInsidePolygon( polysList,
                                                        indexstart, indexend,
                                                        pos2.x, pos2.y ) )
                                connected = true;
                        }
                    }

                    if( connected )
                    {
                        // Set ZoneSubnet to the current subnet value.
                        // If the previous subnet is not 0, merge all items with old subnet
                        // to the new one
                        int old_subnet = item->GetZoneSubNet();
                        item->SetZoneSubNet( subnet );

                        // Merge previous subnet with the current
                        if( (old_subnet > 0) && (old_subnet != subnet) )
                        {
                            for( unsigned jj = 0; jj < candidates.size(); jj++ )
                            {
                                BOARD_CONNECTED_ITEM* item_to_merge = candidates[jj];

                                if( old_subnet == item_to_merge->GetZoneSubNet() )
                                {
                                    item_to_merge->SetZoneSubNet( subnet );
                                }
                            }
                        }   // End if ( old_subnet > 0 )
                    }       // End if( connected )
                }

                // End test candidates for the current filled area
                indexstart = indexend + 1;  // prepare test next area, starting at indexend+1
                                            // (if exists).  End read one area in
                                            // zone->m_FilledPolysList
            }
        } // End read all segments in zone
    } // End read all zones candidates
}