wxString TRACK::GetSelectMenuText() const
{
    wxString text;
    wxString netname;
    NETINFO_ITEM* net;
    BOARD* board = GetBoard();

    // deleting tracks requires all the information we can get to
    // disambiguate all the choices under the cursor!
    if( board )
    {
        net = GetNet();

        if( net )
            netname = net->GetNetname();
        else
            netname = _("Not found");
    }
    else
    {
        wxFAIL_MSG( wxT( "TRACK::GetSelectMenuText: BOARD is NULL" ) );
        netname = wxT( "???" );
    }

    text.Printf( _("Track %s, net [%s] (%d) on layer %s, length: %s" ),
                 GetChars( ShowWidth() ), GetChars( netname ),
                 GetNetCode(), GetChars( GetLayerName() ),
                 GetChars( ::LengthDoubleToString( GetLength() ) ) );

    return text;
}
Exemple #2
0
PNS_PCBNEW_CLEARANCE_RESOLVER::PNS_PCBNEW_CLEARANCE_RESOLVER( PNS_ROUTER* aRouter ) :
    m_router( aRouter )
{
    BOARD* brd = m_router->GetBoard();
    m_clearanceCache.resize( brd->GetNetCount() );
    m_useDpGap = false;

    for( unsigned int i = 0; i < brd->GetNetCount(); i++ )
    {
        NETINFO_ITEM* ni = brd->FindNet( i );
        if( ni == NULL )
            continue;

        CLEARANCE_ENT ent;
        ent.coupledNet = m_router->GetWorld()->PairedNet( i );

        wxString netClassName = ni->GetClassName();
        NETCLASSPTR nc = brd->GetDesignSettings().m_NetClasses.Find( netClassName );

        int clearance = nc->GetClearance();
        ent.clearance = clearance;
        m_clearanceCache[i] = ent;

        TRACE( 1, "Add net %d netclass %s clearance %d", i % netClassName.mb_str() %
            clearance );
    }

    m_overrideEnabled = false;
    m_defaultClearance = Millimeter2iu( 0.254 );    // aBoard->m_NetClasses.Find ("Default clearance")->GetClearance();
    m_overrideNetA = 0;
    m_overrideNetB = 0;
    m_overrideClearance = 0;
}
void NETINFO_LIST::AppendNet( NETINFO_ITEM* aNewElement )
{
    // if there is a net with such name then just assign the correct number
    NETINFO_ITEM* sameName = GetNetItem( aNewElement->GetNetname() );

    if( sameName != NULL )
    {
        aNewElement->m_NetCode = sameName->GetNet();

        return;
    }
    // be sure that net codes are consecutive
    // negative net code means that it has to be auto assigned
    else if( ( aNewElement->m_NetCode != (int) m_netCodes.size() ) || ( aNewElement->m_NetCode < 0 ) )
    {
        aNewElement->m_NetCode = getFreeNetCode();
    }

    // net names & codes are supposed to be unique
    assert( GetNetItem( aNewElement->GetNetname() ) == NULL );
    assert( GetNetItem( aNewElement->GetNet() ) == NULL );

    // add an entry for fast look up by a net name using a map
    m_netNames.insert( std::make_pair( aNewElement->GetNetname(), aNewElement ) );
    m_netCodes.insert( std::make_pair( aNewElement->GetNet(), aNewElement ) );
}
void WIDGET_NET_SELECTOR::SetBoard( BOARD* aBoard )
{
    auto& netinfo = aBoard->GetNetInfo();

    for( unsigned i = 1; i < netinfo.GetNetCount(); i++ )
    {
        NETINFO_ITEM* ni = netinfo.GetNetItem( i );
        NET           net;
        net.m_Name = ni->GetNetname();
        net.m_Code = i;
        m_nets.push_back( net );
    }

    std::sort( m_nets.begin(), m_nets.end() );

    // Add the list of selectable nets to the wxComboBox.
    // Using a wxArrayString is much faster than adding each name separately
    wxArrayString netnames;

    netnames.Add( wxT( "<no net>" ) );    // Always on top of the list

    for( auto& net : m_nets )
    {
        net.m_Pos = netnames.Add( net.m_Name );
    }

    Append( netnames );
}
void TRACK::GetMsgPanelInfoBase_Common( std::vector< MSG_PANEL_ITEM >& aList )
{
    wxString msg;

    // Display Net Name
    if( GetBoard() )
    {
        NETINFO_ITEM* net = GetNet();

        if( net )
            msg = net->GetNetname();
        else
            msg = wxT( "<noname>" );

        aList.push_back( MSG_PANEL_ITEM( _( "NetName" ), msg, RED ) );

        // Display net code : (useful in test or debug)
        msg.Printf( wxT( "%d.%d" ), GetNetCode(), GetSubNet() );
        aList.push_back( MSG_PANEL_ITEM( _( "NetCode" ), msg, RED ) );
    }

#if defined(DEBUG)

    // Display the flags
    msg.Printf( wxT( "0x%08X" ), m_Flags );
    aList.push_back( MSG_PANEL_ITEM( wxT( "Flags" ), msg, BLUE ) );

#if 0
    // Display start and end pointers:
    msg.Printf( wxT( "%p" ), start );
    aList.push_back( MSG_PANEL_ITEM( wxT( "start ptr" ), msg, BLUE ) );
    msg.Printf( wxT( "%p" ), end );
    aList.push_back( MSG_PANEL_ITEM( wxT( "end ptr" ), msg, BLUE ) );
    // Display this ptr
    msg.Printf( wxT( "%p" ), this );
    aList.push_back( MSG_PANEL_ITEM( wxT( "this" ), msg, BLUE ) );
#endif

#if 0
    // Display start and end positions:
    msg.Printf( wxT( "%d %d" ), m_Start.x, m_Start.y );
    aList.push_back( MSG_PANEL_ITEM( wxT( "Start pos" ), msg, BLUE ) );
    msg.Printf( wxT( "%d %d" ), m_End.x, m_End.y );
    aList.push_back( MSG_PANEL_ITEM( wxT( "End pos" ), msg, BLUE ) );
#endif

#endif  // defined(DEBUG)

    // Display the State member
    msg = wxT( ". . " );

    if( GetState( TRACK_LOCKED ) )
        msg[0] = 'F';

    if( GetState( TRACK_AR ) )
        msg[2] = 'A';

    aList.push_back( MSG_PANEL_ITEM( _( "Status" ), msg, MAGENTA ) );
}
Exemple #6
0
PNS_PCBNEW_RULE_RESOLVER::PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER* aRouter ) :
    m_router( aRouter ),
    m_board( aBoard )
{
    PNS::NODE* world = m_router->GetWorld();

    PNS::TOPOLOGY topo( world );
    m_netClearanceCache.resize( m_board->GetNetCount() );

    // Build clearance cache for net classes
    for( unsigned int i = 0; i < m_board->GetNetCount(); i++ )
    {
        NETINFO_ITEM* ni = m_board->FindNet( i );

        if( ni == NULL )
            continue;

        CLEARANCE_ENT ent;
        ent.coupledNet = DpCoupledNet( i );

        wxString netClassName = ni->GetClassName();
        NETCLASSPTR nc = m_board->GetDesignSettings().m_NetClasses.Find( netClassName );

        int clearance = nc->GetClearance();
        ent.clearance = clearance;
        m_netClearanceCache[i] = ent;

        wxLogTrace( "PNS", "Add net %u netclass %s clearance %d", i, netClassName.mb_str(), clearance );
    }

    // Build clearance cache for pads
    for( MODULE* mod = m_board->m_Modules; mod ; mod = mod->Next() )
    {
        auto moduleClearance = mod->GetLocalClearance();

        for( D_PAD* pad = mod->PadsList(); pad; pad = pad->Next() )
        {
            int padClearance = pad->GetLocalClearance();

            if( padClearance > 0 )
                m_localClearanceCache[ pad ] = padClearance;

            else if( moduleClearance > 0 )
                m_localClearanceCache[ pad ] = moduleClearance;
        }
    }

    //printf("DefaultCL : %d\n",  m_board->GetDesignSettings().m_NetClasses.Find ("Default clearance")->GetClearance());

    m_overrideEnabled = false;
    m_defaultClearance = Millimeter2iu( 0.254 );    // m_board->m_NetClasses.Find ("Default clearance")->GetClearance();
    m_overrideNetA = 0;
    m_overrideNetB = 0;
    m_overrideClearance = 0;
    m_useDpGap = false;
}
Exemple #7
0
bool ZONE_CONTAINER::SetNetNameFromNetCode( void )
{
    NETINFO_ITEM* net;

    if( m_Parent && ( net = ( (BOARD*) m_Parent )->FindNet( GetNet() ) ) )
    {
        m_Netname = net->GetNetname();
        return true;
    }

    return false;
}
wxString ZONE_CONTAINER::GetSelectMenuText() const
{
    wxString text;
    NETINFO_ITEM* net;
    BOARD* board = GetBoard();

    int ncont = m_Poly->GetContour( m_CornerSelection );

    if( ncont )
        text << wxT( " " ) << _( "(Cutout)" );

    if( GetIsKeepout() )
        text << wxT( " " ) << _( "(Keepout)" );

    text << wxString::Format( wxT( " (%08lX)" ), m_TimeStamp );

    // Display net name for copper zones
    if( !GetIsKeepout() )
    {
        if( GetNetCode() >= 0 )
        {
            if( board )
            {
                net = GetNet();

                if( net )
                {
                    text << wxT( " [" ) << net->GetNetname() << wxT( "]" );
                }
            }
            else
            {
                text << _( "** NO BOARD DEFINED **" );
            }
        }
        else
        {   // A netcode < 0 is an error:
            // Netname not found or area not initialised
            text << wxT( " [" ) << GetNetname() << wxT( "]" );
            text << wxT( " <" ) << _( "Not Found" ) << wxT( ">" );
        }
    }

    wxString msg;
    msg.Printf( _( "Zone Outline %s on %s" ), GetChars( text ),
                 GetChars( GetLayerName() ) );

    return msg;
}
/* Emit the netlist (which is actually the thing for which GenCAD is used these
 * days!); tracks are handled later */
static void CreateSignalsSection( FILE* aFile, BOARD* aPcb )
{
    wxString      msg;
    NETINFO_ITEM* net;
    D_PAD*        pad;
    MODULE*       module;
    int           NbNoConn = 1;

    fputs( "$SIGNALS\n", aFile );

    for( unsigned ii = 0; ii < aPcb->GetNetCount(); ii++ )
    {
        net = aPcb->FindNet( ii );

        if( net->GetNetname() == wxEmptyString ) // dummy netlist (no connection)
        {
            wxString msg; msg << wxT( "NoConnection" ) << NbNoConn++;
        }

        if( net->GetNet() <= 0 )  // dummy netlist (no connection)
            continue;

        msg = wxT( "SIGNAL " ) + net->GetNetname();

        fputs( TO_UTF8( msg ), aFile );
        fputs( "\n", aFile );

        for( module = aPcb->m_Modules; module; module = module->Next() )
        {
            for( pad = module->Pads(); pad; pad = pad->Next() )
            {
                wxString padname;

                if( pad->GetNetCode() != net->GetNet() )
                    continue;

                pad->StringPadName( padname );
                msg.Printf( wxT( "NODE %s %s" ),
                            GetChars( module->GetReference() ),
                            GetChars( padname ) );

                fputs( TO_UTF8( msg ), aFile );
                fputs( "\n", aFile );
            }
        }
    }

    fputs( "$ENDSIGNALS\n\n", aFile );
}
    PCBNEW_CLEARANCE_FUNC( BOARD* aBoard )
    {
        m_clearanceCache.resize( aBoard->GetNetCount() );

        for( unsigned int i = 0; i < aBoard->GetNetCount(); i++ )
        {
            NETINFO_ITEM* ni = aBoard->FindNet( i );
            wxString netClassName = ni->GetClassName();
            NETCLASS* nc = aBoard->m_NetClasses.Find( netClassName );
            int clearance = nc->GetClearance();
            m_clearanceCache[i] = clearance;
            TRACE( 1, "Add net %d netclass %s clearance %d", i % netClassName.mb_str() %
                    clearance );
        }

        m_defaultClearance = 254000;    // aBoard->m_NetClasses.Find ("Default clearance")->GetClearance();
    }
Exemple #11
0
int PNS_PCBNEW_RULE_RESOLVER::DpCoupledNet( int aNet )
{
    wxString refName = m_board->FindNet( aNet )->GetNetname();
    wxString dummy, coupledNetName;

    if( matchDpSuffix( refName, coupledNetName, dummy ) )
    {
        NETINFO_ITEM* net = m_board->FindNet( coupledNetName );

        if( !net )
            return -1;

        return net->GetNet();
    }

    return -1;
}
Exemple #12
0
int PCBNEW_PAIRING_RESOLVER::PairedNet(int aNet) const
{
    wxString refName = m_board->FindNet( aNet )->GetNetname();
    wxString dummy, coupledNetName;

    if( MatchDpSuffix( refName, coupledNetName, dummy ) )
    {
        NETINFO_ITEM* net = m_board->FindNet( coupledNetName );

        if( !net )
            return -1;

        return net->GetNet();

    }

    return -1;
}
/* Extract the D356 record from the vias */
static void build_via_testpoints( BOARD *aPcb,
    std::vector <D356_RECORD>& aRecords )
{
    wxPoint origin = aPcb->GetAuxOrigin();

    // Enumerate all the track segments and keep the vias
    for( TRACK *track = aPcb->m_Track; track; track = track->Next() )
    {
        if( track->Type() == PCB_VIA_T )
        {
            VIA *via = (VIA*) track;
            NETINFO_ITEM *net = track->GetNet();

            D356_RECORD rk;
            rk.smd = false;
            rk.hole = true;
            if( net )
                rk.netname = net->GetNetname();
            else
                rk.netname = wxEmptyString;
            rk.refdes = wxT("VIA");
            rk.pin = wxT("");
            rk.midpoint = true; // Vias are always midpoints
            rk.drill = via->GetDrillValue();
            rk.mechanical = false;

            LAYER_ID top_layer, bottom_layer;

            via->LayerPair( &top_layer, &bottom_layer );

            rk.access = via_access_code( aPcb, top_layer, bottom_layer );
            rk.x_location = via->GetPosition().x - origin.x;
            rk.y_location = origin.y - via->GetPosition().y;
            rk.x_size = via->GetWidth();
            rk.y_size = 0; // Round so height = 0
            rk.rotation = 0;
            rk.soldermask = 3; // XXX always tented?

            aRecords.push_back( rk );
        }
    }
}
int PNS_TOPOLOGY::DpCoupledNet( int aNet )
{
    BOARD* brd = PNS_ROUTER::GetInstance()->GetBoard();

    wxString refName = brd->FindNet( aNet )->GetNetname();
    wxString dummy, coupledNetName;

    if( MatchDpSuffix( refName, coupledNetName, dummy ) )
    {
        NETINFO_ITEM* net = brd->FindNet( coupledNetName );

        if( !net )
            return -1;

        return net->GetNet();

    }

    return -1;
}
void ROUTER_TOOL::getNetclassDimensions( int aNetCode, int& aWidth,
                                         int& aViaDiameter, int& aViaDrill )
{
    BOARD_DESIGN_SETTINGS &bds = m_board->GetDesignSettings();

    NETCLASSPTR netClass;
    NETINFO_ITEM* ni = m_board->FindNet( aNetCode );

    if( ni )
    {
        wxString netClassName = ni->GetClassName();
        netClass = bds.m_NetClasses.Find( netClassName );
    }

    if( !netClass )
        netClass = bds.GetDefault();

    aWidth = netClass->GetTrackWidth();
    aViaDiameter = netClass->GetViaDiameter();
    aViaDrill = netClass->GetViaDrill();
}
Exemple #16
0
void ZONE_CONTAINER::SetNet( int aNetCode )
{
    BOARD_CONNECTED_ITEM::SetNet( aNetCode );

    if( aNetCode < 0 )
        return;

    BOARD* board = GetBoard();

    if( board )
    {
        NETINFO_ITEM* net = board->FindNet( aNetCode );

        if( net )
            m_Netname = net->GetNetname();
        else
            m_Netname.Empty();
    }
    else
    {
        m_Netname.Empty();
    }
}
Exemple #17
0
bool PNS_PCBNEW_RULE_RESOLVER::DpNetPair( PNS::ITEM* aItem, int& aNetP, int& aNetN )
{
    if( !aItem || !aItem->Parent() || !aItem->Parent()->GetNet() )
        return false;

    wxString netNameP = aItem->Parent()->GetNet()->GetNetname();
    wxString netNameN, netNameCoupled, netNameBase;

    int r = matchDpSuffix( netNameP, netNameCoupled, netNameBase );

    if( r == 0 )
        return false;
    else if( r == 1 )
    {
        netNameN = netNameCoupled;
    }
    else
    {
        netNameN = netNameP;
        netNameP = netNameCoupled;
    }

//    wxLogTrace( "PNS","p %s n %s base %s\n", (const char *)netNameP.c_str(), (const char *)netNameN.c_str(), (const char *)netNameBase.c_str() );

    NETINFO_ITEM* netInfoP = m_board->FindNet( netNameP );
    NETINFO_ITEM* netInfoN = m_board->FindNet( netNameN );

    //wxLogTrace( "PNS","ip %p in %p\n", netInfoP, netInfoN);

    if( !netInfoP || !netInfoN )
        return false;

    aNetP = netInfoP->GetNet();
    aNetN = netInfoN->GetNet();

    return true;
}
void TRACK::DrawShortNetname( EDA_DRAW_PANEL* panel,
        wxDC* aDC, GR_DRAWMODE aDrawMode, EDA_COLOR_T aBgColor )
{
    /* we must filter tracks, to avoid a lot of texts.
     *  - only tracks with a length > 10 * thickness are eligible
     * and, of course, if we are not printing the board
     */
    if( DisplayOpt.DisplayNetNamesMode == 0 || DisplayOpt.DisplayNetNamesMode == 1 )
        return;

    #define THRESHOLD 10

    int len = KiROUND( GetLineLength( m_Start, m_End ) );

    if( len < THRESHOLD * m_Width )
        return;

    // no room to display a text inside track
    if( aDC->LogicalToDeviceXRel( m_Width ) < MIN_TEXT_SIZE )
        return;

    if( GetNetCode() == NETINFO_LIST::UNCONNECTED )
        return;

    NETINFO_ITEM* net = GetNet();

    if( net == NULL )
        return;

    int textlen = net->GetShortNetname().Len();

    if( textlen > 0 )
    {
        // calculate a good size for the text
        int     tsize = std::min( m_Width, len / textlen );
        int     dx = m_End.x - m_Start.x ;
        int     dy = m_End.y - m_Start.y ;
        wxPoint tpos  = m_Start + m_End;
        tpos.x /= 2;
        tpos.y /= 2;

        // Calculate angle: if the track segment is vertical, angle = 90 degrees
        // If horizontal 0 degrees, otherwise compute it
        double angle;        // angle is in 0.1 degree

        if( dy == 0 )        // Horizontal segment
        {
            angle = 0;
        }
        else
        {
            if( dx == 0 )    // Vertical segment
            {
                angle = 900;
            }
            else
            {
                /* atan2 is *not* the solution here, since it can give upside
                   down text. We want to work only in the first and fourth quadrant */
                angle = RAD2DECIDEG( -atan( double( dy ) / double( dx ) ) );
            }
        }

        LAYER_NUM curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
        if( ( aDC->LogicalToDeviceXRel( tsize ) >= MIN_TEXT_SIZE )
         && ( !(!IsOnLayer( curr_layer )&& DisplayOpt.ContrastModeDisplay) ) )
        {
            if( (aDrawMode & GR_XOR) == 0 )
                GRSetDrawMode( aDC, GR_COPY );

            tsize = (tsize * 7) / 10;       // small reduction to give a better look
            EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL;
            DrawGraphicHaloText( clipbox, aDC, tpos,
                                 aBgColor, BLACK, WHITE, net->GetShortNetname(), angle,
                                 wxSize( tsize, tsize ),
                                 GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER,
                                 tsize / 7,
                                 false, false );
        }
    }
}
Exemple #19
0
void PCB_PAD::AddToModule( MODULE* aModule, int aRotation, bool aEncapsulatedPad )
{
    PCB_PAD_SHAPE*  padShape;
    wxString        padShapeName = wxT( "Ellipse" );
    PAD_ATTR_T      padType;
    int             i;
    int             width = 0;
    int             height = 0;

    D_PAD* pad = new D_PAD( aModule );

    aModule->Pads().PushBack( pad );

    if( !m_isHolePlated && m_hole )
    {
        // mechanical hole
        pad->SetShape( PAD_CIRCLE );
        pad->SetAttribute( PAD_HOLE_NOT_PLATED );

        pad->SetDrillShape( PAD_DRILL_CIRCLE );
        pad->SetDrillSize( wxSize( m_hole, m_hole ) );
        pad->SetSize( wxSize( m_hole, m_hole ) );

        pad->SetLayerSet( LSET::AllCuMask() | LSET( 2, B_Mask, F_Mask ) );
    }
    else
    {
        ( m_hole ) ? padType = PAD_STANDARD : padType = PAD_SMD;

        // form layer mask
        for( i = 0; i < (int) m_shapes.GetCount(); i++ )
        {
            padShape = m_shapes[i];

            if( padShape->m_width > 0 && padShape->m_height > 0 )
            {
                if( padShape->m_KiCadLayer == F_Cu ||
                    padShape->m_KiCadLayer == B_Cu )
                {
                    padShapeName = padShape->m_shape;
                    width = padShape->m_width;
                    height = padShape->m_height;

                    // assume this is SMD pad
                    if( padShape->m_KiCadLayer == F_Cu )
                        pad->SetLayerSet( LSET( 3, F_Cu, F_Paste, F_Mask ) );
                    else
                        pad->SetLayerSet( LSET( 3, B_Cu, B_Paste, B_Mask ) );
                    break;
                }
            }
        }

        if( padType == PAD_STANDARD )
            // actually this is a thru-hole pad
            pad->SetLayerSet( LSET::AllCuMask() | LSET( 2, B_Mask, F_Mask ) );

        if( width == 0 || height == 0 )
            THROW_IO_ERROR( wxT( "pad with zero size" ) );

        pad->SetPadName( m_name.text );

        if( padShapeName == wxT( "Oval" )
            || padShapeName == wxT( "Ellipse" )
            || padShapeName == wxT( "MtHole" ) )
        {
            if( width != height )
                pad->SetShape( PAD_OVAL );
            else
                pad->SetShape( PAD_CIRCLE );
        }
        else if( padShapeName == wxT( "Rect" )
                 || padShapeName == wxT( "RndRect" ) )
            pad->SetShape( PAD_RECT );
        else if( padShapeName == wxT( "Polygon" ) )
            pad->SetShape( PAD_RECT ); // approximation

        pad->SetSize( wxSize( width, height ) );
        pad->SetDelta( wxSize( 0, 0 ) );
        pad->SetOrientation( m_rotation + aRotation );

        pad->SetDrillShape( PAD_DRILL_CIRCLE );
        pad->SetOffset( wxPoint( 0, 0 ) );
        pad->SetDrillSize( wxSize( m_hole, m_hole ) );

        pad->SetAttribute( padType );

        // Set the proper net code
        NETINFO_ITEM* netinfo = m_board->FindNet( m_net );
        if( netinfo == NULL )   // I believe this should not happen, but just in case
        {
            // It is a new net
            netinfo = new NETINFO_ITEM( m_board, m_net );
            m_board->AppendNet( netinfo );
        }

        pad->SetNetCode( netinfo->GetNet() );
    }

    if( !aEncapsulatedPad )
    {
        // pad's "Position" is not relative to the module's,
        // whereas Pos0 is relative to the module's but is the unrotated coordinate.
        wxPoint padpos( m_positionX, m_positionY );
        pad->SetPos0( padpos );
        RotatePoint( &padpos, aModule->GetOrientation() );
        pad->SetPosition( padpos + aModule->GetPosition() );
    }
}
void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) throw( IO_ERROR )
{
    sessionBoard = aBoard;      // not owned here

    if( !session )
        THROW_IO_ERROR( _("Session file is missing the \"session\" section") );

    /* Dick 16-Jan-2012: session need not have a placement section.
    if( !session->placement )
        THROW_IO_ERROR( _("Session file is missing the \"placement\" section") );
    */

    if( !session->route )
        THROW_IO_ERROR( _("Session file is missing the \"routes\" section") );

    if( !session->route->library )
        THROW_IO_ERROR( _("Session file is missing the \"library_out\" section") );

    // delete all the old tracks and vias
    aBoard->m_Track.DeleteAll();

    aBoard->DeleteMARKERs();

    buildLayerMaps( aBoard );

    if( session->placement )
    {
        // Walk the PLACEMENT object's COMPONENTs list, and for each PLACE within
        // each COMPONENT, reposition and re-orient each component and put on
        // correct side of the board.
        COMPONENTS& components = session->placement->components;
        for( COMPONENTS::iterator comp=components.begin();  comp!=components.end();  ++comp )
        {
            PLACES& places = comp->places;
            for( unsigned i=0; i<places.size();  ++i )
            {
                PLACE* place = &places[i];  // '&' even though places[] holds a pointer!

                wxString reference = FROM_UTF8( place->component_id.c_str() );
                MODULE* module = aBoard->FindModuleByReference( reference );
                if( !module )
                {
                    THROW_IO_ERROR( wxString::Format( _("Session file has 'reference' to non-existent component \"%s\""),
                                                      GetChars( reference ) ) );
                }

                if( !place->hasVertex )
                    continue;

                UNIT_RES* resolution = place->GetUnits();
                wxASSERT( resolution );

                wxPoint newPos = mapPt( place->vertex, resolution );
                module->SetPosition( newPos );

                if( place->side == T_front )
                {
                    // convert from degrees to tenths of degrees used in KiCad.
                    int orientation = KiROUND( place->rotation * 10.0 );

                    if( module->GetLayer() != F_Cu )
                    {
                        // module is on copper layer (back)
                        module->Flip( module->GetPosition() );
                    }

                    module->SetOrientation( orientation );
                }
                else if( place->side == T_back )
                {
                    int orientation = KiROUND( (place->rotation + 180.0) * 10.0 );

                    if( module->GetLayer() != B_Cu )
                    {
                        // module is on component layer (front)
                        module->Flip( module->GetPosition() );
                    }

                    module->SetOrientation( orientation );
                }
                else
                {
                    // as I write this, the PARSER *is* catching this, so we should never see below:
                    wxFAIL_MSG( wxT("DSN::PARSER did not catch an illegal side := 'back|front'") );
                }
            }
        }
    }

    routeResolution = session->route->GetUnits();

    // Walk the NET_OUTs and create tracks and vias anew.
    NET_OUTS& net_outs = session->route->net_outs;
    for( NET_OUTS::iterator net = net_outs.begin(); net!=net_outs.end(); ++net )
    {
        int         netCode = 0;

        // page 143 of spec says wire's net_id is optional
        if( net->net_id.size() )
        {
            wxString netName = FROM_UTF8( net->net_id.c_str() );
            NETINFO_ITEM* netinfo = aBoard->FindNet( netName );

            if( netinfo )
                netCode = netinfo->GetNet();
            else  // else netCode remains 0
            {
                // int breakhere = 1;
            }
        }

        WIRES& wires = net->wires;
        for( unsigned i = 0; i<wires.size(); ++i )
        {
            WIRE*   wire  = &wires[i];
            DSN_T   shape = wire->shape->Type();

            if( shape != T_path )
            {
                /*  shape == T_polygon is expected from freerouter if you have
                    a zone on a non "power" type layer, i.e. a T_signal layer
                    and the design does a round trip back in as session here.
                    We kept our own zones in the BOARD, so ignore this so called
                    'wire'.

                wxString netId = FROM_UTF8( wire->net_id.c_str() );
                THROW_IO_ERROR( wxString::Format( _("Unsupported wire shape: \"%s\" for net: \"%s\""),
                                                    DLEX::GetTokenString(shape).GetData(),
                                                    netId.GetData()
                    ) );
                */
            }
            else
            {
                PATH*   path = (PATH*) wire->shape;
                for( unsigned pt=0;  pt<path->points.size()-1;  ++pt )
                {
                    /* a debugging aid, may come in handy
                    if( path->points[pt].x == 547800
                    &&  path->points[pt].y == -380250 )
                    {
                        int breakhere = 1;
                    }
                    */

                    TRACK* track = makeTRACK( path, pt, netCode );
                    aBoard->Add( track );
                }
            }
        }

        WIRE_VIAS& wire_vias = net->wire_vias;
        LIBRARY& library = *session->route->library;
        for( unsigned i=0;  i<wire_vias.size();  ++i )
        {
            int         netCode = 0;

            // page 144 of spec says wire_via's net_id is optional
            if( net->net_id.size() )
            {
                wxString netName = FROM_UTF8( net->net_id.c_str() );

                NETINFO_ITEM* net = aBoard->FindNet( netName );
                if( net )
                    netCode = net->GetNet();

                // else netCode remains 0
            }

            WIRE_VIA* wire_via = &wire_vias[i];

            // example: (via Via_15:8_mil 149000 -71000 )

            PADSTACK* padstack = library.FindPADSTACK( wire_via->GetPadstackId() );
            if( !padstack )
            {
                // Dick  Feb 29, 2008:
                // Freerouter has a bug where it will not round trip all vias.
                // Vias which have a (use_via) element will be round tripped.
                // Vias which do not, don't come back in in the session library,
                // even though they may be actually used in the pre-routed,
                // protected wire_vias. So until that is fixed, create the
                // padstack from its name as a work around.


                // Could use a STRING_FORMATTER here and convert the entire
                // wire_via to text and put that text into the exception.
                wxString psid( FROM_UTF8( wire_via->GetPadstackId().c_str() ) );

                THROW_IO_ERROR( wxString::Format( _("A wire_via references a missing padstack \"%s\""),
                                                  GetChars( psid ) ) );
            }

            NETCLASSPTR netclass = aBoard->GetDesignSettings().m_NetClasses.GetDefault();

            int via_drill_default = netclass->GetViaDrill();

            for( unsigned v=0;  v<wire_via->vertexes.size();  ++v )
            {
                ::VIA* via = makeVIA( padstack, wire_via->vertexes[v], netCode, via_drill_default );
                aBoard->Add( via );
            }
        }
    }
}
/**
 * Function SetTrackSegmentWidth
 *  Modify one track segment width or one via diameter and drill (using DRC control).
 *  Basic routine used by other routines when editing tracks or vias
 * @param aTrackItem = the track segment or via to modify
 * @param aItemsListPicker = the list picker to use for an undo command (can be NULL)
 * @param aUseNetclassValue = true to use NetClass value, false to use BOARD::m_designSettings value
 * @return  true if done, false if no not change (because DRC error)
 */
bool PCB_EDIT_FRAME::SetTrackSegmentWidth( TRACK*             aTrackItem,
                                           PICKED_ITEMS_LIST* aItemsListPicker,
                                           bool               aUseNetclassValue )
{
    int           initial_width, new_width;
    int           initial_drill = -1,new_drill = -1;
    bool          change_ok = false;
    NETINFO_ITEM* net = NULL;

    if( aUseNetclassValue )
        net = aTrackItem->GetNet();

    initial_width = aTrackItem->GetWidth();

    if( net )
        new_width = net->GetTrackWidth();
    else
        new_width = GetDesignSettings().GetCurrentTrackWidth();

    if( aTrackItem->Type() == PCB_VIA_T )
    {
        const VIA *via = static_cast<const VIA *>( aTrackItem );

        if( !via->IsDrillDefault() )
            initial_drill = via->GetDrillValue();

        if( net )
        {
            new_width = net->GetViaSize();
        }
        else
        {
            new_width = GetDesignSettings().GetCurrentViaSize();
            new_drill = GetDesignSettings().GetCurrentViaDrill();
        }

        if( via->GetViaType() == VIA_MICROVIA )
        {
            if( net )
                new_width = net->GetMicroViaSize();
            else
                new_width = GetDesignSettings().GetCurrentMicroViaSize();
        }
    }

    aTrackItem->SetWidth( new_width );

    // make a DRC test because the new size is bigger than the old size
    if( initial_width < new_width )
    {
        int diagdrc = OK_DRC;

        if( g_Drc_On )
            diagdrc = m_drc->Drc( aTrackItem, GetBoard()->m_Track );

        if( diagdrc == OK_DRC )
            change_ok = true;
    }
    else if( initial_width > new_width )
    {
        change_ok = true;
    }
    else if( (aTrackItem->Type() == PCB_VIA_T) && (initial_drill != new_drill) )
    {
        // if new width == initial_width: do nothing, unless a via has its drill value changed
        change_ok = true;
    }

    if( change_ok )
    {
        OnModify();

        if( aItemsListPicker )
        {
            aTrackItem->SetWidth( initial_width );
            ITEM_PICKER picker( aTrackItem, UR_CHANGED );
            picker.SetLink( aTrackItem->Clone() );
            aItemsListPicker->PushItem( picker );
            aTrackItem->SetWidth( new_width );

            if( aTrackItem->Type() == PCB_VIA_T )
            {
                // Set new drill value. Note: currently microvias have only a default drill value
                VIA *via = static_cast<VIA *>( aTrackItem );
                if( new_drill > 0 )
                    via->SetDrill( new_drill );
                else
                    via->SetDrillDefault();
            }
        }
    }
    else
    {
        aTrackItem->SetWidth( initial_width );
    }

    return change_ok;
}
Exemple #22
0
/* Route all traces
 * :
 *  1 if OK
 * -1 if escape (stop being routed) request
 * -2 if default memory allocation
 */
int PCB_EDIT_FRAME::Solve( wxDC* DC, int aLayersCount )
{
    int           current_net_code;
    int           row_source, col_source, row_target, col_target;
    int           success, nbsucces = 0, nbunsucces = 0;
    NETINFO_ITEM* net;
    bool          stop = false;
    wxString      msg;
    int           routedCount = 0;      // routed ratsnest count
    bool          two_sides = aLayersCount == 2;

    m_canvas->SetAbortRequest( false );

    s_Clearance = GetBoard()->GetDesignSettings().GetDefault()->GetClearance();

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

    // go until no more work to do
    GetWork( &row_source, &col_source, &current_net_code,
             &row_target, &col_target, &pt_cur_ch ); // First net to route.

    for( ; row_source != ILLEGAL; GetWork( &row_source, &col_source,
                                           &current_net_code, &row_target,
                                           &col_target,
                                           &pt_cur_ch ) )
    {
        // Test to stop routing ( escape key pressed )
        wxYield();

        if( m_canvas->GetAbortRequest() )
        {
            if( IsOK( this, _( "Abort routing?" ) ) )
            {
                success = STOP_FROM_ESC;
                stop    = true;
                break;
            }
            else
            {
                m_canvas->SetAbortRequest( false );
            }
        }

        EraseMsgBox();

        routedCount++;
        net = GetBoard()->FindNet( current_net_code );

        if( net )
        {
            msg.Printf( wxT( "[%8.8s]" ), GetChars( net->GetNetname() ) );
            AppendMsgPanel( wxT( "Net route" ), msg, BROWN );
            msg.Printf( wxT( "%d / %d" ), routedCount, RoutingMatrix.m_RouteCount );
            AppendMsgPanel( wxT( "Activity" ), msg, BROWN );
        }

        segm_oX = GetBoard()->GetBoundingBox().GetX() + (RoutingMatrix.m_GridRouting * col_source);
        segm_oY = GetBoard()->GetBoundingBox().GetY() + (RoutingMatrix.m_GridRouting * row_source);
        segm_fX = GetBoard()->GetBoundingBox().GetX() + (RoutingMatrix.m_GridRouting * col_target);
        segm_fY = GetBoard()->GetBoundingBox().GetY() + (RoutingMatrix.m_GridRouting * row_target);

        // Draw segment.
        GRLine( m_canvas->GetClipBox(), DC,
                segm_oX, segm_oY, segm_fX, segm_fY,
                0, WHITE );
        pt_cur_ch->m_PadStart->Draw( m_canvas, DC, GR_OR | GR_HIGHLIGHT );
        pt_cur_ch->m_PadEnd->Draw( m_canvas, DC, GR_OR | GR_HIGHLIGHT );

        success = Autoroute_One_Track( this, DC,
                                       two_sides, row_source, col_source,
                                       row_target, col_target, pt_cur_ch );

        switch( success )
        {
        case NOSUCCESS:
            pt_cur_ch->m_Status |= CH_UNROUTABLE;
            nbunsucces++;
            break;

        case STOP_FROM_ESC:
            stop = true;
            break;

        case ERR_MEMORY:
            stop = true;
            break;

        default:
            nbsucces++;
            break;
        }

        msg.Printf( wxT( "%d" ), nbsucces );
        AppendMsgPanel( wxT( "OK" ), msg, GREEN );
        msg.Printf( wxT( "%d" ), nbunsucces );
        AppendMsgPanel( wxT( "Fail" ), msg, RED );
        msg.Printf( wxT( "  %d" ), GetBoard()->GetUnconnectedNetCount() );
        AppendMsgPanel( wxT( "Not Connected" ), msg, CYAN );

        // Delete routing from display.
        pt_cur_ch->m_PadStart->Draw( m_canvas, DC, GR_AND );
        pt_cur_ch->m_PadEnd->Draw( m_canvas, DC, GR_AND );

        if( stop )
            break;
    }

    SaveCopyInUndoList( s_ItemsListPicker, UR_UNSPECIFIED );
    s_ItemsListPicker.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items

    return SUCCESS;
}
Exemple #23
0
bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
{
    switch( (IO_MGR::PCB_FILE_T) aFileType )
    {
    case IO_MGR::EAGLE:
        if( OpenProjectFiles( std::vector<wxString>( 1, aFileName ), KICTL_EAGLE_BRD ) )
        {
            wxString projectpath = Kiway().Prj().GetProjectPath();
            wxFileName newfilename;

            newfilename.SetPath( Prj().GetProjectPath() );
            newfilename.SetName( Prj().GetProjectName() );
            newfilename.SetExt( KiCadPcbFileExtension );

            GetBoard()->SetFileName( newfilename.GetFullPath() );
            UpdateTitle();
            OnModify();

            // Extract a footprint library from the design and add it to the fp-lib-table
            wxString newLibPath;
            ArchiveModulesOnBoard( true, newfilename.GetName(), &newLibPath );

            if( newLibPath.Length() > 0 )
            {
                FP_LIB_TABLE* prjlibtable = Prj().PcbFootprintLibs();
                const wxString& project_env = PROJECT_VAR_NAME;
                wxString rel_path, env_path;

                wxGetEnv( project_env, &env_path );

                wxString result( newLibPath );
                rel_path =  result.Replace( env_path,
                                            wxString( "$(" + project_env + ")" ) ) ? result : "" ;

                if( !rel_path.IsEmpty() )
                    newLibPath = rel_path;

                FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( newfilename.GetName(),
                        newLibPath, wxT( "KiCad" ), wxEmptyString );
                prjlibtable->InsertRow( row );
            }

            if( !GetBoard()->GetFileName().IsEmpty() )
            {
                wxString tblName = Prj().FootprintLibTblName();

                try
                {
                    Prj().PcbFootprintLibs()->Save( tblName );
                }
                catch( const IO_ERROR& ioe )
                {
                    wxString msg = wxString::Format( _(
                                    "Error occurred saving project specific footprint library "
                                    "table:\n\n%s" ),
                            GetChars( ioe.What() ) );
                    wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
                }
            }


            // Update module LIB_IDs to point to the just imported Eagle library
            for( MODULE* module : GetBoard()->Modules() )
            {
                LIB_ID libId = module->GetFPID();

                if( libId.GetLibItemName().empty() )
                    continue;

                libId.SetLibNickname( newfilename.GetName() );
                module->SetFPID( libId );
            }


            // Store net names for all pads, to create net remap information
            std::unordered_map<D_PAD*, wxString> netMap;

            for( const auto& pad : GetBoard()->GetPads() )
            {
                NETINFO_ITEM* netinfo = pad->GetNet();

                if( netinfo->GetNet() > 0 && !netinfo->GetNetname().IsEmpty() )
                    netMap[pad] = netinfo->GetNetname();
            }

            // Two stage netlist update:
            // - first, assign valid timestamps to footprints (no reannotation)
            // - second, perform schematic annotation and update footprint references
            //   based on timestamps
            NETLIST netlist;
            FetchNetlistFromSchematic( netlist, NO_ANNOTATION );
            DoUpdatePCBFromNetlist( netlist, false );
            FetchNetlistFromSchematic( netlist, QUIET_ANNOTATION );
            DoUpdatePCBFromNetlist( netlist, true );

            std::unordered_map<wxString, wxString> netRemap;

            // Compare the old net names with the new net names and create a net map
            for( const auto& pad : GetBoard()->GetPads() )
            {
                auto it = netMap.find( pad );

                if( it == netMap.end() )
                    continue;

                NETINFO_ITEM* netinfo = pad->GetNet();

                // Net name has changed, create a remap entry
                if( netinfo->GetNet() > 0 && netMap[pad] != netinfo->GetNetname() )
                    netRemap[netMap[pad]] = netinfo->GetNetname();
            }

            if( !netRemap.empty() )
                fixEagleNets( netRemap );

            return true;
        }

        return false;

    default:
        return false;
    }

    return false;
}
bool PCB_EDIT_FRAME::Other_Layer_Route( TRACK* aTrack, wxDC* DC )
{
    unsigned    itmp;

    if( aTrack == NULL )
    {
        if( GetActiveLayer() != GetScreen()->m_Route_Layer_TOP )
            SetActiveLayer( GetScreen()->m_Route_Layer_TOP );
        else
            SetActiveLayer( GetScreen()->m_Route_Layer_BOTTOM );

        UpdateStatusBar();
        return true;
    }

    // Avoid more than one via on the current location:
    if( GetBoard()->GetViaByPosition( g_CurrentTrackSegment->GetEnd(),
                                      g_CurrentTrackSegment->GetLayer() ) )
        return false;

    for( TRACK* segm = g_FirstTrackSegment;  segm;  segm = segm->Next() )
    {
        if( segm->Type() == PCB_VIA_T && g_CurrentTrackSegment->GetEnd() == segm->GetStart() )
            return false;
    }

    // Is the current segment Ok (no DRC error) ?
    if( g_Drc_On )
    {
        if( BAD_DRC==m_drc->Drc( g_CurrentTrackSegment, GetBoard()->m_Track ) )
            // DRC error, the change layer is not made
            return false;

        // Handle 2 segments.
        if( g_TwoSegmentTrackBuild && g_CurrentTrackSegment->Back() )
        {
            if( BAD_DRC == m_drc->Drc( g_CurrentTrackSegment->Back(), GetBoard()->m_Track ) )
                return false;
        }
    }

    /* Save current state before placing a via.
     * If the via cannot be placed this current state will be reused
     */
    itmp = g_CurrentTrackList.GetCount();
    Begin_Route( g_CurrentTrackSegment, DC );

    m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );

    // create the via
    VIA* via = new VIA( GetBoard() );
    via->SetFlags( IS_NEW );
    via->SetViaType( GetDesignSettings().m_CurrentViaType );
    via->SetNetCode( GetBoard()->GetHighLightNetCode() );
    via->SetPosition( g_CurrentTrackSegment->GetEnd() );

    // for microvias, the size and hole will be changed later.
    via->SetWidth( GetDesignSettings().GetCurrentViaSize());
    via->SetDrill( GetDesignSettings().GetCurrentViaDrill() );

    // Usual via is from copper to component.
    // layer pair is B_Cu and F_Cu.
    via->SetLayerPair( B_Cu, F_Cu );

    LAYER_ID first_layer = GetActiveLayer();
    LAYER_ID last_layer;

    // prepare switch to new active layer:
    if( first_layer != GetScreen()->m_Route_Layer_TOP )
        last_layer = GetScreen()->m_Route_Layer_TOP;
    else
        last_layer = GetScreen()->m_Route_Layer_BOTTOM;

    // Adjust the actual via layer pair
    switch( via->GetViaType() )
    {
    case VIA_BLIND_BURIED:
        via->SetLayerPair( first_layer, last_layer );
        break;

    case VIA_MICROVIA:  // from external to the near neighbor inner layer
        {
            LAYER_ID last_inner_layer = ToLAYER_ID( ( GetBoard()->GetCopperLayerCount() - 2 ) );

            if( first_layer == B_Cu )
                last_layer = last_inner_layer;
            else if( first_layer == F_Cu )
                last_layer = In1_Cu;
            else if( first_layer == last_inner_layer )
                last_layer = B_Cu;
            else if( first_layer == In1_Cu )
                last_layer = F_Cu;
            // else error: will be removed later
            via->SetLayerPair( first_layer, last_layer );

            // Update diameter and hole size, which where set previously
            // for normal vias
            NETINFO_ITEM* net = via->GetNet();
            via->SetWidth( net->GetMicroViaSize() );
            via->SetDrill( net->GetMicroViaDrillSize() );
        }
        break;

    default:
        break;
    }

    if( g_Drc_On && BAD_DRC == m_drc->Drc( via, GetBoard()->m_Track ) )
    {
        // DRC fault: the Via cannot be placed here ...
        delete via;

        m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );

        // delete the track(s) added in Begin_Route()
        while( g_CurrentTrackList.GetCount() > itmp )
        {
            Delete_Segment( DC, g_CurrentTrackSegment );
        }

         SetCurItem( g_CurrentTrackSegment, false );

        // Refresh DRC diag, erased by previous calls
        if( m_drc->GetCurrentMarker() )
            SetMsgPanel( m_drc->GetCurrentMarker() );

        return false;
    }

    SetActiveLayer( last_layer );

    TRACK*  lastNonVia = g_CurrentTrackSegment;

    /* A new via was created. It was Ok.
     */
    g_CurrentTrackList.PushBack( via );

    /* The via is now in linked list and we need a new track segment
     * after the via, starting at via location.
     * it will become the new current segment (from via to the mouse cursor)
     */

    TRACK* track = (TRACK*)lastNonVia->Clone();

    /* the above creates a new segment from the last entered segment, with the
     * current width, flags, netcode, etc... values.
     * layer, start and end point are not correct,
     * and will be modified next
     */

    // set the layer to the new value
    track->SetLayer( GetActiveLayer() );

    /* the start point is the via position and the end point is the cursor
     * which also is on the via (will change when moving mouse)
     */
    track->SetEnd( via->GetStart() );
    track->SetStart( via->GetStart() );

    g_CurrentTrackList.PushBack( track );

    if( g_TwoSegmentTrackBuild )
    {
        // Create a second segment (we must have 2 track segments to adjust)
        g_CurrentTrackList.PushBack( (TRACK*)g_CurrentTrackSegment->Clone() );
    }

    m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
    SetMsgPanel( via );
    UpdateStatusBar();

    return true;
}
void PCB_EDIT_FRAME::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* aZone )
{
    ZONE_EDIT_T     edited;
    ZONE_SETTINGS   zoneInfo = GetZoneSettings();

    m_canvas->SetIgnoreMouseEvents( true );

    // Save initial zones configuration, for undo/redo, before adding new zone
    // note the net name and the layer can be changed, so we must save all zones
    s_AuxiliaryList.ClearListAndDeleteItems();
    s_PickedList.ClearListAndDeleteItems();
    SaveCopyOfZones(s_PickedList, GetBoard(), -1, -1 );

    if( aZone->GetIsKeepout() )
    {
        // edit a keepout area on a copper layer
        zoneInfo << *aZone;
        edited = InvokeKeepoutAreaEditor( this, &zoneInfo );
    }
    else if( aZone->GetLayer() < FIRST_NO_COPPER_LAYER )
    {
        // edit a zone on a copper layer

        zoneInfo << *aZone;

        edited = InvokeCopperZonesEditor( this, &zoneInfo );
    }
    else
    {
        edited = InvokeNonCopperZonesEditor( this, aZone, &zoneInfo );
    }

    m_canvas->MoveCursorToCrossHair();
    m_canvas->SetIgnoreMouseEvents( false );

    if( edited == ZONE_ABORT )
    {
        s_AuxiliaryList.ClearListAndDeleteItems();
        s_PickedList.ClearListAndDeleteItems();
        return;
    }

    SetZoneSettings( zoneInfo );

    if( edited == ZONE_EXPORT_VALUES )
    {
        UpdateCopyOfZonesList( s_PickedList, s_AuxiliaryList, GetBoard() );
        SaveCopyInUndoList(s_PickedList, UR_UNSPECIFIED);
        s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items
        return;
    }

    // Undraw old zone outlines
    for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ )
    {
        ZONE_CONTAINER* edge_zone = GetBoard()->GetArea( ii );
        edge_zone->Draw( m_canvas, DC, GR_XOR );
    }

    zoneInfo.ExportSetting( *aZone );

    NETINFO_ITEM* net = GetBoard()->FindNet( zoneInfo.m_NetcodeSelection );

    if( net )   // net == NULL should not occur
        aZone->SetNetName( net->GetNetname() );

    // Combine zones if possible
    GetBoard()->OnAreaPolygonModified( &s_AuxiliaryList, aZone );

    // Redraw the real new zone outlines
    GetBoard()->RedrawAreasOutlines( m_canvas, DC, GR_OR, -1 );

    UpdateCopyOfZonesList( s_PickedList, s_AuxiliaryList, GetBoard() );
    SaveCopyInUndoList(s_PickedList, UR_UNSPECIFIED);

    s_PickedList.ClearItemsList();  // s_ItemsListPicker is no longer owner of picked items

    OnModify();
}
bool DIALOG_COPPER_ZONE::AcceptOptions( bool aPromptForErrors, bool aUseExportableSetupOnly )
{
    switch( m_PadInZoneOpt->GetSelection() )
    {
    case 3:
        // Pads are not covered
        m_settings.SetPadConnection( PAD_NOT_IN_ZONE );
        break;

    case 2:
        // Use thermal relief for THT pads
        m_settings.SetPadConnection( THT_THERMAL );
        break;

    case 1:
        // Use thermal relief for pads
        m_settings.SetPadConnection( THERMAL_PAD );
        break;

    case 0:
        // pads are covered by copper
        m_settings.SetPadConnection( PAD_IN_ZONE );
        break;
    }

    switch( m_OutlineAppearanceCtrl->GetSelection() )
    {
    case 0:
        m_settings.m_Zone_HatchingStyle = CPolyLine::NO_HATCH;
        break;

    case 1:
        m_settings.m_Zone_HatchingStyle = CPolyLine::DIAGONAL_EDGE;
        break;

    case 2:
        m_settings.m_Zone_HatchingStyle = CPolyLine::DIAGONAL_FULL;
        break;
    }

    m_settings.m_ArcToSegmentsCount = m_ArcApproximationOpt->GetSelection() == 1 ?
                                           ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF :
                                           ARC_APPROX_SEGMENTS_COUNT_LOW_DEF;

    if( m_Config )
    {
        m_Config->Write( ZONE_NET_OUTLINES_HATCH_OPTION_KEY,
                         (long) m_settings.m_Zone_HatchingStyle );
        wxString filter = m_DoNotShowNetNameFilter->GetValue();
        m_Config->Write( ZONE_NET_FILTER_STRING_KEY, filter );
    }

    m_netNameShowFilter = m_ShowNetNameFilter->GetValue();
    m_settings.m_FillMode = (m_FillModeCtrl->GetSelection() == 0) ? 0 : 1;

    wxString txtvalue = m_ZoneClearanceCtrl->GetValue();
    m_settings.m_ZoneClearance = ReturnValueFromString( g_UserUnit, txtvalue );

    // Test if this is a reasonable value for this parameter
    // A too large value can hang Pcbnew
    #define CLEARANCE_MAX_VALUE ZONE_CLEARANCE_MAX_VALUE_MIL*IU_PER_MILS
    if( m_settings.m_ZoneClearance > CLEARANCE_MAX_VALUE )
    {
        wxString msg;
        msg.Printf( _( "Clearance must be smaller than %f\" / %f mm." ),
            ZONE_CLEARANCE_MAX_VALUE_MIL / 1000.0, ZONE_CLEARANCE_MAX_VALUE_MIL * 0.0254 );
        DisplayError( this, msg );
        return false;
    }

    txtvalue = m_ZoneMinThicknessCtrl->GetValue();
    m_settings.m_ZoneMinThickness = ReturnValueFromString( g_UserUnit, txtvalue );

    if( m_settings.m_ZoneMinThickness < (ZONE_THICKNESS_MIN_VALUE_MIL*IU_PER_MILS) )
    {
        wxString msg;
        msg.Printf( _( "Minimum width must be larger than %f\" / %f mm." ),
            ZONE_THICKNESS_MIN_VALUE_MIL / 1000.0, ZONE_THICKNESS_MIN_VALUE_MIL * 0.0254 );
        DisplayError( this, msg );
        return false;
    }

    m_settings.SetCornerSmoothingType( m_cornerSmoothingChoice->GetSelection() );
    txtvalue = m_cornerSmoothingCtrl->GetValue();
    m_settings.SetCornerRadius( ReturnValueFromString( g_UserUnit, txtvalue ) );

    m_settings.m_ZonePriority = m_PriorityLevelCtrl->GetValue();

    if( m_OrientEdgesOpt->GetSelection() == 0 )
        m_settings.m_Zone_45_Only = false;
    else
        m_settings.m_Zone_45_Only = true;

    m_settings.m_ThermalReliefGap = ReturnValueFromTextCtrl( *m_AntipadSizeValue );
    m_settings.m_ThermalReliefCopperBridge = ReturnValueFromTextCtrl( *m_CopperWidthValue );

    if( m_Config )
    {
        ConfigBaseWriteDouble( m_Config, ZONE_CLEARANCE_WIDTH_STRING_KEY,
                               (double) m_settings.m_ZoneClearance / IU_PER_MILS );

        ConfigBaseWriteDouble( m_Config, ZONE_MIN_THICKNESS_WIDTH_STRING_KEY,
            (double) m_settings.m_ZoneMinThickness / IU_PER_MILS );

        ConfigBaseWriteDouble( m_Config, ZONE_THERMAL_RELIEF_GAP_STRING_KEY,
            (double) m_settings.m_ThermalReliefGap / IU_PER_MILS );

        ConfigBaseWriteDouble( m_Config, ZONE_THERMAL_RELIEF_COPPER_WIDTH_STRING_KEY,
            (double) m_settings.m_ThermalReliefCopperBridge / IU_PER_MILS );
    }

    if( m_settings.m_ThermalReliefCopperBridge <= m_settings.m_ZoneMinThickness )
    {
        DisplayError( this,
                     _( "Thermal relief spoke width is smaller than the minimum width." ) );
        return false;
    }

    // If we use only exportable to others zones parameters, exit here:
    if( aUseExportableSetupOnly )
        return true;

    // Get the layer selection for this zone
    int ii = m_LayerSelectionCtrl->GetFirstSelected();

    if( ii < 0 && aPromptForErrors )
    {
        DisplayError( this, _( "No layer selected." ) );
        return false;
    }

    m_settings.m_CurrentZone_Layer = m_LayerId[ii];

    // Get the net name selection for this zone
    ii = m_ListNetNameSelection->GetSelection();

    if( ii < 0 && aPromptForErrors )
    {
        DisplayError( this, _( "No net selected." ) );
        return false;
    }

    if( ii == 0 )   // the not connected option was selected: this is not a good practice: warn:
    {
        if( !IsOK( this, _(
                      "You have chosen the \"not connected\" option. This will create insulated copper islands. Are you sure ?" ) )
            )
            return false;
    }

    wxString net_name = m_ListNetNameSelection->GetString( ii );

    m_settings.m_NetcodeSelection = 0;

    // Search net_code for this net, if a net was selected
    if( m_ListNetNameSelection->GetSelection() > 0 )
    {
        NETINFO_ITEM* net = m_Parent->GetBoard()->FindNet( net_name );
        if( net )
            m_settings.m_NetcodeSelection = net->GetNet();
    }

    return true;
}
void ZONE_CONTAINER::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
{
    wxString msg;

    msg = _( "Zone Outline" );

    // Display Cutout instead of Outline for holes inside a zone
    // i.e. when num contour !=0
    int ncont = m_Poly->GetContour( m_CornerSelection );

    if( ncont )
        msg << wxT( " " ) << _( "(Cutout)" );

    aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, DARKCYAN ) );

    if( GetIsKeepout() )
    {
        msg.Empty();

        if( GetDoNotAllowVias() )
            AccumulateDescription( msg, _("No via") );

        if( GetDoNotAllowTracks() )
            AccumulateDescription( msg, _("No track") );

        if( GetDoNotAllowCopperPour() )
            AccumulateDescription( msg, _("No copper pour") );

        aList.push_back( MSG_PANEL_ITEM( _( "Keepout" ), msg, RED ) );
    }
    else if( IsOnCopperLayer() )
    {
        if( GetNetCode() >= 0 )
        {
            NETINFO_ITEM* equipot = GetNet();

            if( equipot )
                msg = equipot->GetNetname();
            else
                msg = wxT( "<noname>" );
        }
        else // a netcode < 0 is an error
        {
            msg = wxT( " [" );
            msg << GetNetname() + wxT( "]" );
            msg << wxT( " <" ) << _( "Not Found" ) << wxT( ">" );
        }

        aList.push_back( MSG_PANEL_ITEM( _( "NetName" ), msg, RED ) );

#if 1
        // Display net code : (useful in test or debug)
        msg.Printf( wxT( "%d" ), GetNetCode() );
        aList.push_back( MSG_PANEL_ITEM( _( "NetCode" ), msg, RED ) );
#endif

        // Display priority level
        msg.Printf( wxT( "%d" ), GetPriority() );
        aList.push_back( MSG_PANEL_ITEM( _( "Priority" ), msg, BLUE ) );
    }
    else
    {
        aList.push_back( MSG_PANEL_ITEM( _( "Non Copper Zone" ), wxEmptyString, RED ) );
    }

    aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), GetLayerName(), BROWN ) );

    msg.Printf( wxT( "%d" ), (int) m_Poly->m_CornersList.GetCornersCount() );
    aList.push_back( MSG_PANEL_ITEM( _( "Corners" ), msg, BLUE ) );

    if( m_FillMode )
        msg = _( "Segments" );
    else
        msg = _( "Polygons" );

    aList.push_back( MSG_PANEL_ITEM( _( "Fill mode" ), msg, BROWN ) );

    // Useful for statistics :
    msg.Printf( wxT( "%d" ), (int) m_Poly->m_HatchLines.size() );
    aList.push_back( MSG_PANEL_ITEM( _( "Hatch lines" ), msg, BLUE ) );

    if( m_FilledPolysList.GetCornersCount() )
    {
        msg.Printf( wxT( "%d" ), (int) m_FilledPolysList.GetCornersCount() );
        aList.push_back( MSG_PANEL_ITEM( _( "Corners in DrawList" ), msg, BLUE ) );
    }
}
void VIA::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode,
                   const wxPoint& aOffset )
{
    int radius;
    LAYER_NUM curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;

    int fillvia = 0;
    PCB_BASE_FRAME* frame  = (PCB_BASE_FRAME*) panel->GetParent();
    PCB_SCREEN*     screen = frame->GetScreen();

    if( frame->m_DisplayViaFill == FILLED )
        fillvia = 1;

    GRSetDrawMode( aDC, aDrawMode );

    BOARD * brd =  GetBoard( );
    EDA_COLOR_T color = brd->GetVisibleElementColor(VIAS_VISIBLE + GetViaType());

    if( brd->IsElementVisible( PCB_VISIBLE(VIAS_VISIBLE + GetViaType()) ) == false
        && ( color & HIGHLIGHT_FLAG ) != HIGHLIGHT_FLAG )
        return;

    if( DisplayOpt.ContrastModeDisplay )
    {
        if( !IsOnLayer( curr_layer ) )
            ColorTurnToDarkDarkGray( &color );
    }

    if( aDrawMode & GR_HIGHLIGHT )
        ColorChangeHighlightFlag( &color, !(aDrawMode & GR_AND) );

    ColorApplyHighlightFlag( &color );

    SetAlpha( &color, 150 );


    radius = m_Width >> 1;
    // for small via size on screen (radius < 4 pixels) draw a simplified shape

    int radius_in_pixels = aDC->LogicalToDeviceXRel( radius );

    bool fast_draw = false;

    // Vias are drawn as a filled circle or a double circle. The hole will be drawn later
    int drill_radius = GetDrillValue() / 2;

    int inner_radius = radius - aDC->DeviceToLogicalXRel( 2 );

    if( radius_in_pixels < MIN_VIA_DRAW_SIZE )
    {
        fast_draw = true;
        fillvia = false;
    }

    if( fillvia )
    {
        GRFilledCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius, color );
    }
    else
    {
        GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius, 0, color );

        if ( fast_draw )
            return;

        GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, inner_radius, 0, color );
    }

    // Draw the via hole if the display option allows it
    if( DisplayOpt.m_DisplayViaMode != VIA_HOLE_NOT_SHOW )
    {
        // Display all drill holes requested or Display non default holes requested
        if( (DisplayOpt.m_DisplayViaMode == ALL_VIA_HOLE_SHOW)
          || ( (drill_radius > 0 ) && !IsDrillDefault() ) )
        {
            if( fillvia )
            {
                bool blackpenstate = false;

                if( screen->m_IsPrinting )
                {
                    blackpenstate = GetGRForceBlackPenState();
                    GRForceBlackPen( false );
                    color = WHITE;
                }
                else
                {
                    color = BLACK;     // or DARKGRAY;
                }

                if( (aDrawMode & GR_XOR) == 0)
                    GRSetDrawMode( aDC, GR_COPY );

                if( aDC->LogicalToDeviceXRel( drill_radius ) > MIN_DRAW_WIDTH )  // Draw hole if large enough.
                    GRFilledCircle( panel->GetClipBox(), aDC, m_Start.x + aOffset.x,
                                    m_Start.y + aOffset.y, drill_radius, 0, color, color );

                if( screen->m_IsPrinting )
                    GRForceBlackPen( blackpenstate );
            }
            else
            {
                if( drill_radius < inner_radius )         // We can show the via hole
                    GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, drill_radius, 0, color );
            }
        }
    }

    if( ShowClearance( this ) )
    {
        GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius + GetClearance(), 0, color );
    }

    // for Micro Vias, draw a partial cross : X on component layer, or + on copper layer
    // (so we can see 2 superimposed microvias ):
    if( GetViaType() == VIA_MICROVIA )
    {
        int ax, ay, bx, by;

        if( IsOnLayer( LAYER_N_BACK ) )
        {
            ax = radius; ay = 0;
            bx = drill_radius; by = 0;
        }
        else
        {
            ax = ay = (radius * 707) / 1000;
            bx = by = (drill_radius * 707) / 1000;
        }

        /* lines | or \ */
        GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax,
                m_Start.y + aOffset.y - ay,
                m_Start.x + aOffset.x - bx,
                m_Start.y + aOffset.y - by, 0, color );
        GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x + bx,
                m_Start.y + aOffset.y + by,
                m_Start.x + aOffset.x + ax,
                m_Start.y + aOffset.y + ay, 0, color );

        // lines - or /
        GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x + ay,
                m_Start.y + aOffset.y - ax,
                m_Start.x + aOffset.x + by,
                m_Start.y + aOffset.y - bx, 0, color );
        GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - by,
                m_Start.y + aOffset.y + bx,
                m_Start.x + aOffset.x - ay,
                m_Start.y + aOffset.y + ax, 0, color );
    }

    // for Buried Vias, draw a partial line : orient depending on layer pair
    // (so we can see superimposed buried vias ):
    if( GetViaType() == VIA_BLIND_BURIED )
    {
        int ax = 0, ay = radius, bx = 0, by = drill_radius;
        LAYER_NUM layer_top, layer_bottom;

        ( (VIA*) this )->LayerPair( &layer_top, &layer_bottom );

        // lines for the top layer
        RotatePoint( &ax, &ay, layer_top * 3600.0 / brd->GetCopperLayerCount( ) );
        RotatePoint( &bx, &by, layer_top * 3600.0 / brd->GetCopperLayerCount( ) );
        GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax,
                m_Start.y + aOffset.y - ay,
                m_Start.x + aOffset.x - bx,
                m_Start.y + aOffset.y - by, 0, color );

        // lines for the bottom layer
        ax = 0; ay = radius; bx = 0; by = drill_radius;
        RotatePoint( &ax, &ay, layer_bottom * 3600.0 / brd->GetCopperLayerCount( ) );
        RotatePoint( &bx, &by, layer_bottom * 3600.0 / brd->GetCopperLayerCount( ) );
        GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax,
                m_Start.y + aOffset.y - ay,
                m_Start.x + aOffset.x - bx,
                m_Start.y + aOffset.y - by, 0, color );
    }

    // Display the short netname:
    if( GetNetCode() == NETINFO_LIST::UNCONNECTED )
        return;

    if( DisplayOpt.DisplayNetNamesMode == 0 || DisplayOpt.DisplayNetNamesMode == 1 )
        return;

    NETINFO_ITEM* net = GetNet();

    if( net == NULL )
        return;

    int len = net->GetShortNetname().Len();

    if( len > 0 )
    {
        // calculate a good size for the text
        int tsize = m_Width / len;

        if( aDC->LogicalToDeviceXRel( tsize ) >= MIN_TEXT_SIZE )
        {
            tsize = (tsize * 7) / 10;        // small reduction to give a better look, inside via
            if( (aDrawMode & GR_XOR) == 0 )
                GRSetDrawMode( aDC, GR_COPY );

            EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL;
            DrawGraphicHaloText( clipbox, aDC, m_Start,
                                 color, WHITE, BLACK, net->GetShortNetname(), 0,
                                 wxSize( tsize, tsize ),
                                 GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER,
                                 tsize / 7, false, false );
        }
    }
}
void DIALOG_COPPER_ZONE::buildAvailableListOfNets()
{
    wxArrayString   listNetName;

    m_Parent->GetBoard()->ReturnSortedNetnamesList( listNetName, m_NetSortingByPadCount );

    if( m_NetFiltering )
    {
        wxString doNotShowFilter = m_DoNotShowNetNameFilter->GetValue();
        wxString ShowFilter = m_ShowNetNameFilter->GetValue();

        for( unsigned ii = 0; ii < listNetName.GetCount(); ii++ )
        {
            if( listNetName[ii].Matches( doNotShowFilter ) )
            {
                listNetName.RemoveAt( ii );
                ii--;
            }
            else if( !listNetName[ii].Matches( ShowFilter ) )
            {
                listNetName.RemoveAt( ii );
                ii--;
            }
        }
    }

    listNetName.Insert( wxT( "<no net>" ), 0 );

    // Ensure currently selected net for the zone is visible, regardless of filters
    int selectedNetListNdx = -1;
    int net_select = m_settings.m_NetcodeSelection;

    if( net_select > 0 )
    {
        NETINFO_ITEM* equipot = m_Parent->GetBoard()->FindNet( net_select );
        if( equipot )
        {
            selectedNetListNdx = listNetName.Index( equipot->GetNetname() );

            if( wxNOT_FOUND == selectedNetListNdx )
            {
                // the currently selected net must *always* be visible.
                listNetName.Insert( equipot->GetNetname(), 0 );
                selectedNetListNdx = 0;
            }
        }
    }
    else if( net_select == 0 )
        selectedNetListNdx = 0;     // SetSelection() on "<no net>"
    else
    {
        // selectedNetListNdx remains -1, no net selected.
    }

    m_ListNetNameSelection->Clear();
    m_ListNetNameSelection->InsertItems( listNetName, 0 );
    m_ListNetNameSelection->SetSelection( 0 );

    if( selectedNetListNdx >= 0 )
    {
        m_ListNetNameSelection->SetSelection( selectedNetListNdx );
        m_ListNetNameSelection->EnsureVisible( selectedNetListNdx );
    }
}
Exemple #30
0
void BOARD::SynchronizeNetsAndNetClasses()
{
    // D(printf("start\n");)       // simple performance/timing indicator.

    // set all NETs to the default NETCLASS, then later override some
    // as we go through the NETCLASSes.

    int count = m_NetInfo.GetNetCount();
    for( int i=0;  i<count;  ++i )
    {
        NETINFO_ITEM* net = FindNet( i );
        if( net )
            net->SetClass( m_NetClasses.GetDefault() );
    }

    // Add netclass name and pointer to nets.  If a net is in more than one netclass,
    // set the net's name and pointer to only the first netclass.  Subsequent
    // and therefore bogus netclass memberships will be deleted in logic below this loop.
    for( NETCLASSES::iterator clazz=m_NetClasses.begin();  clazz!=m_NetClasses.end();  ++clazz )
    {
        NETCLASS* netclass = clazz->second;

        for( NETCLASS::iterator member = netclass->begin();  member!=netclass->end();  ++member )
        {
            const wxString&  netname = *member;

            // although this overall function seems to be adequately fast,
            // FindNet( wxString ) uses now a fast binary search and is fast
            // event for large net lists
            NETINFO_ITEM* net = FindNet( netname );

            if( net && net->GetClassName() == NETCLASS::Default )
            {
                net->SetClass( netclass );
            }
        }
    }

    // Finally, make sure that every NET is in a NETCLASS, even if that
    // means the Default NETCLASS.  And make sure that all NETCLASSes do not
    // contain netnames that do not exist, by deleting all netnames from
    // every netclass and re-adding them.

    for( NETCLASSES::iterator clazz=m_NetClasses.begin();  clazz!=m_NetClasses.end();  ++clazz )
    {
        NETCLASS* netclass = clazz->second;

        netclass->Clear();
    }

    m_NetClasses.GetDefault()->Clear();

    for( int i=0;  i<count;  ++i )
    {
        NETINFO_ITEM* net = FindNet( i );
        if( net )
        {
            const wxString& classname = net->GetClassName();

            // because of the std:map<> this should be fast, and because of
            // prior logic, netclass should not be NULL.
            NETCLASS* netclass = m_NetClasses.Find( classname );

            wxASSERT( netclass );

            netclass->Add( net->GetNetname() );
        }
    }

    // D(printf("stop\n");)
}