[dasher] Rewrite NewGoTo to be iterative not recursive, and inline into UpdateBounds



commit 72ceb0357927712f363b7c43c097b21787a309f4
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Fri Sep 3 17:53:17 2010 +0100

    Rewrite NewGoTo to be iterative not recursive, and inline into UpdateBounds

 Src/DasherCore/DasherModel.cpp |  108 +++++++++++++++++++--------------------
 Src/DasherCore/DasherModel.h   |    6 --
 2 files changed, 53 insertions(+), 61 deletions(-)
---
diff --git a/Src/DasherCore/DasherModel.cpp b/Src/DasherCore/DasherModel.cpp
index 98b46c3..5e7a2b5 100644
--- a/Src/DasherCore/DasherModel.cpp
+++ b/Src/DasherCore/DasherModel.cpp
@@ -397,76 +397,74 @@ void CDasherModel::OneStepTowards(myint miMousex, myint miMousey, unsigned long
   UpdateBounds(iNewMin, iNewMax, iTime, pAdded, pNumDeleted);
 }
 
-void CDasherModel::UpdateBounds(myint iNewMin, myint iNewMax, unsigned long iTime, Dasher::VECTOR_SYMBOL_PROB* pAdded, int* pNumDeleted) {
+void CDasherModel::UpdateBounds(myint newRootmin, myint newRootmax, unsigned long iTime, Dasher::VECTOR_SYMBOL_PROB* pAdded, int* pNumDeleted) {
   
-  m_dTotalNats += log((iNewMax - iNewMin) / static_cast<double>(m_Rootmax - m_Rootmin));
+  m_dTotalNats += log((newRootmax - newRootmin) / static_cast<double>(m_Rootmax - m_Rootmin));
 
+  m_iDisplayOffset = (m_iDisplayOffset * 90) / 100;
+  
   // Now actually zoom to the new location
-  NewGoTo(iNewMin, iNewMax, pAdded, pNumDeleted);
-}
-
-void CDasherModel::RecordFrame(unsigned long Time) {
-  CFrameRate::RecordFrame(Time);
-  ///GAME MODE TEMP///Pass new frame events onto our teacher
-  GameMode::CDasherGameMode* pTeacher = GameMode::CDasherGameMode::GetTeacher();
-  if(m_bGameMode && pTeacher)
-    pTeacher->NewFrame(Time);
-}
-
-void CDasherModel::NewGoTo(myint newRootmin, myint newRootmax, Dasher::VECTOR_SYMBOL_PROB* pAdded, int* pNumDeleted) {
-
-  // Update the max and min of the root node to make iTargetMin and
-  // iTargetMax the edges of the viewport.
-
-  if(newRootmin + m_iDisplayOffset > (myint)GetLongParameter(LP_MAX_Y) / 2 - 1)
-    newRootmin = (myint)GetLongParameter(LP_MAX_Y) / 2 - 1 - m_iDisplayOffset;
-
-  if(newRootmax + m_iDisplayOffset < (myint)GetLongParameter(LP_MAX_Y) / 2 + 1)
-    newRootmax = (myint)GetLongParameter(LP_MAX_Y) / 2 + 1 - m_iDisplayOffset;
-
-  // Check that we haven't drifted too far. The rule is that we're not
-  // allowed to let the root max and min cross the midpoint of the
-  // screen.
-
-  if(newRootmax < m_Rootmax_max && newRootmin > m_Rootmin_min) {
-    // Only update if we're not making things big enough to risk
-    // overflow. (Otherwise, forcibly choose a new root node, below)
-    
-    if ((newRootmax - newRootmin) > (myint)GetLongParameter(LP_MAX_Y) / 4) {
-      // Also don't allow the update if it will result in making the
-      // root too small. We should have re-generated a deeper root
-      // before now already, but the original root is an exception.
-      m_Rootmax = newRootmax;
-      m_Rootmin = newRootmin;
-    } //else, we just stop - this prevents the user from zooming too far back
-      //outside the root node (when we can't generate an older root).
-    m_iDisplayOffset = (m_iDisplayOffset * 90) / 100;
-  } else {
+  
+  while (newRootmax >= m_Rootmax_max || newRootmin <= m_Rootmin_min) {
     // can't make existing root any bigger because of overflow. So force a new root
     // to be chosen (so that Dasher doesn't just stop!)...
     
     //pick _child_ covering crosshair...
     const myint iWidth(m_Rootmax-m_Rootmin);
-    for (CDasherNode::ChildMap::const_iterator it = m_Root->GetChildren().begin(), E = m_Root->GetChildren().end(); it!=E; it++) {
+    for (CDasherNode::ChildMap::const_iterator it = m_Root->GetChildren().begin(), E = m_Root->GetChildren().end(); ;) {
       CDasherNode *pChild(*it);
       DASHER_ASSERT(m_Rootmin + ((pChild->Lbnd() * iWidth) / GetLongParameter(LP_NORMALIZATION)) <= GetLongParameter(LP_OY));
       if (m_Rootmin + ((pChild->Hbnd() * iWidth) / GetLongParameter(LP_NORMALIZATION)) > GetLongParameter(LP_OY)) {
-        //proceed only if new root is on the game path. If the user's strayed
-        // that far off the game path, having Dasher stop seems reasonable!
-        if (!m_bGameMode || !pChild->GetFlag(NF_GAME)) {
-          //make pChild the root node...but put (newRootmin,newRootmax) somewhere there'll be converted:
-          SGotoItem temp; temp.iN1 = newRootmin; temp.iN2 = newRootmax;
-          m_deGotoQueue.push_back(temp);
-          Make_root(pChild);
-          temp=m_deGotoQueue.back(); m_deGotoQueue.pop_back();
-          // std::cout << "NewGoto Recursing - was (" << newRootmin << "," << newRootmax << "), now (" << temp.iN1 << "," << temp.iN2 << ")" << std::endl;
-          NewGoTo(temp.iN1, temp.iN2, pAdded,pNumDeleted);
+        //found child to make root. proceed only if new root is on the game path....
+        if (m_bGameMode && !pChild->GetFlag(NF_GAME)) {
+          //If the user's strayed that far off the game path,
+          // having Dasher stop seems reasonable!
+          return;
         }
-        return;
+        
+        //make pChild the root node...
+        //we need to update the target coords (newRootmin,newRootmax)
+        // to reflect the new coordinate system based upon pChild as root.
+        //Make_root automatically updates any such pairs stored in m_deGotoQueue, so:
+        SGotoItem temp; temp.iN1 = newRootmin; temp.iN2 = newRootmax;
+        m_deGotoQueue.push_back(temp);
+        //...when we make pChild the root...
+        Make_root(pChild);
+        //...we can retrieve new, equivalent, coordinates for it
+        newRootmin = m_deGotoQueue.back().iN1; newRootmax = m_deGotoQueue.back().iN2;
+        m_deGotoQueue.pop_back();
+        // (note that the next check below will make sure these coords do cover (0, LP_OY))
+        break;
       }
+      ++it;
+      DASHER_ASSERT (it != E); //must find a child!
     }
-    DASHER_ASSERT(false); //did not find a child covering crosshair...?!
   }
+  
+  // Check that we haven't drifted too far. The rule is that we're not
+  // allowed to let the root max and min cross the midpoint of the
+  // screen.
+  newRootmin = min(newRootmin, (myint)GetLongParameter(LP_OY) - 1 - m_iDisplayOffset);
+  newRootmax = max(newRootmax, (myint)GetLongParameter(LP_OY) + 1 - m_iDisplayOffset);  
+  
+  // Only allow the update if it won't make the
+  // root too small. We should have re-generated a deeper root
+  // before now already, but the original root is an exception.
+  // (as is trying to go back beyond the earliest char in the current
+  // alphabet, if there are preceding characters not in that alphabet)
+  if ((newRootmax - newRootmin) > (myint)GetLongParameter(LP_MAX_Y) / 4) {
+    m_Rootmax = newRootmax;
+    m_Rootmin = newRootmin;
+  } //else, we just stop - this prevents the user from zooming too far back
+  //outside the root node (when we can't generate an older root).
+}
+
+void CDasherModel::RecordFrame(unsigned long Time) {
+  CFrameRate::RecordFrame(Time);
+  ///GAME MODE TEMP///Pass new frame events onto our teacher
+  GameMode::CDasherGameMode* pTeacher = GameMode::CDasherGameMode::GetTeacher();
+  if(m_bGameMode && pTeacher)
+    pTeacher->NewFrame(Time);
 }
 
 void CDasherModel::OutputTo(CDasherNode *pNewNode, Dasher::VECTOR_SYMBOL_PROB* pAdded, int* pNumDeleted) {
diff --git a/Src/DasherCore/DasherModel.h b/Src/DasherCore/DasherModel.h
index 90c78eb..1a78dab 100644
--- a/Src/DasherCore/DasherModel.h
+++ b/Src/DasherCore/DasherModel.h
@@ -268,12 +268,6 @@ class Dasher::CDasherModel:public Dasher::CFrameRate, private NoClones
   // Information entered so far in this model
   double m_dTotalNats; 
 
-
-  ///
-  /// Go directly to a given coordinate - check semantics
-  ///
-  void NewGoTo(myint n1, myint n2, Dasher::VECTOR_SYMBOL_PROB* pAdded, int* pNumDeleted);
-
   ///
   /// CDasherModel::Get_new_root_coords( myint Mousex,myint Mousey )
   /// 



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