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;
}
int NFCLoginNet_ServerModule::OnLoginResultsEvent(const NFIDENTID& object, const int nEventID, const NFIDataList& var)
{
	if (3 != var.GetCount()
		|| !var.TypeEx(TDATA_TYPE::TDATA_INT, TDATA_TYPE::TDATA_OBJECT, TDATA_TYPE::TDATA_STRING, TDATA_TYPE::TDATA_UNKNOWN))
	{
		return -1;
	}

	const int nState = var.Int(0);
	const NFIDENTID xIdent = var.Object(1);
	const std::string& strAccount = var.String(2);

	NF_SHARE_PTR<int> xFD = mxClientIdent.GetElement(xIdent);
	if (xFD)
	{
		if (0 != nState)
		{
			//此帐号密码错误或者被封号
			//登录失败
			NFMsg::AckEventResult xMsg;
			xMsg.set_event_code(NFMsg::EGEC_ACCOUNTPWD_INVALID);

			SendMsgPB(NFMsg::EGameMsgID::EGMI_ACK_LOGIN, xMsg, *xFD);

			return 0;
		}

		NetObject* pNetObject = GetNet()->GetNetObject(*xFD);
		if (pNetObject)
		{
			//记录他登录过
			pNetObject->SetConnectKeyState(1);
			pNetObject->SetAccount(strAccount);
		}

		//把服务器列表广播下去

		NFMsg::AckEventResult xData;
		xData.set_event_code(NFMsg::EGEC_ACCOUNT_SUCCESS);

		SendMsgPB(NFMsg::EGameMsgID::EGMI_ACK_LOGIN, xData, *xFD);

		//SynWorldToClient(unAddress);

		m_pLogModule->LogNormal(NFILogModule::NLL_INFO_NORMAL, NFIDENTID(0, *xFD), "Login successed :", strAccount.c_str());

	}
	
	return 0;
}
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;
}
void NETLIST_OBJECT::Show( std::ostream& out, int ndx ) const
{
    wxString path = m_SheetPath.PathHumanReadable();

    out << "<netItem ndx=\"" << ndx << '"' <<
    " type=\"" << ShowType( m_Type ) << '"' <<
    " netCode=\"" << GetNet() << '"' <<
    " sheet=\"" << TO_UTF8( path ) << '"' <<
    ">\n";

    out << " <start " << m_Start << "/> <end " << m_End << "/>\n";

    if( !m_Label.IsEmpty() )
        out << " <label>" << m_Label.mb_str() << "</label>\n";

    out << " <sheetpath>" << m_SheetPath.PathHumanReadable().mb_str() << "</sheetpath>\n";

    switch( m_Type )
    {
    case NET_PIN:
        /* GetRef() needs to be const
        out << " <refOfComp>" << GetComponentParent()->GetRef(&m_SheetPath).mb_str()
            << "</refOfComp>\n";
        */

        if( m_Comp )
            m_Comp->Show( 1, out );

        break;

    default:
        // not all the m_Comp classes have working Show functions.
        ;
    }

/*  was segfault-ing
    if( m_Comp )
        m_Comp->Show( 1, out );     // labels may not have good Show() funcs?
    else
        out << " m_Comp==NULL\n";
*/

    out << "</netItem>\n";
}
void cScenarioTrainHike::SetupLLCLearner(const std::shared_ptr<cSimCharacter>& character, std::shared_ptr<cNeuralNetLearner>& out_learner) const
{
#if defined(HACK_SOCCER_LLC)
	return;
#endif
	auto llc = GetDefaultLLC();
	auto& net = llc->GetNet();
	out_learner->SetNet(net.get());

	auto ac_ctrl = std::dynamic_pointer_cast<cBaseControllerCacla>(llc);
	if (ac_ctrl != nullptr)
	{
		auto ac_learner = std::static_pointer_cast<cACLearner>(out_learner);
		auto& critic = ac_ctrl->GetCritic();
		ac_learner->SetCriticNet(critic.get());
	}
	else
	{
		assert(false); // controller does not support cacla
	}
}
Beispiel #6
0
void D_PAD::Show( int nestLevel, std::ostream& os ) const
{
    char padname[5] = { m_Padname[0], m_Padname[1], m_Padname[2], m_Padname[3], 0 };

    char layerMask[16];

    sprintf( layerMask, "0x%08X", m_layerMask );

    // for now, make it look like XML:
    NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
    " shape=\"" << ShowPadShape() << '"' <<
    " attr=\"" << ShowPadAttr( ) << '"' <<
    " num=\"" << padname << '"' <<
    " net=\"" << m_Netname.mb_str() << '"' <<
    " netcode=\"" << GetNet() << '"' <<
    " layerMask=\"" << layerMask << '"' << m_Pos << "/>\n";

//    NestedSpace( nestLevel+1, os ) << m_Text.mb_str() << '\n';

//    NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str()
//    << ">\n";
}
int NFCLoginNet_ServerModule::OnLoginProcess( const NFIPacket& msg )
{
	NFIDENTID nPlayerID;
	NFMsg::ReqAccountLogin xMsg;
	if (!RecivePB(msg, xMsg, nPlayerID))
	{
		return 0;
	}
    
    NetObject* pNetObject = GetNet()->GetNetObject(msg.GetFd());
    if (pNetObject)
    {
        //还没有登录过
        if (pNetObject->GetConnectKeyState() == 0)
        {
            NFCDataList val;
            val << pNetObject->GetClientID()<< xMsg.account() << xMsg.password();
            m_pEventProcessModule->DoEvent(NFIDENTID(), NFED_ON_CLIENT_LOGIN, val);
        }
    }
	
	return 0;
}
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 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 );
        }
    }
}
void NETINFO_ITEM::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
{
    int       count;
    EDA_ITEM* Struct;
    wxString  txt;
    MODULE*   module;
    D_PAD*    pad;
    double    lengthnet = 0;        // This  is the lenght of tracks on pcb
    double    lengthPadToDie = 0;   // this is the lenght of internal ICs connections

    aList.push_back( MSG_PANEL_ITEM( _( "Net Name" ), GetNetname(), RED ) );

    txt.Printf( wxT( "%d" ), GetNet() );
    aList.push_back( MSG_PANEL_ITEM( _( "Net Code" ), txt, RED ) );

    count  = 0;
    module = m_parent->GetBoard()->m_Modules;

    for( ; module != 0; module = module->Next() )
    {
        for( pad = module->Pads(); pad != 0; pad = pad->Next() )
        {
            if( pad->GetNetCode() == GetNet() )
            {
                count++;
                lengthPadToDie += pad->GetPadToDieLength();
            }
        }
    }

    txt.Printf( wxT( "%d" ), count );
    aList.push_back( MSG_PANEL_ITEM( _( "Pads" ), txt, DARKGREEN ) );

    count  = 0;
    Struct = m_parent->GetBoard()->m_Track;

    for( ; Struct != NULL; Struct = Struct->Next() )
    {
        if( Struct->Type() == PCB_VIA_T )
        {
            if( ( (SEGVIA*) Struct )->GetNetCode() == GetNet() )
                count++;
        }

        if( Struct->Type() == PCB_TRACE_T )
        {
            if( ( (TRACK*) Struct )->GetNetCode() == GetNet() )
                lengthnet += ( (TRACK*) Struct )->GetLength();
        }
    }

    txt.Printf( wxT( "%d" ), count );
    aList.push_back( MSG_PANEL_ITEM( _( "Vias" ), txt, BLUE ) );

    // Displays the full net length (tracks on pcb + internal ICs connections ):
    txt = ::CoordinateToString( lengthnet + lengthPadToDie );
    aList.push_back( MSG_PANEL_ITEM( _( "Net Length:" ), txt, RED ) );

    // Displays the net length of tracks only:
    txt = ::CoordinateToString( lengthnet );
    aList.push_back( MSG_PANEL_ITEM( _( "On Board" ), txt, RED ) );

    // Displays the net length of internal ICs connections (wires inside ICs):
    txt = ::CoordinateToString( lengthPadToDie );
    aList.push_back( MSG_PANEL_ITEM( _( "In Package" ), txt, RED ) );
}
void ZONE_CONTAINER::TestForCopperIslandAndRemoveInsulatedIslands( BOARD* aPcb )
{
    if( m_FilledPolysList.GetCornersCount() == 0 )
        return;

    // Build a list of points connected to the net:
    // list of coordinates of pads and vias on this layer and on this net.
    std::vector <wxPoint> listPointsCandidates;

    for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
    {
        for( D_PAD* pad = module->Pads(); pad != NULL; pad = pad->Next() )
        {
            if( !pad->IsOnLayer( GetLayer() ) )
                continue;

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

            listPointsCandidates.push_back( pad->GetPosition() );
        }
    }

    for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
    {
        if( !track->IsOnLayer( GetLayer() ) )
            continue;

        if( track->GetNet() != GetNet() )
            continue;

        listPointsCandidates.push_back( track->GetStart() );

        if( track->Type() != PCB_VIA_T )
            listPointsCandidates.push_back( track->GetEnd() );
    }

    // test if a point is inside
    unsigned indexstart = 0, indexend;
    bool     connected  = false;

    for( indexend = 0; indexend < m_FilledPolysList.GetCornersCount(); indexend++ )
    {
        if( m_FilledPolysList[indexend].end_contour )    // end of a filled sub-area found
        {
            EDA_RECT bbox = CalculateSubAreaBoundaryBox( indexstart, indexend );

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

                if( !bbox.Contains( pos ) )
                    continue;

                if( TestPointInsidePolygon( m_FilledPolysList, indexstart, indexend,
                                            pos.x, pos.y ) )
                {
                    connected = true;
                    break;
                }
            }

            if( connected )                 // this polygon is connected: analyse next polygon
            {
                indexstart = indexend + 1;  // indexstart points the first point of the next polygon
                connected  = false;
            }
            else                             // Not connected: remove this polygon
            {
                m_FilledPolysList.DeleteCorners( indexstart, indexend );
                indexend = indexstart;   /* indexstart points the first point of the next polygon
                                          * because the current poly is removed */
            }
        }
    }
}
void DIALOG_ERC::TestErc( wxArrayString* aMessagesList )
{
    wxFileName fn;

    m_writeErcFile = m_WriteResultOpt->GetValue();
    m_TestSimilarLabels = m_cbTestSimilarLabels->GetValue();
    m_tstUniqueGlobalLabels = m_cbTestUniqueGlbLabels->GetValue();

    // Build the whole sheet list in hierarchy (sheet, not screen)
    SCH_SHEET_LIST sheets( g_RootSheet );
    sheets.AnnotatePowerSymbols( Prj().SchLibs() );

    if( m_parent->CheckAnnotate( aMessagesList, false ) )
    {
        if( aMessagesList )
        {
            wxString msg = _( "Annotation required!" );
            msg += wxT( "\n" );
            aMessagesList->Add( msg );
        }

        return;
    }

    SCH_SCREENS screens;

    // Erase all previous DRC markers.
    screens.DeleteAllMarkers( MARKER_BASE::MARKER_ERC );

    for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() )
    {
        /* Ff wire list has changed, delete Undo Redo list to avoid pointers on deleted
         * data problems.
         */
        if( screen->SchematicCleanUp() )
            screen->ClearUndoRedoList();
    }

    /* Test duplicate sheet names inside a given sheet, one cannot have sheets with
     * duplicate names (file names can be duplicated).
     */
    TestDuplicateSheetNames( true );

    std::unique_ptr<NETLIST_OBJECT_LIST> objectsConnectedList( m_parent->BuildNetListBase() );

    // Reset the connection type indicator
    objectsConnectedList->ResetConnectionsType();

    unsigned lastItemIdx;
    unsigned nextItemIdx = lastItemIdx = 0;
    int MinConn    = NOC;

    /* The netlist generated by SCH_EDIT_FRAME::BuildNetListBase is sorted
     * by net number, which means we can group netlist items into ranges
     * that live in the same net. The range from nextItem to the current
     * item (exclusive) needs to be checked against the current item. The
     * lastItem variable is used as a helper to pass the last item's number
     * from one loop iteration to the next, which simplifies the initial
     * pass.
     */

    for( unsigned itemIdx = 0; itemIdx < objectsConnectedList->size(); itemIdx++ )
    {
        auto item = objectsConnectedList->GetItem( itemIdx );
        auto lastItem = objectsConnectedList->GetItem( lastItemIdx );

        auto lastNet = lastItem->GetNet();
        auto net = item->GetNet();

        wxASSERT_MSG( lastNet <= net, wxT( "Netlist not correctly ordered" ) );

        if( lastNet != net )
        {
            // New net found:
            MinConn      = NOC;
            nextItemIdx = itemIdx;
        }

        switch( item->m_Type )
        {
        // These items do not create erc problems
        case NET_ITEM_UNSPECIFIED:
        case NET_SEGMENT:
        case NET_BUS:
        case NET_JUNCTION:
        case NET_LABEL:
        case NET_BUSLABELMEMBER:
        case NET_PINLABEL:
        case NET_GLOBBUSLABELMEMBER:
            break;

        case NET_HIERLABEL:
        case NET_HIERBUSLABELMEMBER:
        case NET_SHEETLABEL:
        case NET_SHEETBUSLABELMEMBER:
            // ERC problems when pin sheets do not match hierarchical labels.
            // Each pin sheet must match a hierarchical label
            // Each hierarchical label must match a pin sheet
            objectsConnectedList->TestforNonOrphanLabel( itemIdx, nextItemIdx );
            break;
        case NET_GLOBLABEL:
            if( m_tstUniqueGlobalLabels )
                objectsConnectedList->TestforNonOrphanLabel( itemIdx, nextItemIdx );
            break;

        case NET_NOCONNECT:

            // ERC problems when a noconnect symbol is connected to more than one pin.
            MinConn = NET_NC;

            if( objectsConnectedList->CountPinsInNet( nextItemIdx ) > 1 )
                Diagnose( item, NULL, MinConn, UNC );

            break;

        case NET_PIN:

            // Look for ERC problems between pins:
            TestOthersItems( objectsConnectedList.get(), itemIdx, nextItemIdx, &MinConn );
            break;
        }

        lastItemIdx = itemIdx;
    }

    // Test similar labels (i;e. labels which are identical when
    // using case insensitive comparisons)
    if( m_TestSimilarLabels )
        objectsConnectedList->TestforSimilarLabels();

    // Displays global results:
    updateMarkerCounts( &screens );

    // Display diags:
    DisplayERC_MarkersList();

    // Display new markers:
    m_parent->GetCanvas()->Refresh();

    // Display message
    wxString msg = _( "Finished" );
    msg += wxT( "\n" );
    aMessagesList->Add( msg );

    if( m_writeErcFile )
    {
        fn = g_RootSheet->GetScreen()->GetFileName();
        fn.SetExt( wxT( "erc" ) );

        wxFileDialog dlg( this, _( "ERC File" ), fn.GetPath(), fn.GetFullName(),
                          _( "Electronic rule check file (.erc)|*.erc" ),
                          wxFD_SAVE );

        if( dlg.ShowModal() == wxID_CANCEL )
            return;

        if( WriteDiagnosticERC( dlg.GetPath() ) )
        {
            Close( true );
            ExecuteFile( this, Pgm().GetEditorName(), QuoteFullPath( fn ) );
        }
    }
}
void VIA::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, const wxPoint& aOffset )
{
    wxCHECK_RET( panel != NULL, wxT( "VIA::Draw panel cannot be NULL." ) );

    int radius;
    PCB_LAYER_ID 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();
    auto displ_opts = (PCB_DISPLAY_OPTIONS*)( frame->GetDisplayOptions() );

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

    GRSetDrawMode( aDC, aDrawMode );

    BOARD * brd =  GetBoard();
    COLOR4D color = frame->Settings().Colors().GetItemColor( LAYER_VIAS + GetViaType() );

    if( brd->IsElementVisible( LAYER_VIAS + GetViaType() ) == false
        && !( aDrawMode & GR_HIGHLIGHT ) )
       return;

    // Only draw the via if at least one of the layers it crosses is being displayed
    if( !( brd->GetVisibleLayers() & GetLayerSet() ).any() )
        return;

    if( displ_opts->m_ContrastModeDisplay )
    {
        if( !IsOnLayer( curr_layer ) )
            color = COLOR4D( DARKDARKGRAY );
    }

    if( ( aDrawMode & GR_HIGHLIGHT ) && !( aDrawMode & GR_AND ) )
        color.SetToLegacyHighlightColor();

    color.a = 0.588;


    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 );
    }

    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 );

        // Draw hole if the radius is > 1pixel.
        if( aDC->LogicalToDeviceXRel( drill_radius ) > 1 )
            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( displ_opts, 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( B_Cu ) )
        {
            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;
        PCB_LAYER_ID layer_top, layer_bottom;

        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( displ_opts->m_DisplayNetNamesMode == 0 || displ_opts->m_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->GetClipBox();
            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 VIA::GetMsgPanelInfoBase( std::vector< MSG_PANEL_ITEM >& aList )
{
    wxString msg;
    BOARD*   board = GetBoard();

    switch( GetViaType() )
    {
    default:
    case VIA_NOT_DEFINED:
        msg =  wxT( "???" ); // Not used yet, does not exist currently
        break;

    case VIA_MICROVIA:
        msg = _( "Micro Via" ); // from external layer (TOP or BOTTOM) from
                                    // the near neighbor inner layer only
        break;

    case VIA_BLIND_BURIED:
        msg = _( "Blind/Buried Via" );  // from inner or external to inner
                                            // or external layer (no restriction)
        break;

    case VIA_THROUGH:
        msg =  _( "Through Via" );  // Usual via (from TOP to BOTTOM layer only )
        break;
    }

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

    GetMsgPanelInfoBase_Common( aList );


    // Display layer pair
    PCB_LAYER_ID top_layer, bottom_layer;

    LayerPair( &top_layer, &bottom_layer );

    if( board )
        msg = board->GetLayerName( top_layer ) + wxT( "/" )
            + board->GetLayerName( bottom_layer );
    else
        msg.Printf( wxT( "%d/%d" ), top_layer, bottom_layer );

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

    // Display width
    msg = ::CoordinateToString( (unsigned) m_Width );

    // Display diameter value:
    aList.push_back( MSG_PANEL_ITEM( _( "Diameter" ), msg, DARKCYAN ) );

    // Display drill value
    int drill_value = GetDrillValue();

    msg = ::CoordinateToString( drill_value );

    wxString title = _( "Drill" );
    title += wxT( " " );

    bool drl_specific = true;

    if( GetBoard() )
    {
        NETINFO_ITEM* net = GetNet();
        int drill_class_value = 0;

        if( net )
        {
            if( GetViaType() == VIA_MICROVIA )
                drill_class_value = net->GetMicroViaDrillSize();
            else
                drill_class_value = net->GetViaDrillSize();
        }

        drl_specific = drill_value != drill_class_value;
    }


    if( drl_specific )
        title += _( "(Specific)" );
    else
        title += _( "(NetClass)" );

    aList.push_back( MSG_PANEL_ITEM( title, msg, RED ) );
}