summaryrefslogtreecommitdiff
path: root/src/func.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/func.cc')
-rw-r--r--src/func.cc247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/func.cc b/src/func.cc
new file mode 100644
index 0000000..1d70d98
--- /dev/null
+++ b/src/func.cc
@@ -0,0 +1,247 @@
+/*
+ * OpenSCAD (www.openscad.at)
+ * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "openscad.h"
+
+AbstractFunction::~AbstractFunction()
+{
+}
+
+Value AbstractFunction::evaluate(const Context*, const QVector<QString>&, const QVector<Value>&) const
+{
+ return Value();
+}
+
+QString AbstractFunction::dump(QString indent, QString name) const
+{
+ return QString("%1abstract function %2();\n").arg(indent, name);
+}
+
+Function::~Function()
+{
+ for (int i=0; i < argexpr.size(); i++)
+ delete argexpr[i];
+ delete expr;
+}
+
+Value Function::evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const
+{
+ Context c(ctx);
+ c.args(argnames, argexpr, call_argnames, call_argvalues);
+ if (expr)
+ return expr->evaluate(&c);
+ return Value();
+}
+
+QString Function::dump(QString indent, QString name) const
+{
+ QString text = QString("%1function %2(").arg(indent, name);
+ for (int i=0; i < argnames.size(); i++) {
+ if (i > 0)
+ text += QString(", ");
+ text += argnames[i];
+ if (argexpr[i])
+ text += QString(" = ") + argexpr[i]->dump();
+ }
+ text += QString(") = %1;\n").arg(expr->dump());
+ return text;
+}
+
+QHash<QString, AbstractFunction*> builtin_functions;
+
+BuiltinFunction::~BuiltinFunction()
+{
+}
+
+Value BuiltinFunction::evaluate(const Context*, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const
+{
+ return eval_func(call_argnames, call_argvalues);
+}
+
+QString BuiltinFunction::dump(QString indent, QString name) const
+{
+ return QString("%1builtin function %2();\n").arg(indent, name);
+}
+
+static double deg2rad(double x)
+{
+ while (x < 0.0)
+ x += 360.0;
+ while (x >= 360.0)
+ x -= 360.0;
+ x = x * M_PI * 2.0 / 360.0;
+ return x;
+}
+
+static double rad2deg(double x)
+{
+ x = x * 360.0 / (M_PI * 2.0);
+ while (x < 0.0)
+ x += 360.0;
+ while (x >= 360.0)
+ x -= 360.0;
+ return x;
+}
+
+Value builtin_min(const QVector<QString>&, const QVector<Value> &args)
+{
+ if (args.size() >= 1 && args[0].type == Value::NUMBER) {
+ double val = args[0].num;
+ for (int i = 1; i < args.size(); i++)
+ if (args[1].type == Value::NUMBER)
+ val = fmin(val, args[i].num);
+ return Value(val);
+ }
+ return Value();
+}
+
+Value builtin_max(const QVector<QString>&, const QVector<Value> &args)
+{
+ if (args.size() >= 1 && args[0].type == Value::NUMBER) {
+ double val = args[0].num;
+ for (int i = 1; i < args.size(); i++)
+ if (args[1].type == Value::NUMBER)
+ val = fmax(val, args[i].num);
+ return Value(val);
+ }
+ return Value();
+}
+
+Value builtin_sin(const QVector<QString>&, const QVector<Value> &args)
+{
+ if (args.size() == 1 && args[0].type == Value::NUMBER)
+ return Value(sin(deg2rad(args[0].num)));
+ return Value();
+}
+
+Value builtin_cos(const QVector<QString>&, const QVector<Value> &args)
+{
+ if (args.size() == 1 && args[0].type == Value::NUMBER)
+ return Value(cos(deg2rad(args[0].num)));
+ return Value();
+}
+
+Value builtin_asin(const QVector<QString>&, const QVector<Value> &args)
+{
+ if (args.size() == 1 && args[0].type == Value::NUMBER)
+ return Value(rad2deg(asin(args[0].num)));
+ return Value();
+}
+
+Value builtin_acos(const QVector<QString>&, const QVector<Value> &args)
+{
+ if (args.size() == 1 && args[0].type == Value::NUMBER)
+ return Value(rad2deg(acos(args[0].num)));
+ return Value();
+}
+
+Value builtin_tan(const QVector<QString>&, const QVector<Value> &args)
+{
+ if (args.size() == 1 && args[0].type == Value::NUMBER)
+ return Value(tan(deg2rad(args[0].num)));
+ return Value();
+}
+
+Value builtin_atan(const QVector<QString>&, const QVector<Value> &args)
+{
+ if (args.size() == 1 && args[0].type == Value::NUMBER)
+ return Value(rad2deg(atan(args[0].num)));
+ return Value();
+}
+
+Value builtin_atan2(const QVector<QString>&, const QVector<Value> &args)
+{
+ if (args.size() == 2 && args[0].type == Value::NUMBER && args[1].type == Value::NUMBER)
+ return Value(rad2deg(atan2(args[0].num, args[1].num)));
+ return Value();
+}
+
+Value builtin_pow(const QVector<QString>&, const QVector<Value> &args)
+{
+ if (args.size() == 2 && args[0].type == Value::NUMBER && args[1].type == Value::NUMBER)
+ return Value(pow(args[0].num, args[1].num));
+ return Value();
+}
+
+Value builtin_str(const QVector<QString>&, const QVector<Value> &args)
+{
+ QString str;
+ for (int i = 0; i < args.size(); i++)
+ {
+ if (args[i].type == Value::STRING)
+ str += args[i].text;
+ else
+ str += args[i].dump();
+ }
+ return Value(str);
+}
+
+Value builtin_lookup(const QVector<QString>&, const QVector<Value> &args)
+{
+ double p, low_p, low_v, high_p, high_v;
+ if (args.size() < 2 || !args[0].getnum(p) || args[1].vec.size() < 2 || args[1].vec[0]->vec.size() < 2)
+ return Value();
+ if (!args[1].vec[0]->getv2(low_p, low_v) || !args[1].vec[0]->getv2(high_p, high_v))
+ return Value();
+ for (int i = 1; i < args[1].vec.size(); i++) {
+ double this_p, this_v;
+ if (args[1].vec[i]->getv2(this_p, this_v)) {
+ if (this_p <= p && (this_p > low_p || low_p > p)) {
+ low_p = this_p;
+ low_v = this_v;
+ }
+ if (this_p >= p && (this_p < high_p || high_p < p)) {
+ high_p = this_p;
+ high_v = this_v;
+ }
+ }
+ }
+ if (p <= low_p)
+ return Value(low_v);
+ if (p >= high_p)
+ return Value(high_v);
+ double f = (p-low_p) / (high_p-low_p);
+ return Value(high_v * f + low_v * (1-f));
+}
+
+void initialize_builtin_functions()
+{
+ builtin_functions["min"] = new BuiltinFunction(&builtin_min);
+ builtin_functions["max"] = new BuiltinFunction(&builtin_max);
+ builtin_functions["sin"] = new BuiltinFunction(&builtin_sin);
+ builtin_functions["cos"] = new BuiltinFunction(&builtin_cos);
+ builtin_functions["asin"] = new BuiltinFunction(&builtin_asin);
+ builtin_functions["acos"] = new BuiltinFunction(&builtin_acos);
+ builtin_functions["tan"] = new BuiltinFunction(&builtin_tan);
+ builtin_functions["atan"] = new BuiltinFunction(&builtin_atan);
+ builtin_functions["atan2"] = new BuiltinFunction(&builtin_atan2);
+ builtin_functions["pow"] = new BuiltinFunction(&builtin_pow);
+ builtin_functions["str"] = new BuiltinFunction(&builtin_str);
+ builtin_functions["lookup"] = new BuiltinFunction(&builtin_lookup);
+ initialize_builtin_dxf_dim();
+}
+
+void destroy_builtin_functions()
+{
+ foreach (AbstractFunction *v, builtin_functions)
+ delete v;
+ builtin_functions.clear();
+}
+
contact: Jan Huwald // Impressum