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; }
/** * Function PlaceCells * Initialize the matrix routing by setting obstacles for each occupied cell * a cell set to HOLE is an obstacle for tracks and vias * a cell set to VIA_IMPOSSIBLE is an obstacle for vias only. * a cell set to CELL_is_EDGE is a frontier. * Tracks and vias having the same net code as net_code are skipped * (htey do not are obstacles) * * For single-sided Routing 1: * BOTTOM side is used, and Route_Layer_BOTTOM = Route_Layer_TOP * * If flag == FORCE_PADS: all pads will be put in matrix as obstacles. */ void PlaceCells( BOARD* aPcb, int net_code, int flag ) { int ux0 = 0, uy0 = 0, ux1, uy1, dx, dy; int marge, via_marge; LAYER_MSK layerMask; // use the default NETCLASS? NETCLASS* nc = aPcb->m_NetClasses.GetDefault(); int trackWidth = nc->GetTrackWidth(); int clearance = nc->GetClearance(); int viaSize = nc->GetViaDiameter(); marge = clearance + (trackWidth / 2); via_marge = clearance + (viaSize / 2); // Place PADS on matrix routing: for( unsigned i = 0; i < aPcb->GetPadCount(); ++i ) { D_PAD* pad = aPcb->GetPad( i ); if( net_code != pad->GetNet() || (flag & FORCE_PADS) ) { ::PlacePad( pad, HOLE, marge, WRITE_CELL ); } ::PlacePad( pad, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } // Place outlines of modules on matrix routing, if they are on a copper layer // or on the edge layer TRACK tmpSegm( NULL ); // A dummy track used to create segments. for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) { for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() ) { switch( item->Type() ) { case PCB_MODULE_EDGE_T: { EDGE_MODULE* edge = (EDGE_MODULE*) item; tmpSegm.SetLayer( edge->GetLayer() ); if( tmpSegm.GetLayer() == EDGE_N ) tmpSegm.SetLayer( UNDEFINED_LAYER ); tmpSegm.SetStart( edge->GetStart() ); tmpSegm.SetEnd( edge->GetEnd() ); tmpSegm.SetShape( edge->GetShape() ); tmpSegm.SetWidth( edge->GetWidth() ); tmpSegm.m_Param = edge->GetAngle(); tmpSegm.SetNet( -1 ); TraceSegmentPcb( &tmpSegm, HOLE, marge, WRITE_CELL ); TraceSegmentPcb( &tmpSegm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } break; default: break; } } } // Place board outlines and texts on copper layers: for( BOARD_ITEM* item = aPcb->m_Drawings; item; item = item->Next() ) { switch( item->Type() ) { case PCB_LINE_T: { DRAWSEGMENT* DrawSegm; int type_cell = HOLE; DrawSegm = (DRAWSEGMENT*) item; tmpSegm.SetLayer( DrawSegm->GetLayer() ); if( DrawSegm->GetLayer() == EDGE_N ) { tmpSegm.SetLayer( UNDEFINED_LAYER ); type_cell |= CELL_is_EDGE; } tmpSegm.SetStart( DrawSegm->GetStart() ); tmpSegm.SetEnd( DrawSegm->GetEnd() ); tmpSegm.SetShape( DrawSegm->GetShape() ); tmpSegm.SetWidth( DrawSegm->GetWidth() ); tmpSegm.m_Param = DrawSegm->GetAngle(); tmpSegm.SetNet( -1 ); TraceSegmentPcb( &tmpSegm, type_cell, marge, WRITE_CELL ); } break; case PCB_TEXT_T: { TEXTE_PCB* PtText; PtText = (TEXTE_PCB*) item; if( PtText->GetText().Length() == 0 ) break; EDA_RECT textbox = PtText->GetTextBox( -1 ); ux0 = textbox.GetX(); uy0 = textbox.GetY(); dx = textbox.GetWidth(); dy = textbox.GetHeight(); /* Put bounding box (rectangle) on matrix */ dx /= 2; dy /= 2; ux1 = ux0 + dx; uy1 = uy0 + dy; ux0 -= dx; uy0 -= dy; layerMask = GetLayerMask( PtText->GetLayer() ); TraceFilledRectangle( ux0 - marge, uy0 - marge, ux1 + marge, uy1 + marge, PtText->GetOrientation(), layerMask, HOLE, WRITE_CELL ); TraceFilledRectangle( ux0 - via_marge, uy0 - via_marge, ux1 + via_marge, uy1 + via_marge, PtText->GetOrientation(), layerMask, VIA_IMPOSSIBLE, WRITE_OR_CELL ); } break; default: break; } } /* Put tracks and vias on matrix */ for( TRACK* track = aPcb->m_Track; track; track = track->Next() ) { if( net_code == track->GetNet() ) continue; TraceSegmentPcb( track, HOLE, marge, WRITE_CELL ); TraceSegmentPcb( track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } }
bool DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::Validate() { wxArrayString error_msgs; if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::Validate() ) return false; // Load the start and end points -- all types use these in the checks. int startx = ValueFromString( g_UserUnit, m_Center_StartXCtrl->GetValue() ); int starty = ValueFromString( g_UserUnit, m_Center_StartYCtrl->GetValue() ); int endx = ValueFromString( g_UserUnit, m_EndX_Radius_Ctrl->GetValue() ); int endy = ValueFromString( g_UserUnit, m_EndY_Ctrl->GetValue() ); // Type specific checks. switch( m_item->GetShape() ) { case S_ARC: // Check angle of arc. double angle; m_AngleCtrl->GetValue().ToDouble( &angle ); NORMALIZE_ANGLE_360( angle ); if( angle == 0 ) { error_msgs.Add( _( "The arc angle must be greater than zero." ) ); } // Fall through. case S_CIRCLE: // Check radius. if( (startx == endx) && (starty == endy) ) error_msgs.Add( _( "The radius must be greater than zero." ) ); break; default: // Check start and end are not the same. if( (startx == endx) && (starty == endy) ) error_msgs.Add( _( "The start and end points cannot be the same." ) ); break; } // Check the item thickness. int thickness = ValueFromString( g_UserUnit, m_ThicknessCtrl->GetValue() ); if( thickness <= 0 ) error_msgs.Add( _( "The item thickness must be greater than zero." ) ); // And the default thickness. thickness = ValueFromString( g_UserUnit, m_DefaultThicknessCtrl->GetValue() ); if( thickness <= 0 ) error_msgs.Add( _( "The default thickness must be greater than zero." ) ); if( error_msgs.GetCount() ) { HTML_MESSAGE_BOX dlg( this, _( "Error list" ) ); dlg.ListSet( error_msgs ); dlg.ShowModal(); } return error_msgs.GetCount() == 0; }
bool DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::TransferDataToWindow() { // Set unit symbol wxStaticText* texts_unit[] = { m_StartPointXUnit, m_StartPointYUnit, m_EndPointXUnit, m_EndPointYUnit, m_ThicknessTextUnit, m_DefaulThicknessTextUnit, }; for( size_t ii = 0; ii < DIM( texts_unit ); ii++ ) { texts_unit[ii]->SetLabel( GetAbbreviatedUnitsLabel() ); } wxString msg; // Change texts according to the segment shape: switch( m_item->GetShape() ) { case S_CIRCLE: SetTitle( _( "Circle Properties" ) ); m_StartPointXLabel->SetLabel( _( "Center X" ) ); m_StartPointYLabel->SetLabel( _( "Center Y" ) ); m_EndPointXLabel->SetLabel( _( "Point X" ) ); m_EndPointYLabel->SetLabel( _( "Point Y" ) ); m_AngleText->Show( false ); m_AngleCtrl->Show( false ); m_AngleUnit->Show( false ); break; case S_ARC: SetTitle( _( "Arc Properties" ) ); m_StartPointXLabel->SetLabel( _( "Center X" ) ); m_StartPointYLabel->SetLabel( _( "Center Y" ) ); m_EndPointXLabel->SetLabel( _( "Start Point X" ) ); m_EndPointYLabel->SetLabel( _( "Start Point Y" ) ); m_AngleValue = m_item->GetAngle() / 10.0; break; case S_SEGMENT: SetTitle( _( "Line Segment Properties" ) ); // Fall through. default: m_AngleText->Show( false ); m_AngleCtrl->Show( false ); m_AngleUnit->Show( false ); break; } PutValueInLocalUnits( *m_Center_StartXCtrl, m_item->GetStart().x ); PutValueInLocalUnits( *m_Center_StartYCtrl, m_item->GetStart().y ); PutValueInLocalUnits( *m_EndX_Radius_Ctrl, m_item->GetEnd().x ); PutValueInLocalUnits( *m_EndY_Ctrl, m_item->GetEnd().y ); PutValueInLocalUnits( *m_ThicknessCtrl, m_item->GetWidth() ); PutValueInLocalUnits( *m_DefaultThicknessCtrl, m_brdSettings.m_ModuleSegmentWidth ); // Configure the layers list selector m_LayerSelectionCtrl->SetLayersHotkeys( false ); m_LayerSelectionCtrl->SetLayerSet( LSET::InternalCuMask().set( Edge_Cuts ) ); m_LayerSelectionCtrl->SetBoardFrame( m_parent ); m_LayerSelectionCtrl->Resync(); if( m_LayerSelectionCtrl->SetLayerSelection( m_item->GetLayer() ) < 0 ) { wxMessageBox( _( "This item was on an unknown layer.\n" "It has been moved to the front silk screen layer. Please fix it." ) ); m_LayerSelectionCtrl->SetLayerSelection( F_SilkS ); } return DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataToWindow(); }
void DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::initDlg() /* Initialize messages and values in text control, * according to the item parameters values */ { SetFocus(); m_StandardButtonsSizerOK->SetDefault(); // Set unit symbol wxStaticText * texts_unit[] = { m_StartPointXUnit, m_StartPointYUnit, m_EndPointXUnit, m_EndPointYUnit, m_ThicknessTextUnit, m_DefaulThicknessTextUnit, NULL }; for( int ii = 0; ; ii++ ) { if( texts_unit[ii] == NULL ) break; texts_unit[ii]->SetLabel( GetAbbreviatedUnitsLabel() ); } wxString msg; // Change texts according to the segment shape: switch ( m_item->GetShape() ) { case S_CIRCLE: m_StartPointXLabel->SetLabel(_("Center X")); m_StartPointYLabel->SetLabel(_("Center Y")); m_EndPointXLabel->SetLabel(_("Point X")); m_EndPointYLabel->SetLabel(_("Point Y")); m_Angle_Text->Show(false); m_Angle_Ctrl->Show(false); m_AngleUnit->Show(false); break; case S_ARC: m_StartPointXLabel->SetLabel(_("Center X")); m_StartPointYLabel->SetLabel(_("Center Y")); m_EndPointXLabel->SetLabel(_("Start Point X")); m_EndPointYLabel->SetLabel(_("Start Point Y")); // Here the angle is a double, but the UI is still working // with integers msg << int( m_item->GetAngle() ); m_Angle_Ctrl->SetValue(msg); break; default: m_Angle_Text->Show(false); m_Angle_Ctrl->Show(false); m_AngleUnit->Show(false); break; } PutValueInLocalUnits( *m_Center_StartXCtrl, m_item->GetStart().x ); PutValueInLocalUnits( *m_Center_StartYCtrl, m_item->GetStart().y ); PutValueInLocalUnits( *m_EndX_Radius_Ctrl, m_item->GetEnd().x ); PutValueInLocalUnits( *m_EndY_Ctrl, m_item->GetEnd().y ); PutValueInLocalUnits( *m_ThicknessCtrl, m_item->GetWidth() ); PutValueInLocalUnits( *m_DefaultThicknessCtrl, m_brdSettings.m_ModuleSegmentWidth ); // Configure the layers list selector m_LayerSelectionCtrl->SetLayersHotkeys( false ); m_LayerSelectionCtrl->SetLayerMask( INTERNAL_CU_LAYERS|EDGE_LAYER ); m_LayerSelectionCtrl->SetBoardFrame( m_parent ); m_LayerSelectionCtrl->Resync(); if( m_LayerSelectionCtrl->SetLayerSelection( m_item->GetLayer() ) < 0 ) { wxMessageBox( _("This item has an illegal layer id.\n" "Now, forced on the front silk screen layer. Please, fix it") ); m_LayerSelectionCtrl->SetLayerSelection( SILKSCREEN_N_FRONT ); } }
/* generate shapes of graphic items (outlines) on layer aLayer as polygons, * and adds these polygons to aCornerBuffer * aCornerBuffer = the buffer to store polygons * aInflateValue = a value to inflate shapes * aCircleToSegmentsCount = number of segments to approximate a circle * aCorrectionFactor = the correction to apply to the circle radius * to generate the polygon. * if aCorrectionFactor = 1.0, the polygon is inside the circle * the radius of circle approximated by segments is * initial radius * aCorrectionFactor */ void MODULE::TransformGraphicShapesWithClearanceToPolygonSet( LAYER_NUM aLayer, CPOLYGONS_LIST& aCornerBuffer, int aInflateValue, int aCircleToSegmentsCount, double aCorrectionFactor ) { std::vector<TEXTE_MODULE *> texts; // List of TEXTE_MODULE to convert EDGE_MODULE* outline; for( EDA_ITEM* item = GraphicalItems(); item != NULL; item = item->Next() ) { switch( item->Type() ) { case PCB_MODULE_TEXT_T: if( ((TEXTE_MODULE*)item)->GetLayer() == aLayer ) texts.push_back( (TEXTE_MODULE *) item ); break; case PCB_MODULE_EDGE_T: outline = (EDGE_MODULE*) item; if( outline->GetLayer() != aLayer ) break; switch( outline->GetShape() ) { case S_SEGMENT: TransformRoundedEndsSegmentToPolygon( aCornerBuffer, outline->GetStart(), outline->GetEnd(), aCircleToSegmentsCount, outline->GetWidth() ); break; case S_CIRCLE: TransformRingToPolygon( aCornerBuffer, outline->GetCenter(), outline->GetRadius(), aCircleToSegmentsCount, outline->GetWidth() ); break; case S_ARC: TransformArcToPolygon( aCornerBuffer, outline->GetCenter(), outline->GetArcStart(), outline->GetAngle(), aCircleToSegmentsCount, outline->GetWidth() ); break; case S_POLYGON: // for outline shape = S_POLYGON: // We must compute true coordinates from m_PolyPoints // which are relative to module position and module orientation = 0 for( unsigned ii = 0; ii < outline->GetPolyPoints().size(); ii++ ) { CPolyPt corner( outline->GetPolyPoints()[ii] ); RotatePoint( &corner.x, &corner.y, GetOrientation() ); corner.x += GetPosition().x; corner.y += GetPosition().y; aCornerBuffer.Append( corner ); } aCornerBuffer.CloseLastContour(); break; default: DBG( printf( "Error: Shape %d not implemented!\n", outline->GetShape() ); ) break; } break; default: break; } }
/* Creates the shape of a footprint (section SHAPE) * The shape is always given "normal" (Orient 0, not mirrored) * It's almost guaranteed that the silk layer will be imported wrong but * the shape also contains the pads! */ static void FootprintWriteShape( FILE* aFile, MODULE* module ) { EDGE_MODULE* PtEdge; EDA_ITEM* PtStruct; // Control Y axis change sign for flipped modules int Yaxis_sign = -1; // Flip for bottom side components if( module->GetFlag() ) Yaxis_sign = 1; /* creates header: */ fprintf( aFile, "\nSHAPE %s\n", TO_UTF8( module->GetReference() ) ); if( module->GetAttributes() & MOD_VIRTUAL ) { fprintf( aFile, "INSERT SMD\n" ); } else { if( module->GetAttributes() & MOD_CMS ) { fprintf( aFile, "INSERT SMD\n" ); } else { fprintf( aFile, "INSERT TH\n" ); } } #if 0 /* ATTRIBUTE name and value is unspecified and the original exporter * got the syntax wrong, so CAM350 rejected the whole shape! */ if( module->m_Attributs != MOD_DEFAULT ) { fprintf( aFile, "ATTRIBUTE" ); if( module->m_Attributs & MOD_CMS ) fprintf( aFile, " PAD_SMD" ); if( module->m_Attributs & MOD_VIRTUAL ) fprintf( aFile, " VIRTUAL" ); fprintf( aFile, "\n" ); } #endif // Silk outline; wildly interpreted by various importers: // CAM350 read it right but only closed shapes // ProntoPlace double-flip it (at least the pads are correct) // GerberTool usually get it right... for( PtStruct = module->GraphicalItems(); PtStruct; PtStruct = PtStruct->Next() ) { switch( PtStruct->Type() ) { case PCB_MODULE_TEXT_T: // If we wanted to export text, this is not the correct section break; case PCB_MODULE_EDGE_T: PtEdge = (EDGE_MODULE*) PtStruct; if( PtEdge->GetLayer() == F_SilkS || PtEdge->GetLayer() == B_SilkS ) { switch( PtEdge->GetShape() ) { case S_SEGMENT: fprintf( aFile, "LINE %g %g %g %g\n", (PtEdge->m_Start0.x) / SCALE_FACTOR, (Yaxis_sign * PtEdge->m_Start0.y) / SCALE_FACTOR, (PtEdge->m_End0.x) / SCALE_FACTOR, (Yaxis_sign * PtEdge->m_End0.y ) / SCALE_FACTOR ); break; case S_CIRCLE: { int radius = KiROUND( GetLineLength( PtEdge->m_End0, PtEdge->m_Start0 ) ); fprintf( aFile, "CIRCLE %g %g %g\n", PtEdge->m_Start0.x / SCALE_FACTOR, Yaxis_sign * PtEdge->m_Start0.y / SCALE_FACTOR, radius / SCALE_FACTOR ); break; } case S_ARC: { int arcendx, arcendy; arcendx = PtEdge->m_End0.x - PtEdge->m_Start0.x; arcendy = PtEdge->m_End0.y - PtEdge->m_Start0.y; RotatePoint( &arcendx, &arcendy, -PtEdge->GetAngle() ); arcendx += PtEdge->GetStart0().x; arcendy += PtEdge->GetStart0().y; if( Yaxis_sign == -1 ) { // Flipping Y flips the arc direction too fprintf( aFile, "ARC %g %g %g %g %g %g\n", (arcendx) / SCALE_FACTOR, (Yaxis_sign * arcendy) / SCALE_FACTOR, (PtEdge->m_End0.x) / SCALE_FACTOR, (Yaxis_sign * PtEdge->GetEnd0().y) / SCALE_FACTOR, (PtEdge->GetStart0().x) / SCALE_FACTOR, (Yaxis_sign * PtEdge->GetStart0().y) / SCALE_FACTOR ); } else { fprintf( aFile, "ARC %g %g %g %g %g %g\n", (PtEdge->GetEnd0().x) / SCALE_FACTOR, (Yaxis_sign * PtEdge->GetEnd0().y) / SCALE_FACTOR, (arcendx) / SCALE_FACTOR, (Yaxis_sign * arcendy) / SCALE_FACTOR, (PtEdge->GetStart0().x) / SCALE_FACTOR, (Yaxis_sign * PtEdge->GetStart0().y) / SCALE_FACTOR ); } break; } default: DisplayError( NULL, wxT( "Type Edge Module invalid." ) ); break; } } break; default: break; } } }
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(); }