Listing 2: The SetScale and GetPhysVal methods

BOOL CAxis::SetScale()
{
   // check, if scale can be set
   if (A == B) return FALSE;
   if (vA == vB) return FALSE;
 
   // calculate m, M, and c
   // using epsilontik if necessary
   double E = B.y - A.y;
   double F = B.x - A.x;
   if ( F == 0.0)
   {
      m = 100000.0;
      M = 0.0;
   }
   else if ( E == 0.0 )
   {
      m = 0;
      M = 100000.0;
   }
   else
   {
      m = E / F;
      M = -1.0 / m;
   }
   c = (double) A.y - m * (double) A.x;

   // calculate scaling factor s between 
   // physical and device axis
   double Delta = (B.x - A.x) * (B.x - A.x);
   Delta += (B.y - A.y) * (B.y - A.y);
   Delta = sqrt(Delta);
   if (fLogScale)
   {
      s = ( log(vB) - log(vA) ) / Delta ;
   }
   else
   {
      s = (vB - vA) / Delta ;
   }
   return TRUE;
}

double CAxis::GetPhysVal(CPoint &D)
{
   double v = 0, Px, Py;
   project_data_point (D, Px, Py);
   v = get_physical_value (Px, Py);
   return v;
}

void CAxis::project_data_point (CPoint &D, double &Px, double &Py)
{
   double C = (double) D.y - M * (double) D.x;
   Px = (C - c)/(m - M);
   Py = m * Px + c;
}

double CAxis::get_physical_value (double Px, double Py)
{
   double v;

   // calculate distance A to P 
   // in device coordinates
   double PA_d = (Px - (double) A.x) * (Px - (double) A.x);
   PA_d += (Py - (double) A.y) * (Py - (double) A.y);
   PA_d = sqrt(PA_d);

   // add or subtract?
   double signum = (Px - A.x)*(B.x - A.x) 
      + (Py - A.y)*(B.y - A.y);

   // calculate distance A to P 
   // in physical coordinates
   double PA_p = PA_d * s;

   // calculate physical value
   if (fLogScale)
   {
      if (signum > 0)
      {
         v = PA_d * s + log (vA);
      }
      else
      {
         v = -PA_d * s + log (vA);
      }
      v = exp (v);
   }
   else
   {
      if (signum > 0)
      {
         v = PA_d * s + vA;
      }
      else
      {
         v = -PA_d * s + vA;
      }  
   }
   return v;
}