// CoordinateMapping.cpp - implementation file for CoordinateMapping class // // Developed by: Mike Childs // Started: 2/5/97 // #include "CoordinateMapping.h" #include // Constructor CoordinateMapping::CoordinateMapping( bool maintainAspect ) : d_window(0.0, 0.0, 0.0, 0.0), d_viewport(0.0, 0.0, 0.0, 0.0), d_maintainAspectRatio(maintainAspect), d_a(1.0), d_b(1.0), d_c(0.0), d_d(0.0) { } void CoordinateMapping::mapToViewport( Point2D& point ) const // Map from world-space tp the viewport { double winWidth = d_window.width(); double winHeight = d_window.height(); if ( winWidth != 0 ) { //tempX = ( point.getX() - winLeft ) * ( d_viewport.width() / winWidth ) + viewLeft; point.setX( d_a * point.getX() + d_c ); } if ( winHeight != 0 ) { //tempY = ( point.getY() - winBottom ) * ( d_viewport.height() / winHeight ) + viewBottom; point.setY( d_b * point.getY() + d_d ); } //point.setXY( tempX, tempY ); } void CoordinateMapping::mapToWindow( Point2D& point ) const // Map from viewport to world-space { double tempX(0), tempY(0); double viewWidth = d_viewport.width(); double viewHeight = d_viewport.height(); double viewLeft = d_viewport.getLowerLeft().getX(); double viewBottom = d_viewport.getLowerLeft().getY(); double winLeft = d_window.getLowerLeft().getX(); double winBottom = d_window.getLowerLeft().getY(); if ( viewWidth != 0 ) { tempX = ( point.getX() - viewLeft ) * ( d_window.width() / viewWidth ) + winLeft; } if ( viewHeight != 0 ) { tempY = ( point.getY() - viewBottom ) * ( d_window.height() / viewHeight ) + winBottom; } point.setXY( tempX, tempY ); } void CoordinateMapping::mapToViewport( double& scalar ) const // The aspect ratio should be maintained { // Abort if the aspect ratio isn't being maintained if ( !d_maintainAspectRatio ) { return; } // Compute if the window isn't bad if ( d_window.width() != 0 ) { scalar *= fabs( d_viewport.width() / d_window.width() ); } } void CoordinateMapping::mapToWindow( double& scalar ) const // The aspect ratio should be maintained { // Abort if the aspect ratio isn't being maintained if ( !d_maintainAspectRatio ) { return; } // Compute if the viewport isn't bad if ( d_viewport.width() != 0 ) { scalar *= fabs( d_window.width() / d_viewport.width() ); } } bool CoordinateMapping::pointInWindow( const Point2D& pt ) const { if ( pt.getX() >= d_window.left() && pt.getX() <= d_window.right() && pt.getY() >= d_window.bottom() && pt.getY() <= d_window.top() ) { return true; } else { return false; } } void CoordinateMapping::recalculate() { // Abort if either rectangle has a zero height or width if ( d_viewport.height() == 0 || d_window.height() == 0 || d_viewport.width() == 0 || d_window.width() == 0 ) { return; } // Maintain the aspect ratio if ( d_maintainAspectRatio ) { double viewportWidth = d_viewport.width(); double viewportHeight = d_viewport.height(); double windowWidth = d_window.width(); double windowHeight = d_window.height(); // calculate the aspect ratios double aspectViewport, aspectWindow; aspectViewport = fabs( viewportWidth / viewportHeight ); aspectWindow = fabs( windowWidth / windowHeight ); if ( aspectViewport > aspectWindow ) // Window needs widened { double newWindowWidth = windowHeight * aspectViewport; d_window.inflateRect( ( newWindowWidth - windowWidth ) / 2.0, 0 ); } else { double newWindowHeight = windowWidth / aspectViewport; d_window.inflateRect( 0, ( newWindowHeight - windowHeight ) / 2.0 ); } } double viewportWidth = d_viewport.width(); double viewportHeight = d_viewport.height(); double windowWidth = d_window.width(); double windowHeight = d_window.height(); // Calculate helper values d_a = viewportWidth / windowWidth; d_b = viewportHeight / windowHeight; d_c = ( -d_window.left() * viewportWidth ) / windowWidth + d_viewport.left(); d_d = ( -d_window.bottom() * viewportHeight ) / windowHeight + d_viewport.bottom(); } void CoordinateMapping::zoomBy( double factor ) { // Abort if attempt to zoom by zero if ( factor == 0.0 ) { return; } // Zoom the window if ( factor < 0.0 ) { d_window.scale( -factor, -factor ); } else { d_window.scale( 1.0 / factor, 1.0 / factor ); } recalculate(); } void CoordinateMapping::pan( const Point2D& newCenter ) { // Translate window to new center Point2D center = d_window.getCenter(); d_window.translate( newCenter - center ); recalculate(); } void CoordinateMapping::zoomTo( double factor, const Point2D& newCenter ) { zoomBy( factor ); pan( newCenter ); }