示例#1
0
/*
 *  Delete dangling tracks
 *  Vias:
 *  If a via is only connected to a dangling track, it also will be removed
 */
bool TRACKS_CLEANER::deleteUnconnectedTracks()
{
    if( m_Brd->m_Track == NULL )
        return false;

    bool modified = false;
    bool item_erased;
    do // Iterate when at least one track is deleted
    {
        item_erased = false;
        TRACK* next_track;
        for( TRACK *track = m_Brd->m_Track; track != NULL; track = next_track )
        {
            next_track = track->Next();

            bool flag_erase = false; // Start without a good reason to erase it

            /* if a track endpoint is not connected to a pad, test if
             * the endpoint is connected to another track or to a zone.
             * For via test, an enhancement could be to test if
             * connected to 2 items on different layers. Currently
             * a via must be connected to 2 items, that can be on the
             * same layer */

            // Check if there is nothing attached on the start
            if( !(track->GetState( START_ON_PAD )) )
                flag_erase |= testTrackEndpointDangling( track, ENDPOINT_START );

            // Check if there is nothing attached on the end
            if( !(track->GetState( END_ON_PAD )) )
                flag_erase |= testTrackEndpointDangling( track, ENDPOINT_END );

            if( flag_erase )
            {
                // remove segment from board
                m_Brd->GetRatsnest()->Remove( track );
                track->ViewRelease();
                track->DeleteStructure();

                /* keep iterating, because a track connected to the deleted track
                 * now perhaps is not connected and should be deleted */
                item_erased = true;
                modified = true;
            }
        }
    } while( item_erased );

    return modified;
}
TRACK* GetTrack( TRACK* aStartTrace, const TRACK* aEndTrace,
        const wxPoint& aPosition, LAYER_MSK aLayerMask )
{
    for( TRACK *PtSegm = aStartTrace; PtSegm != NULL; PtSegm = PtSegm->Next() )
    {
        if( PtSegm->GetState( IS_DELETED | BUSY ) == 0 )
        {
            if( aPosition == PtSegm->GetStart() )
            {
                if( aLayerMask & PtSegm->GetLayerMask() )
                    return PtSegm;
            }

            if( aPosition == PtSegm->GetEnd() )
            {
                if( aLayerMask & PtSegm->GetLayerMask() )
                    return PtSegm;
            }
        }

        if( PtSegm == aEndTrace )
            break;
    }

    return NULL;
}
TRACK* GetTrack( TRACK* aStartTrace, const TRACK* aEndTrace,
        const wxPoint& aPosition, LSET aLayerMask )
{
    for( TRACK* seg = aStartTrace;  seg;  seg = seg->Next() )
    {
        if( seg->GetState( IS_DELETED | BUSY ) == 0 )
        {
            if( aPosition == seg->GetStart() )
            {
                if( ( aLayerMask & seg->GetLayerSet() ).any() )
                    return seg;
            }

            if( aPosition == seg->GetEnd() )
            {
                if( ( aLayerMask & seg->GetLayerSet() ).any() )
                    return seg;
            }
        }

        if( seg == aEndTrace )
            break;
    }

    return NULL;
}
示例#4
0
TRACK * Locate_Pistes(TRACK * start_adresse, wxPoint ref, int Layer)
{
TRACK * Track;		/* pointeur sur les pistes */
int l_piste ;					/* demi-largeur de la piste */

	for( Track = start_adresse; Track != NULL; Track = (TRACK*) Track->Pnext)
		{	
		if( Track->GetState(BUSY|DELETED) ) continue;
		/* calcul des coordonnees du segment teste */
		l_piste = Track->m_Width >> 1;  /* l_piste = demi largeur piste */
		ux0 = Track->m_Start.x ; uy0 = Track->m_Start.y ; /* coord de depart */
		dx =  Track->m_End.x ; dy =  Track->m_End.y ; /* coord d'arrivee */

		/* recalcul des coordonnees avec ux0, uy0 = origine des coordonnees */
		dx -= ux0 ; dy -= uy0 ;
		spot_cX = ref.x - ux0 ; spot_cY = ref.y - uy0 ;

		if ( Track->m_StructType == TYPEVIA ) /* VIA rencontree */
			{
			if ((abs(spot_cX) <= l_piste ) && (abs(spot_cY) <=l_piste))
				{
				return(Track) ;
				}
			continue ;
			}

		if(Layer >= 0)
			if( Track->m_Layer != Layer )
				continue;	/* Segments sur couches differentes */
		if( distance(l_piste) ) return(Track) ;
		}
	return(NULL) ;
}
示例#5
0
/*
 * This function try to remove an old track, when a new track is created,
 * and the old track is no more needed
 */
int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC*              aDC,
                                         TRACK*             aNewTrack,
                                         int                aNewTrackSegmentsCount,
                                         PICKED_ITEMS_LIST* aItemsListPicker )
{
    TRACK*  StartTrack, * EndTrack;
    TRACK*  pt_segm;
    TRACK*  pt_del;
    int     ii, jj, nb_segm, nbconnect;
    wxPoint start;
    wxPoint end;
    int     startmasklayer, endmasklayer;

    int     netcode = aNewTrack->GetNet();

    /* Reconstruct the complete track (the new track has to start on a segment of track).
     */
    ListSetState( aNewTrack, aNewTrackSegmentsCount, BUSY, OFF );

    /* If the new track begins with a via, complete the track segment using
     * the following segment as a reference because a  via is often a hub of
     * segments, and does not characterize track.
     */
    if( aNewTrack->Type() == PCB_VIA_T && ( aNewTrackSegmentsCount > 1 ) )
        aNewTrack = aNewTrack->Next();

    aNewTrack = GetBoard()->MarkTrace( aNewTrack, &aNewTrackSegmentsCount, NULL, NULL, true );
    wxASSERT( aNewTrack );

#if 0 && defined(DEBUG)
    TRACK* EndNewTrack;      // The last segment of the list chained to the track

    EndNewTrack = aNewTrack;

    for( ii = 1;  ii < aNewTrackSegmentsCount; ii++ )
    {
        wxASSERT( EndNewTrack->GetState( -1 ) != 0 );
        D( printf( "track %p is newly part of net %d\n", EndNewTrack, netcode ); )
        EndNewTrack = EndNewTrack->Next();
    }
示例#6
0
bool PCB_EDIT_FRAME::RemoveMisConnectedTracks()
{
     /* finds all track segments which are mis-connected (to more than one net).
     * When such a bad segment is found, it is flagged to be removed.
     * All tracks having at least one flagged segment are removed.
     */
    TRACK*          segment;
    TRACK*          other;
    TRACK*          next;
    int             net_code_s, net_code_e;
    bool            isModified = false;

    for( segment = GetBoard()->m_Track;  segment;  segment = (TRACK*) segment->Next() )
    {
        segment->SetState( FLAG0, false );

        // find the netcode for segment using anything connected to the "start" of "segment"
        net_code_s = -1;

        if( segment->start && segment->start->Type()==PCB_PAD_T )
        {
            // get the netcode of the pad to propagate.
            net_code_s = ((D_PAD*)(segment->start))->GetNetCode();
        }
        else
        {
            other = segment->GetTrace( GetBoard()->m_Track, NULL, FLG_START );

            if( other )
                net_code_s = other->GetNetCode();
        }

        if( net_code_s < 0 )
            continue;           // the "start" of segment is not connected

        // find the netcode for segment using anything connected to the "end" of "segment"
        net_code_e = -1;

        if( segment->end && segment->end->Type()==PCB_PAD_T )
        {
            net_code_e = ((D_PAD*)(segment->end))->GetNetCode();
        }
        else
        {
            other = segment->GetTrace( GetBoard()->m_Track, NULL, FLG_END );

            if( other )
                net_code_e = other->GetNetCode();
        }

        if( net_code_e < 0 )
            continue;           // the "end" of segment is not connected

        // Netcodes do not agree, so mark the segment as "to be removed"
        if( net_code_s != net_code_e )
        {
            segment->SetState( FLAG0, true );
        }
    }

    // Remove tracks having a flagged segment
    for( segment = GetBoard()->m_Track; segment; segment = next )
    {
        next = (TRACK*) segment->Next();

        if( segment->GetState( FLAG0 ) )    // Segment is flagged to be removed
        {
            segment->SetState( FLAG0, false );
            isModified = true;
            GetBoard()->m_Status_Pcb = 0;
            Remove_One_Track( NULL, segment );

            // the current segment is deleted,
            // we do not know the next "not yet tested" segment,
            // so restart to the beginning
            next = GetBoard()->m_Track;
        }
    }

    return isModified;
}
示例#7
0
/*
 *  Delete dangling tracks
 *  Vias:
 *  If a via is only connected to a dangling track, it also will be removed
 */
bool TRACKS_CLEANER::deleteUnconnectedTracks()
{
    if( m_Brd->m_Track == NULL )
        return false;

    bool modified = false;
    bool item_erased = true;
    while( item_erased )    // Iterate when at least one track is deleted
    {
        item_erased = false;
        TRACK* next_track;
        for( TRACK * track = m_Brd->m_Track; track ; track = next_track )
        {
            next_track = track->Next();

            int flag_erase = 0; //Not connected indicator
            int type_end = 0;

            if( track->GetState( START_ON_PAD ) )
                type_end |= START_ON_PAD;

            if( track->GetState( END_ON_PAD ) )
                type_end |= END_ON_PAD;

            // if the track start point is not connected to a pad,
            // test if this track start point is connected to another track
            // For via test, an enhancement could be to test if connected
            // to 2 items on different layers.
            // Currently a via must be connected to 2 items, that can be on the same layer
            LAYER_NUM top_layer, bottom_layer;
            ZONE_CONTAINER* zone;

            if( (type_end & START_ON_PAD ) == 0 )
            {
                TRACK* other = track->GetTrace( m_Brd->m_Track, NULL, FLG_START );

                if( other == NULL )     // Test a connection to zones
                {
                    if( track->Type() != PCB_VIA_T )
                    {
                        zone = m_Brd->HitTestForAnyFilledArea( track->GetStart(),
                                                               track->GetLayer(),
                                                               track->GetLayer(),
                                                               track->GetNetCode() );
                    }
                    else
                    {
                        ((SEGVIA*)track)->LayerPair( &top_layer, &bottom_layer );
                        zone = m_Brd->HitTestForAnyFilledArea( track->GetStart(),
                                                               top_layer, bottom_layer,
                                                               track->GetNetCode() );
                    }
                }

                if( (other == NULL) && (zone == NULL) )
                {
                    flag_erase |= 1;
                }
                else    // segment, via or zone connected to this end
                {
                    track->start = other;
                    // If a via is connected to this end,
                    // test if this via has a second item connected.
                    // If no, remove it with the current segment

                    if( other && other->Type() == PCB_VIA_T )
                    {
                        // search for another segment following the via
                        track->SetState( BUSY, true );

                        SEGVIA* via = (SEGVIA*) other;
                        other = via->GetTrace( m_Brd->m_Track, NULL, FLG_START );

                        if( other == NULL )
                        {
                            via->LayerPair( &top_layer, &bottom_layer );
                            zone = m_Brd->HitTestForAnyFilledArea( via->GetStart(),
                                                                   bottom_layer,
                                                                   top_layer,
                                                                   via->GetNetCode() );
                        }

                        if( (other == NULL) && (zone == NULL) )
                            flag_erase |= 2;

                        track->SetState( BUSY, false );
                    }
                }
            }

            // if track end point is not connected to a pad,
            // test if this track end point is connected to an other track
            if( (type_end & END_ON_PAD ) == 0 )
            {
                TRACK* other = track->GetTrace( m_Brd->m_Track, NULL, FLG_END );

                if( other == NULL )     // Test a connection to zones
                {
                    if( track->Type() != PCB_VIA_T )
                    {
                        zone = m_Brd->HitTestForAnyFilledArea( track->GetEnd(),
                                                               track->GetLayer(),
                                                               track->GetLayer(),
                                                               track->GetNetCode() );
                    }
                    else
                    {
                        ((SEGVIA*)track)->LayerPair( &top_layer, &bottom_layer );
                        zone = m_Brd->HitTestForAnyFilledArea( track->GetEnd(),
                                                               top_layer, bottom_layer,
                                                               track->GetNetCode() );
                    }
                }

                if ( (other == NULL) && (zone == NULL) )
                {
                    flag_erase |= 0x10;
                }
                else     // segment, via or zone connected to this end
                {
                    track->end = other;

                    // If a via is connected to this end, test if this via has a second item connected
                    // if no, remove it with the current segment

                    if( other && other->Type() == PCB_VIA_T )
                    {
                        // search for another segment following the via

                        track->SetState( BUSY, true );

                        SEGVIA* via = (SEGVIA*) other;
                        other = via->GetTrace( m_Brd->m_Track, NULL, FLG_END );

                        if( other == NULL )
                        {
                            via->LayerPair( &top_layer, &bottom_layer );
                            zone = m_Brd->HitTestForAnyFilledArea( via->GetEnd(),
                                                                   bottom_layer, top_layer,
                                                                   via->GetNetCode() );
                        }

                        if( (other == NULL) && (zone == NULL) )
                            flag_erase |= 0x20;

                        track->SetState( BUSY, false );
                    }
                }
            }

            if( flag_erase )
            {
                // remove segment from board
                track->DeleteStructure();
                // iterate, because a track connected to the deleted track
                // is now perhaps now not connected and should be deleted
                item_erased = true;
                modified = true;
            }
        }
    }

    return modified;
}
TRACK* TRACK::GetTrack( TRACK* aStartTrace, TRACK* aEndTrace, ENDPOINT_T aEndPoint,
        bool aSameNetOnly, bool aSequential )
{
    const wxPoint &position = GetEndPoint( aEndPoint );
    LAYER_MSK refLayers = GetLayerMask();
    TRACK *previousSegment;
    TRACK *nextSegment;

    if( aSequential )
    {
        // Simple sequential search: from aStartTrace forward to aEndTrace
        previousSegment = NULL;
        nextSegment = aStartTrace;
    }
    else
    {
        /* Local bidirectional search: from this backward to aStartTrace
         * AND forward to aEndTrace. The idea is that nearest segments
         * are found (on average) faster in this way. In fact same-net
         * segments are almost guaranteed to be found faster, in a global
         * search, since they are grouped together in the track list */
        previousSegment = this;
        nextSegment = this;
    }

    while( nextSegment || previousSegment )
    {
        // Terminate the search in the direction if the netcode mismatches
        if( aSameNetOnly )
        {
            if( nextSegment && (nextSegment->GetNetCode() != GetNetCode()) )
                nextSegment = NULL;
            if( previousSegment && (previousSegment->GetNetCode() != GetNetCode()) )
                previousSegment = NULL;
        }

        if( nextSegment )
        {
            if ( (nextSegment != this) &&
                 !nextSegment->GetState( BUSY | IS_DELETED ) &&
                 (refLayers & nextSegment->GetLayerMask()) )
            {
                if( (position == nextSegment->m_Start) ||
                    (position == nextSegment->m_End) )
                    return nextSegment;
            }

            // Keep looking forward
            if( nextSegment == aEndTrace )
                nextSegment = NULL;
            else
                nextSegment = nextSegment->Next();
        }

        // Same as above, looking back. During sequential search this branch is inactive
        if( previousSegment )
        {
            if ( (previousSegment != this) &&
                 !previousSegment->GetState( BUSY | IS_DELETED ) &&
                 (refLayers & previousSegment->GetLayerMask()) )
            {
                if( (position == previousSegment->m_Start) ||
                    (position == previousSegment->m_End) )
                    return previousSegment;
            }

            if( previousSegment == aStartTrace )
                previousSegment = NULL;
            else
                previousSegment = previousSegment->Back();
        }
    }

    return NULL;
}
void DIALOG_GLOBAL_DELETION::AcceptPcbDelete( )
{
    bool gen_rastnest = false;

    m_Parent->SetCurItem( NULL );

    if( m_DelAlls->GetValue() )
    {
        m_Parent->Clear_Pcb( true );
    }
    else
    {
        if( !IsOK( this, _( "Are you sure you want to delete the selected items?" ) ) )
            return;

        BOARD*            pcb = m_Parent->GetBoard();
        PICKED_ITEMS_LIST pickersList;
        ITEM_PICKER       itemPicker( NULL, UR_DELETED );
        BOARD_ITEM*       item;
        BOARD_ITEM*       nextitem;
        RN_DATA*          ratsnest = pcb->GetRatsnest();

        LSET layers_filter = LSET().set();

        if( m_rbLayersOption->GetSelection() != 0 )     // Use current layer only
            layers_filter = LSET( ToLAYER_ID( m_currentLayer ) );

        if( m_DelZones->GetValue() )
        {
            int area_index = 0;
            item = pcb->GetArea( area_index );

            while( item )
            {
                if( layers_filter[item->GetLayer()] )
                {
                    itemPicker.SetItem( item );
                    pickersList.PushItem( itemPicker );
                    pcb->Remove( item );
                    item->ViewRelease();
                    ratsnest->Remove( item );
                    gen_rastnest = true;
                }
                else
                {
                    area_index++;
                }

                item = pcb->GetArea( area_index );
            }
        }

        if( m_DelDrawings->GetValue() || m_DelBoardEdges->GetValue() )
        {
            LSET masque_layer;

            if( m_DelDrawings->GetValue() )
                 masque_layer = LSET::AllNonCuMask().set( Edge_Cuts, false );

            if( m_DelBoardEdges->GetValue() )
                 masque_layer.set( Edge_Cuts );

            masque_layer &= layers_filter;

            for( item = pcb->m_Drawings; item; item = nextitem )
            {
                nextitem = item->Next();

                if( item->Type() == PCB_LINE_T  &&  masque_layer[item->GetLayer()] )
                {
                    itemPicker.SetItem( item );
                    pickersList.PushItem( itemPicker );
                    item->ViewRelease();
                    item->UnLink();
                }
            }
        }

        if( m_DelTexts->GetValue() )
        {
            LSET del_text_layers = layers_filter;

            for( item = pcb->m_Drawings; item; item = nextitem )
            {
                nextitem = item->Next();

                if( item->Type() == PCB_TEXT_T  &&  del_text_layers[item->GetLayer()] )
                {
                    itemPicker.SetItem( item );
                    pickersList.PushItem( itemPicker );
                    item->ViewRelease();
                    item->UnLink();
                }
            }
        }

        if( m_DelModules->GetValue() )
        {
            for( item = pcb->m_Modules; item; item = nextitem )
            {
                nextitem = item->Next();

                if( layers_filter[item->GetLayer()] &&
                    ( ( m_ModuleFilterNormal->GetValue() && !item->IsLocked() ) ||
                      ( m_ModuleFilterLocked->GetValue() && item->IsLocked() ) ) )
                {
                    itemPicker.SetItem( item );
                    pickersList.PushItem( itemPicker );
                    static_cast<MODULE*>( item )->RunOnChildren(
                            boost::bind( &KIGFX::VIEW_ITEM::ViewRelease, _1 ) );
                    ratsnest->Remove( item );
                    item->ViewRelease();
                    item->UnLink();
                    gen_rastnest = true;
                }
            }
        }

        if( m_DelTracks->GetValue() )
        {
            STATUS_FLAGS track_mask_filter = 0;

            if( !m_TrackFilterLocked->GetValue() )
                track_mask_filter |= TRACK_LOCKED;

            if( !m_TrackFilterAR->GetValue() )
                track_mask_filter |= TRACK_AR;

            TRACK* nexttrack;

            for( TRACK *track = pcb->m_Track; track; track = nexttrack )
            {
                nexttrack = track->Next();

                if( ( track->GetState( TRACK_LOCKED | TRACK_AR ) & track_mask_filter ) != 0 )
                    continue;

                if( ( track->GetState( TRACK_LOCKED | TRACK_AR ) == 0 ) &&
                    !m_TrackFilterNormal->GetValue() )
                    continue;

                if( ( track->Type() == PCB_VIA_T ) && !m_TrackFilterVias->GetValue() )
                    continue;

                if( ( track->GetLayerSet() & layers_filter ) == 0 )
                    continue;

                itemPicker.SetItem( track );
                pickersList.PushItem( itemPicker );
                track->ViewRelease();
                ratsnest->Remove( track );
                track->UnLink();
                gen_rastnest = true;
            }
        }

        if( pickersList.GetCount() )
            m_Parent->SaveCopyInUndoList( pickersList, UR_DELETED );

        if( m_DelMarkers->GetValue() )
            pcb->DeleteMARKERs();

        if( gen_rastnest )
            m_Parent->Compile_Ratsnest( NULL, true );

        if( m_Parent->IsGalCanvasActive() )
            pcb->GetRatsnest()->Recalculate();

    }

    m_Parent->GetCanvas()->Refresh();
    m_Parent->OnModify();

    EndModal( 1 );
}
示例#10
0
static void calcule_connexite_1_net(TRACK* pt_start_conn,TRACK* pt_end_conn)
/***************************************************************************/
/* calcule la connexite d'un net constitue de segments de piste consecutifs.
	Entree:
		pt_start_conn = adresse du 1er segment ( debut du net )
		pt_end_conn = adr de fin (dernier segment)
	Les connexions relatives aux pads doivent etre deja calculees, car elles
	ne sont pas ici recalculees ( pour des raisons de temps de calcul, et
	du fait que lors des modif de pistes, les pads ne sont pas touches
*/
{
TRACK * Track;

	/*  Les pointeurs .start et .end sont mis a jour, si la
		 connexion est du type segment a segment.
		la connexion sur pads est supposee etre deja calculee */

	/* Raz des pointeurs sur pistes */
	for( Track = pt_start_conn; Track != NULL; Track = (TRACK*) Track->Pnext)
		{
		Track->m_Sous_Netcode = 0;

		if( Track->GetState(BEGIN_ONPAD) == 0 ) Track->start = NULL;
		if( Track->GetState(END_ONPAD) == 0 ) Track->end = NULL;

		if (Track == pt_end_conn) break;
		}

	/* calcul des connexions */
	for( Track = pt_start_conn; Track != NULL; Track = (TRACK*) Track->Pnext)
		{
		if(Track->m_StructType == TYPEVIA)
			{
			TRACK* pt_segm;
			int layermask = Track->ReturnMaskLayer();
			for( pt_segm = pt_start_conn; pt_segm != NULL; pt_segm = (TRACK*) pt_segm->Pnext)
				{
				int curlayermask = pt_segm->ReturnMaskLayer();
				if( (pt_segm->m_Start.x == Track->m_Start.x) &&
					(pt_segm->m_Start.y == Track->m_Start.y) && ( layermask & curlayermask ) )
					{
					pt_segm->start = Track;
					}
				if( (pt_segm->m_End.x == Track->m_Start.x) &&
					(pt_segm->m_End.y == Track->m_Start.y) && (layermask & curlayermask) )
					{
					pt_segm->end = Track;
					}
				if( pt_segm == pt_end_conn ) break;
				}
			}

		if( Track->start == NULL )
			{
			Track->start = Locate_Piste_Connectee(Track,
								Track,pt_end_conn,START);
			}

		if( Track->end == NULL )
			{
			Track->end = Locate_Piste_Connectee(Track,
								Track,pt_end_conn,END);
			}
		if (Track == pt_end_conn) break;
		}

	/* Generation des sous equipots du net */
	propage_equipot(pt_start_conn,pt_end_conn);

}