50 mutable std::map<std::string, Var> vars;
54 std::map<std::string, Var>::iterator
i = vars.find(name);
55 if (
i != vars.end())
return &
i->second;
61double clamp(
double x) {
return std::max(0., std::min(255.,
x)); }
67 std::cerr <<
"Usage: " <<
argv[0] <<
" <image file> <width> <height> <exprFile>" << std::endl;
76 std::cerr <<
"invalid width/height" << std::endl;
82 std::cerr <<
"Cannot read file " <<
exprFile << std::endl;
85 std::string
exprStr((std::istreambuf_iterator<char>(
istream)), std::istreambuf_iterator<char>());
89 expr.vars[
"u"] = ImageSynthExpr::Var(0.);
90 expr.vars[
"v"] = ImageSynthExpr::Var(0.);
91 expr.vars[
"w"] = ImageSynthExpr::Var(
width);
95 bool valid =
expr.isValid();
97 std::cerr <<
"Invalid expression " << std::endl;
98 std::cerr <<
expr.parseError() << std::endl;
101 if (!
expr.returnType().isFP(3)) {
102 std::cerr <<
"Expected color FP[3] got type " <<
expr.returnType().toString() << std::endl;
107 std::cerr <<
"Evaluating expresion...from " <<
exprFile << std::endl;
108 unsigned char* image =
new unsigned char[
width *
height * 4];
113 double& u =
expr.vars[
"u"].val;
114 double& v =
expr.vars[
"v"].val;
115 unsigned char*
pixel = image;
116 for (
int row = 0; row <
height; row++) {
134 std::cerr <<
"Writing image..." <<
imageFile << std::endl;
abstract class for implementing variable references
virtual void eval(double *result)=0
returns this variable's value by setting result
virtual ExprVarRef * resolveVar(const std::string &name) const
int main(int argc, char *argv[])
double clamp(double x, double lo, double hi)
</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