00001
00002 #ifndef Impala_Visualization_RotorBrowser_RotorBrowserContext_h
00003 #define Impala_Visualization_RotorBrowser_RotorBrowserContext_h
00004
00005 #include "RotorViewCache.h"
00006 #include "Core/Trec/Thread.h"
00007 #include "Basis/CmdOptions.h"
00008
00009 namespace Impala {
00010 namespace Visualization {
00011 namespace RotorBrowser {
00012
00013
00014
00015
00016 class RotorBrowserContext {
00017 public:
00018 typedef Core::Trec::Thread Thread;
00019
00020 RotorBrowserContext(RotorViewCache *cache, Thread *thread,
00021 int initialposition, double direction=0.0, int depth=4)
00022 {
00023 CmdOptions &options = CmdOptions::GetInstance();
00024 mHighResDistance = options.GetInt("mdBrowserHighResDistance");
00025
00026 mContextName = thread->GetName();
00027 mContextNiceName = "";
00028 mCache = cache;
00029 mDirection = direction;
00030 mDrawDirection = DIRECTION_BOTH;
00031 mDepth = depth;
00032 mSwallowMode = SWALLOW_NONE;
00033
00034 mSkip = NULL;
00035 mThread = thread;
00036 mThread->SetOrigin(mPosition = initialposition);
00037
00038 if (mPosition == 0)
00039 GoFirst();
00040 }
00041
00042 Thread* GetThread() { return mThread; }
00043 String GetName() { return mContextName; }
00044 void SetNiceName(String name) { mContextNiceName = name; }
00045 int GetCenter() { return mPosition; }
00046 bool GoLeft() { return GoRelative(-1); }
00047 bool GoRight() { return GoRelative(+1); }
00048 void GoFirst() { mPosition = mThread->GetFirstShot(); }
00049 bool PositionExists(int pos) { return pos >= 0; }
00050 void SetSwallowThread(Thread *t) { mSkip = t; }
00051 void SetSwallowMode(int mode) { mSwallowMode = mode; }
00052 int GetSwallowMode() { return mSwallowMode; }
00053 double GetDirection() { return mDirection; }
00054 void SetDirection(double dir) { mDirection = dir; }
00055 int GetDepth() { return mDepth; }
00056 void SetDepth(int depth) { mDepth = depth; }
00057 void SetDrawDirection(int dir) { mDrawDirection = dir; }
00058 int GetDrawDirection() { return mDrawDirection; }
00059
00060 bool ThreadValid()
00061 {
00062 if (!mCache->ThreadExists(mContextName))
00063 {
00064 ILOG_WARN("Thread " << mContextName <<
00065 " does not exist, but RotorBrowserContext does.");
00066 return false;
00067 }
00068 mThread = mCache->GetThread(mContextName);
00069 return true;
00070 }
00071
00072 void UpdateViewsToContext(bool showCenter = true)
00073 {
00074 if (!ThreadValid())
00075 return;
00076
00077 ILOG_DEBUG("UpdateViewsToContext for " << mContextName);
00078 int start = (mDrawDirection == DIRECTION_UP ? 0 : -mDepth);
00079 int stop = (mDrawDirection == DIRECTION_DOWN ? 0 : mDepth);
00080 for (int i=start; i<=stop; i++)
00081 {
00082 if (i==0 && !showCenter) continue;
00083 int item = GetRelative(i);
00084 if (item < 0) continue;
00085 RotorView *v = mCache->GetViewFor(mContextName, item);
00086
00087 if (i!=0 && v)
00088 v->DisableVideoStills();
00089
00090 float x,y,z,w,h;
00091 CalculateCoordinates(x,y,z,w,h,i);
00092 v->MoveTo(x,y,z,w,h);
00093
00094
00095
00096 if (sAutoNegatives)
00097 {
00098 int absI = abs(i);
00099 float prob = absI==0 ? 0.4 : (absI==1 ? 0.1 : 0.04);
00100 mCache->ShotIsViewed(item,prob);
00101 v->SetViewedProbability(mCache->GetViewedProbability(item));
00102 }
00103 bool highRes = (i >= -mHighResDistance && i <= mHighResDistance);
00104 v->SetShowHighResolution(highRes);
00105 }
00106 }
00107
00108 void UpdateViewsToContext(RotorBrowserContext *active)
00109 {
00110 if (!ThreadValid())
00111 return;
00112
00113 MatchContextTo(active);
00114 UpdateViewsToContext(false);
00115 }
00116
00117
00118 void MatchContextTo(RotorBrowserContext *other)
00119 {
00120 int otherCenter = other->GetCenter();
00121 if (otherCenter != -1)
00122 {
00123 mPosition = otherCenter;
00124 mThread->SetOrigin(mPosition);
00125 }
00126 }
00127
00128 bool GoLast()
00129 {
00130 int max = mThread->GetLength();
00131 mPosition = mThread->GetShotAt(mThread->GetFirstShot(), max - 1);
00132 return mPosition >= 0;
00133 }
00134
00135 bool GoTo(int position)
00136 {
00137 if (position < 0)
00138 return false;
00139 mPosition = position;
00140 return true;
00141 }
00142
00143 bool GoRelative(int rpos)
00144 {
00145 if (rpos == 0)
00146 return true;
00147 int newpos = GetRelative(rpos);
00148 if (newpos >= 0)
00149 {
00150 mPosition = newpos;
00151 ILOG_DEBUG("GoRelative(" << rpos << " -> " << mPosition << ")");
00152 return true;
00153 }
00154 ILOG_DEBUG("GoRelative(" << rpos << " -> failed)");
00155 return false;
00156 }
00157
00158 bool MoveRelative(int rpos)
00159 {
00160 if (rpos < 0)
00161 for (int i=0; i < -rpos; i++) GoLeft();
00162 else
00163 for (int i=0; i < rpos; i++) GoRight();
00164
00165 ILOG_DEBUG("MoveRelative(" << rpos << " -> " << GetRelative(0) << ")");
00166 return true;
00167 }
00168
00169 bool ShouldRelPosSwallow(int rpos)
00170 {
00171 if (!RotorBrowserContext::sGlobalShotSwallow || !mSkip)
00172 return false;
00173 return (rpos < 0 && (mSwallowMode & SWALLOW_NEGATIVE)) ||
00174 (rpos > 0 && (mSwallowMode & SWALLOW_POSITIVE));
00175 }
00176
00177 int GetRelative(int rpos)
00178 {
00179
00180 if (mPosition<0) return -1;
00181 int newpos;
00182 if (ShouldRelPosSwallow(rpos))
00183 newpos = mThread->GetShotAtWhileSkipping(mPosition, rpos, mSkip);
00184 else
00185 newpos = mThread->GetShotAt(mPosition, rpos);
00186 return PositionExists(newpos) ? newpos : -1;
00187 }
00188
00189
00190 bool ShowsPosition(int position)
00191 {
00192 for (int i = -mDepth; i <= mDepth; i++)
00193 if (GetRelative(i) == position)
00194 return true;
00195 return false;
00196 }
00197
00198 String GetNiceName()
00199 {
00200 if (mContextNiceName != "")
00201 return mContextNiceName;
00202 if (mContextName.find("rank_thread_") != String::npos)
00203 return String("R: conceptual ") + mContextName.substr(12);
00204 if (mContextName.find("rank_") != String::npos)
00205 return String("R: ") + mContextName.substr(5);
00206 if (mContextName.find("shots_initialquery") != String::npos)
00207 return String("initial query");
00208 if (mContextName.find("shots_vis_") != String::npos)
00209 return String("R: visual for ") + mContextName.substr(10);
00210 if (mContextName.find("shots_textual:") != String::npos)
00211 return String("T: ") + mContextName.substr(14);
00212 if (mContextName.find("shots_") != String::npos)
00213 return String("S: ") + mContextName.substr(6);
00214
00215 return mContextName;
00216 }
00217
00218 static void SetGlobalShotSwallow(bool swallow)
00219 {
00220 RotorBrowserContext::sGlobalShotSwallow = swallow;
00221 }
00222 static bool GetGlobalShotSwallow()
00223 {
00224 return RotorBrowserContext::sGlobalShotSwallow;
00225 }
00226 static bool GetAutoNegatives()
00227 {
00228 return RotorBrowserContext::sAutoNegatives;
00229 }
00230 static void SetAutoNegatives(bool val)
00231 {
00232 RotorBrowserContext::sAutoNegatives = val;
00233 }
00234
00235 private:
00236 void CalculateCoordinates(float& x, float& y, float& z,
00237 float& w, float& h, int depth)
00238 {
00239 float dist;
00240 switch (abs(depth)) {
00241 case 0: dist = 0.0f; w = 1.8f; break;
00242 case 1: dist = 0.44f; w = 1.3f; break;
00243 default: dist = 0.56f; w = 1.0f; break;
00244 }
00245 if (depth < 0) dist = -dist;
00246
00247 float xInc = cos(mDirection);
00248 float yInc = sin(mDirection);
00249 float fact = 1.1f;
00250 x = xInc * fact * depth + dist * xInc;
00251 y = yInc * fact * depth + dist * yInc;
00252 z = -10.0f + degrade(depth/6.0)*3.0;
00253
00254 h = 1.0f;
00255 if (depth >=2) h -= 0.2 * (depth-2);
00256 if (depth <=-2) h -= 0.2 * -(depth+2);
00257 if (h < 0) h = 0;
00258 }
00259
00260 inline double degrade(double x)
00261 {
00262 return 1.0 - x * x;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272 RotorViewCache* mCache;
00273 Thread* mThread;
00274 Thread* mSkip;
00275 String mContextName;
00276 String mContextNiceName;
00277
00278 int mPosition;
00279 int mDepth;
00280 int mSwallowMode;
00281 int mHighResDistance;
00282 int mDrawDirection;
00283
00284 double mDirection;
00285
00286 static bool sGlobalShotSwallow;
00287 static bool sAutoNegatives;
00288
00289 public:
00290 static const int SWALLOW_NONE = 0;
00291 static const int SWALLOW_POSITIVE = 1;
00292 static const int SWALLOW_NEGATIVE = 2;
00293 static const int SWALLOW_ALL = 3;
00294
00295
00296 static const int DIRECTION_BOTH = 0;
00297 static const int DIRECTION_UP = 1;
00298 static const int DIRECTION_DOWN = 2;
00299
00300
00301 static const int DIRECTION_LEFT = 2;
00302 static const int DIRECTION_RIGHT = 1;
00303
00304 ILOG_VAR_DEC;
00305
00306 };
00307
00308 ILOG_VAR_INIT(RotorBrowserContext, Visualization.RotorBrowser);
00309
00310 bool RotorBrowserContext::sAutoNegatives = false;
00311 bool RotorBrowserContext::sGlobalShotSwallow = false;
00312
00313 }
00314 }
00315 }
00316 #endif