PNS_PCBNEW_RULE_RESOLVER::PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER* aRouter ) : m_router( aRouter ), m_board( aBoard ) { PNS::NODE* world = m_router->GetWorld(); PNS::TOPOLOGY topo( world ); m_netClearanceCache.resize( m_board->GetNetCount() ); // Build clearance cache for net classes for( unsigned int i = 0; i < m_board->GetNetCount(); i++ ) { NETINFO_ITEM* ni = m_board->FindNet( i ); if( ni == NULL ) continue; CLEARANCE_ENT ent; ent.coupledNet = DpCoupledNet( i ); wxString netClassName = ni->GetClassName(); NETCLASSPTR nc = m_board->GetDesignSettings().m_NetClasses.Find( netClassName ); int clearance = nc->GetClearance(); ent.clearance = clearance; m_netClearanceCache[i] = ent; wxLogTrace( "PNS", "Add net %u netclass %s clearance %d", i, netClassName.mb_str(), clearance ); } // Build clearance cache for pads for( MODULE* mod = m_board->m_Modules; mod ; mod = mod->Next() ) { auto moduleClearance = mod->GetLocalClearance(); for( D_PAD* pad = mod->PadsList(); pad; pad = pad->Next() ) { int padClearance = pad->GetLocalClearance(); if( padClearance > 0 ) m_localClearanceCache[ pad ] = padClearance; else if( moduleClearance > 0 ) m_localClearanceCache[ pad ] = moduleClearance; } } //printf("DefaultCL : %d\n", m_board->GetDesignSettings().m_NetClasses.Find ("Default clearance")->GetClearance()); m_overrideEnabled = false; m_defaultClearance = Millimeter2iu( 0.254 ); // m_board->m_NetClasses.Find ("Default clearance")->GetClearance(); m_overrideNetA = 0; m_overrideNetB = 0; m_overrideClearance = 0; m_useDpGap = false; }
void DIALOG_PAD_PROPERTIES::PadPropertiesAccept( wxCommandEvent& event ) { if( !padValuesOK() ) return; bool rastnestIsChanged = false; int isign = m_isFlipped ? -1 : 1; transferDataToPad( m_padMaster ); // m_padMaster is a pattern: ensure there is no net for this pad: m_padMaster->SetNetCode( NETINFO_LIST::UNCONNECTED ); if( m_currentPad ) // Set current Pad parameters { wxSize size; MODULE* module = m_currentPad->GetParent(); m_parent->SaveCopyInUndoList( module, UR_CHANGED ); module->SetLastEditTime(); // redraw the area where the pad was, without pad (delete pad on screen) m_currentPad->SetFlags( DO_NOT_DRAW ); m_parent->GetCanvas()->RefreshDrawingRect( m_currentPad->GetBoundingBox() ); m_currentPad->ClearFlags( DO_NOT_DRAW ); // Update values m_currentPad->SetShape( m_padMaster->GetShape() ); m_currentPad->SetAttribute( m_padMaster->GetAttribute() ); if( m_currentPad->GetPosition() != m_padMaster->GetPosition() ) { m_currentPad->SetPosition( m_padMaster->GetPosition() ); rastnestIsChanged = true; } // compute the pos 0 value, i.e. pad position for module with orientation = 0 // i.e. relative to module origin (module position) wxPoint pt = m_currentPad->GetPosition() - module->GetPosition(); RotatePoint( &pt, -module->GetOrientation() ); m_currentPad->SetPos0( pt ); m_currentPad->SetOrientation( m_padMaster->GetOrientation() * isign + module->GetOrientation() ); m_currentPad->SetSize( m_padMaster->GetSize() ); size = m_padMaster->GetDelta(); size.y *= isign; m_currentPad->SetDelta( size ); m_currentPad->SetDrillSize( m_padMaster->GetDrillSize() ); m_currentPad->SetDrillShape( m_padMaster->GetDrillShape() ); wxPoint offset = m_padMaster->GetOffset(); offset.y *= isign; m_currentPad->SetOffset( offset ); m_currentPad->SetPadToDieLength( m_padMaster->GetPadToDieLength() ); if( m_currentPad->GetLayerSet() != m_padMaster->GetLayerSet() ) { rastnestIsChanged = true; m_currentPad->SetLayerSet( m_padMaster->GetLayerSet() ); } if( m_isFlipped ) m_currentPad->SetLayerSet( FlipLayerMask( m_currentPad->GetLayerSet() ) ); m_currentPad->SetPadName( m_padMaster->GetPadName() ); wxString padNetname; // For PAD_HOLE_NOT_PLATED, ensure there is no net name selected if( m_padMaster->GetAttribute() != PAD_HOLE_NOT_PLATED ) padNetname = m_PadNetNameCtrl->GetValue(); if( m_currentPad->GetNetname() != padNetname ) { const NETINFO_ITEM* netinfo = m_board->FindNet( padNetname ); if( !padNetname.IsEmpty() && netinfo == NULL ) { DisplayError( NULL, _( "Unknown netname, netname not changed" ) ); } else { rastnestIsChanged = true; m_currentPad->SetNetCode( netinfo->GetNet() ); } } m_currentPad->SetLocalClearance( m_padMaster->GetLocalClearance() ); m_currentPad->SetLocalSolderMaskMargin( m_padMaster->GetLocalSolderMaskMargin() ); m_currentPad->SetLocalSolderPasteMargin( m_padMaster->GetLocalSolderPasteMargin() ); m_currentPad->SetLocalSolderPasteMarginRatio( m_padMaster->GetLocalSolderPasteMarginRatio() ); m_currentPad->SetZoneConnection( m_padMaster->GetZoneConnection() ); m_currentPad->SetThermalWidth( m_padMaster->GetThermalWidth() ); m_currentPad->SetThermalGap( m_padMaster->GetThermalGap() ); module->CalculateBoundingBox(); m_parent->SetMsgPanel( m_currentPad ); // redraw the area where the pad was m_parent->GetCanvas()->RefreshDrawingRect( m_currentPad->GetBoundingBox() ); m_parent->OnModify(); } EndModal( wxID_OK ); if( rastnestIsChanged ) // The net ratsnest must be recalculated m_board->m_Status_Pcb = 0; }
void DIALOG_PAD_PROPERTIES::initValues() { wxString msg; double angle; // Disable pad net name wxTextCtrl if the caller is the footprint editor // because nets are living only in the board managed by the board editor m_canEditNetName = m_parent->IsType( FRAME_PCB ); // Setup layers names from board // Should be made first, before calling m_rbCopperLayersSel->SetSelection() m_rbCopperLayersSel->SetString( 0, m_board->GetLayerName( F_Cu ) ); m_rbCopperLayersSel->SetString( 1, m_board->GetLayerName( B_Cu ) ); m_PadLayerAdhCmp->SetLabel( m_board->GetLayerName( F_Adhes ) ); m_PadLayerAdhCu->SetLabel( m_board->GetLayerName( B_Adhes ) ); m_PadLayerPateCmp->SetLabel( m_board->GetLayerName( F_Paste ) ); m_PadLayerPateCu->SetLabel( m_board->GetLayerName( B_Paste ) ); m_PadLayerSilkCmp->SetLabel( m_board->GetLayerName( F_SilkS ) ); m_PadLayerSilkCu->SetLabel( m_board->GetLayerName( B_SilkS ) ); m_PadLayerMaskCmp->SetLabel( m_board->GetLayerName( F_Mask ) ); m_PadLayerMaskCu->SetLabel( m_board->GetLayerName( B_Mask ) ); m_PadLayerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) ); m_PadLayerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) ); m_PadLayerDraft->SetLabel( m_board->GetLayerName( Dwgs_User ) ); m_isFlipped = false; if( m_currentPad ) { MODULE* module = m_currentPad->GetParent(); if( module->GetLayer() == B_Cu ) { m_isFlipped = true; m_staticModuleSideValue->SetLabel( _( "Back side (footprint is mirrored)" ) ); } msg.Printf( wxT( "%.1f" ), module->GetOrientation() / 10.0 ); m_staticModuleRotValue->SetLabel( msg ); } if( m_isFlipped ) { wxPoint pt = m_dummyPad->GetOffset(); NEGATE( pt.y ); m_dummyPad->SetOffset( pt ); wxSize sz = m_dummyPad->GetDelta(); NEGATE( sz.y ); m_dummyPad->SetDelta( sz ); // flip pad's layers m_dummyPad->SetLayerSet( FlipLayerMask( m_dummyPad->GetLayerSet() ) ); } m_staticTextWarningPadFlipped->Show(m_isFlipped); m_PadNumCtrl->SetValue( m_dummyPad->GetPadName() ); m_PadNetNameCtrl->SetValue( m_dummyPad->GetNetname() ); // Display current unit name in dialog: m_PadPosX_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadPosY_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadDrill_X_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadDrill_Y_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadShapeSizeX_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadShapeSizeY_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadShapeOffsetX_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadShapeOffsetY_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadShapeDelta_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadLengthDie_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); // Display current pad masks clearances units m_NetClearanceUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_SolderMaskMarginUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_SolderPasteMarginUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_ThermalWidthUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_ThermalGapUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); // Display current pad parameters units: PutValueInLocalUnits( *m_PadPosition_X_Ctrl, m_dummyPad->GetPosition().x ); PutValueInLocalUnits( *m_PadPosition_Y_Ctrl, m_dummyPad->GetPosition().y ); PutValueInLocalUnits( *m_PadDrill_X_Ctrl, m_dummyPad->GetDrillSize().x ); PutValueInLocalUnits( *m_PadDrill_Y_Ctrl, m_dummyPad->GetDrillSize().y ); PutValueInLocalUnits( *m_ShapeSize_X_Ctrl, m_dummyPad->GetSize().x ); PutValueInLocalUnits( *m_ShapeSize_Y_Ctrl, m_dummyPad->GetSize().y ); PutValueInLocalUnits( *m_ShapeOffset_X_Ctrl, m_dummyPad->GetOffset().x ); PutValueInLocalUnits( *m_ShapeOffset_Y_Ctrl, m_dummyPad->GetOffset().y ); if( m_dummyPad->GetDelta().x ) { PutValueInLocalUnits( *m_ShapeDelta_Ctrl, m_dummyPad->GetDelta().x ); m_trapDeltaDirChoice->SetSelection( 0 ); } else { PutValueInLocalUnits( *m_ShapeDelta_Ctrl, m_dummyPad->GetDelta().y ); m_trapDeltaDirChoice->SetSelection( 1 ); } PutValueInLocalUnits( *m_LengthPadToDieCtrl, m_dummyPad->GetPadToDieLength() ); PutValueInLocalUnits( *m_NetClearanceValueCtrl, m_dummyPad->GetLocalClearance() ); PutValueInLocalUnits( *m_SolderMaskMarginCtrl, m_dummyPad->GetLocalSolderMaskMargin() ); PutValueInLocalUnits( *m_ThermalWidthCtrl, m_dummyPad->GetThermalWidth() ); PutValueInLocalUnits( *m_ThermalGapCtrl, m_dummyPad->GetThermalGap() ); // These 2 parameters are usually < 0, so prepare entering a negative value, if current is 0 PutValueInLocalUnits( *m_SolderPasteMarginCtrl, m_dummyPad->GetLocalSolderPasteMargin() ); if( m_dummyPad->GetLocalSolderPasteMargin() == 0 ) m_SolderPasteMarginCtrl->SetValue( wxT( "-" ) + m_SolderPasteMarginCtrl->GetValue() ); msg.Printf( wxT( "%f" ), m_dummyPad->GetLocalSolderPasteMarginRatio() * 100.0 ); if( m_dummyPad->GetLocalSolderPasteMarginRatio() == 0.0 && msg[0] == '0' ) // Sometimes Printf adds a sign if the value is small m_SolderPasteMarginRatioCtrl->SetValue( wxT( "-" ) + msg ); else m_SolderPasteMarginRatioCtrl->SetValue( msg ); switch( m_dummyPad->GetZoneConnection() ) { default: case UNDEFINED_CONNECTION: m_ZoneConnectionChoice->SetSelection( 0 ); break; case PAD_IN_ZONE: m_ZoneConnectionChoice->SetSelection( 1 ); break; case THERMAL_PAD: m_ZoneConnectionChoice->SetSelection( 2 ); break; case PAD_NOT_IN_ZONE: m_ZoneConnectionChoice->SetSelection( 3 ); break; } if( m_currentPad ) { MODULE* module = m_currentPad->GetParent(); angle = m_currentPad->GetOrientation() - module->GetOrientation(); if( m_isFlipped ) NEGATE( angle ); m_dummyPad->SetOrientation( angle ); } angle = m_dummyPad->GetOrientation(); NORMALIZE_ANGLE_180( angle ); // ? normalizing is in D_PAD::SetOrientation() // Set layers used by this pad: : setPadLayersList( m_dummyPad->GetLayerSet() ); // Pad Orient switch( int( angle ) ) { case 0: m_PadOrient->SetSelection( 0 ); break; case 900: m_PadOrient->SetSelection( 1 ); break; case -900: m_PadOrient->SetSelection( 2 ); break; case 1800: case -1800: m_PadOrient->SetSelection( 3 ); break; default: m_PadOrient->SetSelection( 4 ); break; } switch( m_dummyPad->GetShape() ) { default: case PAD_CIRCLE: m_PadShape->SetSelection( 0 ); break; case PAD_OVAL: m_PadShape->SetSelection( 1 ); break; case PAD_RECT: m_PadShape->SetSelection( 2 ); break; case PAD_TRAPEZOID: m_PadShape->SetSelection( 3 ); break; } msg.Printf( wxT( "%g" ), angle ); m_PadOrientCtrl->SetValue( msg ); // Type of pad selection m_PadType->SetSelection( 0 ); for( unsigned ii = 0; ii < DIM( code_type ); ii++ ) { if( code_type[ii] == m_dummyPad->GetAttribute() ) { m_PadType->SetSelection( ii ); break; } } // Enable/disable Pad name,and pad length die // (disable for NPTH pads (mechanical pads) bool enable = m_dummyPad->GetAttribute() != PAD_HOLE_NOT_PLATED; m_PadNumCtrl->Enable( enable ); m_PadNetNameCtrl->Enable( m_canEditNetName && enable && m_currentPad != NULL ); m_LengthPadToDieCtrl->Enable( enable ); if( m_dummyPad->GetDrillShape() != PAD_DRILL_OBLONG ) m_DrillShapeCtrl->SetSelection( 0 ); else m_DrillShapeCtrl->SetSelection( 1 ); // Update some dialog widgets state (Enable/disable options): wxCommandEvent cmd_event; setPadLayersList( m_dummyPad->GetLayerSet() ); OnDrillShapeSelected( cmd_event ); OnPadShapeSelection( cmd_event ); }
void DIALOG_PAD_PROPERTIES::OnPaintShowPanel( wxPaintEvent& event ) { wxPaintDC dc( m_panelShowPad ); PAD_DRAWINFO drawInfo; EDA_COLOR_T color = BLACK; if( m_dummyPad->GetLayerSet()[F_Cu] ) { color = m_board->GetVisibleElementColor( PAD_FR_VISIBLE ); } if( m_dummyPad->GetLayerSet()[B_Cu] ) { color = ColorMix( color, m_board->GetVisibleElementColor( PAD_BK_VISIBLE ) ); } // What could happen: the pad color is *actually* black, or no // copper was selected if( color == BLACK ) color = LIGHTGRAY; drawInfo.m_Color = color; drawInfo.m_HoleColor = DARKGRAY; drawInfo.m_Offset = m_dummyPad->GetPosition(); drawInfo.m_Display_padnum = true; drawInfo.m_Display_netname = true; if( m_dummyPad->GetAttribute() == PAD_HOLE_NOT_PLATED ) drawInfo.m_ShowNotPlatedHole = true; // Shows the local pad clearance drawInfo.m_PadClearance = m_dummyPad->GetLocalClearance(); wxSize dc_size = dc.GetSize(); dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 ); // Calculate a suitable scale to fit the available draw area int dim = m_dummyPad->GetSize().x + std::abs( m_dummyPad->GetDelta().y); if( m_dummyPad->GetLocalClearance() > 0 ) dim += m_dummyPad->GetLocalClearance() * 2; double scale = (double) dc_size.x / dim; dim = m_dummyPad->GetSize().y + std::abs( m_dummyPad->GetDelta().x); if( m_dummyPad->GetLocalClearance() > 0 ) dim += m_dummyPad->GetLocalClearance() * 2; double altscale = (double) dc_size.y / dim; scale = std::min( scale, altscale ); // Give a margin scale *= 0.7; dc.SetUserScale( scale, scale ); GRResetPenAndBrush( &dc ); m_dummyPad->DrawShape( NULL, &dc, drawInfo ); // Draw X and Y axis. // this is particularly useful to show the reference position of pads // with offset and no hole GRLine( NULL, &dc, -dim, 0, dim, 0, 0, BLUE ); // X axis GRLine( NULL, &dc, 0, -dim, 0, dim, 0, BLUE ); // Y axis event.Skip(); }
void DIALOG_PAD_PROPERTIES::OnPaintShowPanel( wxPaintEvent& event ) { wxPaintDC dc( m_panelShowPad ); PAD_DRAWINFO drawInfo; EDA_COLOR_T color = BLACK; if( m_dummyPad->GetLayerSet()[F_Cu] ) { color = m_board->GetVisibleElementColor( PAD_FR_VISIBLE ); } if( m_dummyPad->GetLayerSet()[B_Cu] ) { color = ColorMix( color, m_board->GetVisibleElementColor( PAD_BK_VISIBLE ) ); } // What could happen: the pad color is *actually* black, or no // copper was selected if( color == BLACK ) color = LIGHTGRAY; drawInfo.m_Color = color; drawInfo.m_HoleColor = DARKGRAY; drawInfo.m_Offset = m_dummyPad->GetPosition(); drawInfo.m_Display_padnum = true; drawInfo.m_Display_netname = true; if( m_dummyPad->GetAttribute() == PAD_HOLE_NOT_PLATED ) drawInfo.m_ShowNotPlatedHole = true; // Shows the local pad clearance drawInfo.m_PadClearance = m_dummyPad->GetLocalClearance(); wxSize dc_size = dc.GetSize(); dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 ); // Calculate a suitable scale to fit the available draw area int dim = m_dummyPad->GetSize().x + std::abs( m_dummyPad->GetDelta().y ); // Invalid x size. User could enter zero, or have deleted all text prior to // entering a new value; this is also treated as zero. If dim is left at // zero, the drawing scale is zero and we get a crash. if( dim == 0 ) { // If drill size has been set, use that. Otherwise default to 1mm. dim = m_dummyPad->GetDrillSize().x; if( dim == 0 ) dim = 1000000; } if( m_dummyPad->GetLocalClearance() > 0 ) dim += m_dummyPad->GetLocalClearance() * 2; double scale = (double) dc_size.x / dim; // If the pad is a circle, use the x size here instead. int ysize; if( m_dummyPad->GetShape() == PAD_CIRCLE ) ysize = m_dummyPad->GetSize().x; else ysize = m_dummyPad->GetSize().y; dim = ysize + std::abs( m_dummyPad->GetDelta().x ); // Invalid y size. See note about x size above. if( dim == 0 ) { dim = m_dummyPad->GetDrillSize().y; if( dim == 0 ) dim = 1000000; } if( m_dummyPad->GetLocalClearance() > 0 ) dim += m_dummyPad->GetLocalClearance() * 2; double altscale = (double) dc_size.y / dim; scale = std::min( scale, altscale ); // Give a margin scale *= 0.7; dc.SetUserScale( scale, scale ); GRResetPenAndBrush( &dc ); m_dummyPad->DrawShape( NULL, &dc, drawInfo ); // Draw X and Y axis. // this is particularly useful to show the reference position of pads // with offset and no hole GRLine( NULL, &dc, -dim, 0, dim, 0, 0, BLUE ); // X axis GRLine( NULL, &dc, 0, -dim, 0, dim, 0, BLUE ); // Y axis event.Skip(); }
void D_PAD::ImportSettingsFromMaster( const D_PAD& aMasterPad ) { SetShape( aMasterPad.GetShape() ); SetLayerSet( aMasterPad.GetLayerSet() ); SetAttribute( aMasterPad.GetAttribute() ); // The pad orientation, for historical reasons is the // pad rotation + parent rotation. // So we have to manage this parent rotation double pad_rot = aMasterPad.GetOrientation(); if( aMasterPad.GetParent() ) pad_rot -= aMasterPad.GetParent()->GetOrientation(); if( GetParent() ) pad_rot += GetParent()->GetOrientation(); SetOrientation( pad_rot ); SetSize( aMasterPad.GetSize() ); SetDelta( wxSize( 0, 0 ) ); SetOffset( aMasterPad.GetOffset() ); SetDrillSize( aMasterPad.GetDrillSize() ); SetDrillShape( aMasterPad.GetDrillShape() ); SetRoundRectRadiusRatio( aMasterPad.GetRoundRectRadiusRatio() ); SetChamferRectRatio( aMasterPad.GetChamferRectRatio() ); SetChamferPositions( aMasterPad.GetChamferPositions() ); switch( aMasterPad.GetShape() ) { case PAD_SHAPE_TRAPEZOID: SetDelta( aMasterPad.GetDelta() ); break; case PAD_SHAPE_CIRCLE: // ensure size.y == size.x SetSize( wxSize( GetSize().x, GetSize().x ) ); break; default: ; } switch( aMasterPad.GetAttribute() ) { case PAD_ATTRIB_SMD: case PAD_ATTRIB_CONN: // These pads do not have hole (they are expected to be only on one // external copper layer) SetDrillSize( wxSize( 0, 0 ) ); break; default: ; } // copy also local settings: SetLocalClearance( aMasterPad.GetLocalClearance() ); SetLocalSolderMaskMargin( aMasterPad.GetLocalSolderMaskMargin() ); SetLocalSolderPasteMargin( aMasterPad.GetLocalSolderPasteMargin() ); SetLocalSolderPasteMarginRatio( aMasterPad.GetLocalSolderPasteMarginRatio() ); SetZoneConnection( aMasterPad.GetZoneConnection() ); SetThermalWidth( aMasterPad.GetThermalWidth() ); SetThermalGap( aMasterPad.GetThermalGap() ); // Add or remove custom pad shapes: SetPrimitives( aMasterPad.GetPrimitives() ); SetAnchorPadShape( aMasterPad.GetAnchorPadShape() ); MergePrimitivesAsPolygon(); }