00001 #ifndef Impala_Visualisation_Plot_Plot_h
00002 #define Impala_Visualisation_Plot_Plot_h
00003
00004 #include "Core/Array/Arrays.h"
00005 #include "OglGui/Window.h"
00006 #include "Visualization/Plot/Plottable.h"
00007
00008 namespace Impala
00009 {
00010 namespace Visualization
00011 {
00012 namespace Plot
00013 {
00014
00015
00024 class Plot : public OglGui::Window
00025 {
00026 public:
00027 Plot(OglGui::Window* parent, int x, int y, int width, int height) :
00028 OglGui::Window(parent, x, y, width, height)
00029 {
00030 Init();
00031
00032 }
00033
00034 Plot(OglGui::Window* parent, int width, int height) :
00035 OglGui::Window(parent, width, height)
00036 {
00037 Init();
00038
00039 }
00040
00041 void Add(Plottable* p)
00042 {
00043 mPlottables.push_back(p);
00044 }
00045
00046 void SetCenter(double x, double y, double z)
00047 {
00048 mCenter[0] = x;
00049 mCenter[1] = y;
00050 mCenter[2] = z;
00051 }
00052
00053 void SetRange(double x, double y, double z)
00054 {
00055 double w=1., h=1.;
00056 if(mDrawAxes)
00057 {
00058
00059 w = mOglWnd->width * 0.5;
00060 w = w/(w-20.0);
00061 h = mOglWnd->height * 0.5;
00062 h = h/(h-20.0);
00063 }
00064 mRange[0] = x*w;
00065 mRange[1] = y*h;
00066 mRange[2] = z;
00067 }
00068
00069 void GetRange(double& left, double& top, double& right, double& bottom)
00070 {
00071 Pixel2Window(20, 20, left, bottom);
00072 Pixel2Window(mOglWnd->width-20, mOglWnd->height-20, right, top);
00073 }
00074
00075 bool IsVisible(double x, double y)
00076 {
00077 double pixX, pixY;
00078 Window2Pixel(x,y,pixX,pixY);
00079 return !(pixX < 0 || pixX > W() || pixY < 0 || pixY > H());
00080 }
00081
00082 void MakeVisibleAtPix(double x, double y, double pixX, double pixY)
00083 {
00084 double atX, atY;
00085 Window2Pixel(x,y,atX,atY);
00086 mUserPan[0] += (pixX - atX)* mRange[0] / ((double)mOglWnd->width *mUserZoom[0]);
00087 mUserPan[1] += (pixY - atY)* mRange[1] / ((double)mOglWnd->height*mUserZoom[1]);
00088 }
00089
00090 void GetUserPan(double& panX, double& panY)
00091 {
00092 panX = mUserPan[0];
00093 panY = mUserPan[1];
00094 }
00095
00096 void SetUserPan(double panX, double panY)
00097 {
00098 mUserPan[0] = panX;
00099 mUserPan[1] = panY;
00100 }
00101
00102 void GetUserZoom(double& zoomX, double& zoomY)
00103 {
00104 zoomX = mUserZoom[0];
00105 zoomY = mUserZoom[1];
00106 }
00107
00108 void SetUserZoom(double zoomX, double zoomY)
00109 {
00110 mUserZoom[0] = zoomX;
00111 mUserZoom[1] = zoomY;
00112 }
00113
00114 void GetRotations(double& roll, double& pitch, double& yaw)
00115 {
00116 roll = mRoll;
00117 pitch = mPitch;
00118 yaw = mYaw;
00119 }
00120
00121
00122
00123
00124
00125
00126 void SetDrawAxes(bool flag)
00127 {
00128 mDrawAxes = flag;
00129 }
00130
00131 bool GetDrawAxes()
00132 {
00133 return mDrawAxes;
00134 }
00135 void Window2Pixel(double wx, double wy, double&px, double& py)
00136 {
00137 wx -= mCenter[0]-mUserPan[0]-(.5*mRange[0]/mUserZoom[0]);
00138 px = wx / ((mRange[0]/mUserZoom[0])/(double)mOglWnd->width);
00139 wy -= mCenter[1]-mUserPan[1]-(.5*mRange[1]/mUserZoom[1]);
00140 py = wy / ((mRange[1]/mUserZoom[1])/(double)mOglWnd->height);
00141 }
00142
00143 void Pixel2Window(double px, double py, double&wx, double& wy)
00144 {
00145 wx = (px*mRange[0]/mUserZoom[0])/(double)mOglWnd->width;
00146 wx += mCenter[0]-mUserPan[0]-(.5*mRange[0]/mUserZoom[0]);
00147 wy = (py*mRange[1]/mUserZoom[1])/(double)mOglWnd->height;
00148 wy += mCenter[1]-mUserPan[1]-(.5*mRange[1]/mUserZoom[1]);
00149 }
00150
00151 void AutoScale()
00152 {
00153 if(mPlottables.size() == 0)
00154 return;
00155 double minx, maxx;
00156 double miny, maxy;
00157 double minz, maxz;
00158 Plottable* p;
00159 p = mPlottables[0];
00160 p->GetDimensionsX(minx, maxx);
00161 p->GetDimensionsY(miny, maxy);
00162 p->GetDimensionsZ(minz, maxz);
00163 for(int i=1 ; i<mPlottables.size() ; i++)
00164 {
00165 double min, max;
00166 p = mPlottables[i];
00167 p->GetDimensionsX(min, max);
00168 if(min<minx)
00169 minx = min;
00170 if(max>maxx)
00171 maxx = max;
00172 p->GetDimensionsY(min, max);
00173 if(min<miny)
00174 miny = min;
00175 if(max>maxy)
00176 maxy = max;
00177 p->GetDimensionsZ(min, max);
00178 if(min<minz)
00179 minz = min;
00180 if(max>maxz)
00181 maxz = max;
00182 }
00183
00184 if(minz == maxz)
00185 {
00186 minz = -1;
00187 maxz = 1;
00188 mIs3d = false;
00189 }
00190 else
00191 mIs3d = true;
00192
00193 SetCenter((maxx+minx)*.5, (maxy+miny)*.5, (maxz+minz)*.5);
00194 SetRange(maxx-minx, maxy-miny, maxz-minz);
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 void TransformMatrices(double w, double h)
00223 {
00224
00225 glMatrixMode(GL_PROJECTION);
00226 glPushMatrix();
00227 glLoadIdentity();
00228
00229 double range[2];
00230 double center[2];
00231 for(int i=0 ; i<2 ; ++i)
00232 {
00233 center[i] = mCenter[i] - mUserPan[i];
00234 range[i] = 0.5*mRange[i] / mUserZoom[i];
00235 }
00236
00237 glOrtho(center[0] - range[0],
00238 center[0] + range[0],
00239 center[1] - range[1],
00240 center[1] + range[1],
00241 -1, 1);
00242
00243 glMatrixMode(GL_MODELVIEW);
00244 glPushMatrix();
00245 }
00246
00247 virtual void DisplayFunc()
00248 {
00249 OGC oldOGC;
00250 OGCSave(&oldOGC);
00251 TransformMatrices(mOglWnd->width, mOglWnd->height);
00252
00253 if(mDrawAxes)
00254 DrawAxes();
00255
00256 for (int i=0 ; i<mPlottables.size() ; i++)
00257 {
00258 mPlottables[i]->Draw(this);
00259 }
00260
00261
00262 glMatrixMode(GL_PROJECTION);
00263 glPopMatrix();
00264 glMatrixMode(GL_MODELVIEW);
00265 glPopMatrix();
00266
00267 OGCRestore(&oldOGC);
00268 }
00269
00270 virtual void MouseFunc(int msg, int but, int state, int x, int y)
00271 {
00272 bool shift = (state & oglShift) != 0;
00273 bool control = (state & oglControl) != 0;
00274
00275 if (msg == oglMouseDown && but == oglRightButton)
00276 {
00277
00278
00279
00280 {
00281 for(int i=0 ; i<2 ; i++)
00282 {
00283 mUserPan[i] = 0;
00284 mUserZoom[i] = 0.9;
00285 }
00286 mUserRoll = mUserPitch = 0;
00287 }
00288 }
00289
00290 if (msg == oglMouseDown && but == oglLeftButton && (shift||control))
00291 {
00292 mDragging = true;
00293 mClickX = x;
00294 mClickY = y;
00295 }
00296
00297 if (msg == oglMouseUp)
00298 mDragging = false;
00299
00300 if (msg == oglMouseMove && mDragging)
00301 {
00302 int dx = x - mClickX;
00303 int dy = y - mClickY;
00304 if(control)
00305 {
00306 mUserZoom[0] *= pow(1.02,(double)dx);
00307 mUserZoom[1] *= pow(1.02,(double)dy);
00308 for(int i=0 ; i<2 ; i++)
00309 if(mUserZoom[i] < 0.01)
00310 mUserZoom[i] = 0.01;
00311 }
00312 else
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 {
00324 mUserPan[0] += (double)dx * mRange[0] / ((double)mOglWnd->width *mUserZoom[0]);
00325 mUserPan[1] += (double)dy * mRange[1] / ((double)mOglWnd->height*mUserZoom[1]);
00326 }
00327 mClickX = x;
00328 mClickY = y;
00329 }
00330
00331 double wx, wy;
00332 Pixel2Window(x, y, wx, wy);
00333 for(int i=0 ; i<mPlottables.size() ; i++)
00334 mPlottables[i]->OnMouse(wx, wy, msg, but, state);
00335 }
00336
00337 protected:
00338 double mRoll, mPitch, mYaw;
00339 double mUserRoll, mUserPitch;
00340 std::vector<Plottable*> mPlottables;
00341 bool mDragging;
00342
00343 bool mDrawAxes;
00344 bool mIs3d;
00345 int mClickX, mClickY;
00346
00347 double mCenter[3];
00348 double mRange[3];
00349 double mUserZoom[2];
00350 double mUserPan[2];
00351 int mFontBase;
00352
00353 void Init()
00354 {
00355 for(int i=0 ; i<3 ; i++)
00356 {
00357 mCenter[i] = 0;
00358 mRange[i] = 2;
00359 }
00360 for(int i=0 ; i<2 ; i++)
00361 {
00362 mUserZoom[i] = 0.9;
00363 mUserPan[i] = 0;
00364 }
00365 mRoll = mPitch = mYaw = 0;
00366 mUserRoll = mUserPitch = 0;
00367 mOglWnd->bgCol = 0xff505050;
00368 mDrawAxes = false;
00369 mDragging = false;
00370 SetIs2d(false);
00371 mIs3d = false;
00372
00373 mFontBase = 0;
00374 }
00375
00376 class Axis
00377 {
00378 public:
00379 void SetRange(double min, double max)
00380 {
00381 mMin = min;
00382 mMax = max;
00383 ComputeTicks();
00384 }
00385
00386 double GetTick(int count)
00387 {
00388 return (double)(count+mFirstTick)*mTickSize;
00389 }
00390
00391 int GetTickCount()
00392 {
00393 return mTickCount;
00394 }
00395
00396 void DrawRulers(double* start, double* end, int axis)
00397 {
00398 double a[3];
00399 double b[3];
00400 int i;
00401 for(i=0 ; i<3 ; i++)
00402 {
00403 a[i] = start[i];
00404 b[i] = end[i];
00405 }
00406 glColor3d(.7,.7,.7);
00407 glBegin(GL_LINES);
00408 for(i=0 ; i<mTickCount ; i++)
00409 {
00410 a[axis] = b[axis] = GetTick(i);
00411 glVertex3dv(a);
00412 glVertex3dv(b);
00413 }
00414 glEnd();
00415 }
00416
00417 private:
00418 void ComputeTicks()
00419 {
00420 double range = mMax - mMin;
00421 double order = floor(log10(range));
00422 mTickSize = pow(10.,order);
00423 double quanta[6] = {.2, .4, .5, .75, 1., 2.};
00424 double quantum = 1.;
00425 for(int i=0 ; i<6 ; i++)
00426 {
00427 if(range / (quanta[i]*mTickSize) >= 4)
00428 quantum = quanta[i];
00429 }
00430 mTickSize *= quantum;
00431 mFirstTick = ceil(mMin / mTickSize);
00432 mTickCount = floor(mMax / mTickSize) - mFirstTick + 1;
00433 }
00434
00435 double mMin, mMax;
00436 int mFirstTick;
00437 int mTickCount;
00438 double mTickSize;
00439 };
00440 Axis mAxisX;
00441 Axis mAxisY;
00442 Axis mAxisZ;
00443
00444 void UpdateAxes()
00445 {
00446 double x1,x2,y1,y2;
00447 Pixel2Window(20, 20, x1, y1);
00448 Pixel2Window(mOglWnd->width-20, mOglWnd->height-20, x2, y2);
00449 mAxisX.SetRange(x1, x2);
00450 mAxisY.SetRange(y1, y2);
00451 }
00452
00453 void DrawAxes()
00454 {
00455 UpdateAxes();
00456 if (!mFontBase)
00457 FindOglFont(mOglWnd, 0, &mFontBase);
00458
00459 glColor3d(1,1,0);
00460 double x1,y1,tick;
00461 Pixel2Window(4, 4, x1, y1);
00462
00463 int i;
00464 for(i=0 ; i<mAxisX.GetTickCount() ; i++)
00465 {
00466 tick = mAxisX.GetTick(i);
00467 glRasterPos3d(tick, y1, 0);
00468 std::ostringstream os;
00469 os << tick;
00470 oglSys.PrintFont(mFontBase, (char*) os.str().c_str());
00471 }
00472 for(i=0 ; i<mAxisY.GetTickCount() ; i++)
00473 {
00474 tick = mAxisY.GetTick(i);
00475 glRasterPos3d(x1, tick, 0);
00476 std::ostringstream os;
00477 os << tick;
00478 oglSys.PrintFont(mFontBase, (char*) os.str().c_str());
00479 }
00480
00481 double x2,y2;
00482 Pixel2Window(20, 20, x1, y1);
00483 Pixel2Window(mOglWnd->width-20, mOglWnd->height-20, x2, y2);
00484 glBegin(GL_LINE_STRIP);
00485 glVertex2d(x2,y1);
00486 glVertex2d(x1,y1);
00487 glVertex2d(x1,y2);
00488 glEnd();
00489
00490 glColor3d(0.6,0.6,0);
00491 glBegin(GL_LINES);
00492 for(i=0 ; i<mAxisX.GetTickCount() ; i++)
00493 {
00494 tick = mAxisX.GetTick(i);
00495 glVertex3d(tick, y1, 0);
00496 glVertex3d(tick, y2, 0);
00497 }
00498 for(i=0 ; i<mAxisY.GetTickCount() ; i++)
00499 {
00500 tick = mAxisY.GetTick(i);
00501 glVertex3d(x1, tick, 0);
00502 glVertex3d(x2, tick, 0);
00503 }
00504 glEnd();
00505
00506 }
00507 };
00508
00509
00510 }
00511 }
00512 }
00513
00514
00515
00516 #endif