[dasher] ScaleFactor and Non-linearity



commit 647dfee20b6c4267611e5efa264ca4c4645cc77c
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Fri Jan 8 21:06:49 2010 +0000

    ScaleFactor and Non-linearity
    
      *Centralise scale-factor and computation of nonlinearity in SetScaleFactor
        *Result for current orientation _only_ in iScalingFactor{X,Y}
        *Changed margin to no longer reduce maxX; aspect ratio varies 0.72-1
      *New, separate, LP_NONLINEAR_X parameter to control degree of X log-scaling
        *Thus BP_NONLINEAR_Y controls Y-axis only => is no longer a misnomer(!)
      *Moved tests of nonlinearity into DasherViewSquare::{i,}{x,y}map
      *iPhone: replaced BP_NONLINEAR_Y on/off misc setting w/ LP_NONLINEAR_X slider

 Src/DasherCore/DasherInterfaceBase.cpp |    1 +
 Src/DasherCore/DasherViewSquare.cpp    |  124 +++++++++++++++----------------
 Src/DasherCore/DasherViewSquare.h      |   15 +---
 Src/DasherCore/DasherViewSquare.inl    |   16 +++--
 Src/DasherCore/Parameters.h            |   11 ++-
 Src/iPhone/Classes/MiscSettings.mm     |    2 +-
 6 files changed, 83 insertions(+), 86 deletions(-)
---
diff --git a/Src/DasherCore/DasherInterfaceBase.cpp b/Src/DasherCore/DasherInterfaceBase.cpp
index d8b785f..6bedc92 100644
--- a/Src/DasherCore/DasherInterfaceBase.cpp
+++ b/Src/DasherCore/DasherInterfaceBase.cpp
@@ -327,6 +327,7 @@ void CDasherInterfaceBase::InterfaceEventHandler(Dasher::CEvent *pEvent) {
       break;
     case LP_MARGIN_WIDTH:
     case BP_NONLINEAR_Y:
+    case LP_NONLINEAR_X:
         ScheduleRedraw();
         break;
     case LP_NODE_BUDGET:
diff --git a/Src/DasherCore/DasherViewSquare.cpp b/Src/DasherCore/DasherViewSquare.cpp
index 52f0c0a..9ae0fce 100644
--- a/Src/DasherCore/DasherViewSquare.cpp
+++ b/Src/DasherCore/DasherViewSquare.cpp
@@ -67,12 +67,7 @@ CDasherViewSquare::CDasherViewSquare(CEventHandler *pEventHandler, CSettingsStor
 
   ChangeScreen(DasherScreen);
 
-  // TODO - Make these parameters
-  // tweak these if you know what you are doing
-  m_dXmpa = 0.2;                // these are for the x non-linearity
-  m_dXmpb = 0.5;
-  m_dXmpc = 0.9;
-
+  //Note, nonlinearity parameters set in SetScaleFactor 
   m_bVisibleRegionValid = false;
   
 }
@@ -88,10 +83,9 @@ void CDasherViewSquare::HandleEvent(Dasher::CEvent *pEvent) {
     Dasher::CParameterNotificationEvent * pEvt(static_cast < Dasher::CParameterNotificationEvent * >(pEvent));
     switch (pEvt->m_iParameter) {
     case LP_REAL_ORIENTATION:
-      m_bVisibleRegionValid = false;
-      break;
     case LP_MARGIN_WIDTH:
     case BP_NONLINEAR_Y:
+    case LP_NONLINEAR_X:
       m_bVisibleRegionValid = false;
       SetScaleFactor();
       break;
@@ -617,11 +611,6 @@ void CDasherViewSquare::Screen2Dasher(screenint iInputX, screenint iInputY, myin
 
   int eOrientation(GetLongParameter(LP_REAL_ORIENTATION));
 
-  myint iScaleFactorX;
-  myint iScaleFactorY;
-  
-  GetScaleFactor(eOrientation, &iScaleFactorX, &iScaleFactorY);
-
   switch(eOrientation) {
   case Dasher::Opts::LeftToRight:
     iDasherX = iCenterX - ( iInputX - iScreenWidth / 2 ) * m_iScalingFactor / iScaleFactorX;
@@ -641,15 +630,22 @@ void CDasherViewSquare::Screen2Dasher(screenint iInputX, screenint iInputY, myin
     break;
   }
 
-  if (GetBoolParameter(BP_NONLINEAR_Y)) {
-    iDasherX = ixmap(iDasherX);
-    iDasherY = iymap(iDasherY);
-  }
+  iDasherX = ixmap(iDasherX);
+  iDasherY = iymap(iDasherY);
   
 }
 
 void CDasherViewSquare::SetScaleFactor( void )
 {
+  //Parameters for X non-linearity.
+  // Set some defaults here, in case we change(d) them later...
+  m_dXmpb = 0.5; //threshold: DasherX's less than (m_dXmpb * MAX_Y) are linear...
+  m_dXmpc = 0.9; //...but multiplied by m_dXmpc; DasherX's above that, are logarithmic...
+
+  //set log scaling coefficient (unused if LP_NONLINEAR_X==0)
+  // note previous value of m_dXmpa = 0.2, i.e. a value of LP_NONLINEAR_X =~= 4.8
+  m_dXmpa = exp(GetLongParameter(LP_NONLINEAR_X)/-3.0); 
+  
   myint iDasherWidth = (myint)GetLongParameter(LP_MAX_Y);
   myint iDasherHeight = iDasherWidth;
 
@@ -661,35 +657,42 @@ void CDasherViewSquare::SetScaleFactor( void )
   myint iDasherMargin( GetLongParameter(LP_MARGIN_WIDTH) ); // Make this a parameter
 
   myint iMinX( 0-iDasherMargin );
-  myint iMaxX( iDasherWidth - 2*iDasherMargin );
+  myint iMaxX( iDasherWidth );
   iCenterX = (iMinX + iMaxX)/2;
   myint iMinY( 0 );
   myint iMaxY( iDasherHeight );
 
-  double dLRHScaleFactor;
-  double dLRVScaleFactor;
-  double dTBHScaleFactor;
-  double dTBVScaleFactor;
-
-  dLRHScaleFactor = iScreenWidth / static_cast<double>( iMaxX - iMinX );
-  dLRVScaleFactor = iScreenHeight / static_cast<double>( iMaxY - iMinY );
-  dTBHScaleFactor = iScreenWidth / static_cast<double>( iMaxY - iMinY );
-  dTBVScaleFactor = iScreenHeight / static_cast<double>( iMaxX - iMinX );
-
-  iLRScaleFactorX = myint(std::max(std::min(dLRHScaleFactor, dLRVScaleFactor), dLRHScaleFactor / 4.0) * m_iScalingFactor);
-  iLRScaleFactorY = myint(std::max(std::min(dLRHScaleFactor, dLRVScaleFactor), dLRVScaleFactor / 4.0) * m_iScalingFactor);
-  iTBScaleFactorX = myint(std::max(std::min(dTBHScaleFactor, dTBVScaleFactor), dTBVScaleFactor / 4.0) * m_iScalingFactor);
-  iTBScaleFactorY = myint(std::max(std::min(dTBHScaleFactor, dTBVScaleFactor), dTBHScaleFactor / 4.0) * m_iScalingFactor);
-}
+  Dasher::Opts::ScreenOrientations eOrientation(Dasher::Opts::ScreenOrientations(GetLongParameter(LP_REAL_ORIENTATION)));
+  
+  double dScaleFactorX, dScaleFactorY;
+  
+  if (eOrientation == Dasher::Opts::LeftToRight || eOrientation == Dasher::Opts::RightToLeft) {
+    dScaleFactorX = iScreenWidth / static_cast<double>( iMaxX - iMinX );
+    dScaleFactorY = iScreenHeight / static_cast<double>( iMaxY - iMinY );
+  } else {
+    dScaleFactorX = iScreenHeight / static_cast<double>( iMaxX - iMinX );
+    dScaleFactorY = iScreenWidth / static_cast<double>( iMaxY - iMinY );
+  }
+  
+  if (dScaleFactorX < dScaleFactorY) {
+    //fewer (pixels per dasher coord) in X direction - i.e., X is more compressed.
+    //So, use X scale for Y too...except first, we'll _try_ to reduce the difference
+    // by changing the relative scaling of X and Y (by at most 20%):
+    double dMul = max(0.8, dScaleFactorX / dScaleFactorY);
+    m_dXmpc *= dMul;
+    dScaleFactorX /= dMul;
 
-void CDasherViewSquare::GetScaleFactor( int eOrientation, myint *iScaleFactorX, myint *iScaleFactorY ) {
-  if(( eOrientation == Dasher::Opts::LeftToRight ) || ( eOrientation == Dasher::Opts::RightToLeft )) {
-    *iScaleFactorX = iLRScaleFactorX;
-    *iScaleFactorY = iLRScaleFactorY;
+    iScaleFactorX = myint(dScaleFactorX * m_iScalingFactor);
+    iScaleFactorY = myint(std::max(dScaleFactorX, dScaleFactorY / 4.0) * m_iScalingFactor);
   } else {
-    *iScaleFactorX = iTBScaleFactorX;
-    *iScaleFactorY = iTBScaleFactorY;
+    //X has more room; use Y scale for both -> will get lots history
+    iScaleFactorX = myint(std::max(dScaleFactorY, dScaleFactorX / 4.0) * m_iScalingFactor);
+    iScaleFactorY = myint(dScaleFactorY * m_iScalingFactor);
+    // however, "compensate" by relaxing the default "relative scaling" of X
+    // (normally only 90% of Y) towards 1...
+    m_dXmpc = std::min(1.0,0.9 * dScaleFactorX / dScaleFactorY);
   }
+  iCenterX *= m_dXmpc;
 }
 
 
@@ -730,11 +733,9 @@ void CDasherViewSquare::Dasher2Screen(myint iDasherX, myint iDasherY, screenint
 
   // Apply the nonlinearities
 
-  if (GetBoolParameter(BP_NONLINEAR_Y)) {
-    iDasherX = xmap(iDasherX);
-    iDasherY = ymap(iDasherY);
-  }
-
+  iDasherX = xmap(iDasherX);
+  iDasherY = ymap(iDasherY);
+  
   // Things we're likely to need:
 
   //myint iDasherWidth = (myint)GetLongParameter(LP_MAX_Y);
@@ -745,12 +746,6 @@ void CDasherViewSquare::Dasher2Screen(myint iDasherX, myint iDasherY, screenint
 
   int eOrientation( GetLongParameter(LP_REAL_ORIENTATION) );
 
-  myint iScaleFactorX;
-  myint iScaleFactorY;
-
-  GetScaleFactor( eOrientation, &iScaleFactorX, &iScaleFactorY);
-
-
   // Note that integer division is rounded *away* from zero here to
   // ensure that this really is the inverse of the map the other way
   // around.
@@ -797,22 +792,23 @@ void CDasherViewSquare::Dasher2Polar(myint iDasherX, myint iDasherY, double &r,
 }
 
 void CDasherViewSquare::DasherLine2Screen(myint x1, myint y1, myint x2, myint y2, vector<CDasherScreen::point> &vPoints) {
-  if (x1!=x2 && y1!=y2 && GetBoolParameter(BP_NONLINEAR_Y)) {
-    //only diagonal lines ever get changed...
-    if ((y1 < m_Y3 && y2 > m_Y3) ||(y2 < m_Y3 && y1 > m_Y3)) {
-      //crosses bottom non-linearity border
-      int x_mid = x1+(x2-x1) * (m_Y3-y1)/(y2-y1);
-      DasherLine2Screen(x1, y1, x_mid, m_Y3, vPoints);
-      x1=x_mid; y1=m_Y3;
-    }//else //no, a single line might cross _both_ borders!
-    if ((y1 > m_Y2 && y2 < m_Y2) || (y2 > m_Y2 && y1 < m_Y2)) {
-      //crosses top non-linearity border
-      int x_mid = x1 + (x2-x1) * (m_Y2-y1)/(y2-y1);
-      DasherLine2Screen(x1, y1, x_mid, m_Y2, vPoints);
-      x1=x_mid; y1=m_Y2;
+  if (x1!=x2 && y1!=y2) { //only diagonal lines ever get changed...
+    if (GetBoolParameter(BP_NONLINEAR_Y)) {
+      if ((y1 < m_Y3 && y2 > m_Y3) ||(y2 < m_Y3 && y1 > m_Y3)) {
+        //crosses bottom non-linearity border
+        int x_mid = x1+(x2-x1) * (m_Y3-y1)/(y2-y1);
+        DasherLine2Screen(x1, y1, x_mid, m_Y3, vPoints);
+        x1=x_mid; y1=m_Y3;
+      }//else //no, a single line might cross _both_ borders!
+      if ((y1 > m_Y2 && y2 < m_Y2) || (y2 > m_Y2 && y1 < m_Y2)) {
+        //crosses top non-linearity border
+        int x_mid = x1 + (x2-x1) * (m_Y2-y1)/(y2-y1);
+        DasherLine2Screen(x1, y1, x_mid, m_Y2, vPoints);
+        x1=x_mid; y1=m_Y2;
+      }
     }
     double dMax(static_cast<double>(GetLongParameter(LP_MAX_Y)));
-    if (GetBoolParameter(BP_NONLINEAR_Y) && (x1 / dMax > m_dXmpb || x2 / dMax > m_dXmpb)) {
+    if (GetLongParameter(LP_NONLINEAR_X) && (x1 / dMax > m_dXmpb || x2 / dMax > m_dXmpb)) {
       //into logarithmic section
       CDasherScreen::point pStart, pScreenMid, pEnd;
       Dasher2Screen(x2, y2, pEnd.x, pEnd.y);
diff --git a/Src/DasherCore/DasherViewSquare.h b/Src/DasherCore/DasherViewSquare.h
index 81ca815..79140ad 100644
--- a/Src/DasherCore/DasherViewSquare.h
+++ b/Src/DasherCore/DasherViewSquare.h
@@ -174,26 +174,17 @@ private:
 
   void DasherLine2Screen(myint x1, myint y1, myint x2, myint y2, vector<CDasherScreen::point> &vPoints);
   
-  // Called on screen size changes
+  // Called on screen size or orientation changes
   void SetScaleFactor();
 
-
-  /// Get the scale factor for conversion between Dasher co-ordinates
-  /// and screen co-ordinates
-
-  void GetScaleFactor( int eOrientation, myint *iScaleFactorX, myint *iScaleFactorY );
-
-
   // Data
  
   double m_dXmpa, m_dXmpb, m_dXmpc;
   screenint iCenterX;
 
   // Cached values for scaling
-  myint iLRScaleFactorX;
-  myint iLRScaleFactorY;
-  myint iTBScaleFactorX;
-  myint iTBScaleFactorY;
+  myint iScaleFactorX;
+  myint iScaleFactorY;
 
   // The factor that scale factors are multipled by 
   myint m_iScalingFactor;
diff --git a/Src/DasherCore/DasherViewSquare.inl b/Src/DasherCore/DasherViewSquare.inl
index 99856bc..446ffd4 100644
--- a/Src/DasherCore/DasherViewSquare.inl
+++ b/Src/DasherCore/DasherViewSquare.inl
@@ -45,6 +45,7 @@ namespace Dasher {
 
   inline myint CDasherViewSquare::ixmap(myint x) const
   {
+    if (GetLongParameter(LP_NONLINEAR_X)==0) return x;
     double dx = x / static_cast<double>(GetLongParameter(LP_MAX_Y));
     if(dx < m_dXmpb * m_dXmpc)
       dx /= m_dXmpc;
@@ -55,6 +56,7 @@ namespace Dasher {
 
   inline myint CDasherViewSquare::xmap(myint x) const
   {
+    if (GetLongParameter(LP_NONLINEAR_X)==0) return x;
     double dx = x / static_cast<double>(GetLongParameter(LP_MAX_Y));
     if(dx < m_dXmpb)
       dx *= m_dXmpc;
@@ -64,6 +66,7 @@ namespace Dasher {
   }
 
   inline myint CDasherViewSquare::ymap(myint y) const {
+    if (!GetBoolParameter(BP_NONLINEAR_Y)) return y;
     if(y > m_Y2)
       return m_Y2 + (y - m_Y2) / m_Y1;
     else if(y < m_Y3)
@@ -73,11 +76,12 @@ namespace Dasher {
   }
 
   inline myint CDasherViewSquare::iymap(myint ydash) const {
-    if(ydash > m_Y2)
-      return (ydash - m_Y2) * m_Y1 + m_Y2;
-    else if(ydash < m_Y3)
-      return (ydash - m_Y3) * m_Y1 + m_Y3;
-    else
-      return ydash;
+    if (GetBoolParameter(BP_NONLINEAR_Y)) {
+      if(ydash > m_Y2)
+        return (ydash - m_Y2) * m_Y1 + m_Y2;
+      else if(ydash < m_Y3)
+        return (ydash - m_Y3) * m_Y1 + m_Y3;
+    }
+    return ydash;
   }
 }
diff --git a/Src/DasherCore/Parameters.h b/Src/DasherCore/Parameters.h
index a7436a2..1dbebb3 100644
--- a/Src/DasherCore/Parameters.h
+++ b/Src/DasherCore/Parameters.h
@@ -57,7 +57,7 @@ enum {
   LP_LM_MIXTURE, LP_MOUSE_POS_BOX, LP_NORMALIZATION, LP_LINE_WIDTH, 
   LP_LM_WORD_ALPHA, LP_USER_LOG_LEVEL_MASK, 
   LP_ZOOMSTEPS, LP_B, LP_S, LP_BUTTON_SCAN_TIME, LP_R, LP_RIGHTZOOM,
-  LP_NODE_BUDGET,
+  LP_NODE_BUDGET, LP_NONLINEAR_X,
   LP_BOOSTFACTOR, LP_AUTOSPEED_SENSITIVITY, LP_SOCKET_PORT, LP_SOCKET_INPUT_X_MIN, LP_SOCKET_INPUT_X_MAX,
   LP_SOCKET_INPUT_Y_MIN, LP_SOCKET_INPUT_Y_MAX, LP_OX, LP_OY, LP_MAX_Y, LP_INPUT_FILTER, 
   LP_CIRCLE_PERCENT, LP_TWO_BUTTON_OFFSET, LP_HOLD_TIME, LP_MULTIPRESS_TIME,
@@ -154,7 +154,7 @@ static bp_table boolparamtable[] = {
   {BP_SOCKET_DEBUG, "SocketInputDebug", PERS, false, "Print information about socket input processing to console"},
   {BP_CIRCLE_START, "CircleStart", PERS, false, "Start on circle mode"},
   {BP_GLOBAL_KEYBOARD, "GlobalKeyboard", PERS, false, "Whether to assume global control of the keyboard"},
-#if defined(WITH_MAEMO) || defined(TARGET_OS_IPHONE)
+#ifdef WITH_MAEMO
   {BP_NONLINEAR_Y, "NonlinearY", PERS, false, "Apply nonlinearities to Y axis (i.e. compress top &amp; bottom)"},
 #else
   {BP_NONLINEAR_Y, "NonlinearY", PERS, true, "Apply nonlinearities to Y axis (i.e. compress top &amp; bottom)"},
@@ -209,11 +209,16 @@ static lp_table longparamtable[] = {
 #endif
   {LP_R, "ButtonModeNonuniformity", PERS, 0, "Button mode box non-uniformity"},
   {LP_RIGHTZOOM, "ButtonCompassModeRightZoom", PERS, 5120, "Zoomfactor (*1024) for compass mode"},
-#ifdef TARGET_OS_IPHONE
+#if defined(WITH_MAEMO) || defined (TARGET_OS_IPHONE)
   {LP_NODE_BUDGET, "NodeBudget", PERS, 1000, "Target (min) number of node objects to maintain"},
 #else
   {LP_NODE_BUDGET, "NodeBudget", PERS, 3000, "Target (min) number of node objects to maintain"},
 #endif
+#ifdef WITH_MAEMO
+  {LP_NONLINEAR_X, "NonLinearX", PERS, 0, "Nonlinear compression of X-axis (0 = none, higher = more extreme)"},
+#else
+  {LP_NONLINEAR_X, "NonLinearX", PERS, 5, "Nonlinear compression of X-axis (0 = none, higher = more extreme)"},
+#endif
   {LP_BOOSTFACTOR, "BoostFactor", !PERS, 100, "Boost/brake factor (multiplied by 100)"},
   {LP_AUTOSPEED_SENSITIVITY, "AutospeedSensitivity", PERS, 100, "Sensitivity of automatic speed control (percent)"},
   {LP_SOCKET_PORT, "SocketPort", PERS, 20320, "UDP/TCP socket to use for network socket input"},
diff --git a/Src/iPhone/Classes/MiscSettings.mm b/Src/iPhone/Classes/MiscSettings.mm
index 4593f88..43f9c01 100644
--- a/Src/iPhone/Classes/MiscSettings.mm
+++ b/Src/iPhone/Classes/MiscSettings.mm
@@ -15,7 +15,7 @@ static SModuleSettings _settings[] = { //note iStep and string description are i
   {LP_NODE_BUDGET, T_LONG, 400, 10000, 1, 0, ""}, //hopefully appropriate for an iPhone 3GS?
   {LP_MARGIN_WIDTH, T_LONG, 100, 900, 1, 0, ""},
   {BP_AUTO_SPEEDCONTROL, T_BOOL, -1, -1, -1, -1, ""},
-  {BP_NONLINEAR_Y, T_BOOL, -1, -1, -1, -1, ""},
+  {LP_NONLINEAR_X, T_LONG, 0, 10, 1, -1, ""},
   {BP_DOUBLE_X, T_BOOL, -1, -1, -1, -1, ""},
 };
 static int _count = sizeof(_settings) / sizeof(_settings[0]);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]