void DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::OnOkClick( wxCommandEvent& event ) /*******************************************************************/ /* Copy values in text control to the item parameters */ { LAYER_NUM layer = m_LayerSelectionCtrl->GetLayerSelection(); if( IsCopperLayer( layer ) ) { /* an edge is put on a copper layer: this it is very dangerous. a * confirmation is requested */ if( !IsOK( NULL, _( "The graphic item will be on a copper layer. This is very dangerous. Are you sure?" ) ) ) return; } m_parent->SaveCopyInUndoList( m_module, UR_MODEDIT ); m_module->SetLastEditTime(); wxString msg; wxPoint coord; msg = m_Center_StartXCtrl->GetValue(); coord.x = ValueFromString( g_UserUnit, msg ); msg = m_Center_StartYCtrl->GetValue(); coord.y = ValueFromString( g_UserUnit, msg ); m_item->SetStart( coord ); m_item->SetStart0( coord ); msg = m_EndX_Radius_Ctrl->GetValue(); coord.x = ValueFromString( g_UserUnit, msg ); msg = m_EndY_Ctrl->GetValue(); coord.y = ValueFromString( g_UserUnit, msg ); m_item->SetEnd( coord ); m_item->SetEnd0( coord ); msg = m_ThicknessCtrl->GetValue(); m_item->SetWidth( ValueFromString( g_UserUnit, msg ) ); msg = m_DefaultThicknessCtrl->GetValue(); int thickness = ValueFromString( g_UserUnit, msg ); m_brdSettings.m_ModuleSegmentWidth = thickness; m_parent->SetDesignSettings( m_brdSettings ); m_item->SetLayer( layer ); if( m_item->GetShape() == S_ARC ) { double angle; m_Angle_Ctrl->GetValue().ToDouble( &angle ); NORMALIZE_ANGLE_360(angle); m_item->SetAngle( angle ); } m_parent->OnModify(); m_parent->SetMsgPanel( m_item ); Close( true ); }
bool DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::TransferDataFromWindow() { if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataFromWindow() ) return false; LAYER_NUM layer = m_LayerSelectionCtrl->GetLayerSelection(); if( IsCopperLayer( layer ) ) { /* an edge is put on a copper layer: this it is very dangerous. a * confirmation is requested */ if( !IsOK( NULL, _( "The graphic item will be on a copper layer. This is very dangerous. Are you sure?" ) ) ) return false;; } m_parent->SaveCopyInUndoList( m_module, UR_MODEDIT ); m_module->SetLastEditTime(); wxString msg; wxPoint coord; msg = m_Center_StartXCtrl->GetValue(); coord.x = ValueFromString( g_UserUnit, msg ); msg = m_Center_StartYCtrl->GetValue(); coord.y = ValueFromString( g_UserUnit, msg ); m_item->SetStart( coord ); m_item->SetStart0( coord ); msg = m_EndX_Radius_Ctrl->GetValue(); coord.x = ValueFromString( g_UserUnit, msg ); msg = m_EndY_Ctrl->GetValue(); coord.y = ValueFromString( g_UserUnit, msg ); m_item->SetEnd( coord ); m_item->SetEnd0( coord ); msg = m_ThicknessCtrl->GetValue(); m_item->SetWidth( ValueFromString( g_UserUnit, msg ) ); msg = m_DefaultThicknessCtrl->GetValue(); int thickness = ValueFromString( g_UserUnit, msg ); m_brdSettings.m_ModuleSegmentWidth = thickness; m_parent->SetDesignSettings( m_brdSettings ); m_item->SetLayer( ToLAYER_ID( layer ) ); if( m_item->GetShape() == S_ARC ) { m_item->SetAngle( m_AngleValue * 10.0 ); } m_parent->OnModify(); m_parent->SetMsgPanel( m_item ); return true; }
/** Mirror marked items, refer to a Vertical axis at position offset * Note: because this function is used in global transform, * if force_all is true, all items will be mirrored */ void MirrorMarkedItems( MODULE* module, wxPoint offset, bool force_all ) { #define SETMIRROR( z ) (z) -= offset.x; (z) = -(z); (z) += offset.x; wxPoint tmp; wxSize tmpz; if( module == NULL ) return; for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { // Skip pads not selected, i.e. not inside the block to mirror: if( !pad->IsSelected() && !force_all ) continue; tmp = pad->GetPosition(); SETMIRROR( tmp.x ); pad->SetPosition( tmp ); pad->SetX0( pad->GetPosition().x ); tmp = pad->GetOffset(); NEGATE( tmp.x ); pad->SetOffset( tmp ); tmpz = pad->GetDelta(); NEGATE( tmpz.x ); pad->SetDelta( tmpz ); pad->SetOrientation( 1800 - pad->GetOrientation() ); } for( EDA_ITEM* item = module->GraphicalItems(); item; item = item->Next() ) { // Skip items not selected, i.e. not inside the block to mirror: if( !item->IsSelected() && !force_all ) continue; switch( item->Type() ) { case PCB_MODULE_EDGE_T: { EDGE_MODULE* em = (EDGE_MODULE*) item; tmp = em->GetStart0(); SETMIRROR( tmp.x ); em->SetStart0( tmp ); em->SetStartX( tmp.x ); tmp = em->GetEnd0(); SETMIRROR( tmp.x ); em->SetEnd0( tmp ); em->SetEndX( tmp.x ); em->SetAngle( -em->GetAngle() ); } break; case PCB_MODULE_TEXT_T: { TEXTE_MODULE* tm = (TEXTE_MODULE*) item; tmp = tm->GetTextPosition(); SETMIRROR( tmp.x ); tm->SetTextPosition( tmp ); tmp.y = tm->GetPos0().y; tm->SetPos0( tmp ); } break; default: break; } item->ClearFlags(); } }
void MODULE::Flip( const wxPoint& aCentre ) { TEXTE_MODULE* text; // Move module to its final position: wxPoint finalPos = m_Pos; finalPos.y = aCentre.y - ( finalPos.y - aCentre.y ); /// Mirror the Y position SetPosition( finalPos ); // Flip layer SetLayer( FlipLayer( GetLayer() ) ); // Reverse mirror orientation. NEGATE( m_Orient ); NORMALIZE_ANGLE_POS( m_Orient ); // Mirror pads to other side of board about the x axis, i.e. vertically. for( D_PAD* pad = m_Pads; pad; pad = pad->Next() ) pad->Flip( m_Pos ); // Mirror reference. text = m_Reference; text->m_Pos.y -= m_Pos.y; NEGATE( text->m_Pos.y ); text->m_Pos.y += m_Pos.y; NEGATE(text->m_Pos0.y); NEGATE_AND_NORMALIZE_ANGLE_POS( text->m_Orient ); text->SetLayer( FlipLayer( text->GetLayer() ) ); text->m_Mirror = IsBackLayer( GetLayer() ); // Mirror value. text = m_Value; text->m_Pos.y -= m_Pos.y; NEGATE( text->m_Pos.y ); text->m_Pos.y += m_Pos.y; NEGATE( text->m_Pos0.y ); NEGATE_AND_NORMALIZE_ANGLE_POS( text->m_Orient ); text->SetLayer( FlipLayer( text->GetLayer() ) ); text->m_Mirror = IsBackLayer( GetLayer() ); // Reverse mirror module graphics and texts. for( EDA_ITEM* item = m_Drawings; item; item = item->Next() ) { switch( item->Type() ) { case PCB_MODULE_EDGE_T: { EDGE_MODULE* em = (EDGE_MODULE*) item; wxPoint s = em->GetStart(); s.y -= m_Pos.y; s.y = -s.y; s.y += m_Pos.y; em->SetStart( s ); wxPoint e = em->GetEnd(); e.y -= m_Pos.y; e.y = -e.y; e.y += m_Pos.y; em->SetEnd( e ); NEGATE( em->m_Start0.y ); NEGATE( em->m_End0.y ); if( em->GetShape() == S_ARC ) { em->SetAngle( -em->GetAngle() ); } em->SetLayer( FlipLayer( em->GetLayer() ) ); } break; case PCB_MODULE_TEXT_T: text = (TEXTE_MODULE*) item; text->m_Pos.y -= m_Pos.y; NEGATE( text->m_Pos.y ); text->m_Pos.y += m_Pos.y; NEGATE( text->m_Pos0.y ); NEGATE_AND_NORMALIZE_ANGLE_POS( text->m_Orient ); text->SetLayer( FlipLayer( text->GetLayer() ) ); text->m_Mirror = IsBackLayer( GetLayer() ); break; default: wxMessageBox( wxT( "MODULE::Flip() error: Unknown Draw Type" ) ); break; } } CalculateBoundingBox(); }
int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) { if( !m_frame->GetModel() ) return 0; DIALOG_DXF_IMPORT dlg( m_frame ); int dlgResult = dlg.ShowModal(); const std::list<BOARD_ITEM*>& list = dlg.GetImportedItems(); if( dlgResult != wxID_OK || list.empty() ) return 0; VECTOR2I cursorPos = m_controls->GetCursorPosition(); VECTOR2I delta = cursorPos - list.front()->GetPosition(); // Add a VIEW_GROUP that serves as a preview for the new item SELECTION preview( m_view ); BOARD_COMMIT commit( m_frame ); // Build the undo list & add items to the current view for( auto item : list ) { assert( item->Type() == PCB_LINE_T || item->Type() == PCB_TEXT_T ); preview.Add( item ); } BOARD_ITEM* firstItem = preview.Front(); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_controls->ShowCursor( true ); m_controls->SetSnapping( true ); SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF ); Activate(); // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { cursorPos = m_controls->GetCursorPosition(); if( evt->IsMotion() ) { delta = cursorPos - firstItem->GetPosition(); for( auto item : preview ) item->Move( wxPoint( delta.x, delta.y ) ); m_view->Update( &preview ); } else if( evt->Category() == TC_COMMAND ) { // TODO it should be handled by EDIT_TOOL, so add items and select? if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { for( auto item : preview ) item->Rotate( wxPoint( cursorPos.x, cursorPos.y ), m_frame->GetRotationAngle() ); m_view->Update( &preview ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { for( auto item : preview ) item->Flip( wxPoint( cursorPos.x, cursorPos.y ) ); m_view->Update( &preview ); } else if( evt->IsCancel() || evt->IsActivate() ) { preview.FreeItems(); break; } } else if ( evt->IsClick( BUT_RIGHT ) ) { showContextMenu(); } else if( evt->IsClick( BUT_LEFT ) ) { // Place the drawing BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); for( auto item : preview ) { if( m_editModules ) { // Modules use different types for the same things, // so we need to convert imported items to appropriate classes. BOARD_ITEM* converted = NULL; switch( item->Type() ) { case PCB_TEXT_T: { TEXTE_PCB* text = static_cast<TEXTE_PCB*>( item ); TEXTE_MODULE* textMod = new TEXTE_MODULE( (MODULE*) parent ); // Assignment operator also copies the item PCB_TEXT_T type, // so it cannot be added to a module which handles PCB_MODULE_TEXT_T textMod->SetPosition( text->GetPosition() ); textMod->SetText( text->GetText() ); textMod->SetSize( text->GetSize() ); textMod->SetThickness( text->GetThickness() ); textMod->SetOrientation( text->GetOrientation() ); textMod->SetTextPosition( text->GetTextPosition() ); textMod->SetSize( text->GetSize() ); textMod->SetMirrored( text->IsMirrored() ); textMod->SetAttributes( text->GetAttributes() ); textMod->SetItalic( text->IsItalic() ); textMod->SetBold( text->IsBold() ); textMod->SetHorizJustify( text->GetHorizJustify() ); textMod->SetVertJustify( text->GetVertJustify() ); textMod->SetMultilineAllowed( text->IsMultilineAllowed() ); converted = textMod; break; } case PCB_LINE_T: { DRAWSEGMENT* seg = static_cast<DRAWSEGMENT*>( item ); EDGE_MODULE* modSeg = new EDGE_MODULE( (MODULE*) parent ); // Assignment operator also copies the item PCB_LINE_T type, // so it cannot be added to a module which handles PCB_MODULE_EDGE_T modSeg->SetWidth( seg->GetWidth() ); modSeg->SetStart( seg->GetStart() ); modSeg->SetEnd( seg->GetEnd() ); modSeg->SetAngle( seg->GetAngle() ); modSeg->SetShape( seg->GetShape() ); modSeg->SetType( seg->GetType() ); modSeg->SetBezControl1( seg->GetBezControl1() ); modSeg->SetBezControl2( seg->GetBezControl2() ); modSeg->SetBezierPoints( seg->GetBezierPoints() ); modSeg->SetPolyPoints( seg->GetPolyPoints() ); converted = modSeg; break; } default: assert( false ); break; } if( converted ) converted->SetLayer( item->GetLayer() ); delete item; item = converted; } if( item ) commit.Add( item ); } commit.Push( _( "Place a DXF drawing" ) ); break; } } preview.Clear(); m_controls->ShowCursor( false ); m_controls->SetSnapping( false ); m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); m_view->Remove( &preview ); return 0; }
MODULE* GPCB_FPL_CACHE::parseMODULE( LINE_READER* aLineReader ) throw( IO_ERROR, PARSE_ERROR ) { #define TEXT_DEFAULT_SIZE ( 40*IU_PER_MILS ) #define OLD_GPCB_UNIT_CONV IU_PER_MILS // Old version unit = 1 mil, so conv_unit is 10 or 0.1 #define NEW_GPCB_UNIT_CONV ( 0.01*IU_PER_MILS ) int paramCnt; double conv_unit = NEW_GPCB_UNIT_CONV; // GPCB unit = 0.01 mils and Pcbnew 0.1 wxPoint textPos; wxString msg; wxArrayString parameters; std::auto_ptr<MODULE> module( new MODULE( NULL ) ); if( aLineReader->ReadLine() == NULL ) THROW_IO_ERROR( "unexpected end of file" ); parameters.Clear(); parseParameters( parameters, aLineReader ); paramCnt = parameters.GetCount(); /* From the Geda PCB documentation, valid Element definitions: * Element [SFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TSFlags] * Element (NFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TNFlags) * Element (NFlags "Desc" "Name" "Value" TX TY TDir TScale TNFlags) * Element (NFlags "Desc" "Name" TX TY TDir TScale TNFlags) * Element ("Desc" "Name" TX TY TDir TScale TNFlags) */ if( parameters[0].CmpNoCase( wxT( "Element" ) ) != 0 ) { msg.Printf( _( "unknown token \"%s\"" ), GetChars( parameters[0] ) ); THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader, aLineReader->LineNumber(), 0 ); } if( paramCnt < 10 || paramCnt > 14 ) { msg.Printf( _( "Element token contains %d parameters." ), paramCnt ); THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader, aLineReader->LineNumber(), 0 ); } // Test symbol after "Element": if [ units = 0.01 mils, and if ( units = 1 mil if( parameters[1] == wxT( "(" ) ) conv_unit = OLD_GPCB_UNIT_CONV; if( paramCnt > 10 ) { module->SetDescription( parameters[3] ); module->SetReference( parameters[4] ); } else { module->SetDescription( parameters[2] ); module->SetReference( parameters[3] ); } // Read value if( paramCnt > 10 ) module->SetValue( parameters[5] ); // With gEDA/pcb, value is meaningful after instantiation, only, so it's // often empty in bare footprints. if( module->Value().GetText().IsEmpty() ) module->Value().SetText( wxT( "Val**" ) ); if( paramCnt == 14 ) { textPos = wxPoint( parseInt( parameters[8], conv_unit ), parseInt( parameters[9], conv_unit ) ); } else { textPos = wxPoint( parseInt( parameters[6], conv_unit ), parseInt( parameters[7], conv_unit ) ); } int orientation = parseInt( parameters[paramCnt-4], 1.0 ); module->Reference().SetOrientation( (orientation % 2) ? 900 : 0 ); // Calculate size: default height is 40 mils, width 30 mil. // real size is: default * ibuf[idx+3] / 100 (size in gpcb is given in percent of default size int thsize = parseInt( parameters[paramCnt-3], TEXT_DEFAULT_SIZE ) / 100; thsize = std::max( (int)( 5 * IU_PER_MILS ), thsize ); // Ensure a minimal size = 5 mils int twsize = thsize * 30 / 40; int thickness = thsize / 8; // gEDA/pcb aligns top/left, not pcbnew's default, center/center. // Compensate for this by shifting the insertion point instead of the // aligment, because alignment isn't changeable in the GUI. textPos.x = textPos.x + twsize * module->GetReference().Len() / 2; textPos.y += thsize / 2; // gEDA/pcb draws a bit too low/left, while pcbnew draws a bit too // high/right. Compensate for similar appearance. textPos.x -= thsize / 10; textPos.y += thsize / 2; module->Reference().SetTextPosition( textPos ); module->Reference().SetPos0( textPos ); module->Reference().SetSize( wxSize( twsize, thsize ) ); module->Reference().SetThickness( thickness ); // gEDA/pcb shows only one of value/reference/description at a time. Which // one is selectable by a global menu setting. pcbnew needs reference as // well as value visible, so place the value right below the reference. module->Value().SetOrientation( module->Reference().GetOrientation() ); module->Value().SetSize( module->Reference().GetSize() ); module->Value().SetThickness( module->Reference().GetThickness() ); textPos.y += thsize * 13 / 10; // 130% line height module->Value().SetTextPosition( textPos ); module->Value().SetPos0( textPos ); while( aLineReader->ReadLine() ) { parameters.Clear(); parseParameters( parameters, aLineReader ); if( parameters.IsEmpty() || parameters[0] == wxT( "(" ) ) continue; if( parameters[0] == wxT( ")" ) ) break; paramCnt = parameters.GetCount(); // Test units value for a string line param (more than 3 parameters : ident [ xx ] ) if( paramCnt > 3 ) { if( parameters[1] == wxT( "(" ) ) conv_unit = OLD_GPCB_UNIT_CONV; else conv_unit = NEW_GPCB_UNIT_CONV; } wxLogTrace( traceFootprintLibrary, wxT( "%s parameter count = %d." ), GetChars( parameters[0] ), paramCnt ); // Parse a line with format: ElementLine [X1 Y1 X2 Y2 Thickness] if( parameters[0].CmpNoCase( wxT( "ElementLine" ) ) == 0 ) { if( paramCnt != 8 ) { msg.Printf( wxT( "ElementLine token contains %d parameters." ), paramCnt ); THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader, aLineReader->LineNumber(), 0 ); } EDGE_MODULE* drawSeg = new EDGE_MODULE( module.get() ); drawSeg->SetLayer( F_SilkS ); drawSeg->SetShape( S_SEGMENT ); drawSeg->SetStart0( wxPoint( parseInt( parameters[2], conv_unit ), parseInt( parameters[3], conv_unit ) ) ); drawSeg->SetEnd0( wxPoint( parseInt( parameters[4], conv_unit ), parseInt( parameters[5], conv_unit ) ) ); drawSeg->SetWidth( parseInt( parameters[6], conv_unit ) ); drawSeg->SetDrawCoord(); module->GraphicalItems().PushBack( drawSeg ); continue; } // Parse an arc with format: ElementArc [X Y Width Height StartAngle DeltaAngle Thickness] if( parameters[0].CmpNoCase( wxT( "ElementArc" ) ) == 0 ) { if( paramCnt != 10 ) { msg.Printf( wxT( "ElementArc token contains %d parameters." ), paramCnt ); THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader, aLineReader->LineNumber(), 0 ); } // Pcbnew does know ellipse so we must have Width = Height EDGE_MODULE* drawSeg = new EDGE_MODULE( module.get() ); drawSeg->SetLayer( F_SilkS ); drawSeg->SetShape( S_ARC ); module->GraphicalItems().PushBack( drawSeg ); // for and arc: ibuf[3] = ibuf[4]. Pcbnew does not know ellipses int radius = ( parseInt( parameters[4], conv_unit ) + parseInt( parameters[5], conv_unit ) ) / 2; wxPoint centre( parseInt( parameters[2], conv_unit ), parseInt( parameters[3], conv_unit ) ); drawSeg->SetStart0( centre ); // Pcbnew start angles are inverted and 180 degrees from Geda PCB angles. double start_angle = parseInt( parameters[6], -10.0 ) + 1800.0; // Pcbnew delta angle direction is the opposite of Geda PCB delta angles. double sweep_angle = parseInt( parameters[7], -10.0 ); // Geda PCB does not support circles. if( sweep_angle == -3600.0 ) drawSeg->SetShape( S_CIRCLE ); // Angle value is clockwise in gpcb and Pcbnew. drawSeg->SetAngle( sweep_angle ); drawSeg->SetEnd0( wxPoint( radius, 0 ) ); // Calculate start point coordinate of arc wxPoint arcStart( drawSeg->GetEnd0() ); RotatePoint( &arcStart, -start_angle ); drawSeg->SetEnd0( centre + arcStart ); drawSeg->SetWidth( parseInt( parameters[8], conv_unit ) ); drawSeg->SetDrawCoord(); continue; } // Parse a Pad with no hole with format: // Pad [rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" SFlags] // Pad (rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" NFlags) // Pad (aX1 aY1 aX2 aY2 Thickness "Name" "Number" NFlags) // Pad (aX1 aY1 aX2 aY2 Thickness "Name" NFlags) if( parameters[0].CmpNoCase( wxT( "Pad" ) ) == 0 ) { if( paramCnt < 10 || paramCnt > 13 ) { msg.Printf( wxT( "Pad token contains %d parameters." ), paramCnt ); THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader, aLineReader->LineNumber(), 0 ); } D_PAD* pad = new D_PAD( module.get() ); static const LSET pad_front( 3, F_Cu, F_Mask, F_Paste ); static const LSET pad_back( 3, B_Cu, B_Mask, B_Paste ); pad->SetShape( PAD_SHAPE_RECT ); pad->SetAttribute( PAD_ATTRIB_SMD ); pad->SetLayerSet( pad_front ); if( testFlags( parameters[paramCnt-2], 0x0080, wxT( "onsolder" ) ) ) pad->SetLayerSet( pad_back ); // Set the pad name: // Pcbnew pad name is used for electrical connection calculations. // Accordingly it should be mapped to gEDA's pin/pad number, // which is used for the same purpose. // gEDA also features a pin/pad "name", which is an arbitrary string // and set to the pin name of the netlist on instantiation. Many gEDA // bare footprints use identical strings for name and number, so this // can be a bit confusing. pad->SetPadName( parameters[paramCnt-3] ); int x1 = parseInt( parameters[2], conv_unit ); int x2 = parseInt( parameters[4], conv_unit ); int y1 = parseInt( parameters[3], conv_unit ); int y2 = parseInt( parameters[5], conv_unit ); int width = parseInt( parameters[6], conv_unit ); wxPoint delta( x2 - x1, y2 - y1 ); double angle = atan2( (double)delta.y, (double)delta.x ); // Get the pad clearance and the solder mask clearance. if( paramCnt == 13 ) { int clearance = parseInt( parameters[7], conv_unit ); // One of gEDA's oddities is that clearance between pad and polygon // is given as the gap on both sides of the pad together, so for // KiCad it has to halfed. pad->SetLocalClearance( clearance / 2 ); // In GEDA, the mask value is the size of the hole in this // solder mask. In Pcbnew, it is a margin, therefore the distance // between the copper and the mask int maskMargin = parseInt( parameters[8], conv_unit ); maskMargin = ( maskMargin - width ) / 2; pad->SetLocalSolderMaskMargin( maskMargin ); } // Negate angle (due to Y reversed axis) and convert it to internal units angle = - RAD2DECIDEG( angle ); pad->SetOrientation( KiROUND( angle ) ); wxPoint padPos( (x1 + x2) / 2, (y1 + y2) / 2 ); pad->SetSize( wxSize( KiROUND( EuclideanNorm( delta ) ) + width, width ) ); padPos += module->GetPosition(); pad->SetPos0( padPos ); pad->SetPosition( padPos ); if( !testFlags( parameters[paramCnt-2], 0x0100, wxT( "square" ) ) ) { if( pad->GetSize().x == pad->GetSize().y ) pad->SetShape( PAD_SHAPE_CIRCLE ); else pad->SetShape( PAD_SHAPE_OVAL ); } module->Add( pad ); continue; } // Parse a Pin with through hole with format: // Pin [rX rY Thickness Clearance Mask Drill "Name" "Number" SFlags] // Pin (rX rY Thickness Clearance Mask Drill "Name" "Number" NFlags) // Pin (aX aY Thickness Drill "Name" "Number" NFlags) // Pin (aX aY Thickness Drill "Name" NFlags) // Pin (aX aY Thickness "Name" NFlags) if( parameters[0].CmpNoCase( wxT( "Pin" ) ) == 0 ) { if( paramCnt < 8 || paramCnt > 12 ) { msg.Printf( wxT( "Pin token contains %d parameters." ), paramCnt ); THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader, aLineReader->LineNumber(), 0 ); } D_PAD* pad = new D_PAD( module.get() ); pad->SetShape( PAD_SHAPE_CIRCLE ); static const LSET pad_set = LSET::AllCuMask() | LSET( 3, F_SilkS, F_Mask, B_Mask ); pad->SetLayerSet( pad_set ); if( testFlags( parameters[paramCnt-2], 0x0100, wxT( "square" ) ) ) pad->SetShape( PAD_SHAPE_RECT ); // Set the pad name: // Pcbnew pad name is used for electrical connection calculations. // Accordingly it should be mapped to gEDA's pin/pad number, // which is used for the same purpose. pad->SetPadName( parameters[paramCnt-3] ); wxPoint padPos( parseInt( parameters[2], conv_unit ), parseInt( parameters[3], conv_unit ) ); int padSize = parseInt( parameters[4], conv_unit ); pad->SetSize( wxSize( padSize, padSize ) ); int drillSize = 0; // Get the pad clearance, solder mask clearance, and drill size. if( paramCnt == 12 ) { int clearance = parseInt( parameters[5], conv_unit ); // One of gEDA's oddities is that clearance between pad and polygon // is given as the gap on both sides of the pad together, so for // KiCad it has to halfed. pad->SetLocalClearance( clearance / 2 ); // In GEDA, the mask value is the size of the hole in this // solder mask. In Pcbnew, it is a margin, therefore the distance // between the copper and the mask int maskMargin = parseInt( parameters[6], conv_unit ); maskMargin = ( maskMargin - padSize ) / 2; pad->SetLocalSolderMaskMargin( maskMargin ); drillSize = parseInt( parameters[7], conv_unit ); } else { drillSize = parseInt( parameters[5], conv_unit ); } pad->SetDrillSize( wxSize( drillSize, drillSize ) ); padPos += module->GetPosition(); pad->SetPos0( padPos ); pad->SetPosition( padPos ); if( pad->GetShape() == PAD_SHAPE_CIRCLE && pad->GetSize().x != pad->GetSize().y ) pad->SetShape( PAD_SHAPE_OVAL ); module->Add( pad ); continue; } } // Recalculate the bounding box module->CalculateBoundingBox(); return module.release(); }