00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TVirtualPad.h"
00013 #include "KeySymbols.h"
00014 #include "TVirtualX.h"
00015 #include "Buttons.h"
00016 #include "TString.h"
00017 #include "TError.h"
00018 #include "TROOT.h"
00019 #include "TMath.h"
00020
00021 #include "TGLPlotCamera.h"
00022 #include "TGL5DPainter.h"
00023 #include "TGLPadUtils.h"
00024 #include "TGLIncludes.h"
00025 #include "TGL5D.h"
00026
00027
00028
00029
00030
00031
00032
00033
00034 TGL5DPainter::TGL5DPainter(TGL5DDataSet *data, TGLPlotCamera *camera, TGLPlotCoordinates *coord)
00035 : TGLPlotPainter(data, camera, coord),
00036 fMeshBuilder(kTRUE),
00037 fInit(kFALSE),
00038 fData(data),
00039 fShowSlider(kFALSE),
00040 fAlpha(0.4),
00041 fNContours(kNContours)
00042 {
00043
00044 if (fData->fV4IsString)
00045 fNContours = Int_t(fData->fV4MinMax.second) - Int_t(fData->fV4MinMax.first) + 1;
00046 }
00047
00048
00049 TGL5DPainter::SurfIter_t TGL5DPainter::AddSurface(Double_t v4, Color_t ci,
00050 Double_t iso, Double_t sigma,
00051 Double_t range, Int_t lownps)
00052 {
00053
00054
00055
00056 fData->SelectPoints(v4, range);
00057
00058 if (fData->SelectedSize() < size_type(lownps)) {
00059 Warning("TGL5DPainter::AddSurface", "Too little points: %d", Int_t(fData->SelectedSize()));
00060 return fIsos.end();
00061 } else {
00062 Info("TGL5DPainter::AddSurface", "Selected %d points", Int_t(fData->SelectedSize()));
00063 }
00064
00065 fKDE.BuildModel(fData, sigma);
00066
00067 Info("TGL5DPainter::AddSurface", "Building the mesh ...");
00068
00069 Rgl::Mc::TGridGeometry<Float_t> geom(fXAxis, fYAxis, fZAxis,
00070 fCoord->GetXScale(),
00071 fCoord->GetYScale(),
00072 fCoord->GetZScale());
00073 Mesh_t mesh;
00074 fMeshBuilder.SetGeometry(fData);
00075
00076 fMeshBuilder.BuildMesh(&fKDE, geom, &mesh, iso);
00077
00078 Info("TGL5DPainter::AddSurface", "Mesh has %d vertices", Int_t(mesh.fVerts.size() / 3));
00079
00080 if (!mesh.fVerts.size())
00081 return fIsos.end();
00082
00083 fIsos.push_front(fDummy);
00084
00085 fIsos.front().fMesh.Swap(mesh);
00086 fIsos.front().f4D = v4;
00087 fIsos.front().fRange = range;
00088 fIsos.front().fShowCloud = kFALSE;
00089 fIsos.front().fHide = kFALSE;
00090 fIsos.front().fColor = ci;
00091
00092
00093
00094 return fIsos.begin();
00095 }
00096
00097
00098 void TGL5DPainter::AddSurface(Double_t v4)
00099 {
00100
00101 const Rgl::Range_t &v4R = fData->fV4MinMax;
00102 const Bool_t isString = fData->fV4IsString;
00103 const Double_t rms = TMath::RMS(fData->fNP, fData->fV4);
00104 const Double_t d = isString ? (v4R.second - v4R.first) / (fNContours - 1)
00105 : 6 * rms / fNContours;
00106
00107 const Double_t range = isString ? 1e-3 : fAlpha * d;
00108
00109 AddSurface(v4, 1, 0.125, 0.05, range);
00110 }
00111
00112
00113 void TGL5DPainter::RemoveSurface(SurfIter_t surf)
00114 {
00115
00116 if (surf == fIsos.end()) {
00117 Error("TGL5DPainter::RemoveSurface", "Invalid iterator, surface does not exist.");
00118 return;
00119 }
00120
00121 fIsos.erase(surf);
00122 }
00123
00124
00125 char *TGL5DPainter::GetPlotInfo(Int_t , Int_t )
00126 {
00127
00128 static char mess[] = {"gl5d"};
00129 return mess;
00130 }
00131
00132
00133 Bool_t TGL5DPainter::InitGeometry()
00134 {
00135
00136
00137
00138
00139 if (fInit)
00140 return kTRUE;
00141
00142 fCoord->SetCoordType(kGLCartesian);
00143
00144 if (!fCoord->SetRanges(fXAxis, fYAxis, fZAxis))
00145 return kFALSE;
00146
00147 fIsos.clear();
00148
00149 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(),
00150 fCoord->GetYRangeScaled(),
00151 fCoord->GetZRangeScaled());
00152 if (fCamera)
00153 fCamera->SetViewVolume(fBackBox.Get3DBox());
00154
00155 const Rgl::Range_t &v4R = fData->fV4MinMax;
00156 const Bool_t isString = fData->fV4IsString;
00157
00158
00159 const Double_t mean = TMath::Mean(fData->fNP, fData->fV4);
00160 const Double_t rms = TMath::RMS(fData->fNP, fData->fV4);
00161 const Double_t min = isString ? v4R.first : mean - 3 * rms;
00162 const Double_t d = isString ? (v4R.second - v4R.first) / (fNContours - 1)
00163 : 6 * rms / fNContours;
00164
00165 const Double_t range = isString ? 1e-3 : fAlpha * d;
00166
00167 Info("InitGeometry", "min = %g, mean = %g, rms = %g, dx = %g", min, mean, rms, d);
00168
00169 for (Int_t j = 0; j < fNContours; ++j) {
00170 const Double_t isoLevel = min + j * d;
00171 Info("TGL5DPainter::InitGeometry", "Iso-level %g, range is %g ...", isoLevel, range);
00172 const Color_t color = j * 6 + 1;
00173 AddSurface(isoLevel, color, 0.125, 0.05, range);
00174 }
00175
00176 if (fIsos.size())
00177 fBoxCut.TurnOnOff();
00178
00179 return fInit = kTRUE;
00180 }
00181
00182
00183 void TGL5DPainter::StartPan(Int_t px, Int_t py)
00184 {
00185
00186 fMousePosition.fX = px;
00187 fMousePosition.fY = fCamera->GetHeight() - py;
00188 fCamera->StartPan(px, py);
00189 fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
00190 }
00191
00192
00193 void TGL5DPainter::Pan(Int_t px, Int_t py)
00194 {
00195
00196 if (fSelectedPart >= fSelectionBase) {
00197 SaveModelviewMatrix();
00198 SaveProjectionMatrix();
00199
00200 fCamera->SetCamera();
00201 fCamera->Apply(fPadPhi, fPadTheta);
00202 fCamera->Pan(px, py);
00203
00204 RestoreProjectionMatrix();
00205 RestoreModelviewMatrix();
00206 } else if (fSelectedPart > 0) {
00207
00208 py = fCamera->GetHeight() - py;
00209
00210 SaveModelviewMatrix();
00211 SaveProjectionMatrix();
00212
00213 fCamera->SetCamera();
00214 fCamera->Apply(fPadPhi, fPadTheta);
00215
00216 if (!fHighColor) {
00217 if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis)) {
00218 fBoxCut.MoveBox(px, py, fSelectedPart);
00219 }
00220 }
00221
00222 RestoreProjectionMatrix();
00223 RestoreModelviewMatrix();
00224 }
00225
00226 fMousePosition.fX = px, fMousePosition.fY = py;
00227 fUpdateSelection = kTRUE;
00228 }
00229
00230
00231 void TGL5DPainter::AddOption(const TString &)
00232 {
00233
00234 }
00235
00236
00237 void TGL5DPainter::ProcessEvent(Int_t event, Int_t , Int_t py)
00238 {
00239
00240
00241 if (event == kKeyPress) {
00242 if (py == kKey_c || py == kKey_C) {
00243 if (fHighColor)
00244 Info("ProcessEvent", "Cut box does not work in high color, please, switch to true color");
00245 else {
00246 fBoxCut.TurnOnOff();
00247 fUpdateSelection = kTRUE;
00248 }
00249 }
00250 } else if (event == kButton1Double && fBoxCut.IsActive()) {
00251 if (fBoxCut.IsActive())
00252 fBoxCut.TurnOnOff();
00253 if (!gVirtualX->IsCmdThread())
00254 gROOT->ProcessLineFast(Form("((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)this));
00255 else
00256 Paint();
00257 }
00258 }
00259
00260
00261 void TGL5DPainter::SetAlpha(Double_t newVal)
00262 {
00263
00264 if (fAlpha != newVal && !fData->fV4IsString) {
00265 fAlpha = newVal;
00266 fInit = kFALSE;
00267 InitGeometry();
00268 }
00269
00270 if (fData->fV4IsString)
00271 Warning("SetAlpha", "Alpha is not required for string data (your 4-th dimension is string).");
00272 }
00273
00274
00275 void TGL5DPainter::SetNContours(Int_t n)
00276 {
00277
00278
00279 if (n <= 0) {
00280 Warning("SetNContours", "Bad number of contours: %d", n);
00281 return;
00282 }
00283
00284 fNContours = n;
00285 fInit = kFALSE;
00286 InitGeometry();
00287 }
00288
00289
00290 void TGL5DPainter::ResetGeometryRanges()
00291 {
00292
00293
00294
00295
00296
00297 fCoord->SetRanges(fXAxis, fYAxis, fZAxis);
00298 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(),
00299 fCoord->GetYRangeScaled(),
00300 fCoord->GetZRangeScaled());
00301 if (fCamera)
00302 fCamera->SetViewVolume(fBackBox.Get3DBox());
00303
00304 for (SurfIter_t surf = fIsos.begin(); surf != fIsos.end(); ++surf) {
00305 fData->SelectPoints(surf->f4D, surf->fRange);
00306 fKDE.BuildModel(fData, 0.05);
00307 Info("TGL5DPainter::ResetGeometryRanges", "Building the mesh ...");
00308
00309 Rgl::Mc::TGridGeometry<Float_t> geom(fXAxis, fYAxis, fZAxis,
00310 fCoord->GetXScale(),
00311 fCoord->GetYScale(),
00312 fCoord->GetZScale());
00313 fMeshBuilder.SetGeometry(fData);
00314 Mesh_t &mesh = surf->fMesh;
00315
00316 mesh.fVerts.clear();
00317 mesh.fNorms.clear();
00318 mesh.fTris.clear();
00319
00320 fMeshBuilder.BuildMesh(&fKDE, geom, &mesh, 0.125);
00321 Info("TGL5DPainter::AddSurface", "Mesh has %d vertices", Int_t(mesh.fVerts.size() / 3));
00322 }
00323
00324 fBoxCut.ResetBoxGeometry();
00325 }
00326
00327
00328 TGL5DPainter::SurfIter_t TGL5DPainter::SurfacesBegin()
00329 {
00330
00331 return fIsos.begin();
00332 }
00333
00334
00335 TGL5DPainter::SurfIter_t TGL5DPainter::SurfacesEnd()
00336 {
00337
00338 return fIsos.end();
00339 }
00340
00341
00342 void TGL5DPainter::InitGL() const
00343 {
00344
00345 glEnable(GL_LIGHTING);
00346 glEnable(GL_LIGHT0);
00347 glEnable(GL_DEPTH_TEST);
00348 glDisable(GL_CULL_FACE);
00349 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
00350 }
00351
00352
00353 void TGL5DPainter::DeInitGL()const
00354 {
00355
00356 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
00357 glDisable(GL_CULL_FACE);
00358 glDisable(GL_DEPTH_TEST);
00359 glDisable(GL_LIGHT0);
00360 glDisable(GL_LIGHTING);
00361 }
00362
00363
00364 void TGL5DPainter::DrawPlot() const
00365 {
00366
00367
00368
00369 const Rgl::PlotTranslation trGuard(this);
00370
00371 fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
00372
00373 if (!fIsos.size())
00374 DrawCloud();
00375 else {
00376
00377 Bool_t needSecondPass = kFALSE;
00378 for (ConstSurfIter_t it = fIsos.begin(); it != fIsos.end(); ++it) {
00379
00380 if (it->fHide)
00381 continue;
00382 if (it->fAlpha != 100) {
00383 needSecondPass = kTRUE;
00384 continue;
00385 }
00386 if (!fSelectionPass)
00387 SetSurfaceColor(it);
00388 glEnable(GL_POLYGON_OFFSET_FILL);
00389 glPolygonOffset(1.f, 1.f);
00390 DrawMesh(it);
00391 glDisable(GL_POLYGON_OFFSET_FILL);
00392
00393 if (!fSelectionPass && it->fHighlight) {
00394 const TGLDisableGuard lightGuard(GL_LIGHTING);
00395 const TGLEnableGuard blendGuard(GL_BLEND);
00396 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00397 glColor4d(1., 0.4, 0., 0.5);
00398 DrawMesh(it);
00399 }
00400 }
00401
00402 if (needSecondPass) {
00403 const TGLEnableGuard blendGuard(GL_BLEND);
00404 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00405 glDepthMask(GL_FALSE);
00406 for (ConstSurfIter_t it = fIsos.begin(); it != fIsos.end(); ++it) {
00407
00408 if (it->fAlpha == 100)
00409 continue;
00410 if (!fSelectionPass)
00411 SetSurfaceColor(it);
00412
00413 glEnable(GL_POLYGON_OFFSET_FILL);
00414 glPolygonOffset(1.f, 1.f);
00415 DrawMesh(it);
00416 glDisable(GL_POLYGON_OFFSET_FILL);
00417
00418 if (!fSelectionPass && it->fHighlight) {
00419 const TGLDisableGuard lightGuard(GL_LIGHTING);
00420 glColor4d(1., 0.4, 0., it->fAlpha / 150.);
00421 DrawMesh(it);
00422 }
00423 }
00424 glDepthMask(GL_TRUE);
00425 }
00426 }
00427
00428 if (fBoxCut.IsActive())
00429 fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
00430 }
00431
00432
00433 void TGL5DPainter::SetSurfaceColor(ConstSurfIter_t it)const
00434 {
00435
00436 Color_t ind = it->fColor;
00437 Float_t rgba[] = {0.f, 0.f, 0.f, it->fAlpha / 100.};
00438 Rgl::Pad::ExtractRGB(ind, rgba);
00439
00440 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, rgba);
00441 const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
00442 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
00443 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.f);
00444 }
00445
00446
00447 void TGL5DPainter::DrawCloud()const
00448 {
00449
00450 const TGLDisableGuard light(GL_LIGHTING);
00451 const TGLDisableGuard depth(GL_DEPTH_TEST);
00452
00453 glColor3d(0.4, 0., 1.);
00454 glPointSize(3.f);
00455
00456 glBegin(GL_POINTS);
00457
00458 const Double_t xs = fCoord->GetXScale();
00459 const Double_t ys = fCoord->GetYScale();
00460 const Double_t zs = fCoord->GetZScale();
00461
00462 for (Int_t i = 0; i < fData->fNP; ++i)
00463 glVertex3d(fData->fV1[i] * xs, fData->fV2[i] * ys, fData->fV3[i] * zs);
00464
00465 glEnd();
00466
00467 glPointSize(1.f);
00468 }
00469
00470
00471 void TGL5DPainter::DrawSubCloud(Double_t v4, Double_t range, Color_t ci)const
00472 {
00473
00474 const TGLDisableGuard light(GL_LIGHTING);
00475
00476 Float_t rgb[3] = {};
00477 Rgl::Pad::ExtractRGB(ci, rgb);
00478
00479 glColor3fv(rgb);
00480 glPointSize(3.f);
00481
00482 glBegin(GL_POINTS);
00483
00484 const Double_t xs = fCoord->GetXScale();
00485 const Double_t ys = fCoord->GetYScale();
00486 const Double_t zs = fCoord->GetZScale();
00487
00488 for (Int_t i = 0; i < fData->fNP; ++i)
00489 if (TMath::Abs(fData->fV4[i] - v4) < range)
00490 glVertex3d(fData->fV1[i] * xs, fData->fV2[i] * ys, fData->fV3[i] * zs);
00491
00492 glEnd();
00493
00494 glPointSize(1.f);
00495 }
00496
00497
00498 void TGL5DPainter::DrawMesh(ConstSurfIter_t surf)const
00499 {
00500
00501
00502 const Mesh_t &m = surf->fMesh;
00503
00504 if (!fBoxCut.IsActive()) {
00505 if (!fSelectionPass)
00506 Rgl::DrawMesh(m.fVerts, m.fNorms, m.fTris);
00507 else {
00508 Rgl::ObjectIDToColor(fSelectionBase, fHighColor);
00509 Rgl::DrawMesh(m.fVerts, m.fTris);
00510 }
00511 } else {
00512 if (!fSelectionPass) {
00513 Rgl::DrawMesh(m.fVerts, m.fNorms, m.fTris, fBoxCut);
00514 } else {
00515 Rgl::ObjectIDToColor(fSelectionBase, fHighColor);
00516 Rgl::DrawMesh(m.fVerts, m.fTris, fBoxCut);
00517 }
00518 }
00519 }