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