Eeschem: fix bug when moving fields in schematic: incorrect field move for rotated+mirrored components

(added InverseTransform( ) in TRANSFORM class)
This commit is contained in:
jean-pierre charras 2011-01-19 11:34:56 +01:00
parent f43f7af5fe
commit 42b9e0e676
6 changed files with 65 additions and 19 deletions

View File

@ -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 )

View File

@ -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 );
}

View File

@ -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
{

View File

@ -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.
*

View File

@ -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),

View File

@ -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,7 +168,7 @@ 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