Example #1
0
/* Redraw the current graphic item during its creation
 * Use this function to show a new outline, in begin command
 */
static void ShowNewEdgeModule( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
                               bool aErase )
{
    BASE_SCREEN* screen = aPanel->GetScreen();
    EDGE_MODULE* edge   = (EDGE_MODULE*) screen->GetCurItem();

    if( edge == NULL )
        return;

    MODULE* module = (MODULE*) edge->GetParent();

    //  if( erase )
    {
        edge->Draw( aPanel, aDC, GR_XOR );
    }

    edge->SetEnd( aPanel->GetParent()->GetCrossHairPosition() );

    // Update relative coordinate.
    edge->SetEnd0( edge->GetEnd() - module->GetPosition() );

    wxPoint pt( edge->GetEnd0() );

    RotatePoint( &pt, -module->GetOrientation() );

    edge->SetEnd0( pt );

    edge->Draw( aPanel, aDC, GR_XOR );

    module->CalculateBoundingBox();
}
int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
{
    boost::optional<VECTOR2D> startingPoint;

    if( m_editModules )
    {
        m_frame->SetToolID( ID_MODEDIT_LINE_TOOL, wxCURSOR_PENCIL, _( "Add graphic line" ) );

        EDGE_MODULE* line = new EDGE_MODULE( m_board->m_Modules );

        while( drawSegment( S_SEGMENT, reinterpret_cast<DRAWSEGMENT*&>( line ), startingPoint  ) )
        {
            if( line )
            {
                m_frame->OnModify();
                m_frame->SaveCopyInUndoList( m_board->m_Modules, UR_MODEDIT );
                line->SetParent( m_board->m_Modules );
                line->SetLocalCoord();
                m_board->m_Modules->GraphicalItems().PushFront( line );
                startingPoint = line->GetEnd();
            }
            else
            {
                startingPoint = boost::none;
            }

            line = new EDGE_MODULE( m_board->m_Modules );
        }
    }
    else // !m_editModules case
    {
        m_frame->SetToolID( ID_PCB_ADD_LINE_BUTT, wxCURSOR_PENCIL, _( "Add graphic line" ) );

        DRAWSEGMENT* line = new DRAWSEGMENT;

        while( drawSegment( S_SEGMENT, line, startingPoint ) )
        {
            if( line )
            {
                m_board->Add( line );
                m_frame->OnModify();
                m_frame->SaveCopyInUndoList( line, UR_NEW );
                startingPoint = line->GetEnd();
            }
            else
            {
                startingPoint = boost::none;
            }

            line = new DRAWSEGMENT;
        }
    }

    m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );

    return 0;
}
/* Move marked items, at new position = old position + offset
 */
void MoveMarkedItems( MODULE* module, wxPoint offset )
{
    EDA_ITEM* item;

    if( module == NULL )
        return;

    if( module->Reference().IsSelected() )
        module->Reference().Move( offset );

    if( module->Value().IsSelected() )
        module->Value().Move( offset );

    D_PAD* pad = module->Pads();

    for( ; pad != NULL; pad = pad->Next() )
    {
        if( !pad->IsSelected() )
            continue;

        pad->SetPosition( pad->GetPosition() + offset );
        pad->SetPos0( pad->GetPos0() + offset );
    }

    item = module->GraphicalItems();

    for( ; item != NULL; item = item->Next() )
    {
        if( !item->IsSelected() )
            continue;

        switch( item->Type() )
        {
        case PCB_MODULE_TEXT_T:
            static_cast<TEXTE_MODULE*>( item )->Move( offset );
            break;

        case PCB_MODULE_EDGE_T:
        {
            EDGE_MODULE* em = (EDGE_MODULE*) item;
            em->SetStart( em->GetStart() + offset );
            em->SetEnd( em->GetEnd() + offset );
            em->SetStart0( em->GetStart0() + offset );
            em->SetEnd0( em->GetEnd0() + offset );
        }
        break;

        default:
            ;
        }
    }

    ClearMarkItems( module );
}
/* Move marked items, at new position = old position + offset
 */
void MoveMarkedItems( MODULE* module, wxPoint offset )
{
    EDA_ITEM* item;

    if( module == NULL )
        return;

    D_PAD* pad = module->Pads();

    for( ; pad != NULL; pad = pad->Next() )
    {
        if( !pad->IsSelected() )
            continue;

        pad->SetPosition( pad->GetPosition() + offset );
        pad->SetPos0( pad->GetPos0() + offset );
    }

    item = module->GraphicalItems();

    for( ; item != NULL; item = item->Next() )
    {
        if( !item->IsSelected() )
            continue;

        switch( item->Type() )
        {
        case PCB_MODULE_TEXT_T:
        {
            TEXTE_MODULE* tm = (TEXTE_MODULE*) item;
            tm->Offset( offset );
            tm->SetPos0( tm->GetPos0() + offset );
        }
        break;

        case PCB_MODULE_EDGE_T:
        {
            EDGE_MODULE* em = (EDGE_MODULE*) item;
            em->SetStart( em->GetStart() + offset );
            em->SetEnd( em->GetEnd() + offset );
            em->SetStart0( em->GetStart0() + offset );
            em->SetEnd0( em->GetEnd0() + offset );
        }
        break;

        default:
            ;
        }

        item->ClearFlags();
    }
}
Example #5
0
MODULE* MWAVE::CreateMicrowaveInductor( INDUCTOR_PATTERN& inductorPattern,
                    PCB_EDIT_FRAME* aPcbFrame, wxString& aErrorMessage )
{
    /* Build a microwave inductor footprint.
     * - Length Mself.lng
     * - Extremities Mself.m_Start and Mself.m_End
     * We must determine:
     * Mself.nbrin = number of segments perpendicular to the direction
     * (The coil nbrin will demicercles + 1 + 2 1 / 4 circle)
     * Mself.lbrin = length of a strand
     * Mself.radius = radius of rounded parts of the coil
     * Mself.delta = segments extremities connection between him and the coil even
     *
     * The equations are
     * Mself.m_Size.x = 2 * Mself.radius + Mself.lbrin
     * Mself.m_Size.y * Mself.delta = 2 + 2 * Mself.nbrin * Mself.radius
     * Mself.lng = 2 * Mself.delta / / connections to the coil
     + (Mself.nbrin-2) * Mself.lbrin / / length of the strands except 1st and last
     + (Mself.nbrin 1) * (PI * Mself.radius) / / length of rounded
     * Mself.lbrin + / 2 - Melf.radius * 2) / / length of 1st and last bit
     *
     * The constraints are:
     * Nbrin >= 2
     * Mself.radius < Mself.m_Size.x
     * Mself.m_Size.y = Mself.radius * 4 + 2 * Mself.raccord
     * Mself.lbrin> Mself.radius * 2
     *
     * The calculation is conducted in the following way:
     * Initially:
     * Nbrin = 2
     * Radius = 4 * m_Size.x (arbitrarily fixed value)
     * Then:
     * Increasing the number of segments to the desired length
     * (Radius decreases if necessary)
     */

    D_PAD*   pad;
    int      ll;
    wxString msg;

    auto pt = inductorPattern.m_End - inductorPattern.m_Start;
    int     min_len = KiROUND( EuclideanNorm( pt ) );
    inductorPattern.m_length = min_len;

    // Enter the desired length.
    msg = StringFromValue( g_UserUnit, inductorPattern.m_length );
    wxTextEntryDialog dlg( nullptr, wxEmptyString, _( "Length of Trace:" ), msg );

    if( dlg.ShowModal() != wxID_OK )
        return nullptr; // canceled by user

    msg = dlg.GetValue();
    inductorPattern.m_length = ValueFromString( g_UserUnit, msg );

    // Control values (ii = minimum length)
    if( inductorPattern.m_length < min_len )
    {
        aErrorMessage = _( "Requested length < minimum length" );
        return nullptr;
    }

    // Calculate the elements.
    std::vector <wxPoint> buffer;
    ll = BuildCornersList_S_Shape( buffer, inductorPattern.m_Start,
                                   inductorPattern.m_End, inductorPattern.m_length,
                                   inductorPattern.m_Width );

    if( !ll )
    {
        aErrorMessage = _( "Requested length too large" );
        return nullptr;
    }

    // Generate footprint. the value is also used as footprint name.
    msg = "L";
    wxTextEntryDialog cmpdlg( nullptr, wxEmptyString, _( "Component Value:" ), msg );
    cmpdlg.SetTextValidator( FILE_NAME_CHAR_VALIDATOR( &msg ) );

    if( ( cmpdlg.ShowModal() != wxID_OK ) || msg.IsEmpty() )
        return nullptr;    //  Aborted by user

    MODULE* module = aPcbFrame->CreateNewModule( msg );

    // here the module is already in the BOARD, CreateNewModule() does that.
    module->SetFPID( LIB_ID( wxString( "mw_inductor" ) ) );
    module->SetAttributes( MOD_VIRTUAL | MOD_CMS );
    module->ClearFlags();
    module->SetPosition( inductorPattern.m_End );

    // Generate segments
    for( unsigned jj = 1; jj < buffer.size(); jj++ )
    {
        EDGE_MODULE* PtSegm;
        PtSegm = new EDGE_MODULE( module );
        PtSegm->SetStart( buffer[jj - 1] );
        PtSegm->SetEnd( buffer[jj] );
        PtSegm->SetWidth( inductorPattern.m_Width );
        PtSegm->SetLayer( module->GetLayer() );
        PtSegm->SetShape( S_SEGMENT );
        PtSegm->SetStart0( PtSegm->GetStart() - module->GetPosition() );
        PtSegm->SetEnd0( PtSegm->GetEnd() - module->GetPosition() );
        module->GraphicalItemsList().PushBack( PtSegm );
    }

    // Place a pad on each end of coil.
    pad = new D_PAD( module );

    module->PadsList().PushFront( pad );

    pad->SetName( "1" );
    pad->SetPosition( inductorPattern.m_End );
    pad->SetPos0( pad->GetPosition() - module->GetPosition() );

    pad->SetSize( wxSize( inductorPattern.m_Width, inductorPattern.m_Width ) );

    pad->SetLayerSet( LSET( module->GetLayer() ) );
    pad->SetAttribute( PAD_ATTRIB_SMD );
    pad->SetShape( PAD_SHAPE_CIRCLE );

    D_PAD* newpad = new D_PAD( *pad );

    module->PadsList().Insert( newpad, pad->Next() );

    pad = newpad;
    pad->SetName( "2" );
    pad->SetPosition( inductorPattern.m_Start );
    pad->SetPos0( pad->GetPosition() - module->GetPosition() );

    // Modify text positions.
    wxPoint refPos( ( inductorPattern.m_Start.x + inductorPattern.m_End.x ) / 2,
                    ( inductorPattern.m_Start.y + inductorPattern.m_End.y ) / 2 );

    wxPoint valPos = refPos;

    refPos.y -= module->Reference().GetTextSize().y;
    module->Reference().SetPosition( refPos );
    valPos.y += module->Value().GetTextSize().y;
    module->Value().SetPosition( valPos );

    module->CalculateBoundingBox();
    return module;
}
/** Rotate marked items, refer to a rotation point at position offset
 * Note: because this function is used in global transform,
 * if force_all is true, all items will be rotated
 */
void RotateMarkedItems( MODULE* module, wxPoint offset, bool force_all )
{
#define ROTATE( z ) RotatePoint( (&z), offset, 900 )

    if( module == NULL )
        return;

    for( D_PAD* pad = module->Pads();  pad;  pad = pad->Next() )
    {
        if( !pad->IsSelected() && !force_all )
            continue;

        wxPoint pos = pad->GetPosition();
        ROTATE( pos );
        pad->SetPosition( pos );

        pad->SetPos0( pad->GetPosition() );
        pad->SetOrientation( pad->GetOrientation() + 900 );
    }

    for( EDA_ITEM* item = module->GraphicalItems();  item;  item = item->Next() )
    {
        if( !item->IsSelected() && !force_all)
            continue;

        switch( item->Type() )
        {
        case PCB_MODULE_EDGE_T:
        {
            EDGE_MODULE* em = (EDGE_MODULE*) item;

            wxPoint tmp = em->GetStart();
            ROTATE( tmp );
            em->SetStart( tmp );
            em->SetStart0( tmp );

            tmp = em->GetEnd();
            ROTATE( tmp );
            em->SetEnd( tmp );
            em->SetEnd0( tmp );
        }
        break;

        case PCB_MODULE_TEXT_T:
        {
            TEXTE_MODULE* tm = (TEXTE_MODULE*) item;
            wxPoint pos = tm->GetTextPosition();
            ROTATE( pos );
            tm->SetTextPosition( pos );
            tm->SetPos0( tm->GetTextPosition() );
            tm->SetOrientation( tm->GetOrientation() + 900 );
        }
        break;

        default:
            ;
        }

        item->ClearFlags();
    }
}
Example #7
0
/**
 * Function PlaceCells
 * Initialize the matrix routing by setting obstacles for each occupied cell
 * a cell set to HOLE is an obstacle for tracks and vias
 * a cell set to VIA_IMPOSSIBLE is an obstacle for vias only.
 * a cell set to CELL_is_EDGE is a frontier.
 * Tracks and vias having the same net code as net_code are skipped
 * (htey do not are obstacles)
 *
 * For single-sided Routing 1:
 * BOTTOM side is used, and Route_Layer_BOTTOM = Route_Layer_TOP
 *
 * If flag == FORCE_PADS: all pads will be put in matrix as obstacles.
 */
void PlaceCells( BOARD* aPcb, int net_code, int flag )
{
    int       ux0 = 0, uy0 = 0, ux1, uy1, dx, dy;
    int       marge, via_marge;
    LAYER_MSK layerMask;

    // use the default NETCLASS?
    NETCLASS* nc = aPcb->m_NetClasses.GetDefault();

    int       trackWidth = nc->GetTrackWidth();
    int       clearance  = nc->GetClearance();
    int       viaSize    = nc->GetViaDiameter();

    marge     = clearance + (trackWidth / 2);
    via_marge = clearance + (viaSize / 2);

    // Place PADS on matrix routing:
    for( unsigned i = 0; i < aPcb->GetPadCount(); ++i )
    {
        D_PAD* pad = aPcb->GetPad( i );

        if( net_code != pad->GetNet() || (flag & FORCE_PADS) )
        {
            ::PlacePad( pad, HOLE, marge, WRITE_CELL );
        }

        ::PlacePad( pad, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
    }

    // Place outlines of modules on matrix routing, if they are on a copper layer
    // or on the edge layer
    TRACK tmpSegm( NULL );  // A dummy track used to create segments.

    for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
    {
        for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() )
        {
            switch( item->Type() )
            {
            case PCB_MODULE_EDGE_T:
            {
                EDGE_MODULE* edge = (EDGE_MODULE*) item;

                tmpSegm.SetLayer( edge->GetLayer() );

                if( tmpSegm.GetLayer() == EDGE_N )
                    tmpSegm.SetLayer( UNDEFINED_LAYER );

                tmpSegm.SetStart( edge->GetStart() );
                tmpSegm.SetEnd(   edge->GetEnd() );
                tmpSegm.SetShape( edge->GetShape() );
                tmpSegm.SetWidth( edge->GetWidth() );
                tmpSegm.m_Param = edge->GetAngle();
                tmpSegm.SetNet( -1 );

                TraceSegmentPcb( &tmpSegm, HOLE, marge, WRITE_CELL );
                TraceSegmentPcb( &tmpSegm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
            }
            break;

            default:
                break;
            }
        }
    }

    // Place board outlines and texts on copper layers:
    for( BOARD_ITEM* item = aPcb->m_Drawings; item; item = item->Next() )
    {
        switch( item->Type() )
        {
        case PCB_LINE_T:
        {
            DRAWSEGMENT* DrawSegm;

            int          type_cell = HOLE;
            DrawSegm = (DRAWSEGMENT*) item;
            tmpSegm.SetLayer( DrawSegm->GetLayer() );

            if( DrawSegm->GetLayer() == EDGE_N )
            {
                tmpSegm.SetLayer( UNDEFINED_LAYER );
                type_cell |= CELL_is_EDGE;
            }

            tmpSegm.SetStart( DrawSegm->GetStart() );
            tmpSegm.SetEnd(   DrawSegm->GetEnd() );
            tmpSegm.SetShape( DrawSegm->GetShape() );
            tmpSegm.SetWidth( DrawSegm->GetWidth() );
            tmpSegm.m_Param = DrawSegm->GetAngle();
            tmpSegm.SetNet( -1 );

            TraceSegmentPcb( &tmpSegm, type_cell, marge, WRITE_CELL );
        }
        break;

        case PCB_TEXT_T:
        {
            TEXTE_PCB* PtText;
            PtText = (TEXTE_PCB*) item;

            if( PtText->GetText().Length() == 0 )
                break;

            EDA_RECT textbox = PtText->GetTextBox( -1 );
            ux0 = textbox.GetX();
            uy0 = textbox.GetY();
            dx  = textbox.GetWidth();
            dy  = textbox.GetHeight();

            /* Put bounding box (rectangle) on matrix */
            dx /= 2;
            dy /= 2;

            ux1 = ux0 + dx;
            uy1 = uy0 + dy;

            ux0 -= dx;
            uy0 -= dy;

            layerMask = GetLayerMask( PtText->GetLayer() );

            TraceFilledRectangle( ux0 - marge, uy0 - marge, ux1 + marge,
                                  uy1 + marge, PtText->GetOrientation(),
                                  layerMask, HOLE, WRITE_CELL );

            TraceFilledRectangle( ux0 - via_marge, uy0 - via_marge,
                                  ux1 + via_marge, uy1 + via_marge,
                                  PtText->GetOrientation(),
                                  layerMask, VIA_IMPOSSIBLE, WRITE_OR_CELL );
        }
        break;

        default:
            break;
        }
    }

    /* Put tracks and vias on matrix */
    for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
    {
        if( net_code == track->GetNet() )
            continue;

        TraceSegmentPcb( track, HOLE, marge, WRITE_CELL );
        TraceSegmentPcb( track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
    }
}
bool DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::TransferDataToWindow()
{
    // Set unit symbol
    wxStaticText* texts_unit[] =
    {
        m_StartPointXUnit,
        m_StartPointYUnit,
        m_EndPointXUnit,
        m_EndPointYUnit,
        m_ThicknessTextUnit,
        m_DefaulThicknessTextUnit,
    };

    for( size_t ii = 0; ii < DIM( texts_unit ); ii++ )
    {
        texts_unit[ii]->SetLabel( GetAbbreviatedUnitsLabel() );
    }

    wxString msg;

    // Change texts according to the segment shape:
    switch( m_item->GetShape() )
    {
    case S_CIRCLE:
        SetTitle( _( "Circle Properties" ) );
        m_StartPointXLabel->SetLabel( _( "Center X" ) );
        m_StartPointYLabel->SetLabel( _( "Center Y" ) );
        m_EndPointXLabel->SetLabel( _( "Point X" ) );
        m_EndPointYLabel->SetLabel( _( "Point Y" ) );
        m_AngleText->Show( false );
        m_AngleCtrl->Show( false );
        m_AngleUnit->Show( false );
        break;

    case S_ARC:
        SetTitle( _( "Arc Properties" ) );
        m_StartPointXLabel->SetLabel( _( "Center X" ) );
        m_StartPointYLabel->SetLabel( _( "Center Y" ) );
        m_EndPointXLabel->SetLabel( _( "Start Point X" ) );
        m_EndPointYLabel->SetLabel( _( "Start Point Y" ) );

        m_AngleValue = m_item->GetAngle() / 10.0;
        break;

    case S_SEGMENT:
        SetTitle( _( "Line Segment Properties" ) );

        // Fall through.
    default:
        m_AngleText->Show( false );
        m_AngleCtrl->Show( false );
        m_AngleUnit->Show( false );
        break;
    }

    PutValueInLocalUnits( *m_Center_StartXCtrl, m_item->GetStart().x );

    PutValueInLocalUnits( *m_Center_StartYCtrl, m_item->GetStart().y );

    PutValueInLocalUnits( *m_EndX_Radius_Ctrl, m_item->GetEnd().x );

    PutValueInLocalUnits( *m_EndY_Ctrl, m_item->GetEnd().y );

    PutValueInLocalUnits( *m_ThicknessCtrl, m_item->GetWidth() );

    PutValueInLocalUnits( *m_DefaultThicknessCtrl, m_brdSettings.m_ModuleSegmentWidth );

    // Configure the layers list selector
    m_LayerSelectionCtrl->SetLayersHotkeys( false );
    m_LayerSelectionCtrl->SetLayerSet( LSET::InternalCuMask().set( Edge_Cuts ) );
    m_LayerSelectionCtrl->SetBoardFrame( m_parent );
    m_LayerSelectionCtrl->Resync();

    if( m_LayerSelectionCtrl->SetLayerSelection( m_item->GetLayer() ) < 0 )
    {
        wxMessageBox( _( "This item was on an unknown layer.\n"
                         "It has been moved to the front silk screen layer. Please fix it." ) );
        m_LayerSelectionCtrl->SetLayerSelection( F_SilkS );
    }

    return DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataToWindow();
}
void DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::initDlg()
/* Initialize messages and values in text control,
 * according to the item parameters values
*/
{
    SetFocus();
    m_StandardButtonsSizerOK->SetDefault();

    // Set unit symbol
    wxStaticText * texts_unit[] =
    {
        m_StartPointXUnit,
        m_StartPointYUnit,
        m_EndPointXUnit,
        m_EndPointYUnit,
        m_ThicknessTextUnit,
        m_DefaulThicknessTextUnit,
        NULL
    };

    for( int ii = 0; ; ii++ )
    {
        if( texts_unit[ii] == NULL )
            break;
        texts_unit[ii]->SetLabel( GetAbbreviatedUnitsLabel() );
    }

    wxString msg;

    // Change texts according to the segment shape:
    switch ( m_item->GetShape() )
    {
    case S_CIRCLE:
        m_StartPointXLabel->SetLabel(_("Center X"));
        m_StartPointYLabel->SetLabel(_("Center Y"));
        m_EndPointXLabel->SetLabel(_("Point X"));
        m_EndPointYLabel->SetLabel(_("Point Y"));
        m_Angle_Text->Show(false);
        m_Angle_Ctrl->Show(false);
        m_AngleUnit->Show(false);
        break;

    case S_ARC:
        m_StartPointXLabel->SetLabel(_("Center X"));
        m_StartPointYLabel->SetLabel(_("Center Y"));
        m_EndPointXLabel->SetLabel(_("Start Point X"));
        m_EndPointYLabel->SetLabel(_("Start Point Y"));

        // Here the angle is a double, but the UI is still working
        // with integers
        msg << int( m_item->GetAngle() );
        m_Angle_Ctrl->SetValue(msg);
        break;

    default:
        m_Angle_Text->Show(false);
        m_Angle_Ctrl->Show(false);
        m_AngleUnit->Show(false);
        break;
    }

    PutValueInLocalUnits( *m_Center_StartXCtrl, m_item->GetStart().x );

    PutValueInLocalUnits( *m_Center_StartYCtrl, m_item->GetStart().y );

    PutValueInLocalUnits( *m_EndX_Radius_Ctrl, m_item->GetEnd().x );

    PutValueInLocalUnits( *m_EndY_Ctrl, m_item->GetEnd().y );

    PutValueInLocalUnits( *m_ThicknessCtrl, m_item->GetWidth() );

    PutValueInLocalUnits( *m_DefaultThicknessCtrl, m_brdSettings.m_ModuleSegmentWidth );

    // Configure the layers list selector
    m_LayerSelectionCtrl->SetLayersHotkeys( false );
    m_LayerSelectionCtrl->SetLayerMask( INTERNAL_CU_LAYERS|EDGE_LAYER );
    m_LayerSelectionCtrl->SetBoardFrame( m_parent );
    m_LayerSelectionCtrl->Resync();
    if( m_LayerSelectionCtrl->SetLayerSelection( m_item->GetLayer() ) < 0 )
    {
        wxMessageBox( _("This item has an illegal layer id.\n"
                        "Now, forced on the front silk screen layer. Please, fix it") );
        m_LayerSelectionCtrl->SetLayerSelection( SILKSCREEN_N_FRONT );
    }
}
/* 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;
        }
    }
Example #11
0
MODULE* PCB_EDIT_FRAME::Genere_Self( wxDC* DC )
{
    D_PAD*   pad;
    int      ll;
    wxString msg;

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

    if( s_inductor_pattern.m_Flag == false )
    {
        DisplayError( this, wxT( "Starting point not init.." ) );
        return NULL;
    }

    s_inductor_pattern.m_Flag = false;

    s_inductor_pattern.m_End = GetCrossHairPosition();

    wxPoint pt = s_inductor_pattern.m_End - s_inductor_pattern.m_Start;
    int     min_len = KiROUND( EuclideanNorm( pt ) );
    s_inductor_pattern.m_lenght = min_len;

    // Enter the desired length.
    msg = StringFromValue( g_UserUnit, s_inductor_pattern.m_lenght );
    wxTextEntryDialog dlg( this, wxEmptyString, _( "Length of Trace:" ), msg );

    if( dlg.ShowModal() != wxID_OK )
        return NULL; // canceled by user

    msg = dlg.GetValue();
    s_inductor_pattern.m_lenght = ValueFromString( g_UserUnit, msg );

    // Control values (ii = minimum length)
    if( s_inductor_pattern.m_lenght < min_len )
    {
        DisplayError( this, _( "Requested length < minimum length" ) );
        return NULL;
    }

    // Calculate the elements.
    s_inductor_pattern.m_Width = GetDesignSettings().GetCurrentTrackWidth();

    std::vector <wxPoint> buffer;
    ll = BuildCornersList_S_Shape( buffer, s_inductor_pattern.m_Start,
                                   s_inductor_pattern.m_End, s_inductor_pattern.m_lenght,
                                   s_inductor_pattern.m_Width );

    if( !ll )
    {
        DisplayError( this, _( "Requested length too large" ) );
        return NULL;
    }

    // Generate footprint. the value is also used as footprint name.
    msg.Empty();
    wxTextEntryDialog cmpdlg( this, wxEmptyString, _( "Component Value:" ), msg );
    cmpdlg.SetTextValidator( FILE_NAME_CHAR_VALIDATOR( &msg ) );

    if( ( cmpdlg.ShowModal() != wxID_OK ) || msg.IsEmpty() )
        return NULL;    //  Aborted by user

    MODULE* module = CreateNewModule( msg );

    // here the module is already in the BOARD, CreateNewModule() does that.
    module->SetFPID( FPID( std::string( "mw_inductor" ) ) );
    module->SetAttributes( MOD_VIRTUAL | MOD_CMS );
    module->ClearFlags();
    module->SetPosition( s_inductor_pattern.m_End );

    // Generate segments
    for( unsigned jj = 1; jj < buffer.size(); jj++ )
    {
        EDGE_MODULE* PtSegm;
        PtSegm = new EDGE_MODULE( module );
        PtSegm->SetStart( buffer[jj - 1] );
        PtSegm->SetEnd( buffer[jj] );
        PtSegm->SetWidth( s_inductor_pattern.m_Width );
        PtSegm->SetLayer( module->GetLayer() );
        PtSegm->SetShape( S_SEGMENT );
        PtSegm->SetStart0( PtSegm->GetStart() - module->GetPosition() );
        PtSegm->SetEnd0( PtSegm->GetEnd() - module->GetPosition() );
        module->GraphicalItems().PushBack( PtSegm );
    }

    // Place a pad on each end of coil.
    pad = new D_PAD( module );

    module->Pads().PushFront( pad );

    pad->SetPadName( wxT( "1" ) );
    pad->SetPosition( s_inductor_pattern.m_End );
    pad->SetPos0( pad->GetPosition() - module->GetPosition() );

    pad->SetSize( wxSize( s_inductor_pattern.m_Width, s_inductor_pattern.m_Width ) );

    pad->SetLayerSet( LSET( module->GetLayer() ) );
    pad->SetAttribute( PAD_ATTRIB_SMD );
    pad->SetShape( PAD_SHAPE_CIRCLE );

    D_PAD* newpad = new D_PAD( *pad );

    module->Pads().Insert( newpad, pad->Next() );

    pad = newpad;
    pad->SetPadName( wxT( "2" ) );
    pad->SetPosition( s_inductor_pattern.m_Start );
    pad->SetPos0( pad->GetPosition() - module->GetPosition() );

    // Modify text positions.
    SetMsgPanel( module );

    wxPoint refPos( ( s_inductor_pattern.m_Start.x + s_inductor_pattern.m_End.x ) / 2,
                    ( s_inductor_pattern.m_Start.y + s_inductor_pattern.m_End.y ) / 2 );

    wxPoint valPos = refPos;

    refPos.y -= module->Reference().GetSize().y;
    module->Reference().SetPosition( refPos );
    valPos.y += module->Value().GetSize().y;
    module->Value().SetPosition( valPos );

    module->CalculateBoundingBox();
    module->Draw( m_canvas, DC, GR_OR );

    return module;
}
void MODULE::Flip( const wxPoint& aCentre )
{
    TEXTE_MODULE* text;

    // Move module to its final position:
    wxPoint finalPos = m_Pos;

    finalPos.y  = aCentre.y - ( finalPos.y - aCentre.y );     /// Mirror the Y position

    SetPosition( finalPos );

    // Flip layer
    SetLayer( FlipLayer( GetLayer() ) );

    // Reverse mirror orientation.
    NEGATE( m_Orient );
    NORMALIZE_ANGLE_POS( m_Orient );

    // Mirror pads to other side of board about the x axis, i.e. vertically.
    for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
        pad->Flip( m_Pos );

    // Mirror reference.
    text = m_Reference;
    text->m_Pos.y -= m_Pos.y;
    NEGATE( text->m_Pos.y );
    text->m_Pos.y += m_Pos.y;
    NEGATE(text->m_Pos0.y);
    NEGATE_AND_NORMALIZE_ANGLE_POS( text->m_Orient );
    text->SetLayer( FlipLayer( text->GetLayer() ) );
    text->m_Mirror = IsBackLayer( GetLayer() );

    // Mirror value.
    text = m_Value;
    text->m_Pos.y -= m_Pos.y;
    NEGATE( text->m_Pos.y );
    text->m_Pos.y += m_Pos.y;
    NEGATE( text->m_Pos0.y );
    NEGATE_AND_NORMALIZE_ANGLE_POS( text->m_Orient );
    text->SetLayer( FlipLayer( text->GetLayer() ) );
    text->m_Mirror = IsBackLayer( GetLayer() );

    // Reverse mirror module graphics and texts.
    for( EDA_ITEM* item = m_Drawings; item; item = item->Next() )
    {
        switch( item->Type() )
        {
        case PCB_MODULE_EDGE_T:
            {
                EDGE_MODULE* em = (EDGE_MODULE*) item;

                wxPoint s = em->GetStart();
                s.y -= m_Pos.y;
                s.y  = -s.y;
                s.y += m_Pos.y;
                em->SetStart( s );

                wxPoint e = em->GetEnd();
                e.y -= m_Pos.y;
                e.y  = -e.y;
                e.y += m_Pos.y;
                em->SetEnd( e );

                NEGATE( em->m_Start0.y );
                NEGATE( em->m_End0.y );

                if( em->GetShape() == S_ARC )
                {
                    em->SetAngle( -em->GetAngle() );
                }

                em->SetLayer( FlipLayer( em->GetLayer() ) );
            }
            break;

        case PCB_MODULE_TEXT_T:
            text = (TEXTE_MODULE*) item;
            text->m_Pos.y -= m_Pos.y;
            NEGATE( text->m_Pos.y );
            text->m_Pos.y += m_Pos.y;
            NEGATE( text->m_Pos0.y );
            NEGATE_AND_NORMALIZE_ANGLE_POS( text->m_Orient );
            text->SetLayer( FlipLayer( text->GetLayer() ) );
            text->m_Mirror = IsBackLayer( GetLayer() );
            break;

        default:
            wxMessageBox( wxT( "MODULE::Flip() error: Unknown Draw Type" ) );
            break;
        }
    }

    CalculateBoundingBox();
}
Example #13
0
MODULE* PCB_EDIT_FRAME::Genere_Self( wxDC* DC )
{
    D_PAD*   pad;
    int      ll;
    wxString msg;

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

    if( Self_On == 0 )
    {
        DisplayError( this, wxT( "Starting point not init.." ) );
        return NULL;
    }

    Self_On = 0;

    Mself.m_End = GetCrossHairPosition();

    wxPoint pt = Mself.m_End - Mself.m_Start;
    int     min_len = KiROUND( EuclideanNorm( pt ) );
    Mself.lng = min_len;

    // Enter the desired length.
    msg = StringFromValue( g_UserUnit, Mself.lng );
    wxTextEntryDialog dlg( this, _( "Length:" ), _( "Length" ), msg );

    if( dlg.ShowModal() != wxID_OK )
        return NULL; // canceled by user

    msg = dlg.GetValue();
    Mself.lng = ValueFromString( g_UserUnit, msg );

    // Control values (ii = minimum length)
    if( Mself.lng < min_len )
    {
        DisplayError( this, _( "Requested length < minimum length" ) );
        return NULL;
    }

    // Calculate the elements.
    Mself.m_Width = GetBoard()->GetCurrentTrackWidth();

    std::vector <wxPoint> buffer;
    ll = BuildCornersList_S_Shape( buffer, Mself.m_Start, Mself.m_End, Mself.lng, Mself.m_Width );

    if( !ll )
    {
        DisplayError( this, _( "Requested length too large" ) );
        return NULL;
    }

    // Generate module.
    MODULE* module;
    module = Create_1_Module( wxEmptyString );

    if( module == NULL )
        return NULL;

    // here the module is already in the BOARD, Create_1_Module() does that.
    module->SetFPID( FPID( std::string( "MuSelf" ) ) );
    module->SetAttributes( MOD_VIRTUAL | MOD_CMS );
    module->ClearFlags();
    module->SetPosition( Mself.m_End );

    // Generate segments
    for( unsigned jj = 1; jj < buffer.size(); jj++ )
    {
        EDGE_MODULE* PtSegm;
        PtSegm = new EDGE_MODULE( module );
        PtSegm->SetStart( buffer[jj - 1] );
        PtSegm->SetEnd( buffer[jj] );
        PtSegm->SetWidth( Mself.m_Width );
        PtSegm->SetLayer( module->GetLayer() );
        PtSegm->SetShape( S_SEGMENT );
        PtSegm->SetStart0( PtSegm->GetStart() - module->GetPosition() );
        PtSegm->SetEnd0(   PtSegm->GetEnd()   - module->GetPosition() );
        module->GraphicalItems().PushBack( PtSegm );
    }

    // Place a pad on each end of coil.
    pad = new D_PAD( module );

    module->Pads().PushFront( pad );

    pad->SetPadName( wxT( "1" ) );
    pad->SetPosition( Mself.m_End );
    pad->SetPos0( pad->GetPosition() - module->GetPosition() );

    pad->SetSize( wxSize( Mself.m_Width, Mself.m_Width ) );

    pad->SetLayerMask( GetLayerMask( module->GetLayer() ) );
    pad->SetAttribute( PAD_SMD );
    pad->SetShape( PAD_CIRCLE );

    D_PAD* newpad = new D_PAD( *pad );

    module->Pads().Insert( newpad, pad->Next() );

    pad = newpad;
    pad->SetPadName( wxT( "2" ) );
    pad->SetPosition( Mself.m_Start );
    pad->SetPos0( pad->GetPosition() - module->GetPosition() );

    // Modify text positions.
    SetMsgPanel( module );

    wxPoint refPos( ( Mself.m_Start.x + Mself.m_End.x ) / 2,
                    ( Mself.m_Start.y + Mself.m_End.y ) / 2 );

    wxPoint valPos = refPos;

    refPos.y -= module->Reference().GetSize().y;
    module->Reference().SetTextPosition( refPos );
    valPos.y += module->Value().GetSize().y;
    module->Value().SetTextPosition( valPos );
    module->Reference().SetPos0( module->Reference().GetTextPosition() - module->GetPosition() );
    module->Value().SetPos0( module->Value().GetTextPosition() - module->GetPosition() );

    module->CalculateBoundingBox();
    module->Draw( m_canvas, DC, GR_OR );

    return module;
}