* Add DRECT, DPOINT, and DSIZE (double rect, point, and size) using Torsten's vector2d.h

as a starting point
* Make double Distance() take double arguments and remove internal range checking.
* Start on EDA_DRAW_FRAME::AdjustScrollBars() and use "double" for most all calculations
  in anticipation of setting INT_MAX INT_MIN limits eventually.
This commit is contained in:
Dick Hollenbeck 2012-04-23 16:56:26 -05:00
parent d8b60a14e1
commit 33616f3051
11 changed files with 695 additions and 298 deletions

View File

@ -70,17 +70,19 @@ void BASE_SCREEN::InitDataPoints( const wxSize& aPageSizeIU )
{
if( m_Center )
{
m_crossHairPosition.x = m_crossHairPosition.y = 0;
m_crossHairPosition.x = 0;
m_crossHairPosition.y = 0;
m_DrawOrg.x = -aPageSizeIU.x / 2;
m_DrawOrg.y = -aPageSizeIU.y / 2;
}
else
{
m_DrawOrg.x = m_DrawOrg.y = 0;
m_crossHairPosition.x = aPageSizeIU.x / 2;
m_crossHairPosition.y = aPageSizeIU.y / 2;
m_DrawOrg.x = 0;
m_DrawOrg.y = 0;
}
m_O_Curseur.x = m_O_Curseur.y = 0;
@ -142,6 +144,8 @@ bool BASE_SCREEN::SetZoom( double coeff )
if( coeff == m_Zoom )
return false;
wxLogDebug( "Zoom:%16g 1/Zoom:%16g", coeff, 1/coeff );
m_Zoom = coeff;
return true;
@ -168,12 +172,10 @@ bool BASE_SCREEN::SetNextZoom()
bool BASE_SCREEN::SetPreviousZoom()
{
size_t i;
if( m_ZoomList.IsEmpty() || m_Zoom <= m_ZoomList[0] )
return false;
for( i = m_ZoomList.GetCount(); i != 0; i-- )
for( unsigned i = m_ZoomList.GetCount(); i != 0; i-- )
{
if( m_Zoom > m_ZoomList[i - 1] )
{
@ -191,8 +193,7 @@ bool BASE_SCREEN::SetLastZoom()
if( m_ZoomList.IsEmpty() || m_Zoom == m_ZoomList.Last() )
return false;
SetZoom( m_ZoomList.Last() );
return true;
return SetZoom( m_ZoomList.Last() );
}
@ -216,11 +217,9 @@ void BASE_SCREEN::SetGrid( const wxRealPoint& size )
{
wxASSERT( !m_grids.empty() );
size_t i;
GRID_TYPE nearest_grid = m_grids[0];
for( i = 0; i < m_grids.size(); i++ )
for( unsigned i = 0; i < m_grids.size(); i++ )
{
if( m_grids[i].m_Size == size )
{
@ -228,7 +227,7 @@ void BASE_SCREEN::SetGrid( const wxRealPoint& size )
return;
}
// keep trace of the nearest grill size, if the exact size is not found
// keep track of the nearest larger grid size, if the exact size is not found
if ( size.x < m_grids[i].m_Size.x )
nearest_grid = m_grids[i];
}
@ -245,9 +244,7 @@ void BASE_SCREEN::SetGrid( int id )
{
wxASSERT( !m_grids.empty() );
size_t i;
for( i = 0; i < m_grids.size(); i++ )
for( unsigned i = 0; i < m_grids.size(); i++ )
{
if( m_grids[i].m_Id == id )
{
@ -266,9 +263,7 @@ void BASE_SCREEN::SetGrid( int id )
void BASE_SCREEN::AddGrid( const GRID_TYPE& grid )
{
size_t i;
for( i = 0; i < m_grids.size(); i++ )
for( unsigned i = 0; i < m_grids.size(); i++ )
{
if( m_grids[i].m_Size == grid.m_Size && grid.m_Id != ID_POPUP_GRID_USER )
{

View File

@ -41,6 +41,7 @@
#include <kicad_device_context.h>
#include <dialog_helpers.h>
#include <base_units.h>
#include <vector2d.h>
#include <wx/fontdlg.h>
@ -495,211 +496,6 @@ bool EDA_DRAW_FRAME::HandleBlockEnd( wxDC* DC )
}
void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPosition )
{
int unitsX, unitsY, posX, posY;
wxSize clientSize, logicalClientSize, virtualSize;
BASE_SCREEN* screen = GetScreen();
bool noRefresh = true;
if( screen == NULL || m_canvas == NULL )
return;
double scalar = screen->GetScalingFactor();
wxLogTrace( traceScrollSettings, wxT( "Center Position = ( %d, %d ), scalar = %0.5f." ),
aCenterPosition.x, aCenterPosition.y, scalar );
// Calculate the portion of the drawing that can be displayed in the
// client area at the current zoom level.
clientSize = m_canvas->GetClientSize();
// The logical size of the client window.
logicalClientSize.x = KiROUND( (double) clientSize.x / scalar );
logicalClientSize.y = KiROUND( (double) clientSize.y / scalar );
// A corner of the drawing in internal units.
wxSize corner = GetPageSizeIU();
// The drawing rectangle logical units
wxRect drawingRect( wxPoint( 0, 0 ), corner );
wxLogTrace( traceScrollSettings, wxT( "Logical drawing rect = ( %d, %d, %d, %d )." ),
drawingRect.x, drawingRect.y, drawingRect.width, drawingRect.height );
wxLogTrace( traceScrollSettings, wxT( " left %d, right %d, top %d, bottome %d" ),
drawingRect.GetLeft(), drawingRect.GetRight(),
drawingRect.GetTop(), drawingRect.GetBottom() );
// The size of the client rectangle in logical units.
int x = KiROUND( (double) aCenterPosition.x - ( (double) logicalClientSize.x / 2.0 ) );
int y = KiROUND( (double) aCenterPosition.y - ( (double) logicalClientSize.y / 2.0 ) );
// If drawn around the center, adjust the client rectangle accordingly.
if( screen->m_Center )
{
x += KiROUND( (double) drawingRect.width / 2.0 );
y += KiROUND( (double) drawingRect.height / 2.0 );
}
wxRect logicalClientRect( wxPoint( x, y ), logicalClientSize );
wxLogTrace( traceScrollSettings, wxT( "Logical client rect = ( %d, %d, %d, %d )." ),
logicalClientRect.x, logicalClientRect.y,
logicalClientRect.width, logicalClientRect.height );
wxLogTrace( traceScrollSettings, wxT( " left %d, right %d, top %d, bottome %d" ),
logicalClientRect.GetLeft(), logicalClientRect.GetRight(),
logicalClientRect.GetTop(), logicalClientRect.GetBottom() );
if( drawingRect == logicalClientRect )
{
virtualSize = drawingRect.GetSize();
}
else
{
if( drawingRect.GetLeft() < logicalClientRect.GetLeft() && drawingRect.GetRight() > logicalClientRect.GetRight() )
{
virtualSize.x = drawingRect.GetSize().x;
}
else
{
int drawingCenterX = drawingRect.x + ( drawingRect.width / 2 );
int clientCenterX = logicalClientRect.x + ( logicalClientRect.width / 2 );
if( logicalClientRect.width > drawingRect.width )
{
if( drawingCenterX > clientCenterX )
virtualSize.x = ( drawingCenterX - logicalClientRect.GetLeft() ) * 2;
else if( drawingCenterX < clientCenterX )
virtualSize.x = ( logicalClientRect.GetRight() - drawingCenterX ) * 2;
else
virtualSize.x = logicalClientRect.width;
}
else
{
if( drawingCenterX > clientCenterX )
virtualSize.x = drawingRect.width +
( (drawingRect.GetLeft() - logicalClientRect.GetLeft() ) * 2 );
else if( drawingCenterX < clientCenterX )
virtualSize.x = drawingRect.width +
( (logicalClientRect.GetRight() - drawingRect.GetRight() ) * 2 );
else
virtualSize.x = drawingRect.width;
}
}
if( drawingRect.GetTop() < logicalClientRect.GetTop() && drawingRect.GetBottom() > logicalClientRect.GetBottom() )
{
virtualSize.y = drawingRect.GetSize().y;
}
else
{
int drawingCenterY = drawingRect.y + ( drawingRect.height / 2 );
int clientCenterY = logicalClientRect.y + ( logicalClientRect.height / 2 );
if( logicalClientRect.height > drawingRect.height )
{
if( drawingCenterY > clientCenterY )
virtualSize.y = ( drawingCenterY - logicalClientRect.GetTop() ) * 2;
else if( drawingCenterY < clientCenterY )
virtualSize.y = ( logicalClientRect.GetBottom() - drawingCenterY ) * 2;
else
virtualSize.y = logicalClientRect.height;
}
else
{
if( drawingCenterY > clientCenterY )
virtualSize.y = drawingRect.height +
( ( drawingRect.GetTop() - logicalClientRect.GetTop() ) * 2 );
else if( drawingCenterY < clientCenterY )
virtualSize.y = drawingRect.height +
( ( logicalClientRect.GetBottom() - drawingRect.GetBottom() ) * 2 );
else
virtualSize.y = drawingRect.height;
}
}
}
if( screen->m_Center )
{
screen->m_DrawOrg.x = -( KiROUND( (double) virtualSize.x / 2.0 ) );
screen->m_DrawOrg.y = -( KiROUND( (double) virtualSize.y / 2.0 ) );
}
else
{
screen->m_DrawOrg.x = -( KiROUND( (double) (virtualSize.x - drawingRect.width) / 2.0 ) );
screen->m_DrawOrg.y = -( KiROUND( (double) (virtualSize.y - drawingRect.height) / 2.0 ) );
}
/* Always set scrollbar pixels per unit to 1 unless you want the zoom
* around cursor to jump around. This reported problem occurs when the
* zoom point is not on a pixel per unit increment. If you set the
* pixels per unit to 10, you have potential for the zoom point to
* jump around +/-5 pixels from the nearest grid point.
*/
screen->m_ScrollPixelsPerUnitX = screen->m_ScrollPixelsPerUnitY = 1;
// Calculate the number of scroll bar units for the given zoom level in device units.
unitsX = KiROUND( (double) virtualSize.x * scalar );
unitsY = KiROUND( (double) virtualSize.y * scalar );
// Calculate the scroll bar position in logical units to place the center position at
// the center of client rectangle.
screen->SetScrollCenterPosition( aCenterPosition );
posX = aCenterPosition.x - KiROUND( (double) logicalClientRect.width / 2.0 ) -
screen->m_DrawOrg.x;
posY = aCenterPosition.y - KiROUND( (double) logicalClientRect.height / 2.0 ) -
screen->m_DrawOrg.y;
// Convert scroll bar position to device units.
posX = KiROUND( (double) posX * scalar );
posY = KiROUND( (double) posY * scalar );
if( posX < 0 )
{
wxLogTrace( traceScrollSettings, wxT( "Required scroll bar X position %d" ), posX );
posX = 0;
}
if( posX > unitsX )
{
wxLogTrace( traceScrollSettings, wxT( "Required scroll bar X position %d" ), posX );
posX = unitsX;
}
if( posY < 0 )
{
wxLogTrace( traceScrollSettings, wxT( "Required scroll bar Y position %d" ), posY );
posY = 0;
}
if( posY > unitsY )
{
wxLogTrace( traceScrollSettings, wxT( "Required scroll bar Y position %d" ), posY );
posY = unitsY;
}
screen->m_ScrollbarPos = wxPoint( posX, posY );
screen->m_ScrollbarNumber = wxSize( unitsX, unitsY );
wxLogTrace( traceScrollSettings,
wxT( "Drawing = (%d, %d), Client = (%d, %d), Offset = (%d, %d), \
SetScrollbars(%d, %d, %d, %d, %d, %d)" ),
virtualSize.x, virtualSize.y, logicalClientSize.x, logicalClientSize.y,
screen->m_DrawOrg.x, screen->m_DrawOrg.y,
screen->m_ScrollPixelsPerUnitX, screen->m_ScrollPixelsPerUnitY,
screen->m_ScrollbarNumber.x, screen->m_ScrollbarNumber.y,
screen->m_ScrollbarPos.x, screen->m_ScrollbarPos.y );
m_canvas->SetScrollbars( screen->m_ScrollPixelsPerUnitX,
screen->m_ScrollPixelsPerUnitY,
screen->m_ScrollbarNumber.x,
screen->m_ScrollbarNumber.y,
screen->m_ScrollbarPos.x,
screen->m_ScrollbarPos.y, noRefresh );
}
void EDA_DRAW_FRAME::SetLanguage( wxCommandEvent& event )
{
EDA_BASE_FRAME::SetLanguage( event );
@ -858,3 +654,188 @@ bool EDA_DRAW_FRAME::HandleBlockBegin( wxDC* aDC, int aKey, const wxPoint& aPosi
Block->SetMessageBlock( this );
return true;
}
void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
{
BASE_SCREEN* screen = GetScreen();
if( screen == NULL || m_canvas == NULL )
return;
// There are no safety limits on these calculations, so in NANOMETRES build it
// still blows up. This is incomplete work.
double scale = screen->GetScalingFactor();
wxLogTrace( traceScrollSettings, wxT( "Center Position = ( %d, %d ), scale = %.16g" ),
aCenterPositionIU.x, aCenterPositionIU.y, scale );
// Calculate the portion of the drawing that can be displayed in the
// client area at the current zoom level.
// visible viewport in device units ~ pixels
wxSize clientSizeDU = m_canvas->GetClientSize();
// Size of the client window in IU
DSIZE clientSizeIU( clientSizeDU.x / scale, clientSizeDU.y / scale );
// Full drawing or "page" rectangle in internal units
DRECT pageRectIU( 0, 0, GetPageSizeIU().x, GetPageSizeIU().y );
// The upper left corner of the client rectangle in internal units.
double xIU = aCenterPositionIU.x - clientSizeIU.x / 2.0;
double yIU = aCenterPositionIU.y - clientSizeIU.y / 2.0;
// If drawn around the center, adjust the client rectangle accordingly.
if( screen->m_Center )
{
// half page offset.
xIU += pageRectIU.width / 2.0;
yIU += pageRectIU.height / 2.0;
}
DRECT clientRectIU( xIU, yIU, clientSizeIU.x, clientSizeIU.y );
DSIZE virtualSizeIU;
if( pageRectIU.GetLeft() < clientRectIU.GetLeft() && pageRectIU.GetRight() > clientRectIU.GetRight() )
{
virtualSizeIU.x = pageRectIU.GetSize().x;
}
else
{
double drawingCenterX = pageRectIU.x + ( pageRectIU.width / 2 );
double clientCenterX = clientRectIU.x + ( clientRectIU.width / 2 );
if( clientRectIU.width > pageRectIU.width )
{
if( drawingCenterX > clientCenterX )
virtualSizeIU.x = ( drawingCenterX - clientRectIU.GetLeft() ) * 2;
else if( drawingCenterX < clientCenterX )
virtualSizeIU.x = ( clientRectIU.GetRight() - drawingCenterX ) * 2;
else
virtualSizeIU.x = clientRectIU.width;
}
else
{
if( drawingCenterX > clientCenterX )
virtualSizeIU.x = pageRectIU.width +
( (pageRectIU.GetLeft() - clientRectIU.GetLeft() ) * 2 );
else if( drawingCenterX < clientCenterX )
virtualSizeIU.x = pageRectIU.width +
( (clientRectIU.GetRight() - pageRectIU.GetRight() ) * 2 );
else
virtualSizeIU.x = pageRectIU.width;
}
}
if( pageRectIU.GetTop() < clientRectIU.GetTop() && pageRectIU.GetBottom() > clientRectIU.GetBottom() )
{
virtualSizeIU.y = pageRectIU.GetSize().y;
}
else
{
int drawingCenterY = pageRectIU.y + ( pageRectIU.height / 2 );
int clientCenterY = clientRectIU.y + ( clientRectIU.height / 2 );
if( clientRectIU.height > pageRectIU.height )
{
if( drawingCenterY > clientCenterY )
virtualSizeIU.y = ( drawingCenterY - clientRectIU.GetTop() ) * 2;
else if( drawingCenterY < clientCenterY )
virtualSizeIU.y = ( clientRectIU.GetBottom() - drawingCenterY ) * 2;
else
virtualSizeIU.y = clientRectIU.height;
}
else
{
if( drawingCenterY > clientCenterY )
virtualSizeIU.y = pageRectIU.height +
( ( pageRectIU.GetTop() - clientRectIU.GetTop() ) * 2 );
else if( drawingCenterY < clientCenterY )
virtualSizeIU.y = pageRectIU.height +
( ( clientRectIU.GetBottom() - pageRectIU.GetBottom() ) * 2 );
else
virtualSizeIU.y = pageRectIU.height;
}
}
if( screen->m_Center )
{
screen->m_DrawOrg.x = -KiROUND( virtualSizeIU.x / 2.0 );
screen->m_DrawOrg.y = -KiROUND( virtualSizeIU.y / 2.0 );
}
else
{
screen->m_DrawOrg.x = -KiROUND( ( virtualSizeIU.x - pageRectIU.width ) / 2.0 );
screen->m_DrawOrg.y = -KiROUND( ( virtualSizeIU.y - pageRectIU.height ) / 2.0 );
}
/* Always set scrollbar pixels per unit to 1 unless you want the zoom
* around cursor to jump around. This reported problem occurs when the
* zoom point is not on a pixel per unit increment. If you set the
* pixels per unit to 10, you have potential for the zoom point to
* jump around +/-5 pixels from the nearest grid point.
*/
screen->m_ScrollPixelsPerUnitX = screen->m_ScrollPixelsPerUnitY = 1;
// Number of scroll bar units for the given zoom level in device units.
double unitsX = virtualSizeIU.x * scale;
double unitsY = virtualSizeIU.y * scale;
// Calculate the scroll bar position in internal units to place the
// center position at the center of client rectangle.
screen->SetScrollCenterPosition( aCenterPositionIU );
double posX = aCenterPositionIU.x - clientRectIU.width /2.0 - screen->m_DrawOrg.x;
double posY = aCenterPositionIU.y - clientRectIU.height/2.0 - screen->m_DrawOrg.y;
// Convert scroll bar position to device units.
posX = KiROUND( posX * scale );
posY = KiROUND( posY * scale );
if( posX < 0 )
{
wxLogTrace( traceScrollSettings, wxT( "Required scroll bar X position %d" ), posX );
posX = 0;
}
if( posX > unitsX )
{
wxLogTrace( traceScrollSettings, wxT( "Required scroll bar X position %d" ), posX );
posX = unitsX;
}
if( posY < 0 )
{
wxLogTrace( traceScrollSettings, wxT( "Required scroll bar Y position %d" ), posY );
posY = 0;
}
if( posY > unitsY )
{
wxLogTrace( traceScrollSettings, wxT( "Required scroll bar Y position %d" ), posY );
posY = unitsY;
}
screen->m_ScrollbarPos = wxPoint( KiROUND( posX ), KiROUND( posY ) );
screen->m_ScrollbarNumber = wxSize( KiROUND( unitsX ), KiROUND( unitsY ) );
wxLogTrace( traceScrollSettings,
wxT( "Drawing = (%.16g, %.16g), Client = (%.16g, %.16g), Offset = (%d, %d), SetScrollbars(%d, %d, %d, %d, %d, %d)" ),
virtualSizeIU.x, virtualSizeIU.y, clientSizeIU.x, clientSizeIU.y,
screen->m_DrawOrg.x, screen->m_DrawOrg.y,
screen->m_ScrollPixelsPerUnitX, screen->m_ScrollPixelsPerUnitY,
screen->m_ScrollbarNumber.x, screen->m_ScrollbarNumber.y,
screen->m_ScrollbarPos.x, screen->m_ScrollbarPos.y );
bool noRefresh = true;
m_canvas->SetScrollbars( screen->m_ScrollPixelsPerUnitX,
screen->m_ScrollPixelsPerUnitY,
screen->m_ScrollbarNumber.x,
screen->m_ScrollbarNumber.y,
screen->m_ScrollbarPos.x,
screen->m_ScrollbarPos.y, noRefresh );
}

View File

@ -158,28 +158,34 @@ void EDA_DRAW_PANEL::DrawCrossHair( wxDC* aDC, int aColor )
if( m_cursorLevel != 0 || aDC == NULL || !m_showCrossHair )
return;
wxPoint Cursor = GetScreen()->GetCrossHairPosition();
wxPoint cursor = GetScreen()->GetCrossHairPosition();
GRSetDrawMode( aDC, GR_XOR );
if( GetParent()->m_cursorShape != 0 ) /* Draws full screen crosshair. */
if( GetParent()->m_cursorShape != 0 ) // Draws full screen crosshair.
{
wxSize clientSize = GetClientSize();
wxPoint lineStart = wxPoint( Cursor.x, aDC->DeviceToLogicalY( 0 ) );
wxPoint lineEnd = wxPoint( Cursor.x, aDC->DeviceToLogicalY( clientSize.y ) );
GRLine( &m_ClipBox, aDC, lineStart, lineEnd, 0, aColor ); // Y axis
lineStart = wxPoint( aDC->DeviceToLogicalX( 0 ), Cursor.y );
lineEnd = wxPoint( aDC->DeviceToLogicalX( clientSize.x ), Cursor.y );
GRLine( &m_ClipBox, aDC, lineStart, lineEnd, 0, aColor ); // X axis
// Y axis
wxPoint lineStart( cursor.x, aDC->DeviceToLogicalY( 0 ) );
wxPoint lineEnd( cursor.x, aDC->DeviceToLogicalY( clientSize.y ) );
GRLine( &m_ClipBox, aDC, lineStart, lineEnd, 0, aColor );
// X axis
lineStart = wxPoint( aDC->DeviceToLogicalX( 0 ), cursor.y );
lineEnd = wxPoint( aDC->DeviceToLogicalX( clientSize.x ), cursor.y );
GRLine( &m_ClipBox, aDC, lineStart, lineEnd, 0, aColor );
}
else
{
int len = aDC->DeviceToLogicalXRel( CURSOR_SIZE );
GRLine( &m_ClipBox, aDC, Cursor.x - len, Cursor.y,
Cursor.x + len, Cursor.y, 0, aColor );
GRLine( &m_ClipBox, aDC, Cursor.x, Cursor.y - len,
Cursor.x, Cursor.y + len, 0, aColor );
GRLine( &m_ClipBox, aDC, cursor.x - len, cursor.y,
cursor.x + len, cursor.y, 0, aColor );
GRLine( &m_ClipBox, aDC, cursor.x, cursor.y - len,
cursor.x, cursor.y + len, 0, aColor );
}
}
@ -469,7 +475,7 @@ void EDA_DRAW_PANEL::EraseScreen( wxDC* DC )
m_ClipBox.GetRight(), m_ClipBox.GetBottom(),
0, g_DrawBgColor, g_DrawBgColor );
/* Set to one (1) to draw bounding box validate bounding box calculation. */
// Set to one (1) to draw bounding box validate bounding box calculation.
#if DEBUG_SHOW_CLIP_RECT
EDA_RECT bBox = m_ClipBox;
GRRect( NULL, DC, bBox.GetOrigin().x, bBox.GetOrigin().y,
@ -823,7 +829,7 @@ void EDA_DRAW_PANEL::OnMouseWheel( wxMouseEvent& event )
wxRect rect = wxRect( wxPoint( 0, 0 ), GetClientSize() );
/* Ignore scroll events if the cursor is outside the drawing area. */
// Ignore scroll events if the cursor is outside the drawing area.
if( event.GetWheelRotation() == 0 || !GetParent()->IsEnabled()
|| !rect.Contains( event.GetPosition() ) )
{
@ -937,12 +943,12 @@ void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event )
if( event.MiddleDown() )
localbutt = GR_M_MIDDLE_DOWN;
localrealbutt |= localbutt; /* compensation default wxGTK */
localrealbutt |= localbutt; // compensation default wxGTK
INSTALL_UNBUFFERED_DC( DC, this );
DC.SetBackground( *wxBLACK_BRUSH );
/* Compute the cursor position in drawing (logical) units. */
// Compute the cursor position in drawing (logical) units.
screen->SetMousePosition( event.GetLogicalPosition( DC ) );
int kbstat = 0;
@ -1101,7 +1107,7 @@ void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event )
GetEventHandler()->ProcessEvent( cmd );
}
/* Calling the general function on mouse changes (and pseudo key commands) */
// Calling the general function on mouse changes (and pseudo key commands)
GetParent()->GeneralControl( &DC, event.GetLogicalPosition( DC ), 0 );
/*******************************/
@ -1165,17 +1171,16 @@ void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event )
if( !m_enableMiddleButtonPan && event.MiddleIsDown() )
cmd_type |= MOUSE_MIDDLE;
/* A block command is started if the drag is enough. A small
* drag is ignored (it is certainly a little mouse move when
* clicking) not really a drag mouse
*/
// A block command is started if the drag is enough. A small
// drag is ignored (it is certainly a little mouse move when
// clicking) not really a drag mouse
if( MinDragEventCount < MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND )
MinDragEventCount++;
else
{
if( !GetParent()->HandleBlockBegin( &DC, cmd_type, m_CursorStartPos ) )
{
// should not occurs: error
// should not occur: error
GetParent()->DisplayToolMsg(
wxT( "EDA_DRAW_PANEL::OnMouseEvent() Block Error" ) );
}

View File

@ -52,15 +52,13 @@ void EDA_DRAW_FRAME::RedrawScreen( const wxPoint& aCenterPoint, bool aWarpPointe
m_canvas->Refresh();
m_canvas->Update();
}
}
/** Redraw the screen with best zoom level and the best centering
* that shows all the page or the board
*/
void EDA_DRAW_FRAME::Zoom_Automatique( bool aWarpPointer )
{
BASE_SCREEN * screen = GetScreen();
BASE_SCREEN* screen = GetScreen();
screen->SetZoom( BestZoom() ); // Set the best zoom and get center point.
if( screen->m_FirstRedraw )
@ -76,16 +74,15 @@ void EDA_DRAW_FRAME::Zoom_Automatique( bool aWarpPointer )
*/
void EDA_DRAW_FRAME::Window_Zoom( EDA_RECT& Rect )
{
double scalex, bestscale;
wxSize size;
/* Compute the best zoom */
// Compute the best zoom
Rect.Normalize();
size = m_canvas->GetClientSize();
wxSize size = m_canvas->GetClientSize();
// Use ceil to at least show the full rect
scalex = (double) Rect.GetSize().x / size.x;
bestscale = (double) Rect.GetSize().y / size.y;
double scalex = (double) Rect.GetSize().x / size.x;
double bestscale = (double) Rect.GetSize().y / size.y;
bestscale = MAX( bestscale, scalex );
GetScreen()->SetScalingFactor( bestscale );
@ -102,7 +99,6 @@ void EDA_DRAW_FRAME::OnZoom( wxCommandEvent& event )
if( m_canvas == NULL )
return;
int i;
int id = event.GetId();
bool zoom_at_cursor = false;
BASE_SCREEN* screen = GetScreen();
@ -151,9 +147,11 @@ void EDA_DRAW_FRAME::OnZoom( wxCommandEvent& event )
break;
default:
unsigned i;
i = id - ID_POPUP_ZOOM_LEVEL_START;
if( ( i < 0 ) || ( (size_t) i >= screen->m_ZoomList.GetCount() ) )
if( i >= screen->m_ZoomList.GetCount() )
{
wxLogDebug( wxT( "%s %d: index %d is outside the bounds of the zoom list." ),
__TFILE__, __LINE__, i );
@ -175,7 +173,7 @@ void EDA_DRAW_FRAME::AddMenuZoomAndGrid( wxMenu* MasterMenu )
int maxZoomIds;
int zoom;
wxString msg;
BASE_SCREEN * screen = m_canvas->GetScreen();
BASE_SCREEN* screen = m_canvas->GetScreen();
msg = AddHotkeyName( _( "Center" ), m_HotkeysZoomAndGridList, HK_ZOOM_CENTER );
AddMenuItem( MasterMenu, ID_POPUP_ZOOM_CENTER, msg, KiBitmap( zoom_center_on_screen_xpm ) );
@ -199,7 +197,7 @@ void EDA_DRAW_FRAME::AddMenuZoomAndGrid( wxMenu* MasterMenu )
maxZoomIds = ( (size_t) maxZoomIds < screen->m_ZoomList.GetCount() ) ?
maxZoomIds : screen->m_ZoomList.GetCount();
/* Populate zoom submenu. */
// Populate zoom submenu.
for( int i = 0; i < maxZoomIds; i++ )
{
msg.Printf( wxT( "%g" ), screen->m_ZoomList[i] );
@ -210,7 +208,7 @@ void EDA_DRAW_FRAME::AddMenuZoomAndGrid( wxMenu* MasterMenu )
zoom_choice->Check( ID_POPUP_ZOOM_LEVEL_START + i, true );
}
/* Create grid submenu as required. */
// Create grid submenu as required.
if( screen->GetGridCount() )
{
wxMenu* gridMenu = new wxMenu;

View File

@ -276,16 +276,22 @@ public:
/**
* Function SetScalingFactor
* @param aScale = the the current scale used to draw items on screen
* draw coordinates are user coordinates * GetScalingFactor()
* sets the scaling factor of "device units per logical unit".
* If the output device is a screen, then "device units" are pixels. The
* "logical unit" is wx terminology, and corresponds to KiCad's "Internal Unit (IU)".
*
* Another way of thinking of scaling factor, when applied to a screen,
* is "pixelsPerIU".
* @param aScale = the the current scale used to draw items onto the device context wxDC.
* device coordinates (pixels) = IU coordinates * GetScalingFactor()
*/
void SetScalingFactor( double aScale );
/**
* Function GetZoom
* returns the
* @return the current zoom factor
* Note: the zoom factor is NOT the scaling factor
* the scaling factor is m_ZoomScalar * GetZoom()
*/
double GetZoom() const;
@ -420,7 +426,7 @@ public:
void ClearBlockCommand() { m_BlockLocate.Clear(); }
wxPoint GetScrollCenterPosition() const { return m_scrollCenter; }
const wxPoint& GetScrollCenterPosition() const { return m_scrollCenter; }
void SetScrollCenterPosition( const wxPoint& aCenterPosition )
{
m_scrollCenter = aCenterPosition;

399
include/vector2d.h Normal file
View File

@ -0,0 +1,399 @@
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2010 Virtenio GmbH, Torsten Hueter, torsten.hueter <at> virtenio.de
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef VECTOR2D_H_
#define VECTOR2D_H_
#include <cmath>
#include <wx/gdicmn.h>
/// Forward declaration for template friends
template<class T> class VECTOR2;
/*
#include <iostream>
template<class T> ostream& operator<<( ostream &stream, const VECTOR2<T>& vector );
*/
/**
* Class VECTOR2
* defines a general 2D-vector.
*
* This class uses templates to be universal. Several operators are provided to help easy implementing
* of linear algebra equations.
*
*/
template<class T> class VECTOR2
{
public:
T x, y;
// Constructors
/// Construct a 2D-vector with x, y = 0
VECTOR2();
/// Copy constructor
VECTOR2( const VECTOR2<T>& aVector );
/// Constructor with a wxPoint as argument
VECTOR2( const wxPoint& aPoint );
/// Constructor with a wxSize as argument
VECTOR2( const wxSize& aSize );
/// Construct a vector with given components x, y
VECTOR2( T x, T y );
/// Destructor
// virtual ~VECTOR2();
/**
* Function Euclidean Norm
* computes the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
* It is used to calculate the length of the vector.
* @return Scalar, the euclidean norm
*/
T EuclideanNorm();
/**
* Function Perpendicular
* computes the perpendicular vector
* @return Perpendicular vector
*/
VECTOR2<T> Perpendicular();
/**
* Function Angle
* computes the angle of the vector
* @return vector angle
*/
T Angle();
// Operators
/// Assignment operator
VECTOR2<T>& operator=( const VECTOR2<T>& aVector );
/// Vector addition operator
VECTOR2<T> operator+( const VECTOR2<T>& aVector );
/// Compound assignment operator
VECTOR2<T>& operator+=( const VECTOR2<T>& aVector );
/// Vector subtraction operator
VECTOR2<T> operator-( const VECTOR2<T>& aVector );
/// Compound assignment operator
VECTOR2<T>& operator-=( const VECTOR2<T>& aVector );
/// Negate Vector operator
VECTOR2<T> operator-();
/// Scalar product operator
T operator*( const VECTOR2<T>& aVector );
/// Multiplication with a factor
VECTOR2<T> operator*( const T& aFactor );
/// Cross product operator
T operator^( const VECTOR2<T>& aVector );
/// Equality operator
const bool operator==( const VECTOR2<T>& aVector );
/// Not equality operator
const bool operator!=( const VECTOR2<T>& aVector );
/// Smaller than operator
bool operator<( const VECTOR2<T>& aVector );
bool operator<=( const VECTOR2<T>& aVector );
/// Greater than operator
bool operator>( const VECTOR2<T>& aVector );
bool operator>=( const VECTOR2<T>& aVector );
/// Casting to int vector
// operator VECTOR2<int>();
/// Type casting operator for the class wxPoint
//operator wxPoint();
// friend ostream& operator<< <T> ( ostream &stream, const VECTOR2<T>& vector );
};
// ----------------------
// --- Implementation ---
// ----------------------
template<class T> VECTOR2<T>::VECTOR2( VECTOR2<T> const& aVector ) :
x( aVector.x ), y( aVector.y )
{
}
template<class T> VECTOR2<T>::VECTOR2()
{
x = y = 0.0;
}
template<class T> VECTOR2<T>::VECTOR2( wxPoint const& aPoint )
{
x = T( aPoint.x );
y = T( aPoint.y );
}
template<class T> VECTOR2<T>::VECTOR2( wxSize const& aSize )
{
x = T( aSize.x );
y = T( aSize.y );
}
template<class T> VECTOR2<T>::VECTOR2( T aX, T aY )
{
x = aX;
y = aY;
}
// Not required at the moment for this class
//template<class T> VECTOR2<T>::~VECTOR2()
//{
// // TODO Auto-generated destructor stub
//}
template<class T> T VECTOR2<T>::EuclideanNorm()
{
return sqrt( ( *this ) * ( *this ) );
}
template<class T> T VECTOR2<T>::Angle()
{
return atan2(y, x);
}
template<class T> VECTOR2<T> VECTOR2<T>::Perpendicular(){
VECTOR2<T> perpendicular(-y, x);
return perpendicular;
}
/*
template<class T> ostream &operator<<( ostream &aStream, const VECTOR2<T>& aVector )
{
aStream << "[ " << aVector.x << " | " << aVector.y << " ]";
return aStream;
}
*/
template<class T> VECTOR2<T> &VECTOR2<T>::operator=( const VECTOR2<T>& aVector )
{
x = aVector.x;
y = aVector.y;
return *this;
}
template<class T> VECTOR2<T> &VECTOR2<T>::operator+=( const VECTOR2<T>& aVector )
{
x += aVector.x;
y += aVector.y;
return *this;
}
template<class T> VECTOR2<T>& VECTOR2<T>::operator-=( const VECTOR2<T>& aVector )
{
x -= aVector.x;
y -= aVector.y;
return *this;
}
//template<class T> VECTOR2<T>::operator wxPoint()
//{
// wxPoint point;
// point.x = (int) x;
// point.y = (int) y;
// return point;
//}
//
//// Use correct rounding for casting to wxPoint
//template<> VECTOR2<double>::operator wxPoint()
//{
// wxPoint point;
// point.x = point.x >= 0 ? (int) ( x + 0.5 ) : (int) ( x - 0.5 );
// point.y = point.y >= 0 ? (int) ( y + 0.5 ) : (int) ( y - 0.5 );
// return point;
//}
// Use correct rounding for casting double->int
//template<> VECTOR2<double>::operator VECTOR2<int>()
//{
// VECTOR2<int> vector;
// vector.x = vector.x >= 0 ? (int) ( x + 0.5 ) : (int) ( x - 0.5 );
// vector.y = vector.y >= 0 ? (int) ( y + 0.5 ) : (int) ( y - 0.5 );
// return vector;
//}
template<class T> VECTOR2<T> VECTOR2<T>::operator+( const VECTOR2<T>& aVector )
{
return VECTOR2<T> ( x + aVector.x, y + aVector.y );
}
template<class T> VECTOR2<T> VECTOR2<T>::operator-( const VECTOR2<T>& aVector )
{
return VECTOR2<T> ( x - aVector.x, y - aVector.y );
}
template<class T> VECTOR2<T> VECTOR2<T>::operator-()
{
return VECTOR2<T> ( -x, -y );
}
template<class T> T VECTOR2<T>::operator*( const VECTOR2<T>& aVector )
{
return aVector.x * x + aVector.y * y;
}
template<class T> VECTOR2<T> VECTOR2<T>::operator*( const T& aFactor )
{
VECTOR2<T> vector( x * aFactor, y * aFactor );
return vector;
}
template<class T> VECTOR2<T> operator*( const T& aFactor, const VECTOR2<T>& aVector){
VECTOR2<T> vector( aVector.x * aFactor, aVector.y * aFactor );
return vector;
}
template<class T> T VECTOR2<T>::operator^( const VECTOR2<T>& aVector )
{
return x * aVector.y - y * aVector.x;
}
template<class T> bool VECTOR2<T>::operator<( const VECTOR2<T>& o )
{
// VECTOR2<T> vector( aVector );
return (double( x ) * x + double( y ) * y) < (double( o.x ) * o.x + double( o.y ) * y);
}
template<class T> bool VECTOR2<T>::operator<=( const VECTOR2<T>& aVector )
{
VECTOR2<T> vector( aVector );
return ( *this * *this ) <= ( vector * vector );
}
template<class T> bool VECTOR2<T>::operator>( const VECTOR2<T>& aVector )
{
VECTOR2<T> vector( aVector );
return ( *this * *this ) > ( vector * vector );
}
template<class T> bool VECTOR2<T>::operator>=( const VECTOR2<T>& aVector )
{
VECTOR2<T> vector( aVector );
return ( *this * *this ) >= ( vector * vector );
}
template<class T> bool const VECTOR2<T>::operator==( VECTOR2<T> const& aVector )
{
return ( aVector.x == x ) && ( aVector.y == y );
}
template<class T> bool const VECTOR2<T>::operator!=( VECTOR2<T> const& aVector )
{
return ( aVector.x != x ) || ( aVector.y != y );
}
/**
* Class RECT
* is a description of a rectangle in cartesion coordinate system.
*/
template<class T> class RECT
{
public:
RECT() : x(0), y(0), width(0), height(0) {}
RECT( T aX, T aY, T aWidth, T aHeight ):
x( aX ), y( aY ), width( aWidth ), height( aHeight )
{}
/// Copy constructor
RECT( const RECT<T>& aRect ) :
x( aRect.x ), y( aRect.y ), width( aRect.width ), height( aRect.height )
{}
/// Constructor with a wxPoint as argument?
VECTOR2<T> GetSize() const { return VECTOR2<T> ( width, height ); }
VECTOR2<T> GetPosition() const { return VECTOR2<T> ( x, y ); }
T GetLeft() const { return x; }
void SetLeft( T n ) { width += x - n; x = n; }
void MoveLeftTo( T n ) { x = n; }
T GetTop() const { return y; }
void SetTop( T n ) { height += y - n; y = n; }
void MoveTopTo( T n ) { y = n; }
T GetBottom() const { return y + height; }
void SetBottom( T n ) { height += n - ( y + height ); }
void MoveBottomTo( T n ) { y = n - height; }
T GetRight() const { return x + width; }
void SetRight( T n ) { width += n - ( x + width ); }
void MoveRightTo( T n ) { x = n - width; }
VECTOR2<T> GetLeftTop() const { return VECTOR2<T>( x , y ); }
void SetLeftTop( const VECTOR2<T>& pt ) { width += x - pt.x; height += y - pt.y; x = pt.x; y = pt.y; }
void MoveLeftTopTo( const VECTOR2<T> &pt ) { x = pt.x; y = pt.y; }
VECTOR2<T> GetLeftBottom() const { return VECTOR2<T>( x, y + height ); }
void SetLeftBottom( const VECTOR2<T>& pt ) { width += x - pt.x; height += pt.y - (y + height); x = pt.x; }
void MoveLeftBottomTo( const VECTOR2<T>& pt ) { x = pt.x; y = pt.y - height; }
VECTOR2<T> GetRightTop() const { return VECTOR2<T>( x + width, y ); }
void SetRightTop( const VECTOR2<T>& pt ) { width += pt.x - ( x + width ); height += y - pt.y; y = pt.y; }
void MoveRightTopTo( const VECTOR2<T>& pt ) { x = pt.x - width; y = pt.y; }
VECTOR2<T> GetRightBottom() const { return VECTOR2<T>( x + width, y + height ); }
void SetRightBottom( const VECTOR2<T>& pt ) { width += pt.x - ( x + width ); height += pt.y - ( y + height); }
void MoveRightBottomTo( const VECTOR2<T>& pt ) { x = pt.x - width; y = pt.y - height; }
VECTOR2<T> GetCentre() const { return VECTOR2<T>( x + width/2, y + height/2 ); }
void SetCentre( const VECTOR2<T>& pt ) { MoveCentreTo( pt ); }
void MoveCentreTo( const VECTOR2<T>& pt ) { x += pt.x - (x + width/2), y += pt.y - (y + height/2); }
T x, y, width, height;
};
typedef VECTOR2<double> DPOINT;
typedef DPOINT DSIZE;
typedef RECT<double> DRECT;
#endif // VECTOR2D_H_

View File

@ -647,6 +647,11 @@ public:
*/
void RedrawScreen( const wxPoint& aCenterPoint, bool aWarpPointer );
/**
* Function Zoom_Automatique
* redraws the screen with best zoom level and the best centering
* that shows all the page or the board
*/
void Zoom_Automatique( bool aWarpPointer );
/* Set the zoom level to show the area Rect */

View File

@ -810,8 +810,12 @@ void PCB_BASE_FRAME::updateZoomSelectBox()
{
msg = _( "Zoom " );
wxString value;
value.Printf( wxT( "%g" ), GetScreen()->m_ZoomList[i]);
wxString value = wxString::Format( wxT( "%g" ),
// @todo could do scaling here and show a "percentage"
GetScreen()->m_ZoomList[i]
);
msg += value;
m_zoomSelectBox->Append( msg );
@ -821,6 +825,7 @@ void PCB_BASE_FRAME::updateZoomSelectBox()
}
}
/* Function GetActiveViewerFrame
* return a reference to the current Module Viewer Frame if exists
* if called from the PCB editor, this is the m_ModuleViewerFrame

View File

@ -42,6 +42,12 @@
*/
static const double pcbZoomList[] =
{
#if defined( USE_PCBNEW_NANOMETRES )
ZOOM_FACTOR( 0.1 ),
ZOOM_FACTOR( 0.2 ),
ZOOM_FACTOR( 0.3 ),
#endif
ZOOM_FACTOR( 0.5 ),
ZOOM_FACTOR( 1.0 ),
ZOOM_FACTOR( 1.5 ),
@ -57,10 +63,14 @@ static const double pcbZoomList[] =
ZOOM_FACTOR( 80.0 ),
ZOOM_FACTOR( 120.0 ),
ZOOM_FACTOR( 200.0 ),
ZOOM_FACTOR( 350.0 ),
ZOOM_FACTOR( 300.0 ),
#if !defined( USE_PCBNEW_NANOMETRES )
ZOOM_FACTOR( 500.0 ),
ZOOM_FACTOR( 1000.0 ),
ZOOM_FACTOR( 2000.0 )
#endif
};
@ -98,6 +108,9 @@ static GRID_TYPE pcbGridList[] =
PCB_SCREEN::PCB_SCREEN( const wxSize& aPageSizeIU ) :
BASE_SCREEN( SCREEN_T )
{
wxSize displayz = wxGetDisplaySize();
for( unsigned i = 0; i < DIM( pcbZoomList ); ++i )
m_ZoomList.Add( pcbZoomList[i] );

View File

@ -12,6 +12,14 @@
#define NM_PER_MIL 25400
double Distance( double x1, double y1, double x2, double y2 )
{
double dx = x1 - x2;
double dy = y1 - y2;
double d = sqrt( dx * dx + dy * dy );
return d;
}
/**
* Function TestLineHit
@ -1031,7 +1039,7 @@ int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1,
y2 = el2.Center.Y + el2.yrad* sin( s2 );
}
double d = Distance( (int) x, (int) y, (int) x2, (int) y2 );
double d = Distance( x, y, x2, y2 );
if( d < dmin )
{
@ -1101,7 +1109,7 @@ double GetPointToLineDistance( double a, double b, int x, int y, double* xpp, do
}
// find distance
return Distance( x, y, (int) xp, (int) yp );
return Distance( x, y, xp, yp );
}
@ -1151,7 +1159,7 @@ double GetPointToLineSegmentDistance( int x, int y, int xi, int yi, int xf, int
// find distance
if( InRange( xp, xi, xf ) && InRange( yp, yi, yf ) )
return Distance( x, y, (int) xp, (int) yp );
return Distance( x, y, xp, yp );
else
return min( Distance( x, y, xi, yi ), Distance( x, y, xf, yf ) );
}
@ -1177,26 +1185,6 @@ bool InRange( double x, double xi, double xf )
}
// Get distance between 2 points
//
double Distance( int x1, int y1, int x2, int y2 )
{
double dx = x1 - x2;
double dy = y1 - y2;
double d = sqrt( dx * dx + dy * dy );
if( d > INT_MAX || d < INT_MIN )
{
wxASSERT( 0 );
}
// wxASSERT( d <= INT_MAX && d >= INT_MIN );
return int( d );
}
// this finds approximate solutions
// note: this works best if el2 is smaller than el1
//
@ -1368,7 +1356,7 @@ double GetArcClearance( EllipseKH* el1, EllipseKH* el2,
double x2 = el2->Center.X + el2->xrad * cos( theta2 );
double y2 = el2->Center.Y + el2->yrad * sin( theta2 );
double d = Distance( (int) x, (int) y, (int) x2, (int) y2 );
double d = Distance( x, y, x2, y2 );
if( d < dmin )
{

View File

@ -71,7 +71,9 @@ double GetPointToLineSegmentDistance( int x, int y, int xi, int yi, int xf, int
double GetPointToLineDistance( double a, double b, int x, int y, double * xp=NULL, double * yp=NULL );
bool InRange( double x, double xi, double xf );
double Distance( int x1, int y1, int x2, int y2 );
double Distance( double x1, double y1, double x2, double y2 );
int GetArcIntersections( EllipseKH * el1, EllipseKH * el2,
double * x1=NULL, double * y1=NULL,
double * x2=NULL, double * y2=NULL );