/* generate shapes of graphic items (outlines) on layer aLayer as polygons,
 * and adds these polygons to aCornerBuffer
 * aCornerBuffer = the buffer to store polygons
 * aInflateValue = a value to inflate shapes
 * aCircleToSegmentsCount = number of segments to approximate a circle
 * aCorrectionFactor = the correction to apply to the circle radius
 *  to generate the polygon.
 *  if aCorrectionFactor = 1.0, the polygon is inside the circle
 *  the radius of circle approximated by segments is
 *  initial radius * aCorrectionFactor
 */
void MODULE::TransformGraphicShapesWithClearanceToPolygonSet(
                        LAYER_NUM aLayer,
                        CPOLYGONS_LIST& aCornerBuffer,
                        int                    aInflateValue,
                        int                    aCircleToSegmentsCount,
                        double                 aCorrectionFactor )
{
    std::vector<TEXTE_MODULE *> texts;  // List of TEXTE_MODULE to convert
    EDGE_MODULE* outline;

    for( EDA_ITEM* item = GraphicalItems(); item != NULL; item = item->Next() )
    {
        switch( item->Type() )
        {
        case PCB_MODULE_TEXT_T:
            if( ((TEXTE_MODULE*)item)->GetLayer() == aLayer )
                texts.push_back( (TEXTE_MODULE *) item );
            break;

        case PCB_MODULE_EDGE_T:
            outline = (EDGE_MODULE*) item;
            if( outline->GetLayer() != aLayer )
                break;

            switch( outline->GetShape() )
            {
            case S_SEGMENT:
                TransformRoundedEndsSegmentToPolygon( aCornerBuffer,
                                           outline->GetStart(),
                                           outline->GetEnd(),
                                           aCircleToSegmentsCount,
                                           outline->GetWidth() );
                break;

            case S_CIRCLE:
                TransformRingToPolygon( aCornerBuffer, outline->GetCenter(),
                                outline->GetRadius(), aCircleToSegmentsCount,
                                outline->GetWidth() );
                break;

            case S_ARC:
                TransformArcToPolygon( aCornerBuffer,
                            outline->GetCenter(), outline->GetArcStart(),
                            outline->GetAngle(),
                            aCircleToSegmentsCount, outline->GetWidth() );
                break;

            case S_POLYGON:
                // for outline shape = S_POLYGON:
                // We must compute true coordinates from m_PolyPoints
                // which are relative to module position and module orientation = 0
                for( unsigned ii = 0; ii < outline->GetPolyPoints().size(); ii++ )
                {
                    CPolyPt corner( outline->GetPolyPoints()[ii] );
                    RotatePoint( &corner.x, &corner.y, GetOrientation() );
                    corner.x += GetPosition().x;
                    corner.y += GetPosition().y;
                    aCornerBuffer.Append( corner );
                }
                aCornerBuffer.CloseLastContour();
                break;

            default:
                DBG( printf( "Error: Shape %d not implemented!\n",
                        outline->GetShape() ); )
                break;
            }
                break;

            default:
                break;
        }
    }
Esempio n. 2
0
MODULE* PCB_EDIT_FRAME::Create_MuWaveComponent( int shape_type )
{
    int      oX;
    D_PAD*   pad;
    MODULE*  module;
    wxString msg, cmp_name;
    int      pad_count = 2;
    int      angle     = 0;
    // Ref and value text size (O = use board default value.
    // will be set to a value depending on the footprint size, if possible
    int      text_size = 0;

    // Enter the size of the gap or stub
    int      gap_size = GetDesignSettings().GetCurrentTrackWidth();

    switch( shape_type )
    {
    case 0:
        msg = _( "Gap" );
        cmp_name = wxT( "muwave_gap" );
        text_size = gap_size;
        break;

    case 1:
        msg = _( "Stub" );
        cmp_name  = wxT( "muwave_stub" );
        text_size = gap_size;
        pad_count = 2;
        break;

    case 2:
        msg = _( "Arc Stub" );
        cmp_name  = wxT( "muwave_arcstub" );
        pad_count = 1;
        break;

    default:
        msg = wxT( "???" );
        break;
    }

    wxString          value = StringFromValue( g_UserUnit, gap_size );
    wxTextEntryDialog dlg( this, msg, _( "Create microwave module" ), value );

    if( dlg.ShowModal() != wxID_OK )
    {
        m_canvas->MoveCursorToCrossHair();
        return NULL; // cancelled by user
    }

    value    = dlg.GetValue();
    gap_size = ValueFromString( g_UserUnit, value );

    bool abort = false;

    if( shape_type == 2 )
    {
        double            fcoeff = 10.0, fval;
        msg.Printf( wxT( "%3.1f" ), angle / fcoeff );
        wxTextEntryDialog angledlg( this, _( "Angle in degrees:" ),
                                    _( "Create microwave module" ), msg );

        if( angledlg.ShowModal() != wxID_OK )
        {
            m_canvas->MoveCursorToCrossHair();
            return NULL; // cancelled by user
        }

        msg = angledlg.GetValue();

        if( !msg.ToDouble( &fval ) )
        {
            DisplayError( this, _( "Incorrect number, abort" ) );
            abort = true;
        }

        angle = std::abs( KiROUND( fval * fcoeff ) );

        if( angle > 1800 )
            angle = 1800;
    }

    if( abort )
    {
        m_canvas->MoveCursorToCrossHair();
        return NULL;
    }

    module = CreateMuWaveBaseFootprint( cmp_name, text_size, pad_count );
    pad    = module->Pads();

    switch( shape_type )
    {
    case 0:     //Gap :
        oX = -( gap_size + pad->GetSize().x ) / 2;
        pad->SetX0( oX );

        pad->SetX( pad->GetPos0().x + pad->GetPosition().x );

        pad = pad->Next();

        pad->SetX0( oX + gap_size + pad->GetSize().x );
        pad->SetX( pad->GetPos0().x + pad->GetPosition().x );
        break;

    case 1:     //Stub :
        pad->SetPadName( wxT( "1" ) );
        pad = pad->Next();
        pad->SetY0( -( gap_size + pad->GetSize().y ) / 2 );
        pad->SetSize( wxSize( pad->GetSize().x, gap_size ) );
        pad->SetY( pad->GetPos0().y + pad->GetPosition().y );
        break;

    case 2:     // Arc Stub created by a polygonal approach:
    {
        EDGE_MODULE* edge = new EDGE_MODULE( module );
        module->GraphicalItems().PushFront( edge );

        edge->SetShape( S_POLYGON );
        edge->SetLayer( F_Cu );

        int numPoints = (angle / 50) + 3;     // Note: angles are in 0.1 degrees
        std::vector<wxPoint>& polyPoints = edge->GetPolyPoints();
        polyPoints.reserve( numPoints );

        edge->m_Start0.y = -pad->GetSize().y / 2;

        polyPoints.push_back( wxPoint( 0, 0 ) );

        int theta = -angle / 2;

        for( int ii = 1; ii<numPoints - 1; ii++ )
        {
            wxPoint pt( 0, -gap_size );

            RotatePoint( &pt.x, &pt.y, theta );

            polyPoints.push_back( pt );

            theta += 50;

            if( theta > angle / 2 )
                theta = angle / 2;
        }

        // Close the polygon:
        polyPoints.push_back( polyPoints[0] );
    }
        break;

    default:
        break;
    }

    module->CalculateBoundingBox();
    GetBoard()->m_Status_Pcb = 0;
    OnModify();
    return module;
}