36 TGL5DPainter::TGL5DPainter(TGL5DDataSet *data, TGLPlotCamera *camera, TGLPlotCoordinates *coord)
37 : TGLPlotPainter(data, camera, coord),
43 fNContours(kNContours)
45 if (fData->fV4IsString)
46 fNContours = Int_t(fData->fV4MinMax.second) - Int_t(fData->fV4MinMax.first) + 1;
54 TGL5DPainter::SurfIter_t TGL5DPainter::AddSurface(Double_t v4, Color_t ci,
55 Double_t iso, Double_t sigma,
56 Double_t range, Int_t lownps)
58 fData->SelectPoints(v4, range);
60 if (fData->SelectedSize() < size_type(lownps)) {
61 Warning(
"TGL5DPainter::AddSurface",
"Too little points: %d", Int_t(fData->SelectedSize()));
64 Info(
"TGL5DPainter::AddSurface",
"Selected %d points", Int_t(fData->SelectedSize()));
67 fKDE.BuildModel(fData, sigma);
69 Info(
"TGL5DPainter::AddSurface",
"Building the mesh ...");
71 Rgl::Mc::TGridGeometry<Float_t> geom(fXAxis, fYAxis, fZAxis,
76 fMeshBuilder.SetGeometry(fData);
78 fMeshBuilder.BuildMesh(&fKDE, geom, &mesh, iso);
80 Info(
"TGL5DPainter::AddSurface",
"Mesh has %d vertices", Int_t(mesh.fVerts.size() / 3));
82 if (!mesh.fVerts.size())
85 fIsos.push_front(fDummy);
87 fIsos.front().fMesh.Swap(mesh);
88 fIsos.front().f4D = v4;
89 fIsos.front().fRange = range;
90 fIsos.front().fShowCloud = kFALSE;
91 fIsos.front().fHide = kFALSE;
92 fIsos.front().fColor = ci;
102 void TGL5DPainter::AddSurface(Double_t v4)
104 const Rgl::Range_t &v4R = fData->fV4MinMax;
105 const Bool_t isString = fData->fV4IsString;
106 const Double_t rms = TMath::RMS(fData->fNP, fData->fV4);
107 const Double_t d = isString ? (v4R.second - v4R.first) / (fNContours - 1)
108 : 6 * rms / fNContours;
110 const Double_t range = isString ? 1e-3 : fAlpha * d;
112 AddSurface(v4, 1, 0.125, 0.05, range);
118 void TGL5DPainter::RemoveSurface(SurfIter_t surf)
120 if (surf == fIsos.end()) {
121 Error(
"TGL5DPainter::RemoveSurface",
"Invalid iterator, surface does not exist.");
131 char *TGL5DPainter::GetPlotInfo(Int_t , Int_t )
133 static char mess[] = {
"gl5d"};
143 Bool_t TGL5DPainter::InitGeometry()
148 fCoord->SetCoordType(kGLCartesian);
150 if (!fCoord->SetRanges(fXAxis, fYAxis, fZAxis))
155 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(),
156 fCoord->GetYRangeScaled(),
157 fCoord->GetZRangeScaled());
159 fCamera->SetViewVolume(fBackBox.Get3DBox());
161 const Rgl::Range_t &v4R = fData->fV4MinMax;
162 const Bool_t isString = fData->fV4IsString;
165 const Double_t mean = TMath::Mean(fData->fNP, fData->fV4);
166 const Double_t rms = TMath::RMS(fData->fNP, fData->fV4);
167 const Double_t min = isString ? v4R.first : mean - 3 * rms;
168 const Double_t d = isString ? (v4R.second - v4R.first) / (fNContours - 1)
169 : 6 * rms / fNContours;
171 const Double_t range = isString ? 1e-3 : fAlpha * d;
173 Info(
"InitGeometry",
"min = %g, mean = %g, rms = %g, dx = %g", min, mean, rms, d);
175 for (Int_t j = 0; j < fNContours; ++j) {
176 const Double_t isoLevel = min + j * d;
177 Info(
"TGL5DPainter::InitGeometry",
"Iso-level %g, range is %g ...", isoLevel, range);
178 const Color_t color = j * 6 + 1;
179 AddSurface(isoLevel, color, 0.125, 0.05, range);
185 return fInit = kTRUE;
191 void TGL5DPainter::StartPan(Int_t px, Int_t py)
193 fMousePosition.fX = px;
194 fMousePosition.fY = fCamera->GetHeight() - py;
195 fCamera->StartPan(px, py);
196 fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
202 void TGL5DPainter::Pan(Int_t px, Int_t py)
204 if (fSelectedPart >= fSelectionBase) {
205 SaveModelviewMatrix();
206 SaveProjectionMatrix();
208 fCamera->SetCamera();
209 fCamera->Apply(fPadPhi, fPadTheta);
210 fCamera->Pan(px, py);
212 RestoreProjectionMatrix();
213 RestoreModelviewMatrix();
214 }
else if (fSelectedPart > 0) {
216 py = fCamera->GetHeight() - py;
218 SaveModelviewMatrix();
219 SaveProjectionMatrix();
221 fCamera->SetCamera();
222 fCamera->Apply(fPadPhi, fPadTheta);
225 if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis)) {
226 fBoxCut.MoveBox(px, py, fSelectedPart);
230 RestoreProjectionMatrix();
231 RestoreModelviewMatrix();
234 fMousePosition.fX = px, fMousePosition.fY = py;
235 fUpdateSelection = kTRUE;
241 void TGL5DPainter::AddOption(
const TString &)
247 void TGL5DPainter::ProcessEvent(Int_t event, Int_t , Int_t py)
250 if (event == kKeyPress) {
251 if (py == kKey_c || py == kKey_C) {
253 Info(
"ProcessEvent",
"Cut box does not work in high color, please, switch to true color");
256 fUpdateSelection = kTRUE;
259 }
else if (event == kButton1Double && fBoxCut.IsActive()) {
260 if (fBoxCut.IsActive())
262 if (!gVirtualX->IsCmdThread())
263 gROOT->ProcessLineFast(Form(
"((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)
this));
272 void TGL5DPainter::SetAlpha(Double_t newVal)
274 if (fAlpha != newVal && !fData->fV4IsString) {
280 if (fData->fV4IsString)
281 Warning(
"SetAlpha",
"Alpha is not required for string data (your 4-th dimension is string).");
287 void TGL5DPainter::SetNContours(Int_t n)
290 Warning(
"SetNContours",
"Bad number of contours: %d", n);
306 void TGL5DPainter::ResetGeometryRanges()
308 fCoord->SetRanges(fXAxis, fYAxis, fZAxis);
309 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(),
310 fCoord->GetYRangeScaled(),
311 fCoord->GetZRangeScaled());
313 fCamera->SetViewVolume(fBackBox.Get3DBox());
315 for (SurfIter_t surf = fIsos.begin(); surf != fIsos.end(); ++surf) {
316 fData->SelectPoints(surf->f4D, surf->fRange);
317 fKDE.BuildModel(fData, 0.05);
318 Info(
"TGL5DPainter::ResetGeometryRanges",
"Building the mesh ...");
320 Rgl::Mc::TGridGeometry<Float_t> geom(fXAxis, fYAxis, fZAxis,
323 fCoord->GetZScale());
324 fMeshBuilder.SetGeometry(fData);
325 Mesh_t &mesh = surf->fMesh;
331 fMeshBuilder.BuildMesh(&fKDE, geom, &mesh, 0.125);
332 Info(
"TGL5DPainter::AddSurface",
"Mesh has %d vertices", Int_t(mesh.fVerts.size() / 3));
335 fBoxCut.ResetBoxGeometry();
341 TGL5DPainter::SurfIter_t TGL5DPainter::SurfacesBegin()
343 return fIsos.begin();
349 TGL5DPainter::SurfIter_t TGL5DPainter::SurfacesEnd()
357 void TGL5DPainter::InitGL()
const
359 glEnable(GL_LIGHTING);
361 glEnable(GL_DEPTH_TEST);
362 glDisable(GL_CULL_FACE);
363 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
369 void TGL5DPainter::DeInitGL()
const
371 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
372 glDisable(GL_CULL_FACE);
373 glDisable(GL_DEPTH_TEST);
374 glDisable(GL_LIGHT0);
375 glDisable(GL_LIGHTING);
381 void TGL5DPainter::DrawPlot()
const
384 const Rgl::PlotTranslation trGuard(
this);
386 fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
392 Bool_t needSecondPass = kFALSE;
393 for (ConstSurfIter_t it = fIsos.begin(); it != fIsos.end(); ++it) {
397 if (it->fAlpha != 100) {
398 needSecondPass = kTRUE;
403 glEnable(GL_POLYGON_OFFSET_FILL);
404 glPolygonOffset(1.f, 1.f);
406 glDisable(GL_POLYGON_OFFSET_FILL);
408 if (!fSelectionPass && it->fHighlight) {
409 const TGLDisableGuard lightGuard(GL_LIGHTING);
410 const TGLEnableGuard blendGuard(GL_BLEND);
411 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
412 glColor4d(1., 0.4, 0., 0.5);
417 if (needSecondPass) {
418 const TGLEnableGuard blendGuard(GL_BLEND);
419 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
420 glDepthMask(GL_FALSE);
421 for (ConstSurfIter_t it = fIsos.begin(); it != fIsos.end(); ++it) {
423 if (it->fAlpha == 100)
428 glEnable(GL_POLYGON_OFFSET_FILL);
429 glPolygonOffset(1.f, 1.f);
431 glDisable(GL_POLYGON_OFFSET_FILL);
433 if (!fSelectionPass && it->fHighlight) {
434 const TGLDisableGuard lightGuard(GL_LIGHTING);
435 glColor4d(1., 0.4, 0., it->fAlpha / 150.);
439 glDepthMask(GL_TRUE);
443 if (fBoxCut.IsActive())
444 fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
450 void TGL5DPainter::SetSurfaceColor(ConstSurfIter_t it)
const
452 Color_t ind = it->fColor;
453 Float_t rgba[] = {0.f, 0.f, 0.f,
static_cast<Float_t
>(it->fAlpha / 100.)};
454 Rgl::Pad::ExtractRGBA(ind, rgba);
456 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, rgba);
457 const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
458 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
459 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.f);
465 void TGL5DPainter::DrawCloud()
const
467 const TGLDisableGuard light(GL_LIGHTING);
468 const TGLDisableGuard depth(GL_DEPTH_TEST);
470 glColor3d(0.4, 0., 1.);
475 const Double_t xs = fCoord->GetXScale();
476 const Double_t ys = fCoord->GetYScale();
477 const Double_t zs = fCoord->GetZScale();
479 for (Int_t i = 0; i < fData->fNP; ++i)
480 glVertex3d(fData->fV1[i] * xs, fData->fV2[i] * ys, fData->fV3[i] * zs);
490 void TGL5DPainter::DrawSubCloud(Double_t v4, Double_t range, Color_t ci)
const
492 const TGLDisableGuard light(GL_LIGHTING);
494 Float_t rgba[4] = {};
495 Rgl::Pad::ExtractRGBA(ci, rgba);
502 const Double_t xs = fCoord->GetXScale();
503 const Double_t ys = fCoord->GetYScale();
504 const Double_t zs = fCoord->GetZScale();
506 for (Int_t i = 0; i < fData->fNP; ++i)
507 if (TMath::Abs(fData->fV4[i] - v4) < range)
508 glVertex3d(fData->fV1[i] * xs, fData->fV2[i] * ys, fData->fV3[i] * zs);
518 void TGL5DPainter::DrawMesh(ConstSurfIter_t surf)
const
520 const Mesh_t &m = surf->fMesh;
522 if (!fBoxCut.IsActive()) {
524 Rgl::DrawMesh(m.fVerts, m.fNorms, m.fTris);
526 Rgl::ObjectIDToColor(fSelectionBase, fHighColor);
527 Rgl::DrawMesh(m.fVerts, m.fTris);
530 if (!fSelectionPass) {
531 Rgl::DrawMesh(m.fVerts, m.fNorms, m.fTris, fBoxCut);
533 Rgl::ObjectIDToColor(fSelectionBase, fHighColor);
534 Rgl::DrawMesh(m.fVerts, m.fTris, fBoxCut);