/* * Creates a footprint position file * aSide = 0 -> Back (bottom) side) * aSide = 1 -> Front (top) side) * aSide = 2 -> both sides * if aFullFileName is empty, the file is not created, only the * count of footprints to place is returned */ int PCB_EDIT_FRAME::DoGenFootprintsPositionFile( const wxString& aFullFileName, bool aUnitsMM, bool aForceSmdItems, int aSide ) { MODULE* module; char line[1024]; File_Place_Offset = GetAuxOrigin(); // Calculating the number of useful modules (CMS attribute, not VIRTUAL) int moduleCount = 0; for( module = GetBoard()->m_Modules; module; module = module->Next() ) { if( aSide < 2 ) { if( module->GetLayer() == B_Cu && aSide == 1) continue; if( module->GetLayer() == F_Cu && aSide == 0) continue; } if( module->GetAttributes() & MOD_VIRTUAL ) { DBG( printf( "skipping module %s because it's virtual\n", TO_UTF8( module->GetReference() ) );) continue; }
TEXTE_MODULE::TEXTE_MODULE( MODULE* parent, TEXT_TYPE text_type ) : BOARD_ITEM( parent, PCB_MODULE_TEXT_T ), EDA_TEXT() { MODULE* module = (MODULE*) m_Parent; m_Type = text_type; m_NoShow = false; // Set text tickness to a default value m_Thickness = Millimeter2iu( 0.15 ); SetLayer( SILKSCREEN_N_FRONT ); if( module && ( module->Type() == PCB_MODULE_T ) ) { m_Pos = module->GetPosition(); if( IsBackLayer( module->GetLayer() ) ) { SetLayer( SILKSCREEN_N_BACK ); m_Mirror = true; } else { SetLayer( SILKSCREEN_N_FRONT ); m_Mirror = false; } } }
TEXTE_MODULE::TEXTE_MODULE( MODULE* parent, TEXT_TYPE text_type ) : BOARD_ITEM( parent, PCB_MODULE_TEXT_T ), EDA_TEXT() { MODULE* module = static_cast<MODULE*>( m_Parent ); m_Type = text_type; m_unlocked = false; // Set text thickness to a default value SetThickness( Millimeter2iu( 0.15 ) ); SetLayer( F_SilkS ); // Set position and give a default layer if a valid parent footprint exists if( module && ( module->Type() == PCB_MODULE_T ) ) { SetTextPos( module->GetPosition() ); if( IsBackLayer( module->GetLayer() ) ) { SetLayer( B_SilkS ); SetMirrored( true ); } } SetDrawCoord(); }
bool FOOTPRINT_EDIT_FRAME::Load_Module_From_BOARD( MODULE* aModule ) { MODULE* newModule; PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, false ); if( frame == NULL ) // happens if no board editor opened return false; if( aModule == NULL ) { if( ! frame->GetBoard() || ! frame->GetBoard()->m_Modules ) return false; aModule = SelectFootprint( frame->GetBoard() ); } if( aModule == NULL ) return false; SetCurItem( NULL ); Clear_Pcb( false ); GetBoard()->m_Status_Pcb = 0; newModule = new MODULE( *aModule ); newModule->SetParent( GetBoard() ); newModule->SetLink( aModule->GetTimeStamp() ); aModule = newModule; GetBoard()->Add( newModule ); newModule->ClearFlags(); // Clear references to net info, because the footprint editor // does know any thing about nets handled by the current edited board. // Morever the main board can change or the net info relative to this main board // can change while editing this footprint in the footprint editor for( D_PAD* pad = newModule->Pads(); pad; pad = pad->Next() ) pad->SetNetCode( NETINFO_LIST::UNCONNECTED ); SetCrossHairPosition( wxPoint( 0, 0 ) ); PlaceModule( newModule, NULL ); // Put it on FRONT layer, // because this is the default in ModEdit, and in libs if( newModule->GetLayer() != LAYER_N_FRONT ) newModule->Flip( newModule->GetPosition() ); // Put it in orientation 0, // because this is the default orientation in ModEdit, and in libs Rotate_Module( NULL, newModule, 0, false ); GetScreen()->ClrModify(); Zoom_Automatique( false ); return true; }
/* * Creates a footprint position file * aSide = 0 -> Back (bottom) side) * aSide = 1 -> Front (top) side) * aSide = 2 -> both sides * if aFullFileName is empty, the file is not created, only the * count of footprints to place is returned */ int PCB_EDIT_FRAME::DoGenFootprintsPositionFile( const wxString& aFullFileName, bool aUnitsMM, bool aForceSmdItems, int aSide, bool aFormatCSV ) { MODULE* footprint; // Minimal text lengths: int lenRefText = 8; int lenValText = 8; int lenPkgText = 16; File_Place_Offset = GetAuxOrigin(); // Calculating the number of useful footprints (CMS attribute, not VIRTUAL) int footprintCount = 0; // Select units: double conv_unit = aUnitsMM ? conv_unit_mm : conv_unit_inch; const char *unit_text = aUnitsMM ? unit_text_mm : unit_text_inch; // Build and sort the list of footprints alphabetically std::vector<LIST_MOD> list; list.reserve( footprintCount ); for( footprint = GetBoard()->m_Modules; footprint; footprint = footprint->Next() ) { if( aSide != PCB_BOTH_SIDES ) { if( footprint->GetLayer() == B_Cu && aSide == PCB_FRONT_SIDE) continue; if( footprint->GetLayer() == F_Cu && aSide == PCB_BACK_SIDE) continue; } if( footprint->GetAttributes() & MOD_VIRTUAL ) { DBG( printf( "skipping footprint %s because it's virtual\n", TO_UTF8( footprint->GetReference() ) );) continue; }
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; }
// Redraw the BOARD items but not cursors, axis or grid void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* DC, GR_DRAWMODE aDrawMode, const wxPoint& offset ) { /* The order of drawing is flexible on some systems and not on others. For * OSes which use OR to draw, the order is not important except for the * effect of the highlight and its relationship to markers. See comment * below. * This order independence comes from the fact that a binary OR operation is * commutative in nature. * However on the OSX, the OR operation is not used, and so this sequence * below is chosen to give MODULEs the highest visible priority. */ /* Draw all tracks and zones. As long as dark colors are used for the * tracks, Then the OR draw mode should show tracks underneath other * tracks. But a white track will cover any other color since it has * more bits to OR in. */ for( TRACK* track = m_Track; track; track = track->Next() ) { if( track->IsMoving() ) continue; track->Draw( aPanel, DC, aDrawMode ); } // Draw areas (i.e. zones) for( int ii = 0; ii < GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = GetArea( ii ); // Areas must be drawn here only if not moved or dragged, // because these areas are drawn by ManageCursor() in a specific manner if( ( zone->GetEditFlags() & (IN_EDIT | IS_DRAGGED | IS_MOVED) ) == 0 ) { zone->Draw( aPanel, DC, aDrawMode ); zone->DrawFilledArea( aPanel, DC, aDrawMode ); } } // Draw the graphic items for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) { if( item->IsMoving() ) continue; switch( item->Type() ) { case PCB_DIMENSION_T: case PCB_TEXT_T: case PCB_TARGET_T: case PCB_LINE_T: item->Draw( aPanel, DC, aDrawMode ); break; default: break; } } LSET all_cu = LSET::AllCuMask(); for( MODULE* module = m_Modules; module; module = module->Next() ) { bool display = true; LSET layerMask = all_cu; if( module->IsMoving() ) continue; if( !IsElementVisible( LAYER_MOD_FR ) ) { if( module->GetLayer() == F_Cu ) display = false; layerMask.set( F_Cu, false ); } if( !IsElementVisible( LAYER_MOD_BK ) ) { if( module->GetLayer() == B_Cu ) display = false; layerMask.set( B_Cu, false ); } if( display ) module->Draw( aPanel, DC, aDrawMode ); else Trace_Pads_Only( aPanel, DC, module, 0, 0, layerMask, aDrawMode ); } // draw the BOARD's markers last, otherwise the high light will erase any marker on a pad for( unsigned i = 0; i < m_markers.size(); ++i ) { m_markers[i]->Draw( aPanel, DC, aDrawMode ); } }
/** * Function Draw * Draw the text according to the footprint pos and orient * @param panel = draw panel, Used to know the clip box * @param DC = Current Device Context * @param offset = draw offset (usually wxPoint(0,0) * @param draw_mode = GR_OR, GR_XOR.. */ void TEXTE_MODULE::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE draw_mode, const wxPoint& offset ) { MODULE* module = (MODULE*) m_Parent; /* parent must *not* be NULL (a module text without a footprint parent has no sense) */ wxASSERT( module ); if( panel == NULL ) return; BOARD* brd = GetBoard( ); EDA_COLOR_T color; // Determine the element color or suppress it element if hidden switch( module->GetLayer() ) { case LAYER_N_BACK: if( !brd->IsElementVisible( MOD_TEXT_BK_VISIBLE ) ) return; color = brd->GetVisibleElementColor( MOD_TEXT_BK_VISIBLE ); break; case LAYER_N_FRONT: if( !brd->IsElementVisible( MOD_TEXT_FR_VISIBLE ) ) return; color = brd->GetVisibleElementColor( MOD_TEXT_FR_VISIBLE ); break; default: color = brd->GetLayerColor( module->GetLayer() ); } // 'Ghost' the element if forced show if( m_NoShow ) { if( !brd->IsElementVisible( MOD_TEXT_INVISIBLE ) ) return; color = brd->GetVisibleElementColor( MOD_TEXT_INVISIBLE ); } // Draw mode compensation for the width PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) panel->GetParent(); int width = m_Thickness; if( ( frame->m_DisplayModText == LINE ) || ( DC->LogicalToDeviceXRel( width ) <= MIN_DRAW_WIDTH ) ) width = 0; else if( frame->m_DisplayModText == SKETCH ) width = -width; GRSetDrawMode( DC, draw_mode ); wxPoint pos( m_Pos.x - offset.x, m_Pos.y - offset.y); // Draw the text anchor point if( brd->IsElementVisible( ANCHOR_VISIBLE ) ) { EDA_COLOR_T anchor_color = brd->GetVisibleElementColor(ANCHOR_VISIBLE); GRDrawAnchor( panel->GetClipBox(), DC, pos.x, pos.y, DIM_ANCRE_TEXTE, anchor_color ); } // Draw the text proper, with the right attributes wxSize size = m_Size; double orient = GetDrawRotation(); // If the text is mirrored : negate size.x (mirror / Y axis) if( m_Mirror ) size.x = -size.x; EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL; DrawGraphicText( clipbox, DC, pos, color, m_Text, orient, size, m_HJustify, m_VJustify, width, m_Italic, m_Bold ); // Enable these line to draw the bounding box (debug tests purposes only) #if 0 { EDA_RECT BoundaryBox = GetBoundingBox(); GRRect( clipbox, DC, BoundaryBox, 0, BROWN ); } #endif }
void PCB_EDIT_FRAME::Block_SelectItems() { int layerMask; GetScreen()->m_BlockLocate.Normalize(); PICKED_ITEMS_LIST* itemsList = &GetScreen()->m_BlockLocate.m_ItemsSelection; ITEM_PICKER picker( NULL, UR_UNSPECIFIED ); // Add modules if( blockIncludeModules ) { for( MODULE* module = m_Pcb->m_Modules; module != NULL; module = module->Next() ) { int layer = module->GetLayer(); if( module->HitTest( GetScreen()->m_BlockLocate ) && ( !module->IsLocked() || blockIncludeLockedModules ) ) { if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsModuleLayerVisible( layer ) ) { picker.SetItem ( module ); itemsList->PushItem( picker ); } } } } // Add tracks and vias if( blockIncludeTracks ) { for( TRACK* pt_segm = m_Pcb->m_Track; pt_segm != NULL; pt_segm = pt_segm->Next() ) { if( pt_segm->HitTest( GetScreen()->m_BlockLocate ) ) { if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsLayerVisible( pt_segm->GetLayer() ) ) { picker.SetItem ( pt_segm ); itemsList->PushItem( picker ); } } } } // Add graphic items layerMask = EDGE_LAYER; if( blockIncludeItemsOnTechLayers ) layerMask = ALL_LAYERS; if( !blockIncludeBoardOutlineLayer ) layerMask &= ~EDGE_LAYER; for( BOARD_ITEM* PtStruct = m_Pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() ) { if( !m_Pcb->IsLayerVisible( PtStruct->GetLayer() ) && ! blockIncludeItemsOnInvisibleLayers) continue; bool select_me = false; switch( PtStruct->Type() ) { case PCB_LINE_T: if( (GetLayerMask( PtStruct->GetLayer() ) & layerMask) == 0 ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) ) break; select_me = true; // This item is in bloc: select it break; case PCB_TEXT_T: if( !blockIncludePcbTexts ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) ) break; select_me = true; // This item is in bloc: select it break; case PCB_TARGET_T: if( ( GetLayerMask( PtStruct->GetLayer() ) & layerMask ) == 0 ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) ) break; select_me = true; // This item is in bloc: select it break; case PCB_DIMENSION_T: if( ( GetLayerMask( PtStruct->GetLayer() ) & layerMask ) == 0 ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) ) break; select_me = true; // This item is in bloc: select it break; default: break; } if( select_me ) { picker.SetItem ( PtStruct ); itemsList->PushItem( picker ); } } // Add zones if( blockIncludeZones ) { for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ ) { ZONE_CONTAINER* area = m_Pcb->GetArea( ii ); if( area->HitTest( GetScreen()->m_BlockLocate ) ) { if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsLayerVisible( area->GetLayer() ) ) { BOARD_ITEM* zone_c = (BOARD_ITEM*) area; picker.SetItem ( zone_c ); itemsList->PushItem( picker ); } } } } }
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 ); }
/** * Function Inspect * is the examining function within the INSPECTOR which is passed to the * Iterate function. Searches and collects all the objects that the old * function PcbGeneralLocateAndDisplay() would find, except that it keeps all * that it finds and does not do any displaying. * * @param testItem An EDA_ITEM to examine. * @param testData The const void* testData, not used here. * @return SEARCH_RESULT - SEARCH_QUIT if the Iterator is to stop the scan, * else SCAN_CONTINUE; */ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, const void* testData ) { BOARD_ITEM* item = (BOARD_ITEM*) testItem; MODULE* module = NULL; D_PAD* pad = NULL; bool pad_through = false; SEGVIA* via = NULL; MARKER_PCB* marker = NULL; #if 0 // debugging static int breakhere = 0; switch( item->Type() ) { case PCB_PAD_T: { MODULE* m = (MODULE*) item->GetParent(); if( m->GetReference() == wxT( "Y2" ) ) { breakhere++; } } break; case PCB_VIA_T: breakhere++; break; case PCB_TRACE_T: breakhere++; break; case PCB_ZONE_T: breakhere++; break; case PCB_TEXT_T: breakhere++; break; case PCB_LINE_T: breakhere++; break; case PCB_DIMENSION_T: breakhere++; break; case PCB_MODULE_TEXT_T: { TEXTE_MODULE* tm = (TEXTE_MODULE*) item; if( tm->GetText() == wxT( "10uH" ) ) { breakhere++; } } break; case PCB_MODULE_T: { MODULE* m = (MODULE*) item; if( m->GetReference() == wxT( "C98" ) ) { breakhere++; } } break; case PCB_MARKER_T: breakhere++; break; default: breakhere++; break; } #endif switch( item->Type() ) { case PCB_PAD_T: // there are pad specific visibility controls. // Criterias to select a pad is: // for smd pads: the module parent must be seen, and pads on the corresponding // board side must be seen // if pad is a thru hole, then it can be visible when its parent module is not. // for through pads: pads on Front or Back board sides must be seen pad = (D_PAD*) item; if( (pad->GetAttribute() != PAD_SMD) && (pad->GetAttribute() != PAD_CONN) ) // a hole is present, so multiple layers { // proceed to the common tests below, but without the parent module test, // by leaving module==NULL, but having pad != null pad_through = true; } else // smd, so use pads test after module test { module = (MODULE*) item->GetParent(); } break; case PCB_VIA_T: // vias are on many layers, so layer test is specific via = (SEGVIA*) item; break; case PCB_TRACE_T: break; case PCB_ZONE_T: break; case PCB_ZONE_AREA_T: break; case PCB_TEXT_T: break; case PCB_LINE_T: break; case PCB_DIMENSION_T: break; case PCB_TARGET_T: break; case PCB_MODULE_TEXT_T: module = (MODULE*) item->GetParent(); if( m_Guide->IgnoreMTextsMarkedNoShow() && !( (TEXTE_MODULE*) item )->IsVisible() ) goto exit; if( module ) { if( m_Guide->IgnoreMTextsOnCopper() && module->GetLayer()==LAYER_N_BACK ) goto exit; if( m_Guide->IgnoreMTextsOnCmp() && module->GetLayer()==LAYER_N_FRONT ) goto exit; if( m_Guide->IgnoreModulesVals() && item == &module->Value() ) goto exit; if( m_Guide->IgnoreModulesRefs() && item == &module->Reference() ) goto exit; } break; case PCB_MODULE_T: module = (MODULE*) item; break; case PCB_MARKER_T: marker = (MARKER_PCB*) item; break; default: break; } // common tests: if( module ) // true from case PCB_PAD_T, PCB_MODULE_TEXT_T, or PCB_MODULE_T { if( m_Guide->IgnoreModulesOnCu() && module->GetLayer()==LAYER_N_BACK ) goto exit; if( m_Guide->IgnoreModulesOnCmp() && module->GetLayer()==LAYER_N_FRONT ) goto exit; } // Pads are not sensitive to the layer visibility controls. // They all have their own separate visibility controls // skip them if not visible if( pad ) { if( m_Guide->IgnorePads() ) goto exit; if( ! pad_through ) { if( m_Guide->IgnorePadsOnFront() && pad->IsOnLayer(LAYER_N_FRONT ) ) goto exit; if( m_Guide->IgnorePadsOnBack() && pad->IsOnLayer(LAYER_N_BACK ) ) goto exit; } } if( marker ) { // Markers are not sensitive to the layer if( marker->HitTest( m_RefPos ) ) Append( item ); goto exit; } if( item->IsOnLayer( m_Guide->GetPreferredLayer() ) || m_Guide->IgnorePreferredLayer() ) { LAYER_NUM layer = item->GetLayer(); // Modules and their subcomponents: text and pads are not sensitive to the layer // visibility controls. They all have their own separate visibility controls // for vias, GetLayer() has no meaning, but IsOnLayer() works fine if( via || module || pad || m_Guide->IsLayerVisible( layer ) || !m_Guide->IgnoreNonVisibleLayers() ) { if( !m_Guide->IsLayerLocked( layer ) || !m_Guide->IgnoreLockedLayers() ) { if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() ) { if( item->HitTest( m_RefPos ) ) { Append( item ); goto exit; } } } } } if( m_Guide->IncludeSecondary() ) { // for now, "secondary" means "tolerate any layer". It has // no effect on other criteria, since there is a separate "ignore" control for // those in the COLLECTORS_GUIDE LAYER_NUM layer = item->GetLayer(); // Modules and their subcomponents: text and pads are not sensitive to the layer // visibility controls. They all have their own separate visibility controls if( via || module || pad || m_Guide->IsLayerVisible( layer ) || !m_Guide->IgnoreNonVisibleLayers() ) { if( !m_Guide->IsLayerLocked( layer ) || !m_Guide->IgnoreLockedLayers() ) { if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() ) { if( item->HitTest( m_RefPos ) ) { Append2nd( item ); goto exit; } } } } } exit: return SEARCH_CONTINUE; // always when collecting }
bool FOOTPRINT_EDIT_FRAME::Load_Module_From_BOARD( MODULE* aModule ) { MODULE* newModule; PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) Kiway().Player( FRAME_PCB, false ); if( frame == NULL ) // happens if no board editor opened return false; if( aModule == NULL ) { if( ! frame->GetBoard() || ! frame->GetBoard()->m_Modules ) return false; aModule = SelectFootprint( frame->GetBoard() ); } if( aModule == NULL ) return false; SetCurItem( NULL ); Clear_Pcb( false ); GetBoard()->m_Status_Pcb = 0; newModule = new MODULE( *aModule ); newModule->SetParent( GetBoard() ); newModule->SetLink( aModule->GetTimeStamp() ); aModule = newModule; newModule->ClearFlags(); newModule->RunOnChildren( boost::bind( &clearModuleItemFlags, _1 ) ); GetBoard()->Add( newModule ); // Clear references to any net info, because the footprint editor // does know any thing about nets handled by the current edited board. // Morever we do not want to save any reference to an unknown net when // saving the footprint in lib cache // so we force the ORPHANED dummy net info for all pads newModule->ClearAllNets(); SetCrossHairPosition( wxPoint( 0, 0 ) ); PlaceModule( newModule, NULL ); newModule->SetPosition( wxPoint( 0, 0 ) ); // cursor in GAL may not be initialized at the moment // Put it on FRONT layer, // because this is the default in ModEdit, and in libs if( newModule->GetLayer() != F_Cu ) newModule->Flip( newModule->GetPosition() ); // Put it in orientation 0, // because this is the default orientation in ModEdit, and in libs Rotate_Module( NULL, newModule, 0, false ); GetScreen()->ClrModify(); Zoom_Automatique( false ); if( IsGalCanvasActive() ) updateView(); return true; }
/* Driver function: processing starts here */ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& aEvent ) { wxFileName fn = GetBoard()->GetFileName(); FILE* file; wxString ext = wxT( "cad" ); wxString wildcard = _( "GenCAD 1.4 board files (.cad)|*.cad" ); fn.SetExt( ext ); wxString pro_dir = wxPathOnly( Prj().GetProjectFullName() ); wxFileDialog dlg( this, _( "Save GenCAD Board File" ), pro_dir, fn.GetFullName(), wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); if( dlg.ShowModal() == wxID_CANCEL ) return; if( ( file = wxFopen( dlg.GetPath(), wxT( "wt" ) ) ) == NULL ) { wxString msg; msg.Printf( _( "Unable to create <%s>" ), GetChars( dlg.GetPath() ) ); DisplayError( this, msg ); return; } SetLocaleTo_C_standard(); // No pesky decimal separators in gencad // Update some board data, to ensure a reliable gencad export GetBoard()->ComputeBoundingBox(); // Save the auxiliary origin for the rest of the module GencadOffsetX = GetAuxOrigin().x; GencadOffsetY = GetAuxOrigin().y; // No idea on *why* this should be needed... maybe to fix net names? Compile_Ratsnest( NULL, true ); /* Temporary modification of footprints that are flipped (i.e. on bottom * layer) to convert them to non flipped footprints. * This is necessary to easily export shapes to GenCAD, * that are given as normal orientation (non flipped, rotation = 0)) * these changes will be undone later */ BOARD* pcb = GetBoard(); MODULE* module; for( module = pcb->m_Modules; module; module = module->Next() ) { module->SetFlag( 0 ); if( module->GetLayer() == B_Cu ) { module->Flip( module->GetPosition() ); module->SetFlag( 1 ); } } /* Gencad has some mandatory and some optional sections: some importer * need the padstack section (which is optional) anyway. Also the * order of the section *is* important */ CreateHeaderInfoData( file, this ); // Gencad header CreateBoardSection( file, pcb ); // Board perimeter CreatePadsShapesSection( file, pcb ); // Pads and padstacks CreateArtworksSection( file ); // Empty but mandatory /* Gencad splits a component info in shape, component and device. * We don't do any sharing (it would be difficult since each module is * customizable after placement) */ CreateShapesSection( file, pcb ); CreateComponentsSection( file, pcb ); CreateDevicesSection( file, pcb ); // In a similar way the netlist is split in net, track and route CreateSignalsSection( file, pcb ); CreateTracksInfoData( file, pcb ); CreateRoutesSection( file, pcb ); fclose( file ); SetLocaleTo_Default(); // revert to the current locale // Undo the footprints modifications (flipped footprints) for( module = pcb->m_Modules; module; module = module->Next() ) { if( module->GetFlag() ) { module->Flip( module->GetPosition() ); module->SetFlag( 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; }
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; }
void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) throw( IO_ERROR ) { sessionBoard = aBoard; // not owned here if( !session ) THROW_IO_ERROR( _("Session file is missing the \"session\" section") ); /* Dick 16-Jan-2012: session need not have a placement section. if( !session->placement ) THROW_IO_ERROR( _("Session file is missing the \"placement\" section") ); */ if( !session->route ) THROW_IO_ERROR( _("Session file is missing the \"routes\" section") ); if( !session->route->library ) THROW_IO_ERROR( _("Session file is missing the \"library_out\" section") ); // delete all the old tracks and vias aBoard->m_Track.DeleteAll(); aBoard->DeleteMARKERs(); buildLayerMaps( aBoard ); if( session->placement ) { // Walk the PLACEMENT object's COMPONENTs list, and for each PLACE within // each COMPONENT, reposition and re-orient each component and put on // correct side of the board. COMPONENTS& components = session->placement->components; for( COMPONENTS::iterator comp=components.begin(); comp!=components.end(); ++comp ) { PLACES& places = comp->places; for( unsigned i=0; i<places.size(); ++i ) { PLACE* place = &places[i]; // '&' even though places[] holds a pointer! wxString reference = FROM_UTF8( place->component_id.c_str() ); MODULE* module = aBoard->FindModuleByReference( reference ); if( !module ) { THROW_IO_ERROR( wxString::Format( _("Session file has 'reference' to non-existent component \"%s\""), GetChars( reference ) ) ); } if( !place->hasVertex ) continue; UNIT_RES* resolution = place->GetUnits(); wxASSERT( resolution ); wxPoint newPos = mapPt( place->vertex, resolution ); module->SetPosition( newPos ); if( place->side == T_front ) { // convert from degrees to tenths of degrees used in KiCad. int orientation = KiROUND( place->rotation * 10.0 ); if( module->GetLayer() != F_Cu ) { // module is on copper layer (back) module->Flip( module->GetPosition() ); } module->SetOrientation( orientation ); } else if( place->side == T_back ) { int orientation = KiROUND( (place->rotation + 180.0) * 10.0 ); if( module->GetLayer() != B_Cu ) { // module is on component layer (front) module->Flip( module->GetPosition() ); } module->SetOrientation( orientation ); } else { // as I write this, the PARSER *is* catching this, so we should never see below: wxFAIL_MSG( wxT("DSN::PARSER did not catch an illegal side := 'back|front'") ); } } } } routeResolution = session->route->GetUnits(); // Walk the NET_OUTs and create tracks and vias anew. NET_OUTS& net_outs = session->route->net_outs; for( NET_OUTS::iterator net = net_outs.begin(); net!=net_outs.end(); ++net ) { int netCode = 0; // page 143 of spec says wire's net_id is optional if( net->net_id.size() ) { wxString netName = FROM_UTF8( net->net_id.c_str() ); NETINFO_ITEM* netinfo = aBoard->FindNet( netName ); if( netinfo ) netCode = netinfo->GetNet(); else // else netCode remains 0 { // int breakhere = 1; } } WIRES& wires = net->wires; for( unsigned i = 0; i<wires.size(); ++i ) { WIRE* wire = &wires[i]; DSN_T shape = wire->shape->Type(); if( shape != T_path ) { /* shape == T_polygon is expected from freerouter if you have a zone on a non "power" type layer, i.e. a T_signal layer and the design does a round trip back in as session here. We kept our own zones in the BOARD, so ignore this so called 'wire'. wxString netId = FROM_UTF8( wire->net_id.c_str() ); THROW_IO_ERROR( wxString::Format( _("Unsupported wire shape: \"%s\" for net: \"%s\""), DLEX::GetTokenString(shape).GetData(), netId.GetData() ) ); */ } else { PATH* path = (PATH*) wire->shape; for( unsigned pt=0; pt<path->points.size()-1; ++pt ) { /* a debugging aid, may come in handy if( path->points[pt].x == 547800 && path->points[pt].y == -380250 ) { int breakhere = 1; } */ TRACK* track = makeTRACK( path, pt, netCode ); aBoard->Add( track ); } } } WIRE_VIAS& wire_vias = net->wire_vias; LIBRARY& library = *session->route->library; for( unsigned i=0; i<wire_vias.size(); ++i ) { int netCode = 0; // page 144 of spec says wire_via's net_id is optional if( net->net_id.size() ) { wxString netName = FROM_UTF8( net->net_id.c_str() ); NETINFO_ITEM* net = aBoard->FindNet( netName ); if( net ) netCode = net->GetNet(); // else netCode remains 0 } WIRE_VIA* wire_via = &wire_vias[i]; // example: (via Via_15:8_mil 149000 -71000 ) PADSTACK* padstack = library.FindPADSTACK( wire_via->GetPadstackId() ); if( !padstack ) { // Dick Feb 29, 2008: // Freerouter has a bug where it will not round trip all vias. // Vias which have a (use_via) element will be round tripped. // Vias which do not, don't come back in in the session library, // even though they may be actually used in the pre-routed, // protected wire_vias. So until that is fixed, create the // padstack from its name as a work around. // Could use a STRING_FORMATTER here and convert the entire // wire_via to text and put that text into the exception. wxString psid( FROM_UTF8( wire_via->GetPadstackId().c_str() ) ); THROW_IO_ERROR( wxString::Format( _("A wire_via references a missing padstack \"%s\""), GetChars( psid ) ) ); } NETCLASSPTR netclass = aBoard->GetDesignSettings().m_NetClasses.GetDefault(); int via_drill_default = netclass->GetViaDrill(); for( unsigned v=0; v<wire_via->vertexes.size(); ++v ) { ::VIA* via = makeVIA( padstack, wire_via->vertexes[v], netCode, via_drill_default ); aBoard->Add( via ); } } } }
void PCB_EDIT_FRAME::Block_SelectItems() { LSET layerMask; bool selectOnlyComplete = GetScreen()->m_BlockLocate.GetWidth() > 0 ; GetScreen()->m_BlockLocate.Normalize(); PICKED_ITEMS_LIST* itemsList = &GetScreen()->m_BlockLocate.GetItems(); ITEM_PICKER picker( NULL, UR_UNSPECIFIED ); // Add modules if( blockIncludeModules ) { for( MODULE* module = m_Pcb->m_Modules; module; module = module->Next() ) { LAYER_ID layer = module->GetLayer(); if( module->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) && ( !module->IsLocked() || blockIncludeLockedModules ) ) { if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsModuleLayerVisible( layer ) ) { picker.SetItem ( module ); itemsList->PushItem( picker ); } } } } // Add tracks and vias if( blockIncludeTracks ) { for( TRACK* track = m_Pcb->m_Track; track != NULL; track = track->Next() ) { if( track->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) { if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsLayerVisible( track->GetLayer() ) ) { picker.SetItem( track ); itemsList->PushItem( picker ); } } } } // Add graphic items layerMask = LSET( Edge_Cuts ); if( blockIncludeItemsOnTechLayers ) layerMask.set(); if( !blockIncludeBoardOutlineLayer ) layerMask.set( Edge_Cuts, false ); for( BOARD_ITEM* PtStruct = m_Pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() ) { if( !m_Pcb->IsLayerVisible( PtStruct->GetLayer() ) && ! blockIncludeItemsOnInvisibleLayers) continue; bool select_me = false; switch( PtStruct->Type() ) { case PCB_LINE_T: if( !layerMask[PtStruct->GetLayer()] ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) break; select_me = true; // This item is in bloc: select it break; case PCB_TEXT_T: if( !blockIncludePcbTexts ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) break; select_me = true; // This item is in bloc: select it break; case PCB_TARGET_T: if( !layerMask[PtStruct->GetLayer()] ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) break; select_me = true; // This item is in bloc: select it break; case PCB_DIMENSION_T: if( !layerMask[PtStruct->GetLayer()] ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) break; select_me = true; // This item is in bloc: select it break; default: break; } if( select_me ) { picker.SetItem ( PtStruct ); itemsList->PushItem( picker ); } } // Add zones if( blockIncludeZones ) { for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ ) { ZONE_CONTAINER* area = m_Pcb->GetArea( ii ); if( area->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) { if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsLayerVisible( area->GetLayer() ) ) { BOARD_ITEM* zone_c = (BOARD_ITEM*) area; picker.SetItem ( zone_c ); itemsList->PushItem( picker ); } } } } }
EDGE_MODULE* FOOTPRINT_EDIT_FRAME::Begin_Edge_Module( EDGE_MODULE* aEdge, wxDC* DC, int type_edge ) { MODULE* module = GetBoard()->m_Modules; int angle = 0; if( module == NULL ) return NULL; if( aEdge == NULL ) // Start a new edge item { SaveCopyInUndoList( module, UR_MODEDIT ); aEdge = new EDGE_MODULE( module ); MoveVector.x = MoveVector.y = 0; // Add the new item to the Drawings list head module->m_Drawings.PushFront( aEdge ); // Update characteristics of the segment or arc. aEdge->SetFlags( IS_NEW ); aEdge->SetAngle( angle ); aEdge->SetShape( type_edge ); if( aEdge->GetShape() == S_ARC ) aEdge->SetAngle( ArcValue ); aEdge->SetWidth( GetDesignSettings().m_ModuleSegmentWidth ); aEdge->SetLayer( module->GetLayer() ); if( module->GetLayer() == LAYER_N_FRONT ) aEdge->SetLayer( SILKSCREEN_N_FRONT ); if( module->GetLayer() == LAYER_N_BACK ) aEdge->SetLayer( SILKSCREEN_N_BACK ); // Initialize the starting point of the new segment or arc aEdge->SetStart( GetScreen()->GetCrossHairPosition() ); // Initialize the ending point of the new segment or arc aEdge->SetEnd( aEdge->GetStart() ); // Initialize the relative coordinates aEdge->SetStart0( aEdge->GetStart() - module->GetPosition() ); RotatePoint( &aEdge->m_Start0, -module->m_Orient ); aEdge->m_End0 = aEdge->m_Start0; module->CalculateBoundingBox(); m_canvas->SetMouseCapture( ShowNewEdgeModule, Abort_Move_ModuleOutline ); } /* Segment creation in progress. * The ending coordinate is updated by the function * ShowNewEdgeModule() called on move mouse event * during the segment creation */ else { if( type_edge == S_SEGMENT ) { if( aEdge->m_Start0 != aEdge->m_End0 ) { aEdge->Draw( m_canvas, DC, GR_OR ); EDGE_MODULE* newedge = new EDGE_MODULE( *aEdge ); // insert _after_ aEdge, which is the same as inserting before aEdge->Next() module->m_Drawings.Insert( newedge, aEdge->Next() ); aEdge->ClearFlags(); aEdge = newedge; // point now new item aEdge->SetFlags( IS_NEW ); aEdge->SetWidth( GetDesignSettings().m_ModuleSegmentWidth ); aEdge->SetStart( GetScreen()->GetCrossHairPosition() ); aEdge->SetEnd( aEdge->GetStart() ); // Update relative coordinate. aEdge->SetStart0( aEdge->GetStart() - module->GetPosition() ); wxPoint pt( aEdge->GetStart0() ); RotatePoint( &pt, -module->GetOrientation() ); aEdge->SetStart0( pt ); aEdge->SetEnd0( aEdge->GetStart0() ); module->CalculateBoundingBox(); module->m_LastEdit_Time = time( NULL ); OnModify(); } } else { wxMessageBox( wxT( "Begin_Edge() error" ) ); } } return aEdge; }