const EDA_RECT MODULE::GetBoundingBox() const
{
    EDA_RECT area = GetFootprintRect();

    // Calculate extended area including text fields
    area.Merge( m_Reference->GetBoundingBox() );
    area.Merge( m_Value->GetBoundingBox() );

    // Add the Clearance shape size: (shape around the pads when the
    // clearance is shown.  Not optimized, but the draw cost is small
    // (perhaps smaller than optimization).
    int biggest_clearance = GetBoard()->GetBiggestClearanceValue();
    area.Inflate( biggest_clearance );

    return area;
}
EDA_RECT MODULE::GetFootprintRect() const
{
    EDA_RECT area;

    area.SetOrigin( m_Pos );
    area.SetEnd( m_Pos );
    area.Inflate( Millimeter2iu( 0.25 ) );   // Give a min size to the area

    for( const BOARD_ITEM* item = m_Drawings.GetFirst(); item; item = item->Next() )
    {
        const EDGE_MODULE *edge = dynamic_cast<const EDGE_MODULE*>( item );
        if( edge )
            area.Merge( edge->GetBoundingBox() );
    }

    for( D_PAD* pad = m_Pads;  pad;  pad = pad->Next() )
        area.Merge( pad->GetBoundingBox() );

    return area;
}
Example #3
0
EDA_RECT SELECTION::GetBoundingBox() const
{
    EDA_RECT bbox;

    bbox = Front()->GetBoundingBox();
    auto i = m_items.begin();
    ++i;

    for( ; i != m_items.end(); ++i )
        bbox.Merge( (*i)->GetBoundingBox() );

    return bbox;
}
Example #4
0
VECTOR2I SELECTION::GetCenter() const
{
    VECTOR2I centre;

    if( Size() == 1 )
    {
        centre = static_cast<GERBER_DRAW_ITEM*>( Front() )->GetPosition();
    }
    else
    {
        EDA_RECT bbox = Front()->GetBoundingBox();
        auto i = m_items.begin();
        ++i;

        for( ; i != m_items.end(); ++i )
        {
            bbox.Merge( (*i)->GetBoundingBox() );
        }

        centre = bbox.Centre();
    }

    return centre;
}
Example #5
0
VECTOR2I SELECTION::GetCenter() const
{
    VECTOR2I centre;

    if( Size() == 1 )
    {
        centre = Front()->GetCenter();
    }
    else
    {
        EDA_RECT bbox = Front()->GetBoundingBox();
        auto i = m_items.begin();
        ++i;

        for( ; i != m_items.end(); ++i )
        {
            bbox.Merge( (*i)->GetBoundingBox() );
        }

        centre = bbox.Centre();
    }

    return centre;
}
Example #6
0
const EDA_RECT D_PAD::GetBoundingBox() const
{
    EDA_RECT area;
    wxPoint quadrant1, quadrant2, quadrant3, quadrant4;
    int x, y, r, dx, dy;

    wxPoint center = ShapePos();
    wxPoint endPoint;

    EDA_RECT endRect;

    switch( GetShape() )
    {
    case PAD_SHAPE_CIRCLE:
        area.SetOrigin( center );
        area.Inflate( m_Size.x / 2 );
        break;

    case PAD_SHAPE_OVAL:
        /* To get the BoundingBox of an oval pad:
         * a) If the pad is ROUND, see method for PAD_SHAPE_CIRCLE above
         * OTHERWISE:
         * b) Construct EDA_RECT for portion between circular ends
         * c) Rotate that EDA_RECT
         * d) Add the circular ends to the EDA_RECT
         */

        // Test if the shape is circular
        if( m_Size.x == m_Size.y )
        {
            area.SetOrigin( center );
            area.Inflate( m_Size.x / 2 );
            break;
        }

        if( m_Size.x > m_Size.y )
        {
            // Pad is horizontal
            dx = ( m_Size.x - m_Size.y ) / 2;
            dy = m_Size.y / 2;

            // Location of end-points
            x = dx;
            y = 0;
            r = dy;
        }
        else
        {
            // Pad is vertical
            dx = m_Size.x / 2;
            dy = ( m_Size.y - m_Size.x ) / 2;

            x = 0;
            y = dy;
            r = dx;
        }

        // Construct the center rectangle and rotate
        area.SetOrigin( center );
        area.Inflate( dx, dy );
        area = area.GetBoundingBoxRotated( center, m_Orient );

        endPoint = wxPoint( x, y );
        RotatePoint( &endPoint, m_Orient );

        // Add points at each quadrant of circular regions
        endRect.SetOrigin( center + endPoint );
        endRect.Inflate( r );

        area.Merge( endRect );

        endRect.SetSize( 0, 0 );
        endRect.SetOrigin( center - endPoint );
        endRect.Inflate( r );

        area.Merge( endRect );

        break;

    case PAD_SHAPE_RECT:
    case PAD_SHAPE_ROUNDRECT:
        // Use two opposite corners and track their rotation
        // (use symmetry for other points)
        quadrant1.x =  m_Size.x/2;
        quadrant1.y =  m_Size.y/2;
        quadrant2.x = -m_Size.x/2;
        quadrant2.y =  m_Size.y/2;

        RotatePoint( &quadrant1, m_Orient );
        RotatePoint( &quadrant2, m_Orient );
        dx = std::max( std::abs( quadrant1.x ) , std::abs( quadrant2.x )  );
        dy = std::max( std::abs( quadrant1.y ) , std::abs( quadrant2.y )  );

        // Set the bbox
        area.SetOrigin( ShapePos() );
        area.Inflate( dx, dy );
        break;

    case PAD_SHAPE_TRAPEZOID:
        // Use the four corners and track their rotation
        // (Trapezoids will not be symmetric)

        quadrant1.x =  (m_Size.x + m_DeltaSize.y)/2;
        quadrant1.y =  (m_Size.y - m_DeltaSize.x)/2;

        quadrant2.x = -(m_Size.x + m_DeltaSize.y)/2;
        quadrant2.y =  (m_Size.y + m_DeltaSize.x)/2;

        quadrant3.x = -(m_Size.x - m_DeltaSize.y)/2;
        quadrant3.y = -(m_Size.y + m_DeltaSize.x)/2;

        quadrant4.x =  (m_Size.x - m_DeltaSize.y)/2;
        quadrant4.y = -(m_Size.y - m_DeltaSize.x)/2;

        RotatePoint( &quadrant1, m_Orient );
        RotatePoint( &quadrant2, m_Orient );
        RotatePoint( &quadrant3, m_Orient );
        RotatePoint( &quadrant4, m_Orient );

        x  = std::min( quadrant1.x, std::min( quadrant2.x, std::min( quadrant3.x, quadrant4.x) ) );
        y  = std::min( quadrant1.y, std::min( quadrant2.y, std::min( quadrant3.y, quadrant4.y) ) );
        dx = std::max( quadrant1.x, std::max( quadrant2.x, std::max( quadrant3.x, quadrant4.x) ) );
        dy = std::max( quadrant1.y, std::max( quadrant2.y, std::max( quadrant3.y, quadrant4.y) ) );

        area.SetOrigin( ShapePos().x + x, ShapePos().y + y );
        area.SetSize( dx-x, dy-y );
        break;

    case PAD_SHAPE_CUSTOM:
        {
        SHAPE_POLY_SET polySet( m_customShapeAsPolygon );
        // Move shape to actual position
        CustomShapeAsPolygonToBoardPosition( &polySet, GetPosition(), GetOrientation() );
        quadrant1 = m_Pos;
        quadrant2 = m_Pos;

        for( int cnt = 0; cnt < polySet.OutlineCount(); ++cnt )
        {
            const SHAPE_LINE_CHAIN& poly = polySet.COutline( cnt );

            for( int ii = 0; ii < poly.PointCount(); ++ii )
            {
                quadrant1.x = std::min( quadrant1.x, poly.CPoint( ii ).x );
                quadrant1.y = std::min( quadrant1.y, poly.CPoint( ii ).y );
                quadrant2.x = std::max( quadrant2.x, poly.CPoint( ii ).x );
                quadrant2.y = std::max( quadrant2.y, poly.CPoint( ii ).y );
            }
        }

        area.SetOrigin( quadrant1 );
        area.SetEnd( quadrant2 );
        }
        break;

    default:
        break;
    }

    return area;
}
bool PCB_EDIT_FRAME::AppendBoardFile( const wxString& aFullFileName, int aCtl )
{
    IO_MGR::PCB_FILE_T  pluginType = plugin_type( aFullFileName, aCtl );
    PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) );

    // keep trace of existing items, in order to know what are the new items
    // (for undo command for instance)

    // Tracks are inserted, not append, so mark existing tracks to know what are
    // the new tracks
    for( TRACK* track = GetBoard()->m_Track; track; track = track->Next() )
        track->SetFlags( FLAG0 );

    // Other items are append to the item list, so keep trace to the
    // last existing item is enough
    MODULE* module = GetBoard()->m_Modules.GetLast();
    BOARD_ITEM* drawing = GetBoard()->m_Drawings.GetLast();
    int zonescount = GetBoard()->GetAreaCount();

    // Keep also the count of copper layers, because we can happen boards
    // with different copper layers counts,
    // and the enabled layers
    int initialCopperLayerCount = GetBoard()->GetCopperLayerCount();
    LSET initialEnabledLayers = GetBoard()->GetEnabledLayers();

    try
    {
        PROPERTIES  props;
        char        xbuf[30];
        char        ybuf[30];

        // EAGLE_PLUGIN can use this info to center the BOARD, but it does not yet.
        sprintf( xbuf, "%d", GetPageSizeIU().x );
        sprintf( ybuf, "%d", GetPageSizeIU().y );

        props["page_width"]  = xbuf;
        props["page_height"] = ybuf;

        GetDesignSettings().m_NetClasses.Clear();
        pi->Load( aFullFileName, GetBoard(), &props );
    }
    catch( const IO_ERROR& ioe )
    {
        for( TRACK* track = GetBoard()->m_Track; track; track = track->Next() )
            track->ClearFlags( FLAG0 );

        wxString msg = wxString::Format( _(
                "Error loading board.\n%s" ),
                GetChars( ioe.What() )
                );
        DisplayError( this, msg );

        return false;
    }

    // Now prepare a block move command to place the new items, and
    // prepare the undo command.
    BLOCK_SELECTOR& blockmove = GetScreen()->m_BlockLocate;
    HandleBlockBegin( NULL, BLOCK_PRESELECT_MOVE, wxPoint( 0, 0) );
    PICKED_ITEMS_LIST& blockitemsList = blockmove.GetItems();
    PICKED_ITEMS_LIST undoListPicker;
    ITEM_PICKER picker( NULL, UR_NEW );

    EDA_RECT bbox;          // the new items bounding box, for block move
    bool bboxInit = true;   // true until the bounding box is initialized

    for( TRACK* track = GetBoard()->m_Track; track; track = track->Next() )
    {
        if( track->GetFlags() & FLAG0  )
        {
            track->ClearFlags( FLAG0 );
            continue;
        }

        track->SetFlags( IS_MOVED );
        picker.SetItem( track );
        undoListPicker.PushItem( picker );
        blockitemsList.PushItem( picker );

        if( bboxInit )
            bbox = track->GetBoundingBox();
        else
            bbox.Merge( track->GetBoundingBox() );

        bboxInit = false;
    }

    if( module )
        module = module->Next();
    else
        module = GetBoard()->m_Modules;

    for( ; module; module = module->Next() )
    {
        module->SetFlags( IS_MOVED );
        picker.SetItem( module );
        undoListPicker.PushItem( picker );
        blockitemsList.PushItem( picker );

        if( bboxInit )
            bbox = module->GetBoundingBox();
        else
            bbox.Merge( module->GetBoundingBox() );

        bboxInit = false;
    }

    if( drawing )
        drawing = drawing->Next();
    else
        drawing = GetBoard()->m_Drawings;

    for( ; drawing; drawing = drawing->Next() )
    {
        drawing->SetFlags( IS_MOVED );
        picker.SetItem( drawing );
        undoListPicker.PushItem( picker );
        blockitemsList.PushItem( picker );

        if( bboxInit )
            bbox = drawing->GetBoundingBox();
        else
            bbox.Merge( drawing->GetBoundingBox() );

        bboxInit = false;
    }

    for( ZONE_CONTAINER* zone = GetBoard()->GetArea( zonescount ); zone;
         zone = GetBoard()->GetArea( zonescount ) )
    {
        zone->SetFlags( IS_MOVED );
        picker.SetItem( zone );
        undoListPicker.PushItem( picker );
        blockitemsList.PushItem( picker );
        zonescount++;

        if( bboxInit )
            bbox = zone->GetBoundingBox();
        else
            bbox.Merge( zone->GetBoundingBox() );

        bboxInit = false;
    }

    SaveCopyInUndoList( undoListPicker, UR_NEW );

    // we should not ask PLUGINs to do these items:
    int copperLayerCount = GetBoard()->GetCopperLayerCount();

    if( copperLayerCount > initialCopperLayerCount )
        GetBoard()->SetCopperLayerCount( copperLayerCount );

    // Enable all used layers, and make them visible:
    LSET enabledLayers = GetBoard()->GetEnabledLayers();
    enabledLayers |= initialEnabledLayers;
    GetBoard()->SetEnabledLayers( enabledLayers );
    GetBoard()->SetVisibleLayers( enabledLayers );
    ReCreateLayerBox();
    ReFillLayerWidget();

    if( IsGalCanvasActive() )
        static_cast<PCB_DRAW_PANEL_GAL*>( GetGalCanvas() )->SyncLayersVisibility( GetBoard() );

    GetBoard()->BuildListOfNets();
    GetBoard()->SynchronizeNetsAndNetClasses();

    SetStatusText( wxEmptyString );
    BestZoom();

    // Finish block move command:
    wxPoint cpos = GetNearestGridPosition( bbox.Centre() );
    blockmove.SetOrigin( bbox.GetOrigin() );
    blockmove.SetSize( bbox.GetSize() );
    blockmove.SetLastCursorPosition( cpos );
    HandleBlockEnd( NULL );

    return true;
}
const EDA_RECT DRAWSEGMENT::GetBoundingBox() const
{
    EDA_RECT bbox;

    bbox.SetOrigin( m_Start );

    switch( m_Shape )
    {
    case S_SEGMENT:
        bbox.SetEnd( m_End );
        break;

    case S_CIRCLE:
        bbox.Inflate( GetRadius() );
        break;

    case S_ARC:
        {
            bbox.Merge( m_End );
            wxPoint end = m_End;
            RotatePoint( &end, m_Start, -m_Angle );
            bbox.Merge( end );
        }
        break;

    case S_POLYGON:
        {
            wxPoint p_end;
            MODULE* module = GetParentModule();

            for( unsigned ii = 0; ii < m_PolyPoints.size(); ii++ )
            {
                wxPoint pt = m_PolyPoints[ii];

                if( module ) // Transform, if we belong to a module
                {
                    RotatePoint( &pt, module->GetOrientation() );
                    pt += module->GetPosition();
                }

                if( ii == 0 )
                    p_end = pt;

                bbox.SetX( std::min( bbox.GetX(), pt.x ) );
                bbox.SetY( std::min( bbox.GetY(), pt.y ) );
                p_end.x   = std::max( p_end.x, pt.x );
                p_end.y   = std::max( p_end.y, pt.y );
            }

            bbox.SetEnd( p_end );
        }
        break;

    default:
        ;
    }

    bbox.Inflate( ((m_Width+1) / 2) + 1 );
    bbox.Normalize();

    return bbox;
}
const EDA_RECT DRAWSEGMENT::GetBoundingBox() const
{
    EDA_RECT bbox;

    bbox.SetOrigin( m_Start );

    switch( m_Shape )
    {
    case S_SEGMENT:
        bbox.SetEnd( m_End );
        break;

    case S_CIRCLE:
        bbox.Inflate( GetRadius() );
        break;

    case S_ARC:
        {
            bbox.Merge( m_End );
            wxPoint end = m_End;
            RotatePoint( &end, m_Start, -m_Angle );
            bbox.Merge( end );

            // Determine the starting quarter
            // 0 right-bottom
            // 1 left-bottom
            // 2 left-top
            // 3 right-top
            unsigned int quarter = 0;       // assume right-bottom

            if( m_End.y < m_Start.y )       // change to left-top
                quarter |= 3;

            if( m_End.x < m_Start.x )       // for left side, the LSB is 2nd bit negated
                quarter ^= 1;

            int radius = GetRadius();
            int angle = (int) GetArcAngleStart() % 900 + m_Angle;
            bool directionCW = ( m_Angle > 0 );      // Is the direction of arc clockwise?

            if( !directionCW )
            {
                angle = 900 - angle;
                quarter = ( quarter + 3 ) % 4;       // -1 modulo arithmetic
            }

            while( angle > 900 )
            {
                switch( quarter )
                {
                case 0:
                    bbox.Merge( wxPoint( m_Start.x, m_Start.y + radius ) );     // down
                    break;

                case 1:
                    bbox.Merge( wxPoint( m_Start.x - radius, m_Start.y ) );     // left
                    break;

                case 2:
                    bbox.Merge( wxPoint( m_Start.x, m_Start.y - radius ) );     // up
                    break;

                case 3:
                    bbox.Merge( wxPoint( m_Start.x + radius, m_Start.y ) );     // right
                    break;
                }

                if( directionCW )
                    ++quarter;
                else
                    quarter += 3;       // -1 modulo arithmetic

                quarter %= 4;
                angle -= 900;
            }
        }
        break;

    case S_POLYGON:
        {
            wxPoint p_end;
            MODULE* module = GetParentModule();

            for( unsigned ii = 0; ii < m_PolyPoints.size(); ii++ )
            {
                wxPoint pt = m_PolyPoints[ii];

                if( module ) // Transform, if we belong to a module
                {
                    RotatePoint( &pt, module->GetOrientation() );
                    pt += module->GetPosition();
                }

                if( ii == 0 )
                    p_end = pt;

                bbox.SetX( std::min( bbox.GetX(), pt.x ) );
                bbox.SetY( std::min( bbox.GetY(), pt.y ) );
                p_end.x   = std::max( p_end.x, pt.x );
                p_end.y   = std::max( p_end.y, pt.y );
            }

            bbox.SetEnd( p_end );
        }
        break;

    default:
        ;
    }

    bbox.Inflate( ((m_Width+1) / 2) + 1 );
    bbox.Normalize();

    return bbox;
}