From 42b9e0e6769670b8e1bd6e670bdf42e89693a63f Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Wed, 19 Jan 2011 11:34:56 +0100 Subject: [PATCH] Eeschem: fix bug when moving fields in schematic: incorrect field move for rotated+mirrored components (added InverseTransform( ) in TRANSFORM class) --- 3d-viewer/3d_draw.cpp | 2 +- eeschema/edit_component_in_schematic.cpp | 17 +++++++---------- eeschema/transform.cpp | 24 ++++++++++++++++++++++++ eeschema/transform.h | 15 +++++++++++++-- pcbnew/export_vrml.cpp | 5 ++++- pcbnew/printout_controler.cpp | 21 ++++++++++++++++----- 6 files changed, 65 insertions(+), 19 deletions(-) diff --git a/3d-viewer/3d_draw.cpp b/3d-viewer/3d_draw.cpp index b0c844d1d3..42ae24593b 100644 --- a/3d-viewer/3d_draw.cpp +++ b/3d-viewer/3d_draw.cpp @@ -653,7 +653,7 @@ void MODULE::Draw3D( Pcb3D_GLCanvas* glcanvas ) pad->Draw3D( glcanvas ); } - /* Draw module shape: 3D shape if exists (or module edge if not exists) */ + /* Draw module shape: 3D shape if exists (or module outlines if not exists) */ S3D_MASTER* Struct3D = m_3D_Drawings; bool As3dShape = FALSE; if( g_Parm_3D_Visu.m_Draw3DModule ) diff --git a/eeschema/edit_component_in_schematic.cpp b/eeschema/edit_component_in_schematic.cpp index e4f831d7a7..e178076821 100644 --- a/eeschema/edit_component_in_schematic.cpp +++ b/eeschema/edit_component_in_schematic.cpp @@ -46,16 +46,9 @@ void SCH_EDIT_FRAME::StartMoveCmpField( SCH_FIELD* aField, wxDC* DC ) pos = comp->m_Pos; - /* Positions are computed by the transpose matrix. Rotating mirror. */ + /* Positions are computed by the rotation/mirror transform. */ newpos = aField->m_Pos - pos; - // Empirically this is necessary. The Y coordinate appears to be inverted - // under some circumstances, but that inversion is not preserved by all - // combinations of mirroring and rotation. The following clause is true - // when the number of rotations and the number of mirrorings are both odd. - if( comp->GetTransform().x2 * comp->GetTransform().y1 < 0 ) - NEGATE( newpos.y ); - newpos = comp->GetTransform().TransformCoordinate( newpos ) + pos; DrawPanel->CursorOff( DC ); @@ -206,10 +199,14 @@ static void MoveCmpField( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) pos = ( (SCH_COMPONENT*) currentField->GetParent() )->m_Pos; - /* Positions are calculated by the transpose matrix, Rotating mirror. */ + // Actual positions are calculated by the rotation/mirror transform + // But here we want the relative position of the moved field + // and we know the actual position. + // So we are using the inverse rotation/mirror transform. wxPoint pt( panel->GetScreen()->m_Curseur - pos ); - currentField->m_Pos = pos + component->GetTransform().TransformCoordinate( pt ); + TRANSFORM itrsfm = component->GetTransform().InverseTransform(); + currentField->m_Pos = pos + itrsfm.TransformCoordinate( pt ); currentField->Draw( panel, DC, wxPoint( 0, 0 ), g_XorMode ); } diff --git a/eeschema/transform.cpp b/eeschema/transform.cpp index 86763a77ba..1080a133f2 100644 --- a/eeschema/transform.cpp +++ b/eeschema/transform.cpp @@ -31,6 +31,30 @@ wxPoint TRANSFORM::TransformCoordinate( const wxPoint& aPoint ) const ( x2 * aPoint.x ) + ( y2 * aPoint.y ) ); } +/* +* Calculate the Inverse mirror/rotation transform. +*/ +TRANSFORM TRANSFORM::InverseTransform( ) const +{ + int invx1; + int invx2; + int invy1; + int invy2; + + /* Calculates the inverse matrix coeffs: + * for a matrix m{x1, x2, y1, y2} + * the inverse matrix is 1/(x1*y2 -x2*y1) m{y2,-x2,-y1,x1) + */ + int det = x1*y2 -x2*y1; // Is never null, because the inverse matrix exists + invx1 = y2/det; + invx2 = -x2/det; + invy1 = -y1/det; + invy2 = x1/det; + + TRANSFORM invtransform( invx1, invy1, invx2, invy2 ); + return invtransform; +} + bool TRANSFORM::MapAngles( int* aAngle1, int* aAngle2 ) const { diff --git a/eeschema/transform.h b/eeschema/transform.h index 9c3fb18cab..f0562eeea5 100644 --- a/eeschema/transform.h +++ b/eeschema/transform.h @@ -59,13 +59,24 @@ public: bool operator!=( const TRANSFORM& aTransform ) const { return !( *this == aTransform ); } /** - * Calculate new coordinate according to the transform. - * + * Calculate new coordinate according to the mirror/rotation transform. + * Useful to calculate actual coordinates of a point + * from coordinates relative to a component + * which are given for a non rotated, non mirrored item * @param aPoint = The position to transform * @return The transformed coordinate. */ wxPoint TransformCoordinate( const wxPoint& aPoint ) const; + /** + * Calculate the Inverse mirror/rotation transform. + * Useful to calculate coordinates relative to a component + * which must be for a non rotated, non mirrored item + * from the actual coordinate. + * @return The inverse transform. + */ + TRANSFORM InverseTransform( ) const; + /** * Calculate new angles according to the transform. * diff --git a/pcbnew/export_vrml.cpp b/pcbnew/export_vrml.cpp index 2da79c9d63..8e485e4a6f 100644 --- a/pcbnew/export_vrml.cpp +++ b/pcbnew/export_vrml.cpp @@ -1091,9 +1091,12 @@ static void export_vrml_module( BOARD* aPcb, MODULE* aModule, int offsety = wxRound( vrmlm->m_MatPosition.y * UNITS_3D_TO_PCB_UNITS ); double offsetz = vrmlm->m_MatPosition.z * UNITS_3D_TO_PCB_UNITS; - RotatePoint(&offsetx, &offsety, aModule->m_Orient); if ( isFlipped ) NEGATE(offsetz); + else // In normal mode, Y axis is reversed in Pcbnew. + NEGATE(offsety); + + RotatePoint(&offsetx, &offsety, aModule->m_Orient); fprintf( aOutputFile, " translation %g %g %g\n", (double) (offsetx + aModule->m_Pos.x), diff --git a/pcbnew/printout_controler.cpp b/pcbnew/printout_controler.cpp index d980ec8da1..ea4b1e296d 100644 --- a/pcbnew/printout_controler.cpp +++ b/pcbnew/printout_controler.cpp @@ -143,13 +143,24 @@ void BOARD_PRINTOUT_CONTROLER::DrawPage() WinEDA_BasePcbFrame* pcbframe = (WinEDA_BasePcbFrame*) m_Parent; pcbframe->GetBoard()->ComputeBoundaryBox(); + EDA_Rect brd_BBox = pcbframe->GetBoard()->m_BoundaryBox; + // In module editor, the module is located at 0,0 but for printing + // it is moved to SheetSize.x/2, SheetSize.y/2. + // So the equivalent board must be moved: + if( m_Parent->m_Ident == MODULE_EDITOR_FRAME ) + { + wxPoint mv_offset; + mv_offset.x = SheetSize.x / 2; + mv_offset.y = SheetSize.y / 2; + brd_BBox.Move( mv_offset ); + } /* Compute the PCB size in internal units*/ userscale = m_PrintParams.m_PrintScale; if( userscale == 0 ) // fit in page { int extra_margin = 4000*2; // Margin = 4000 units pcb = 0.4 inch - SheetSize.x = pcbframe->GetBoard()->m_BoundaryBox.GetWidth() + extra_margin; - SheetSize.y = pcbframe->GetBoard()->m_BoundaryBox.GetHeight() + extra_margin; + SheetSize.x = brd_BBox.GetWidth() + extra_margin; + SheetSize.y = brd_BBox.GetHeight() + extra_margin; userscale = 0.99; } @@ -157,8 +168,8 @@ void BOARD_PRINTOUT_CONTROLER::DrawPage() if( (m_PrintParams.m_PrintScale > 1.0) // scale > 1 -> Recadrage || (m_PrintParams.m_PrintScale == 0) ) // fit in page { - DrawOffset += pcbframe->GetBoard()->m_BoundaryBox.Centre(); - } + DrawOffset += brd_BBox.Centre(); + } if( m_PrintParams.m_PageSetupData ) { @@ -266,7 +277,7 @@ void BOARD_PRINTOUT_CONTROLER::DrawPage() * for scales > 1, the DrawOffset was already computed to have the board centre * to the middle of the page. */ - wxPoint pcb_centre = pcbframe->GetBoard()->m_BoundaryBox.Centre(); + wxPoint pcb_centre = brd_BBox.Centre(); if( userscale <= 1.0 ) DrawOffset.y += pcb_centre.y - (ysize / 2); #ifdef USE_WX_ZOOM