コード例 #1
0
/* Test a list of track segments, to create or propagate a sub netcode to pads and
 * segments connected together.
 * The track list must be sorted by nets, and all segments
 * from m_firstTrack to m_lastTrack have the same net
 * When 2 items are connected (a track to a pad, or a track to an other track),
 * they are grouped in a cluster.
 * The .m_Subnet member is the cluster identifier (subnet id)
 * For a given net, if all tracks are created, there is only one cluster.
 * but if not all tracks are created, there are more than one cluster,
 * and some ratsnests will be left active.
 * A ratsnest is active when it "connect" 2 items having different subnet id
 */
void CONNECTIONS::Propagate_SubNets()
{
    int sub_netcode = 1;

    TRACK* curr_track = (TRACK*)m_firstTrack;
    if( curr_track )
        curr_track->SetSubNet( sub_netcode );

    // Examine connections between tracks and pads
    for( ; curr_track != NULL; curr_track = curr_track->Next() )
    {
        // First: handling connections to pads
        for( unsigned ii = 0; ii < curr_track->m_PadsConnected.size(); ii++ )
        {
            D_PAD * pad = curr_track->m_PadsConnected[ii];

            if( curr_track->GetSubNet() )        // the track segment is already a cluster member
            {
                if( pad->GetSubNet() > 0 )
                {
                    // The pad is already a cluster member, so we can merge the 2 clusters
                    Merge_SubNets( pad->GetSubNet(), curr_track->GetSubNet() );
                }
                else
                {
                    /* The pad is not yet attached to a cluster , so we can add this pad to
                     * the cluster */
                    pad->SetSubNet( curr_track->GetSubNet() );
                }
            }
            else                              // the track segment is not attached to a cluster
            {
                if( pad->GetSubNet() > 0 )
                {
                    // it is connected to a pad in a cluster, merge this track
                    curr_track->SetSubNet( pad->GetSubNet() );
                }
                else
                {
                    /* it is connected to a pad not in a cluster, so we must create a new
                     * cluster (only with the 2 items: the track and the pad) */
                    sub_netcode++;
                    curr_track->SetSubNet( sub_netcode );
                    pad->SetSubNet( curr_track->GetSubNet() );
                }
            }
        }

        // Test connections between segments
        for( unsigned ii = 0; ii < curr_track->m_TracksConnected.size(); ii++ )
        {
            BOARD_CONNECTED_ITEM* track = curr_track->m_TracksConnected[ii];

            if( curr_track->GetSubNet() )   // The current track is already a cluster member
            {
                // The other track is already a cluster member, so we can merge the 2 clusters
                if( track->GetSubNet() )
                {
                    Merge_SubNets( track->GetSubNet(), curr_track->GetSubNet() );
                }
                else
                {
                    // The other track is not yet attached to a cluster , so we can add this
                    // other track to the cluster
                    track->SetSubNet( curr_track->GetSubNet() );
                }
            }
            else        // the current track segment is not yet attached to a cluster
            {
                if( track->GetSubNet() )
                {
                    // The other track is already a cluster member, so we can add
                    // the current segment to the cluster
                    curr_track->SetSubNet( track->GetSubNet() );
                }
                else
                {
                    // it is connected to an other segment not in a cluster, so we must
                    // create a new cluster (only with the 2 track segments)
                    sub_netcode++;
                    curr_track->SetSubNet( sub_netcode );
                    track->SetSubNet( curr_track->GetSubNet() );
                }
            }
        }

        if( curr_track == m_lastTrack )
            break;
    }

    // Examine connections between intersecting pads, and propagate
    // sub_netcodes to intersecting pads
    for( unsigned ii = 0; ii < m_sortedPads.size(); ii++ )
    {
        D_PAD* curr_pad = m_sortedPads[ii];

        for( unsigned jj = 0; jj < curr_pad->m_PadsConnected.size(); jj++ )
        {
            D_PAD* pad = curr_pad->m_PadsConnected[jj];

            if( curr_pad->GetSubNet() )   // the current pad is already attached to a cluster
            {
                if( pad->GetSubNet() > 0 )
                {
                    // The pad is already a cluster member, so we can merge the 2 clusters
                    // Store the initial subnets, which will be modified by Merge_PadsSubNets
                    int subnet1 = pad->GetSubNet();
                    int subnet2 = curr_pad->GetSubNet();

                    // merge subnets of pads only, even those not connected by tracks
                    Merge_PadsSubNets( subnet1, subnet2 );

                    // merge subnets of tracks (and pads, which are already merged)
                    Merge_SubNets( subnet1, subnet2 );
                }
                else
                {
                    // The pad is not yet attached to a cluster,
                    // so we can add this pad to the cluster
                    pad->SetSubNet( curr_pad->GetSubNet() );
                }
            }
            else   // the current pad is not attached to a cluster
            {
                if( pad->GetSubNet() > 0 )
                {
                    // the connected pad is in a cluster,
                    // so we can add the current pad to the cluster
                    curr_pad->SetSubNet( pad->GetSubNet() );
                }
                else
                {
                    // the connected pad is not in a cluster,
                    // so we must create a new cluster, with the 2 pads.
                    sub_netcode++;
                    curr_pad->SetSubNet( sub_netcode );
                    pad->SetSubNet( curr_pad->GetSubNet() );
                }
            }
        }
    }
}
コード例 #2
0
/**
 * Function Merge_SubNets_Connected_By_CopperAreas(BOARD* aPcb, int aNetcode)
 * Used after connections by tracks calculations
 * Merge subnets, in tracks ans pads when they are connected by a filled copper area
 * for pads, this is the .m_physical_connexion member which is tested and modified
 * for tracks, this is the .m_Subnet member which is tested and modified
 * these members are block numbers (or cluster numbers) for a given net,
 * calculated by Build_Pads_Info_Connections_By_Tracks()
 * The result is merging 2 blocks (or subnets)
 * @param aPcb = the current board
 * @param aNetcode = netcode to consider
 */
void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode )
{
    // Ensure a zone with the given netcode exists: examine all zones:
    bool found = false;

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

        if( aNetcode == zone->GetNetCode() )
        {
            found = true;
            break;
        }
    }

    if( !found )  // No zone with this netcode, therefore no connection by zone
        return;

    // list of pads and tracks candidates to test:
    // It is static to avoid multiple memory realloc.
    static std::vector <BOARD_CONNECTED_ITEM*> Candidates;
    Candidates.clear();

    // Build the list of pads candidates connected to the net:
    NETINFO_ITEM* net = aPcb->FindNet( aNetcode );
    wxASSERT( 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;
    track = aPcb->m_Track.GetFirst()->GetStartNetCode( aNetcode );
    for( ; track; track = track->Next() )
    {
        if( track->GetNetCode() != aNetcode )
            break;
        Candidates.push_back( track );
    }

    if( Candidates.size() == 0 )
        return;

    int next_subnet_free_number = 0;
    for( unsigned ii = 0; ii < Candidates.size(); ii++ )
    {
        int subnet = Candidates[ii]->GetSubNet();
        next_subnet_free_number = std::max( next_subnet_free_number, subnet );
    }

    next_subnet_free_number++;     // This is a subnet we can use with not connected items
                                   // by tracks, but connected by zone.

    // Sort by zone_subnet:
    sort( Candidates.begin(), Candidates.end(), CmpZoneSubnetValue );

    // Some items can be not connected, but they can be connected to a filled area:
    // give them a subnet common to these items connected only by the area,
    // and not already used.
    // a value like next_subnet_free_number+zone_subnet is right
    for( unsigned jj = 0; jj < Candidates.size(); jj++ )
    {
        BOARD_CONNECTED_ITEM* item = Candidates[jj];
        if ( item->GetSubNet() == 0 && (item->GetZoneSubNet() > 0) )
        {
            item->SetSubNet( next_subnet_free_number + item->GetZoneSubNet() );
        }
    }

    // Now, for each zone subnet, we search for 2 items with different subnets.
    // if found, the 2 subnet are merged in the whole candidate list.
    int old_subnet      = 0;
    int old_zone_subnet = 0;
    for( unsigned ii = 0; ii < Candidates.size(); ii++ )
    {
        BOARD_CONNECTED_ITEM* item = Candidates[ii];
        int zone_subnet = item->GetZoneSubNet();

        if( zone_subnet == 0 )  // Not connected by a filled area, skip it
            continue;

        int subnet = item->GetSubNet();

        if( zone_subnet != old_zone_subnet )  // a new zone subnet is found
        {
            old_subnet = subnet;
            old_zone_subnet = zone_subnet;
            continue;
        }

        zone_subnet = old_zone_subnet;

        // 2 successive items already from the same cluster: nothing to do
        if( subnet == old_subnet )
            continue;

        // Here we have 2 items connected by the same area have 2 differents subnets: merge subnets
        if( (subnet > old_subnet) || ( subnet <= 0) )
            EXCHG( subnet, old_subnet );

        for( unsigned jj = 0; jj < Candidates.size(); jj++ )
        {
            BOARD_CONNECTED_ITEM * item_to_merge = Candidates[jj];

            if( item_to_merge->GetSubNet() == old_subnet )
                item_to_merge->SetSubNet( subnet );
        }

        old_subnet = subnet;
    }
}