43 void ReplaceUVNames(TString &equation)
46 const Ssiz_t len = equation.Length();
51 for (Ssiz_t i = 0; i < len;) {
52 const char c = equation[i];
58 if (c ==
'u' || c ==
'v') {
61 if (i == len || (!isalpha(equation[i]) && !isdigit(equation[i]) && equation[i] !=
'_')) {
63 equation[i - 1] = c ==
'u' ?
'x' : (++vFound,
'y');
67 while (i < len && (isalpha(equation[i]) || isdigit(equation[i]) || equation[i] ==
'_'))
71 while (i < len && (isalpha(equation[i]) || isdigit(equation[i]) || equation[i] ==
'_'))
118 ClassImp(TGLParametricEquation);
126 TGLParametricEquation::TGLParametricEquation(
const TString &name,
const TString &xFun,
const TString &yFun,
127 const TString &zFun, Double_t uMin, Double_t uMax,
128 Double_t vMin, Double_t vMax)
129 : TNamed(name, name),
133 fConstrained(kFALSE),
136 if (!xFun.Length() || !yFun.Length() || !zFun.Length()) {
137 Error(
"TGLParametricEquation",
"One of string expressions is empty");
142 TString equation(xFun);
144 ReplaceUVNames(equation);
145 fXEquation.reset(
new TF2(name +
"xEquation", equation.Data(), uMin, uMax, vMin, vMax));
147 if (fXEquation->IsZombie()) {
154 ReplaceUVNames(equation);
155 fYEquation.reset(
new TF2(name +
"yEquation", equation.Data(), uMin, uMax, vMin, vMax));
157 if (fYEquation->IsZombie()) {
164 ReplaceUVNames(equation);
165 fZEquation.reset(
new TF2(name +
"zEquation", equation.Data(), uMin, uMax, vMin, vMax));
167 if (fZEquation->IsZombie())
174 TGLParametricEquation::TGLParametricEquation(
const TString &name, ParametricEquation_t equation,
175 Double_t uMin, Double_t uMax, Double_t vMin, Double_t vMax)
176 : TNamed(name, name),
180 fConstrained(kFALSE),
184 Error(
"TGLParametricEquation",
"Function ptr is null");
192 Rgl::Range_t TGLParametricEquation::GetURange()
const
200 Rgl::Range_t TGLParametricEquation::GetVRange()
const
208 Bool_t TGLParametricEquation::IsConstrained()
const
216 void TGLParametricEquation::SetConstrained(Bool_t c)
224 Bool_t TGLParametricEquation::IsModified()
const
232 void TGLParametricEquation::SetModified(Bool_t m)
240 void TGLParametricEquation::EvalVertex(TGLVertex3 &newVertex, Double_t u, Double_t v)
const
243 return fEquation(newVertex, u, v);
248 newVertex.X() = fXEquation->Eval(u, v);
249 newVertex.Y() = fYEquation->Eval(u, v);
250 newVertex.Z() = fZEquation->Eval(u, v);
256 Int_t TGLParametricEquation::DistancetoPrimitive(Int_t px, Int_t py)
259 return fPainter->DistancetoPrimitive(px, py);
266 void TGLParametricEquation::ExecuteEvent(Int_t event, Int_t px, Int_t py)
269 return fPainter->ExecuteEvent(event, px, py);
275 char *TGLParametricEquation::GetObjectInfo(Int_t , Int_t )
const
277 static char mess[] = {
"parametric surface" };
284 void TGLParametricEquation::Paint(Option_t * )
287 fPainter.reset(
new TGLHistPainter(
this));
288 fPainter->Paint(
"dummyoption");
295 ClassImp(TGLParametricPlot);
300 TGLParametricPlot::TGLParametricPlot(TGLParametricEquation *eq,
301 TGLPlotCamera *camera)
302 : TGLPlotPainter(camera),
308 fXAxis = &fCartesianXAxis;
309 fYAxis = &fCartesianYAxis;
310 fZAxis = &fCartesianZAxis;
312 fCoord = &fCartesianCoord;
324 Bool_t TGLParametricPlot::InitGeometry()
328 if (fMeshSize * fMeshSize != (Int_t)fMesh.size() || fEquation->IsModified()) {
329 if (fEquation->IsZombie())
332 fEquation->SetModified(kFALSE);
334 fMesh.resize(fMeshSize * fMeshSize);
335 fMesh.SetRowLen(fMeshSize);
337 const Rgl::Range_t uRange(fEquation->GetURange());
338 const Rgl::Range_t vRange(fEquation->GetVRange());
340 const Double_t dU = (uRange.second - uRange.first) / (fMeshSize - 1);
341 const Double_t dV = (vRange.second - vRange.first) / (fMeshSize - 1);
342 const Double_t dd = 0.001;
343 Double_t u = uRange.first;
346 fEquation->EvalVertex(min, uRange.first, vRange.first);
347 TGLVertex3 max(min), newVert, v1, v2;
348 using namespace TMath;
350 for (Int_t i = 0; i < fMeshSize; ++i) {
351 Double_t v = vRange.first;
352 for (Int_t j = 0; j < fMeshSize; ++j) {
353 fEquation->EvalVertex(newVert, u, v);
354 min.X() = Min(min.X(), newVert.X());
355 max.X() = Max(max.X(), newVert.X());
356 min.Y() = Min(min.Y(), newVert.Y());
357 max.Y() = Max(max.Y(), newVert.Y());
358 min.Z() = Min(min.Z(), newVert.Z());
359 max.Z() = Max(max.Z(), newVert.Z());
361 fMesh[i][j].fPos = newVert;
368 TH3F hist(
"tmp",
"tmp", 2, -1., 1., 2, -1., 1., 2, -1., 1.);
369 hist.SetDirectory(0);
373 hist.GetXaxis()->Copy(fCartesianXAxis);
374 hist.GetYaxis()->Copy(fCartesianYAxis);
375 hist.GetZaxis()->Copy(fCartesianZAxis);
377 fCartesianXAxis.Set(fMeshSize, min.X(), max.X());
378 fCartesianXAxis.SetTitle(
"x");
379 fCartesianYAxis.Set(fMeshSize, min.Y(), max.Y());
380 fCartesianYAxis.SetTitle(
"y");
381 fCartesianZAxis.Set(fMeshSize, min.Z(), max.Z());
382 fCartesianZAxis.SetTitle(
"z");
384 if (!fCoord->SetRanges(&fCartesianXAxis, &fCartesianYAxis, &fCartesianZAxis))
387 for (Int_t i = 0; i < fMeshSize; ++i) {
388 for (Int_t j = 0; j < fMeshSize; ++j) {
389 TGLVertex3 &ver = fMesh[i][j].fPos;
390 ver.X() *= fCoord->GetXScale(), ver.Y() *= fCoord->GetYScale(), ver.Z() *= fCoord->GetZScale();
395 for (Int_t i = 0; i < fMeshSize; ++i) {
396 Double_t v = vRange.first;
397 for (Int_t j = 0; j < fMeshSize; ++j) {
398 TGLVertex3 &ver = fMesh[i][j].fPos;
399 fEquation->EvalVertex(v1, u + dd, v);
400 fEquation->EvalVertex(v2, u, v + dd);
401 v1.X() *= fCoord->GetXScale(), v1.Y() *= fCoord->GetYScale(), v1.Z() *= fCoord->GetZScale();
402 v2.X() *= fCoord->GetXScale(), v2.Y() *= fCoord->GetYScale(), v2.Z() *= fCoord->GetZScale();
403 Normal2Plane(ver.CArr(), v1.CArr(), v2.CArr(), fMesh[i][j].fNormal.Arr());
409 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(),
410 fCoord->GetYRangeScaled(),
411 fCoord->GetZRangeScaled());
412 if (fCamera) fCamera->SetViewVolume(fBackBox.Get3DBox());
421 void TGLParametricPlot::StartPan(Int_t px, Int_t py)
423 fMousePosition.fX = px;
424 fMousePosition.fY = fCamera->GetHeight() - py;
425 fCamera->StartPan(px, py);
426 fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
433 void TGLParametricPlot::Pan(Int_t px, Int_t py)
436 SaveModelviewMatrix();
437 SaveProjectionMatrix();
439 fCamera->SetCamera();
440 fCamera->Apply(fPadPhi, fPadTheta);
442 if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis))
443 fBoxCut.MoveBox(px, fCamera->GetHeight() - py, fSelectedPart);
445 fCamera->Pan(px, py);
447 RestoreProjectionMatrix();
448 RestoreModelviewMatrix();
451 fUpdateSelection = kTRUE;
457 char *TGLParametricPlot::GetPlotInfo(Int_t , Int_t )
459 static char mess[] = {
"parametric surface" };
466 void TGLParametricPlot::AddOption(
const TString &)
474 void TGLParametricPlot::ProcessEvent(Int_t event, Int_t , Int_t py)
476 if (event == kButton1Double && fBoxCut.IsActive()) {
478 if (!gVirtualX->IsCmdThread())
479 gROOT->ProcessLineFast(Form(
"((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)
this));
482 }
else if (event == kKeyPress) {
483 if (py == kKey_c || py == kKey_C) {
485 Info(
"ProcessEvent",
"Switch to true color to use box cut");
488 fUpdateSelection = kTRUE;
490 }
else if (py == kKey_s || py == kKey_S) {
491 fColorScheme == 20 ? fColorScheme = -1 : ++fColorScheme;
493 }
else if (py == kKey_w || py == kKey_W) {
494 fShowMesh = !fShowMesh;
495 }
else if (py == kKey_l || py == kKey_L) {
496 fMeshSize == kHigh ? fMeshSize = kLow : fMeshSize += 15;
506 void TGLParametricPlot::InitGL()
const
508 glEnable(GL_DEPTH_TEST);
509 glEnable(GL_LIGHTING);
511 glDisable(GL_CULL_FACE);
512 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
518 void TGLParametricPlot::DeInitGL()
const
520 glDisable(GL_DEPTH_TEST);
521 glDisable(GL_LIGHTING);
522 glDisable(GL_LIGHT0);
523 glDisable(GL_CULL_FACE);
524 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
530 void TGLParametricPlot::DrawPlot()
const
533 const Rgl::PlotTranslation trGuard(
this);
535 if (!fSelectionPass) {
538 glEnable(GL_POLYGON_OFFSET_FILL);
539 glPolygonOffset(1.f, 1.f);
542 Rgl::ObjectIDToColor(fSelectionBase, fHighColor);
545 glBegin(GL_TRIANGLES);
547 for (Int_t i = 0; i < fMeshSize - 1; ++i) {
548 for (Int_t j = 0; j < fMeshSize - 1; ++j) {
549 if (fBoxCut.IsActive()) {
552 const Double_t xMin = Min(Min(fMesh[i][j].fPos.X(), fMesh[i + 1][j].fPos.X()), Min(fMesh[i][j + 1].fPos.X(), fMesh[i + 1][j + 1].fPos.X()));
553 const Double_t xMax = Max(Max(fMesh[i][j].fPos.X(), fMesh[i + 1][j].fPos.X()), Max(fMesh[i][j + 1].fPos.X(), fMesh[i + 1][j + 1].fPos.X()));
554 const Double_t yMin = Min(Min(fMesh[i][j].fPos.Y(), fMesh[i + 1][j].fPos.Y()), Min(fMesh[i][j + 1].fPos.Y(), fMesh[i + 1][j + 1].fPos.Y()));
555 const Double_t yMax = Max(Max(fMesh[i][j].fPos.Y(), fMesh[i + 1][j].fPos.Y()), Max(fMesh[i][j + 1].fPos.Y(), fMesh[i + 1][j + 1].fPos.Y()));
556 const Double_t zMin = Min(Min(fMesh[i][j].fPos.Z(), fMesh[i + 1][j].fPos.Z()), Min(fMesh[i][j + 1].fPos.Z(), fMesh[i + 1][j + 1].fPos.Z()));
557 const Double_t zMax = Max(Max(fMesh[i][j].fPos.Z(), fMesh[i + 1][j].fPos.Z()), Max(fMesh[i][j + 1].fPos.Z(), fMesh[i + 1][j + 1].fPos.Z()));
559 if (fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
563 glNormal3dv(fMesh[i + 1][j + 1].fNormal.CArr());
564 if(fColorScheme != -1)
565 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i + 1][j + 1].fRGBA);
566 glVertex3dv(fMesh[i + 1][j + 1].fPos.CArr());
568 glNormal3dv(fMesh[i][j + 1].fNormal.CArr());
569 if(fColorScheme != -1)
570 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i][j + 1].fRGBA);
571 glVertex3dv(fMesh[i][j + 1].fPos.CArr());
573 glNormal3dv(fMesh[i][j].fNormal.CArr());
574 if(fColorScheme != -1)
575 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i][j].fRGBA);
576 glVertex3dv(fMesh[i][j].fPos.CArr());
578 glNormal3dv(fMesh[i + 1][j].fNormal.CArr());
579 if(fColorScheme != -1)
580 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i + 1][j].fRGBA);
581 glVertex3dv(fMesh[i + 1][j].fPos.CArr());
583 glNormal3dv(fMesh[i + 1][j + 1].fNormal.CArr());
584 if(fColorScheme != -1)
585 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i + 1][j + 1].fRGBA);
586 glVertex3dv(fMesh[i + 1][j + 1].fPos.CArr());
588 glNormal3dv(fMesh[i][j].fNormal.CArr());
589 if(fColorScheme != -1)
590 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i][j].fRGBA);
591 glVertex3dv(fMesh[i][j].fPos.CArr());
597 if (!fSelectionPass && fShowMesh) {
598 glDisable(GL_POLYGON_OFFSET_FILL);
599 const TGLDisableGuard lightGuard(GL_LIGHTING);
600 const TGLEnableGuard blendGuard(GL_BLEND);
601 const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
603 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
604 glColor4d(0., 0., 0., 0.5);
605 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
607 for (Int_t i = 0; i < fMeshSize - 1; ++i) {
608 for (Int_t j = 0; j < fMeshSize - 1; ++j) {
609 if (fBoxCut.IsActive()) {
612 const Double_t xMin = Min(Min(fMesh[i][j].fPos.X(), fMesh[i + 1][j].fPos.X()), Min(fMesh[i][j + 1].fPos.X(), fMesh[i + 1][j + 1].fPos.X()));
613 const Double_t xMax = Max(Max(fMesh[i][j].fPos.X(), fMesh[i + 1][j].fPos.X()), Max(fMesh[i][j + 1].fPos.X(), fMesh[i + 1][j + 1].fPos.X()));
614 const Double_t yMin = Min(Min(fMesh[i][j].fPos.Y(), fMesh[i + 1][j].fPos.Y()), Min(fMesh[i][j + 1].fPos.Y(), fMesh[i + 1][j + 1].fPos.Y()));
615 const Double_t yMax = Max(Max(fMesh[i][j].fPos.Y(), fMesh[i + 1][j].fPos.Y()), Max(fMesh[i][j + 1].fPos.Y(), fMesh[i + 1][j + 1].fPos.Y()));
616 const Double_t zMin = Min(Min(fMesh[i][j].fPos.Z(), fMesh[i + 1][j].fPos.Z()), Min(fMesh[i][j + 1].fPos.Z(), fMesh[i + 1][j + 1].fPos.Z()));
617 const Double_t zMax = Max(Max(fMesh[i][j].fPos.Z(), fMesh[i + 1][j].fPos.Z()), Max(fMesh[i][j + 1].fPos.Z(), fMesh[i + 1][j + 1].fPos.Z()));
619 if (fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
623 glVertex3dv(fMesh[i][j].fPos.CArr());
624 glVertex3dv(fMesh[i][j + 1].fPos.CArr());
625 glVertex3dv(fMesh[i + 1][j + 1].fPos.CArr());
626 glVertex3dv(fMesh[i + 1][j].fPos.CArr());
631 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
634 if (fBoxCut.IsActive())
635 fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
643 void TGLParametricPlot::InitColors()
645 if (fColorScheme == -1)
648 const Rgl::Range_t uRange(fEquation->GetURange());
650 const Float_t dU = Float_t((uRange.second - uRange.first) / (fMeshSize - 1));
651 Float_t u = Float_t(uRange.first);
653 for (Int_t i = 0; i < fMeshSize; ++i) {
654 for (Int_t j = 0; j < fMeshSize; ++j)
655 Rgl::GetColor(u, uRange.first, uRange.second, fColorScheme, fMesh[i][j].fRGBA);
663 void TGLParametricPlot::DrawSectionXOZ()
const
670 void TGLParametricPlot::DrawSectionYOZ()
const
677 void TGLParametricPlot::DrawSectionXOY()
const
684 void TGLParametricPlot::SetSurfaceColor()
const
686 const Float_t specular[] = {1.f, 1.f, 1.f, 1.f};
687 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
688 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.f);
690 if (fColorScheme == -1) {
691 const Float_t outerDiff[] = {0.5f, 0.42f, 0.f, 1.f};
692 glMaterialfv(GL_FRONT, GL_DIFFUSE, outerDiff);
693 const Float_t innerDiff[] = {0.5f, 0.2f, 0.f, 1.f};
694 glMaterialfv(GL_BACK, GL_DIFFUSE, innerDiff);