void MODULE::MoveAnchorPosition( const wxPoint& aMoveVector ) { /* Move the reference point of the footprint * the footprints elements (pads, outlines, edges .. ) are moved * but: * - the footprint position is not modified. * - the relative (local) coordinates of these items are modified */ wxPoint footprintPos = GetPosition(); /* Update the relative coordinates: * The coordinates are relative to the anchor point. * Calculate deltaX and deltaY from the anchor. */ wxPoint moveVector = aMoveVector; RotatePoint( &moveVector, -GetOrientation() ); // Update of the reference and value. m_Reference->SetPos0( m_Reference->GetPos0() + moveVector ); m_Reference->SetDrawCoord(); m_Value->SetPos0( m_Value->GetPos0() + moveVector ); m_Value->SetDrawCoord(); // Update the pad local coordinates. for( D_PAD* pad = Pads(); pad; pad = pad->Next() ) { pad->SetPos0( pad->GetPos0() + moveVector ); pad->SetPosition( pad->GetPos0() + footprintPos ); } // Update the draw element coordinates. for( EDA_ITEM* item = GraphicalItems(); item; item = item->Next() ) { switch( item->Type() ) { case PCB_MODULE_EDGE_T: { EDGE_MODULE* edge = static_cast<EDGE_MODULE*>( item ); edge->m_Start0 += moveVector; edge->m_End0 += moveVector; edge->SetDrawCoord(); break; } case PCB_MODULE_TEXT_T: { TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( item ); text->SetPos0( text->GetPos0() + moveVector ); text->SetDrawCoord(); break; } default: break; } } CalculateBoundingBox(); }
/* Creates the footprint shape list. * Since module shape is customizable after the placement we cannot share them; * instead we opt for the one-module-one-shape-one-component-one-device approach */ static void CreateShapesSection( FILE* aFile, BOARD* aPcb ) { MODULE* module; D_PAD* pad; const char* layer; wxString pinname; const char* mirror = "0"; fputs( "$SHAPES\n", aFile ); const LSET all_cu = LSET::AllCuMask(); for( module = aPcb->m_Modules; module; module = module->Next() ) { FootprintWriteShape( aFile, module ); for( pad = module->Pads(); pad; pad = pad->Next() ) { /* Funny thing: GenCAD requires the pad side even if you use * padstacks (which are theorically optional but gerbtools *requires* them). Now the trouble thing is that 'BOTTOM' * is interpreted by someone as a padstack flip even * if the spec explicitly says it's not... */ layer = "ALL"; if( ( pad->GetLayerSet() & all_cu ) == LSET( B_Cu ) ) { layer = module->GetFlag() ? "TOP" : "BOTTOM"; } else if( ( pad->GetLayerSet() & all_cu ) == LSET( F_Cu ) ) { layer = module->GetFlag() ? "BOTTOM" : "TOP"; } pad->StringPadName( pinname ); if( pinname.IsEmpty() ) pinname = wxT( "none" ); double orient = pad->GetOrientation() - module->GetOrientation(); NORMALIZE_ANGLE_POS( orient ); // Bottom side modules use the flipped padstack fprintf( aFile, (module->GetFlag()) ? "PIN %s PAD%dF %g %g %s %g %s\n" : "PIN %s PAD%d %g %g %s %g %s\n", TO_UTF8( pinname ), pad->GetSubRatsnest(), pad->GetPos0().x / SCALE_FACTOR, -pad->GetPos0().y / SCALE_FACTOR, layer, orient / 10.0, mirror ); } } fputs( "$ENDSHAPES\n\n", aFile ); }
/* Move marked items, at new position = old position + offset */ void MoveMarkedItems( MODULE* module, wxPoint offset ) { EDA_ITEM* item; if( module == NULL ) return; if( module->Reference().IsSelected() ) module->Reference().Move( offset ); if( module->Value().IsSelected() ) module->Value().Move( offset ); D_PAD* pad = module->Pads(); for( ; pad != NULL; pad = pad->Next() ) { if( !pad->IsSelected() ) continue; pad->SetPosition( pad->GetPosition() + offset ); pad->SetPos0( pad->GetPos0() + offset ); } item = module->GraphicalItems(); for( ; item != NULL; item = item->Next() ) { if( !item->IsSelected() ) continue; switch( item->Type() ) { case PCB_MODULE_TEXT_T: static_cast<TEXTE_MODULE*>( item )->Move( offset ); break; case PCB_MODULE_EDGE_T: { EDGE_MODULE* em = (EDGE_MODULE*) item; em->SetStart( em->GetStart() + offset ); em->SetEnd( em->GetEnd() + offset ); em->SetStart0( em->GetStart0() + offset ); em->SetEnd0( em->GetEnd0() + offset ); } break; default: ; } } ClearMarkItems( module ); }
/* Move marked items, at new position = old position + offset */ void MoveMarkedItems( MODULE* module, wxPoint offset ) { EDA_ITEM* item; if( module == NULL ) return; D_PAD* pad = module->Pads(); for( ; pad != NULL; pad = pad->Next() ) { if( !pad->IsSelected() ) continue; pad->SetPosition( pad->GetPosition() + offset ); pad->SetPos0( pad->GetPos0() + offset ); } item = module->GraphicalItems(); for( ; item != NULL; item = item->Next() ) { if( !item->IsSelected() ) continue; switch( item->Type() ) { case PCB_MODULE_TEXT_T: { TEXTE_MODULE* tm = (TEXTE_MODULE*) item; tm->Offset( offset ); tm->SetPos0( tm->GetPos0() + offset ); } break; case PCB_MODULE_EDGE_T: { EDGE_MODULE* em = (EDGE_MODULE*) item; em->SetStart( em->GetStart() + offset ); em->SetEnd( em->GetEnd() + offset ); em->SetStart0( em->GetStart0() + offset ); em->SetEnd0( em->GetEnd0() + offset ); } break; default: ; } item->ClearFlags(); } }
/** Rotate marked items, refer to a rotation point at position offset * Note: because this function is used in global transform, * if force_all is true, all items will be rotated */ void RotateMarkedItems( MODULE* module, wxPoint offset, bool force_all ) { #define ROTATE( z ) RotatePoint( (&z), offset, 900 ) if( module == NULL ) return; if( module->Reference().IsSelected() || force_all ) module->Reference().Rotate( offset, 900 ); if( module->Value().IsSelected() || force_all ) module->Value().Rotate( offset, 900 ); for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { if( !pad->IsSelected() && !force_all ) continue; wxPoint pos = pad->GetPos0(); ROTATE( pos ); pad->SetPos0( pos ); pad->SetOrientation( pad->GetOrientation() + 900 ); pad->SetDrawCoord(); } for( EDA_ITEM* item = module->GraphicalItems(); item; item = item->Next() ) { if( !item->IsSelected() && !force_all ) continue; switch( item->Type() ) { case PCB_MODULE_EDGE_T: ((EDGE_MODULE*) item)->Rotate( offset, 900 ); break; case PCB_MODULE_TEXT_T: static_cast<TEXTE_MODULE*>( item )->Rotate( offset, 900 ); break; default: break; } } ClearMarkItems( module ); }
/* * Move the footprint anchor position to the current cursor position. */ void FOOTPRINT_EDIT_FRAME::Place_Ancre( MODULE* aModule ) { wxPoint moveVector; if( aModule == NULL ) return; moveVector = aModule->m_Pos - GetScreen()->GetCrossHairPosition(); aModule->m_Pos = GetScreen()->GetCrossHairPosition(); /* Update the relative coordinates: * The coordinates are relative to the anchor point. * Calculate deltaX and deltaY from the anchor. */ RotatePoint( &moveVector, -aModule->m_Orient ); // Update the pad coordinates. for( D_PAD* pad = (D_PAD*) aModule->m_Pads; pad; pad = pad->Next() ) { pad->SetPos0( pad->GetPos0() + moveVector ); } // Update the draw element coordinates. for( EDA_ITEM* item = aModule->m_Drawings; item; item = item->Next() ) { switch( item->Type() ) { case PCB_MODULE_EDGE_T: #undef STRUCT #define STRUCT ( (EDGE_MODULE*) item ) STRUCT->m_Start0 += moveVector; STRUCT->m_End0 += moveVector; break; case PCB_MODULE_TEXT_T: #undef STRUCT #define STRUCT ( (TEXTE_MODULE*) item ) STRUCT->SetPos0( STRUCT->GetPos0() + moveVector ); break; default: break; } } aModule->CalculateBoundingBox(); }
void MODULE::SetOrientation( double newangle ) { double angleChange = newangle - m_Orient; // change in rotation wxPoint pt; NORMALIZE_ANGLE_POS( newangle ); m_Orient = newangle; for( D_PAD* pad = m_Pads; pad; pad = pad->Next() ) { pt = pad->GetPos0(); pad->SetOrientation( pad->GetOrientation() + angleChange ); RotatePoint( &pt, m_Orient ); pad->SetPosition( GetPosition() + pt ); } // Update of the reference and value. m_Reference->SetDrawCoord(); m_Value->SetDrawCoord(); // Displace contours and text of the footprint. for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) { if( item->Type() == PCB_MODULE_EDGE_T ) { EDGE_MODULE* edge = (EDGE_MODULE*) item; edge->SetDrawCoord(); } else if( item->Type() == PCB_MODULE_TEXT_T ) { TEXTE_MODULE* text = (TEXTE_MODULE*) item; text->SetDrawCoord(); } } CalculateBoundingBox(); }
MODULE* PCB_EDIT_FRAME::Create_MuWaveComponent( int shape_type ) { int oX; D_PAD* pad; MODULE* module; wxString msg, cmp_name; int pad_count = 2; int angle = 0; // Ref and value text size (O = use board default value. // will be set to a value depending on the footprint size, if possible int text_size = 0; // Enter the size of the gap or stub int gap_size = GetDesignSettings().GetCurrentTrackWidth(); switch( shape_type ) { case 0: msg = _( "Gap" ); cmp_name = wxT( "muwave_gap" ); text_size = gap_size; break; case 1: msg = _( "Stub" ); cmp_name = wxT( "muwave_stub" ); text_size = gap_size; pad_count = 2; break; case 2: msg = _( "Arc Stub" ); cmp_name = wxT( "muwave_arcstub" ); pad_count = 1; break; default: msg = wxT( "???" ); break; } wxString value = StringFromValue( g_UserUnit, gap_size ); wxTextEntryDialog dlg( this, msg, _( "Create microwave module" ), value ); if( dlg.ShowModal() != wxID_OK ) { m_canvas->MoveCursorToCrossHair(); return NULL; // cancelled by user } value = dlg.GetValue(); gap_size = ValueFromString( g_UserUnit, value ); bool abort = false; if( shape_type == 2 ) { double fcoeff = 10.0, fval; msg.Printf( wxT( "%3.1f" ), angle / fcoeff ); wxTextEntryDialog angledlg( this, _( "Angle in degrees:" ), _( "Create microwave module" ), msg ); if( angledlg.ShowModal() != wxID_OK ) { m_canvas->MoveCursorToCrossHair(); return NULL; // cancelled by user } msg = angledlg.GetValue(); if( !msg.ToDouble( &fval ) ) { DisplayError( this, _( "Incorrect number, abort" ) ); abort = true; } angle = std::abs( KiROUND( fval * fcoeff ) ); if( angle > 1800 ) angle = 1800; } if( abort ) { m_canvas->MoveCursorToCrossHair(); return NULL; } module = CreateMuWaveBaseFootprint( cmp_name, text_size, pad_count ); pad = module->Pads(); switch( shape_type ) { case 0: //Gap : oX = -( gap_size + pad->GetSize().x ) / 2; pad->SetX0( oX ); pad->SetX( pad->GetPos0().x + pad->GetPosition().x ); pad = pad->Next(); pad->SetX0( oX + gap_size + pad->GetSize().x ); pad->SetX( pad->GetPos0().x + pad->GetPosition().x ); break; case 1: //Stub : pad->SetPadName( wxT( "1" ) ); pad = pad->Next(); pad->SetY0( -( gap_size + pad->GetSize().y ) / 2 ); pad->SetSize( wxSize( pad->GetSize().x, gap_size ) ); pad->SetY( pad->GetPos0().y + pad->GetPosition().y ); break; case 2: // Arc Stub created by a polygonal approach: { EDGE_MODULE* edge = new EDGE_MODULE( module ); module->GraphicalItems().PushFront( edge ); edge->SetShape( S_POLYGON ); edge->SetLayer( F_Cu ); int numPoints = (angle / 50) + 3; // Note: angles are in 0.1 degrees std::vector<wxPoint>& polyPoints = edge->GetPolyPoints(); polyPoints.reserve( numPoints ); edge->m_Start0.y = -pad->GetSize().y / 2; polyPoints.push_back( wxPoint( 0, 0 ) ); int theta = -angle / 2; for( int ii = 1; ii<numPoints - 1; ii++ ) { wxPoint pt( 0, -gap_size ); RotatePoint( &pt.x, &pt.y, theta ); polyPoints.push_back( pt ); theta += 50; if( theta > angle / 2 ) theta = angle / 2; } // Close the polygon: polyPoints.push_back( polyPoints[0] ); } break; default: break; } module->CalculateBoundingBox(); GetBoard()->m_Status_Pcb = 0; OnModify(); return module; }