41 void ReplaceUVNames(
TString &equation)
49 for (
Ssiz_t i = 0; i < len;) {
50 const char c = equation[i];
56 if (c ==
'u' || c ==
'v') {
59 if (i == len || (!isalpha(equation[i]) && !isdigit(equation[i]) && equation[i] !=
'_')) {
61 equation[i - 1] = c ==
'u' ?
'x' : (++vFound,
'y');
65 while (i < len && (isalpha(equation[i]) || isdigit(equation[i]) || equation[i] ==
'_'))
69 while (i < len && (isalpha(equation[i]) || isdigit(equation[i]) || equation[i] ==
'_'))
134 if (!xFun.Length() || !yFun.Length() || !zFun.Length()) {
135 Error(
"TGLParametricEquation",
"One of string expressions is empty");
140 TString equation(xFun);
142 ReplaceUVNames(equation);
143 fXEquation.reset(
new TF2(name +
"xEquation", equation.Data(), uMin, uMax, vMin, vMax));
145 if (fXEquation->IsZombie()) {
152 ReplaceUVNames(equation);
153 fYEquation.reset(
new TF2(name +
"yEquation", equation.Data(), uMin, uMax, vMin, vMax));
155 if (fYEquation->IsZombie()) {
162 ReplaceUVNames(equation);
163 fZEquation.reset(
new TF2(name +
"zEquation", equation.Data(), uMin, uMax, vMin, vMax));
165 if (fZEquation->IsZombie())
182 Error(
"TGLParametricEquation",
"Function ptr is null");
257 return fPainter->DistancetoPrimitive(px, py);
267 return fPainter->ExecuteEvent(event, px, py);
275 static char mess[] = {
"parametric surface" };
306 fXAxis = &fCartesianXAxis;
307 fYAxis = &fCartesianYAxis;
308 fZAxis = &fCartesianZAxis;
310 fCoord = &fCartesianCoord;
326 if (fMeshSize * fMeshSize != (
Int_t)fMesh.size() ||
fEquation->IsModified()) {
332 fMesh.resize(fMeshSize * fMeshSize);
333 fMesh.SetRowLen(fMeshSize);
338 const Double_t dU = (uRange.second - uRange.first) / (fMeshSize - 1);
339 const Double_t dV = (vRange.second - vRange.first) / (fMeshSize - 1);
344 fEquation->EvalVertex(min, uRange.first, vRange.first);
346 using namespace TMath;
348 for (
Int_t i = 0; i < fMeshSize; ++i) {
350 for (
Int_t j = 0; j < fMeshSize; ++j) {
352 min.
X() =
Min(min.
X(), newVert.
X());
353 max.X() =
Max(max.X(), newVert.
X());
354 min.
Y() =
Min(min.
Y(), newVert.
Y());
355 max.Y() =
Max(max.Y(), newVert.
Y());
356 min.
Z() =
Min(min.
Z(), newVert.
Z());
357 max.Z() =
Max(max.Z(), newVert.
Z());
359 fMesh[i][j].fPos = newVert;
366 TH3F hist(
"tmp",
"tmp", 2, -1., 1., 2, -1., 1., 2, -1., 1.);
375 fCartesianXAxis.Set(fMeshSize, min.
X(), max.X());
376 fCartesianXAxis.SetTitle(
"x");
377 fCartesianYAxis.Set(fMeshSize, min.
Y(), max.Y());
378 fCartesianYAxis.SetTitle(
"y");
379 fCartesianZAxis.Set(fMeshSize, min.
Z(), max.Z());
380 fCartesianZAxis.SetTitle(
"z");
382 if (!fCoord->SetRanges(&fCartesianXAxis, &fCartesianYAxis, &fCartesianZAxis))
385 for (
Int_t i = 0; i < fMeshSize; ++i) {
386 for (
Int_t j = 0; j < fMeshSize; ++j) {
388 ver.
X() *= fCoord->GetXScale(), ver.
Y() *= fCoord->GetYScale(), ver.
Z() *= fCoord->GetZScale();
393 for (
Int_t i = 0; i < fMeshSize; ++i) {
395 for (
Int_t j = 0; j < fMeshSize; ++j) {
399 v1.
X() *= fCoord->GetXScale(), v1.
Y() *= fCoord->GetYScale(), v1.
Z() *= fCoord->GetZScale();
400 v2.
X() *= fCoord->GetXScale(), v2.
Y() *= fCoord->GetYScale(), v2.
Z() *= fCoord->GetZScale();
407 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(),
408 fCoord->GetYRangeScaled(),
409 fCoord->GetZRangeScaled());
410 if (fCamera) fCamera->SetViewVolume(fBackBox.Get3DBox());
421 fMousePosition.fX = px;
422 fMousePosition.fY = fCamera->GetHeight() - py;
423 fCamera->StartPan(px, py);
424 fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
434 SaveModelviewMatrix();
435 SaveProjectionMatrix();
437 fCamera->SetCamera();
438 fCamera->Apply(fPadPhi, fPadTheta);
440 if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis))
441 fBoxCut.MoveBox(px, fCamera->GetHeight() - py, fSelectedPart);
443 fCamera->Pan(px, py);
445 RestoreProjectionMatrix();
446 RestoreModelviewMatrix();
449 fUpdateSelection =
kTRUE;
457 static char mess[] = {
"parametric surface" };
477 gROOT->ProcessLineFast(
Form(
"((TGLPlotPainter *)0x%lx)->Paint()", (
ULong_t)
this));
483 Info(
"ProcessEvent",
"Switch to true color to use box cut");
486 fUpdateSelection =
kTRUE;
489 fColorScheme == 20 ? fColorScheme = -1 : ++fColorScheme;
492 fShowMesh = !fShowMesh;
494 fMeshSize ==
kHigh ? fMeshSize = kLow : fMeshSize += 15;
506 glEnable(GL_DEPTH_TEST);
507 glEnable(GL_LIGHTING);
509 glDisable(GL_CULL_FACE);
510 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
518 glDisable(GL_DEPTH_TEST);
519 glDisable(GL_LIGHTING);
520 glDisable(GL_LIGHT0);
521 glDisable(GL_CULL_FACE);
522 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
533 if (!fSelectionPass) {
536 glEnable(GL_POLYGON_OFFSET_FILL);
537 glPolygonOffset(1.
f, 1.
f);
543 glBegin(GL_TRIANGLES);
545 for (
Int_t i = 0; i < fMeshSize - 1; ++i) {
546 for (
Int_t j = 0; j < fMeshSize - 1; ++j) {
547 if (fBoxCut.IsActive()) {
550 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()));
551 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()));
552 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()));
553 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()));
554 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()));
555 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()));
557 if (fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
561 glNormal3dv(fMesh[i + 1][j + 1].fNormal.CArr());
562 if(fColorScheme != -1)
563 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i + 1][j + 1].fRGBA);
564 glVertex3dv(fMesh[i + 1][j + 1].fPos.CArr());
566 glNormal3dv(fMesh[i][j + 1].fNormal.CArr());
567 if(fColorScheme != -1)
568 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i][j + 1].fRGBA);
569 glVertex3dv(fMesh[i][j + 1].fPos.CArr());
571 glNormal3dv(fMesh[i][j].fNormal.CArr());
572 if(fColorScheme != -1)
573 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i][j].fRGBA);
574 glVertex3dv(fMesh[i][j].fPos.CArr());
576 glNormal3dv(fMesh[i + 1][j].fNormal.CArr());
577 if(fColorScheme != -1)
578 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i + 1][j].fRGBA);
579 glVertex3dv(fMesh[i + 1][j].fPos.CArr());
581 glNormal3dv(fMesh[i + 1][j + 1].fNormal.CArr());
582 if(fColorScheme != -1)
583 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i + 1][j + 1].fRGBA);
584 glVertex3dv(fMesh[i + 1][j + 1].fPos.CArr());
586 glNormal3dv(fMesh[i][j].fNormal.CArr());
587 if(fColorScheme != -1)
588 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i][j].fRGBA);
589 glVertex3dv(fMesh[i][j].fPos.CArr());
595 if (!fSelectionPass && fShowMesh) {
596 glDisable(GL_POLYGON_OFFSET_FILL);
601 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
602 glColor4d(0., 0., 0., 0.5);
603 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
605 for (
Int_t i = 0; i < fMeshSize - 1; ++i) {
606 for (
Int_t j = 0; j < fMeshSize - 1; ++j) {
607 if (fBoxCut.IsActive()) {
610 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()));
611 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()));
612 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()));
613 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()));
614 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()));
615 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()));
617 if (fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
621 glVertex3dv(fMesh[i][j].fPos.CArr());
622 glVertex3dv(fMesh[i][j + 1].fPos.CArr());
623 glVertex3dv(fMesh[i + 1][j + 1].fPos.CArr());
624 glVertex3dv(fMesh[i + 1][j].fPos.CArr());
629 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
632 if (fBoxCut.IsActive())
633 fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
643 if (fColorScheme == -1)
648 const Float_t dU =
Float_t((uRange.second - uRange.first) / (fMeshSize - 1));
651 for (
Int_t i = 0; i < fMeshSize; ++i) {
652 for (
Int_t j = 0; j < fMeshSize; ++j)
653 Rgl::GetColor(u, uRange.first, uRange.second, fColorScheme, fMesh[i][j].fRGBA);
684 const Float_t specular[] = {1.f, 1.f, 1.f, 1.f};
685 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
686 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.
f);
688 if (fColorScheme == -1) {
689 const Float_t outerDiff[] = {0.5f, 0.42f, 0.f, 1.f};
690 glMaterialfv(GL_FRONT, GL_DIFFUSE, outerDiff);
691 const Float_t innerDiff[] = {0.5f, 0.2f, 0.f, 1.f};
692 glMaterialfv(GL_BACK, GL_DIFFUSE, innerDiff);
ParametricEquation_t fEquation
Camera for TGLPlotPainter and sub-classes.
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
void Pan(Int_t px, Int_t py)
User's moving mouse cursor, with middle mouse button pressed (for pad).
virtual void SetDirectory(TDirectory *dir)
By default when an histogram is created, it is added to the list of histogram objects in the current ...
tomato 3-D histogram with a float per channel (see TH1 documentation)}
std::pair< Double_t, Double_t > Range_t
void DrawSectionXOY() const
No such sections.
Bool_t IsConstrained() const
Check is constrained.
Rgl::Range_t GetURange() const
[uMin, uMax]
void SetConstrained(Bool_t c)
Set constrained.
Short_t Min(Short_t a, Short_t b)
void EvalVertex(TGLVertex3 &newVertex, Double_t u, Double_t v) const
Calculate vertex.
Int_t DistancetoPrimitive(Int_t px, Int_t py)
Check, if parametric surface is under cursor.
virtual void Copy(TObject &axis) const
Copy axis structure to another axis.
T * Normal2Plane(const T v1[3], const T v2[3], const T v3[3], T normal[3])
void DrawSectionYOZ() const
No such sections.
3 component (x/y/z) vertex class.
The TNamed class is the base class for all named ROOT classes.
TGLParametricEquation(const TString &name, const TString &xEquation, const TString &yEquation, const TString &zEquation, Double_t uMin, Double_t uMax, Double_t vMin, Double_t vMax)
Surface is defined by three strings.
static const Float_t kHigh
void Error(const char *location, const char *msgfmt,...)
Rgl::Range_t GetVRange() const
[vMin, vMax]
void ObjectIDToColor(Int_t objectID, Bool_t highColor)
Object id encoded as rgb triplet.
Bool_t IsModified() const
Something was changed in parametric equation (or constrained option was changed). ...
void SetSurfaceColor() const
Set material properties.
void DrawSectionXOZ() const
No such sections.
void(* ParametricEquation_t)(TGLVertex3 &, Double_t u, Double_t v)
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
char * Form(const char *fmt,...)
A parametric surface is a surface defined by a parametric equation, involving two parameters (u...
A 2-Dim function with parameters.
Base class for plot-painters that provide GL rendering of various 2D and 3D histograms, functions and parametric surfaces.
void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Pass event to painter.
Bool_t InitGeometry()
Build mesh.
void InitGL() const
Initialize gl state.
void AddOption(const TString &option)
No additional options for parametric surfaces.
The histogram painter class using OpenGL.
void GetColor(Float_t v, Float_t vmin, Float_t vmax, Int_t type, Float_t *rgba)
This function creates color for parametric surface's vertex, using its 'u' value. ...
void StartPan(Int_t px, Int_t py)
User clicks right mouse button (in a pad).
const Double_t * CArr() const
void Paint(Option_t *option)
Delegate paint.
void SetModified(Bool_t m)
Set modified.
Short_t Max(Short_t a, Short_t b)
void DrawPlot() const
Draw parametric surface.
void ProcessEvent(Int_t event, Int_t px, Int_t py)
Change color/mesh size or switch on/off mesh/box cut.
void InitColors()
Calculate colors for vertices, using one of 20 color themes.
char * GetObjectInfo(Int_t px, Int_t py) const
No object info yet.
void DeInitGL() const
Initialize gl state.
char * GetPlotInfo(Int_t px, Int_t py)
No object info yet.