SeExpr
ExprGrapher2d.cpp
Go to the documentation of this file.
1/*
2* Copyright Disney Enterprises, Inc. All rights reserved.
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License
6* and the following modification to it: Section 6 Trademarks.
7* deleted and replaced with:
8*
9* 6. Trademarks. This License does not grant permission to use the
10* trade names, trademarks, service marks, or product names of the
11* Licensor and its affiliates, except as required for reproducing
12* the content of the NOTICE file.
13*
14* You may obtain a copy of the License at
15* http://www.apache.org/licenses/LICENSE-2.0
16*
17* @file ExprGrapher2d.cpp
18* @brief A 2d image graph view for expression editing previewing
19* @author jlacewel
20*/
21
22#include "ExprGrapher2d.h"
23#include <QGridLayout>
24#include <QLineEdit>
25#include <QDoubleValidator>
26#include <QHBoxLayout>
27#include <QLabel>
28
29ExprGrapherWidget::ExprGrapherWidget(QWidget* parent, int width, int height)
30 : view(new ExprGrapherView(*this, this, width, height)), expr("", SeExpr2::ExprType().FP(1)) {
31 Q_UNUSED(parent);
32 setFixedSize(width, height + 30);
33 QVBoxLayout* vbox = new QVBoxLayout;
34 vbox->setMargin(0);
35 setLayout(vbox);
36 vbox->addWidget(view, 0, Qt::AlignLeft | Qt::AlignTop);
37 QHBoxLayout* hbox = new QHBoxLayout;
38 vbox->addLayout(hbox);
39 hbox->setMargin(0);
40
41 float xmin, xmax, ymin, ymax, z;
42 view->getWindow(xmin, xmax, ymin, ymax, z);
43 scale = new QLineEdit();
44 QDoubleValidator* valValidator = new QDoubleValidator(0.0, 10000000.0, 6, scale);
45 scale->setValidator(valValidator);
46 scale->setValidator(valValidator);
48
49 connect(scale, SIGNAL(returnPressed()), this, SLOT(scaleValueEdited()));
50 connect(view, SIGNAL(scaleValueManipulated()), this, SLOT(scaleValueManipulated()));
51 connect(view, SIGNAL(clicked()), this, SLOT(forwardPreview()));
52
53 hbox->addWidget(new QLabel("Width"), 0);
54 hbox->addWidget(scale, 0);
55}
56
58 float xmin, xmax, ymin, ymax, z;
59 view->getWindow(xmin, xmax, ymin, ymax, z);
60 float xdiff = xmax - xmin, ydiff = ymax - ymin;
61 float xcenter = .5 * (xmax + xmin), ycenter = .5 * (ymin + ymax);
62 float newScale = atof(scale->text().toStdString().c_str());
63
64 float aspect = ydiff / xdiff;
65
66 xmin = xcenter - newScale;
67 xmax = xcenter + newScale;
68 ymin = ycenter - aspect * newScale;
69 ymax = ycenter + aspect * newScale;
70 view->setWindow(xmin, xmax, ymin, ymax, z);
71}
72
74 float xmin, xmax, ymin, ymax, z;
75 view->getWindow(xmin, xmax, ymin, ymax, z);
76 scale->setText(QString("%1").arg(.5 * (xmax - xmin)));
77}
78
81
82 view->update();
83}
84
86
87ExprGrapherView::ExprGrapherView(ExprGrapherWidget& widget, QWidget* parent, int width, int height)
88 : QGLWidget(parent), widget(widget), _image(NULL), _width(width), _height(height), scaling(false),
89 translating(false) {
90 this->setFixedSize(width, height);
91
92 _image = new float[3 * _width * _height];
93 setWindow(-1, 1, -1, 1, 0);
94 clear();
95
96 setCursor(Qt::OpenHandCursor);
97}
98
100
101void ExprGrapherView::setWindow(float xmin, float xmax, float ymin, float ymax, float z) {
102 this->z = z;
103 this->xmin = xmin;
104 this->xmax = xmax;
105 this->ymin = ymin;
106 this->ymax = ymax;
107
108 dx = (xmax - xmin) / _width;
109 dy = (ymax - ymin) / _height;
110}
111
112void ExprGrapherView::getWindow(float& xmin, float& xmax, float& ymin, float& ymax, float& z) {
113 z = this->z;
114 xmin = this->xmin;
115 xmax = this->xmax;
116 ymin = this->ymin;
117 ymax = this->ymax;
118}
119
121 for (int row = 0; row < _height; ++row) {
122 for (int col = 0; col < _width; ++col) {
123 int index = 3 * row * _width + 3 * col;
124 _image[index] = 1.0f;
125 _image[index + 1] = 0.0f;
126 _image[index + 2] = 0.0f;
127 }
128 }
129}
130
131void ExprGrapherView::mousePressEvent(QMouseEvent* event) {
132 if (event->button() == Qt::MidButton) {
133 setCursor(Qt::ClosedHandCursor);
134 translating = true;
135 }
136 if (event->button() == Qt::RightButton) {
137 setCursor(Qt::SizeAllCursor);
138 scaling = true;
139 }
140 event_oldx = event->x();
141 event_oldy = event->y();
142}
143void ExprGrapherView::mouseReleaseEvent(QMouseEvent* event) {
144 if (event->button() == Qt::LeftButton) emit clicked();
145 scaling = translating = false;
146 setCursor(Qt::OpenHandCursor);
147}
148void ExprGrapherView::mouseMoveEvent(QMouseEvent* event) {
149 int x = event->x(), y = event->y();
150 float offsetx = dx * (x - event_oldx);
151 float offsety = -dy * (y - event_oldy);
152
153 if (translating) {
154 xmin -= offsetx;
155 xmax -= offsetx;
156 ymin -= offsety;
157 ymax -= offsety;
158 update();
159 repaint();
160 } else if (scaling) {
161 float offset = (fabs(offsetx) > fabs(offsety)) ? offsetx : offsety;
162
163 float width = .5 * (xmax - xmin), height = .5 * (ymax - ymin);
164 float xcenter = .5 * (xmin + xmax), ycenter = .5 * (ymin + ymax);
165 // Use float args for pow() to fix Windows compile error
166 float scale_factor = pow(10.f, -offset / (xmax - xmin));
167 width *= scale_factor;
168 height *= scale_factor;
169 setWindow(xcenter - width, xcenter + width, ycenter - height, ycenter + height, z);
171 update();
172 repaint();
173 }
174 event_oldx = x;
175 event_oldy = y;
176}
177
179
180 if (!widget.expr.isValid()) {
181 clear();
182 updateGL();
183 return;
184 }
185
186 float dv = 1.0f / _height;
187 float du = 1.0f / _width;
188
189 float y = .5 * dy + ymin;
190 float v = .5 * dv;
191 int index = 0;
192 for (int row = 0; row < _height; row++, y += dy, v += dv) {
193 float x = .5 * dx + xmin;
194 float u = .5 * du;
195 widget.expr.v.value = v;
196 for (int col = 0; col < _width; col++, x += dy, u += du) {
197 widget.expr.u.value = u;
199 const double* value = widget.expr.evalFP();
200 _image[index] = value[0];
201 _image[index + 1] = value[1];
202 _image[index + 2] = value[2];
203 index += 3;
204 }
205 }
206
207 updateGL();
208}
209
211 glMatrixMode(GL_PROJECTION);
212 glLoadIdentity();
213 glOrtho(0.0f, (GLfloat)_width, 0.0, (GLfloat)_height, -1.0, 1.0);
214 glMatrixMode(GL_MODELVIEW);
215 glLoadIdentity();
216
217 glDisable(GL_DEPTH_TEST);
218 glDepthFunc(0);
219 glClearColor(1, 0, 0, 1);
220 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
221
222 glRasterPos2i(0, 0);
223 glDrawPixels(_width, _height, GL_RGB, GL_FLOAT, _image);
224}
ExprGrapherView(ExprGrapherWidget &widget, QWidget *parent, int width, int height)
void getWindow(float &xmin, float &xmax, float &ymin, float &ymax, float &z)
void scaleValueManipulated()
virtual ~ExprGrapherView()
void setWindow(float xmin, float xmax, float ymin, float ymax, float z)
void mouseReleaseEvent(QMouseEvent *event)
void mousePressEvent(QMouseEvent *event)
ExprGrapherWidget & widget
Definition: ExprGrapher2d.h:36
void mouseMoveEvent(QMouseEvent *event)
ExprGrapherView * view
Definition: ExprGrapher2d.h:74
BasicExpression expr
Definition: ExprGrapher2d.h:75
void scaleValueManipulated()
QLineEdit * scale
Definition: ExprGrapher2d.h:71
ExprGrapherWidget(QWidget *parent, int width, int height)
void setDesiredReturnType(const ExprType &type)
Definition: Expression.cpp:159
const double * evalFP(VarBlock *varBlock=nullptr) const
Definition: Expression.cpp:304
bool isValid() const
Definition: Expression.h:133
Vec< double, 3, false > Vec3d
Definition: Vec.h:384
</pre >< h3 > Binding our variable reference</h3 > If we now tried to use the variable would still not be found by our expressions To make it bindable we need to override the resolveVar() function as follows</pre >< h3 > Variable setting</h3 > Next we need to make a way of setting the variable As the controlling code will use the expression it will repeatedly alternate between setting the independent variables that are used and calling evaluate(). What it has to do depends very much on the application. In this case we only need to set the independent variable x as</pre >< h2 > Evaluating expressions</h2 > Evaluating an expression is pretty easy But before we can do that we need to make an instance< pre > GrapherExpr expr("x+x^2")
</pre >< h3 > A simple variable reference</h3 > This is not a very interesting subclass of expression until we add some additional variables Variables on some applications may be very dynamic In this we only need x
Definition: tutorial.txt:108
< br > pow($a, 0.5)+ $b< br >< br ></div > External variables can also be overridden by local assignment. &nbsp
This is the same as the prman cellnoise function< br ></div >< br > float< b > float y< br > float< b > float float z
Definition: userdoc.txt:218
This is the same as the prman cellnoise function< br ></div >< br > float< b > float y< br > float< b > float y
Definition: userdoc.txt:218
The result is computed int int< br >< div style="margin-left: 40px;"> Picks values randomly between loRange and hiRange based on supplied index(which is automatically hashed). &nbsp
For any rgb or hsl value(except for negative s values)