/** * @file class_module_transform_functions.cpp * @brief Functions of class MODULE to handle some geometric changes such as move, rotate ... */ #include "fctsys.h" #include "wxstruct.h" #include "trigo.h" #include "pcbcommon.h" #include "pcbnew.h" #include "macros.h" #include "protos.h" #include "class_pad.h" #include "class_edge_mod.h" #include "class_module.h" /* Calculate the layer number for changing cu / cmp layers for Cu / CMP * (Copper, Mask, Paste, solder) */ int ChangeSideNumLayer( int oldlayer ) { int newlayer; switch( oldlayer ) { case LAYER_N_BACK: newlayer = LAYER_N_FRONT; break; case LAYER_N_FRONT: newlayer = LAYER_N_BACK; break; case SILKSCREEN_N_BACK: newlayer = SILKSCREEN_N_FRONT; break; case SILKSCREEN_N_FRONT: newlayer = SILKSCREEN_N_BACK; break; case ADHESIVE_N_BACK: newlayer = ADHESIVE_N_FRONT; break; case ADHESIVE_N_FRONT: newlayer = ADHESIVE_N_BACK; break; case SOLDERMASK_N_BACK: newlayer = SOLDERMASK_N_FRONT; break; case SOLDERMASK_N_FRONT: newlayer = SOLDERMASK_N_BACK; break; case SOLDERPASTE_N_BACK: newlayer = SOLDERPASTE_N_FRONT; break; case SOLDERPASTE_N_FRONT: newlayer = SOLDERPASTE_N_BACK; break; default: newlayer = oldlayer; } return newlayer; } /* Calculate the mask layer when flipping a footprint * BACK and FRONT copper layers , mask, paste, solder layers are swapped */ int ChangeSideMaskLayer( int aMask ) { int newMask; newMask = aMask & ~(LAYER_BACK | LAYER_FRONT | SILKSCREEN_LAYER_BACK | SILKSCREEN_LAYER_FRONT | ADHESIVE_LAYER_BACK | ADHESIVE_LAYER_FRONT | SOLDERMASK_LAYER_BACK | SOLDERMASK_LAYER_FRONT | SOLDERPASTE_LAYER_BACK | SOLDERPASTE_LAYER_FRONT | ADHESIVE_LAYER_BACK | ADHESIVE_LAYER_FRONT); if( aMask & LAYER_BACK ) newMask |= LAYER_FRONT; if( aMask & LAYER_FRONT ) newMask |= LAYER_BACK; if( aMask & SILKSCREEN_LAYER_BACK ) newMask |= SILKSCREEN_LAYER_FRONT; if( aMask & SILKSCREEN_LAYER_FRONT ) newMask |= SILKSCREEN_LAYER_BACK; if( aMask & ADHESIVE_LAYER_BACK ) newMask |= ADHESIVE_LAYER_FRONT; if( aMask & ADHESIVE_LAYER_FRONT ) newMask |= ADHESIVE_LAYER_BACK; if( aMask & SOLDERMASK_LAYER_BACK ) newMask |= SOLDERMASK_LAYER_FRONT; if( aMask & SOLDERMASK_LAYER_FRONT ) newMask |= SOLDERMASK_LAYER_BACK; if( aMask & SOLDERPASTE_LAYER_BACK ) newMask |= SOLDERPASTE_LAYER_FRONT; if( aMask & SOLDERPASTE_LAYER_FRONT ) newMask |= SOLDERPASTE_LAYER_BACK; if( aMask & ADHESIVE_LAYER_BACK ) newMask |= ADHESIVE_LAYER_FRONT; if( aMask & ADHESIVE_LAYER_FRONT ) newMask |= ADHESIVE_LAYER_BACK; return newMask; } /** * Function Move (virtual) * move this object. * @param aMoveVector - the move vector for this object. */ void MODULE::Move(const wxPoint& aMoveVector) { wxPoint newpos = m_Pos + aMoveVector; SetPosition( newpos ); } /** * Function Rotate * Rotate this object. * @param aRotCentre - the rotation point. * @param aAngle - the rotation angle in 0.1 degree. */ void MODULE::Rotate(const wxPoint& aRotCentre, int aAngle) { wxPoint newpos = m_Pos; RotatePoint( &newpos, aRotCentre, aAngle ); SetPosition( newpos ); SetOrientation( m_Orient + aAngle ); } /** * Function Flip * Flip this object, i.e. change the board side for this object * @param aCentre - the rotation point. */ void MODULE::Flip( const wxPoint& aCentre ) { D_PAD* pt_pad; TEXTE_MODULE* pt_texte; EDGE_MODULE* pt_edgmod; EDA_ITEM* PtStruct; // 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( ChangeSideNumLayer( GetLayer() ) ); /* Reverse mirror orientation. */ NEGATE( m_Orient ); NORMALIZE_ANGLE_POS( m_Orient ); /* Mirror inversion layers pads. */ pt_pad = m_Pads; for( ; pt_pad != NULL; pt_pad = pt_pad->Next() ) { pt_pad->m_Pos.y -= m_Pos.y; pt_pad->m_Pos.y = -pt_pad->m_Pos.y; pt_pad->m_Pos.y += m_Pos.y; NEGATE( pt_pad->m_Pos0.y ); NEGATE( pt_pad->m_Offset.y ); NEGATE( pt_pad->m_DeltaSize.y ); NEGATE_AND_NORMALIZE_ANGLE_POS( pt_pad->m_Orient ); /* flip pads layers*/ pt_pad->m_layerMask = ChangeSideMaskLayer( pt_pad->m_layerMask ); } /* Mirror reference. */ pt_texte = m_Reference; pt_texte->m_Pos.y -= m_Pos.y; pt_texte->m_Pos.y = -pt_texte->m_Pos.y; pt_texte->m_Pos.y += m_Pos.y; NEGATE(pt_texte->m_Pos0.y); pt_texte->m_Mirror = false; NEGATE_AND_NORMALIZE_ANGLE_POS( pt_texte->m_Orient ); pt_texte->SetLayer( GetLayer() ); pt_texte->SetLayer( ChangeSideNumLayer( pt_texte->GetLayer() ) ); if( GetLayer() == LAYER_N_BACK ) pt_texte->SetLayer( SILKSCREEN_N_BACK ); if( GetLayer() == LAYER_N_FRONT ) pt_texte->SetLayer( SILKSCREEN_N_FRONT ); if( (GetLayer() == SILKSCREEN_N_BACK) || (GetLayer() == ADHESIVE_N_BACK) || (GetLayer() == LAYER_N_BACK) ) pt_texte->m_Mirror = true; /* Mirror value. */ pt_texte = m_Value; pt_texte->m_Pos.y -= m_Pos.y; NEGATE( pt_texte->m_Pos.y ); pt_texte->m_Pos.y += m_Pos.y; NEGATE( pt_texte->m_Pos0.y ); pt_texte->m_Mirror = false; NEGATE_AND_NORMALIZE_ANGLE_POS( pt_texte->m_Orient ); pt_texte->SetLayer( GetLayer() ); pt_texte->SetLayer( ChangeSideNumLayer( pt_texte->GetLayer() ) ); if( GetLayer() == LAYER_N_BACK ) pt_texte->SetLayer( SILKSCREEN_N_BACK ); if( GetLayer() == LAYER_N_FRONT ) pt_texte->SetLayer( SILKSCREEN_N_FRONT ); if( (GetLayer() == SILKSCREEN_N_BACK) || (GetLayer() == ADHESIVE_N_BACK) || (GetLayer() == LAYER_N_BACK) ) pt_texte->m_Mirror = true; /* Reverse mirror footprints. */ PtStruct = m_Drawings; for( ; PtStruct != NULL; PtStruct = PtStruct->Next() ) { switch( PtStruct->Type() ) { case PCB_MODULE_EDGE_T: pt_edgmod = (EDGE_MODULE*) PtStruct; pt_edgmod->m_Start.y -= m_Pos.y; pt_edgmod->m_Start.y = -pt_edgmod->m_Start.y; pt_edgmod->m_Start.y += m_Pos.y; pt_edgmod->m_End.y -= m_Pos.y; pt_edgmod->m_End.y = -pt_edgmod->m_End.y; pt_edgmod->m_End.y += m_Pos.y; NEGATE( pt_edgmod->m_Start0.y ); NEGATE( pt_edgmod->m_End0.y ); if( pt_edgmod->m_Shape == S_ARC ) { NEGATE(pt_edgmod->m_Angle); } pt_edgmod->SetLayer( ChangeSideNumLayer( pt_edgmod->GetLayer() ) ); break; case PCB_MODULE_TEXT_T: /* Reverse mirror position and mirror. */ pt_texte = (TEXTE_MODULE*) PtStruct; pt_texte->m_Pos.y -= m_Pos.y; pt_texte->m_Pos.y = -pt_texte->m_Pos.y; pt_texte->m_Pos.y += m_Pos.y; NEGATE( pt_texte->m_Pos0.y ); pt_texte->m_Mirror = false; NEGATE_AND_NORMALIZE_ANGLE_POS( pt_texte->m_Orient ); pt_texte->SetLayer( GetLayer() ); pt_texte->SetLayer( ChangeSideNumLayer( pt_texte->GetLayer() ) ); if( GetLayer() == LAYER_N_BACK ) pt_texte->SetLayer( SILKSCREEN_N_BACK ); if( GetLayer() == LAYER_N_FRONT ) pt_texte->SetLayer( SILKSCREEN_N_FRONT ); if( GetLayer() == SILKSCREEN_N_BACK || GetLayer() == ADHESIVE_N_BACK || GetLayer() == LAYER_N_BACK ) { pt_texte->m_Mirror = true; } break; default: wxMessageBox( wxT( "MODULE::Flip() error: Unknown Draw Type" ) ); break; } } CalculateBoundingBox(); } void MODULE::SetPosition( const wxPoint& newpos ) { wxPoint delta = newpos - m_Pos; m_Pos += delta; m_Reference->m_Pos += delta; m_Value->m_Pos += delta; for( D_PAD* pad = m_Pads; pad; pad = pad->Next() ) { pad->m_Pos += delta; } EDA_ITEM* PtStruct = m_Drawings; for( ; PtStruct != NULL; PtStruct = PtStruct->Next() ) { switch( PtStruct->Type() ) { case PCB_MODULE_EDGE_T: { EDGE_MODULE* pt_edgmod = (EDGE_MODULE*) PtStruct; pt_edgmod->SetDrawCoord(); break; } case PCB_MODULE_TEXT_T: { TEXTE_MODULE* pt_texte = (TEXTE_MODULE*) PtStruct; pt_texte->m_Pos += delta; break; } default: wxMessageBox( wxT( "Draw type undefined." ) ); break; } } CalculateBoundingBox(); } void MODULE::SetOrientation( int newangle ) { int px, py; newangle -= m_Orient; // = Change in rotation m_Orient += newangle; NORMALIZE_ANGLE_POS( m_Orient ); for( D_PAD* pad = m_Pads; pad; pad = pad->Next() ) { px = pad->m_Pos0.x; py = pad->m_Pos0.y; pad->m_Orient += newangle; /* change m_Orientation */ NORMALIZE_ANGLE_POS( pad->m_Orient ); RotatePoint( &px, &py, m_Orient ); pad->m_Pos.x = m_Pos.x + px; pad->m_Pos.y = m_Pos.y + py; } /* 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* pt_edgmod = (EDGE_MODULE*) item; pt_edgmod->SetDrawCoord(); } if( item->Type() == PCB_MODULE_TEXT_T ) { TEXTE_MODULE* pt_texte = (TEXTE_MODULE*) item; pt_texte->SetDrawCoord(); } } CalculateBoundingBox(); }