unsigned MODULE::GetUniquePadCount( INCLUDE_NPTH_T aIncludeNPTH ) const { std::set<wxUint32> usedNames; // Create a set of used pad numbers for( D_PAD* pad = Pads(); pad; pad = pad->Next() ) { // Skip pads not on copper layers (used to build complex // solder paste shapes for instance) if( ( pad->GetLayerSet() & LSET::AllCuMask() ).none() ) continue; // Skip pads with no name, because they are usually "mechanical" // pads, not "electrical" pads if( pad->GetPadName().IsEmpty() ) continue; if( !aIncludeNPTH ) { // skip NPTH if( pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED ) { continue; } } usedNames.insert( pad->GetPackedPadName() ); } return usedNames.size(); }
BOARD_ITEM* MODULE::DuplicateAndAddItem( const BOARD_ITEM* aItem, bool aIncrementPadNumbers ) { BOARD_ITEM* new_item = NULL; switch( aItem->Type() ) { case PCB_PAD_T: { D_PAD* new_pad = new D_PAD( *static_cast<const D_PAD*>( aItem ) ); Pads().PushBack( new_pad ); new_item = new_pad; break; } case PCB_MODULE_TEXT_T: { const TEXTE_MODULE* old_text = static_cast<const TEXTE_MODULE*>( aItem ); // do not duplicate value or reference fields // (there can only be one of each) if( old_text->GetType() == TEXTE_MODULE::TEXT_is_DIVERS ) { TEXTE_MODULE* new_text = new TEXTE_MODULE( *old_text ); GraphicalItems().PushBack( new_text ); new_item = new_text; } break; } case PCB_MODULE_EDGE_T: { EDGE_MODULE* new_edge = new EDGE_MODULE( *static_cast<const EDGE_MODULE*>(aItem) ); GraphicalItems().PushBack( new_edge ); new_item = new_edge; break; } case PCB_MODULE_T: // Ignore the module itself break; default: // Un-handled item for duplication wxASSERT_MSG( false, "Duplication not supported for items of class " + aItem->GetClass() ); break; } if( aIncrementPadNumbers && new_item ) { new_item->IncrementItemReference(); } return new_item; }
void MODULE::ClearAllNets() { // Force the ORPHANED dummy net info for all pads. // ORPHANED dummy net does not depend on a board for( D_PAD* pad = Pads(); pad; pad = pad->Next() ) pad->SetNetCode( NETINFO_LIST::ORPHANED ); }
void MODULE::CopyNetlistSettings( MODULE* aModule ) { // Don't do anything foolish like trying to copy to yourself. wxCHECK_RET( aModule != NULL && aModule != this, wxT( "Cannot copy to NULL or yourself." ) ); // Not sure what to do with the value field. Use netlist for now. aModule->SetPosition( GetPosition() ); if( aModule->GetLayer() != GetLayer() ) aModule->Flip( aModule->GetPosition() ); if( aModule->GetOrientation() != GetOrientation() ) aModule->Rotate( aModule->GetPosition(), GetOrientation() ); aModule->SetLocalSolderMaskMargin( GetLocalSolderMaskMargin() ); aModule->SetLocalClearance( GetLocalClearance() ); aModule->SetLocalSolderPasteMargin( GetLocalSolderPasteMargin() ); aModule->SetLocalSolderPasteMarginRatio( GetLocalSolderPasteMarginRatio() ); aModule->SetZoneConnection( GetZoneConnection() ); aModule->SetThermalWidth( GetThermalWidth() ); aModule->SetThermalGap( GetThermalGap() ); for( D_PAD* pad = Pads(); pad; pad = pad->Next() ) { D_PAD* newPad = aModule->FindPadByName( pad->GetPadName() ); if( newPad ) pad->CopyNetlistSettings( newPad ); } // Not sure about copying description, keywords, 3D models or any other // local user changes to footprint. Stick with the new footprint settings // called out in the footprint loaded in the netlist. aModule->CalculateBoundingBox(); }
void MODULE::MoveAnchorPosition( const wxPoint& aMoveVector ) { /* Move the reference point of the footprint * the footprints elements (pads, outlines, edges .. ) are moved * but: * - the footprint position is not modified. * - the relative (local) coordinates of these items are modified */ wxPoint footprintPos = GetPosition(); /* Update the relative coordinates: * The coordinates are relative to the anchor point. * Calculate deltaX and deltaY from the anchor. */ wxPoint moveVector = aMoveVector; RotatePoint( &moveVector, -GetOrientation() ); // Update of the reference and value. m_Reference->SetPos0( m_Reference->GetPos0() + moveVector ); m_Reference->SetDrawCoord(); m_Value->SetPos0( m_Value->GetPos0() + moveVector ); m_Value->SetDrawCoord(); // Update the pad local coordinates. for( D_PAD* pad = Pads(); pad; pad = pad->Next() ) { pad->SetPos0( pad->GetPos0() + moveVector ); pad->SetPosition( pad->GetPos0() + footprintPos ); } // Update the draw element coordinates. for( EDA_ITEM* item = GraphicalItems(); item; item = item->Next() ) { switch( item->Type() ) { case PCB_MODULE_EDGE_T: { EDGE_MODULE* edge = static_cast<EDGE_MODULE*>( item ); edge->m_Start0 += moveVector; edge->m_End0 += moveVector; edge->SetDrawCoord(); break; } case PCB_MODULE_TEXT_T: { TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( item ); text->SetPos0( text->GetPos0() + moveVector ); text->SetDrawCoord(); break; } default: break; } } CalculateBoundingBox(); }
wxString MODULE::GetNextPadName( bool aFillSequenceGaps ) const { std::set<int> usedNumbers; // Create a set of used pad numbers for( D_PAD* pad = Pads(); pad; pad = pad->Next() ) { int padNumber = getTrailingInt( pad->GetPadName() ); usedNumbers.insert( padNumber ); } const int nextNum = getNextNumberInSequence( usedNumbers, aFillSequenceGaps ); return wxString::Format( wxT( "%i" ), nextNum ); }
/* generate pads shapes on layer aLayer as polygons, * and adds these polygons to aCornerBuffer * aCornerBuffer = the buffer to store polygons * aInflateValue = an additionnal size to add to pad shapes * aCircleToSegmentsCount = number of segments to approximate a circle * aCorrectionFactor = the correction to apply to a 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::TransformPadsShapesWithClearanceToPolygon( LAYER_NUM aLayer, CPOLYGONS_LIST& aCornerBuffer, int aInflateValue, int aCircleToSegmentsCount, double aCorrectionFactor ) { D_PAD* pad = Pads(); wxSize margin; for( ; pad != NULL; pad = pad->Next() ) { if( !pad->IsOnLayer(aLayer) ) continue; switch( aLayer ) { case SOLDERMASK_N_FRONT: case SOLDERMASK_N_BACK: margin.x = margin.y = pad->GetSolderMaskMargin() + aInflateValue; break; case SOLDERPASTE_N_FRONT: case SOLDERPASTE_N_BACK: margin = pad->GetSolderPasteMargin(); margin.x += aInflateValue; margin.y += aInflateValue; break; default: margin.x = margin.y = aInflateValue; break; } pad->BuildPadShapePolygon( aCornerBuffer, margin, aCircleToSegmentsCount, aCorrectionFactor ); } }
void MODULE::TransformPadsShapesWithClearanceToPolygon( LAYER_ID aLayer, SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aCircleToSegmentsCount, double aCorrectionFactor, bool aSkipNPTHPadsWihNoCopper ) { D_PAD* pad = Pads(); wxSize margin; for( ; pad != NULL; pad = pad->Next() ) { if( !pad->IsOnLayer(aLayer) ) continue; // NPTH pads are not drawn on layers if the shape size and pos is the same // as their hole: if( aSkipNPTHPadsWihNoCopper && pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED ) { if( pad->GetDrillSize() == pad->GetSize() && pad->GetOffset() == wxPoint( 0, 0 ) ) { switch( pad->GetShape() ) { case PAD_SHAPE_CIRCLE: if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE ) continue; break; case PAD_SHAPE_OVAL: if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE ) continue; break; default: break; } } } switch( aLayer ) { case F_Mask: case B_Mask: margin.x = margin.y = pad->GetSolderMaskMargin() + aInflateValue; break; case F_Paste: case B_Paste: margin = pad->GetSolderPasteMargin(); margin.x += aInflateValue; margin.y += aInflateValue; break; default: margin.x = margin.y = aInflateValue; break; } pad->BuildPadShapePolygon( aCornerBuffer, margin, aCircleToSegmentsCount, aCorrectionFactor ); } }