mirror of https://github.com/vitalif/openscad
#409 Pass Value objects as shared_ptr instances instead of by Value to battle excess stack usage
parent
ef262f62a2
commit
406e6e1bac
|
@ -94,19 +94,19 @@ std::string Builtins::isDeprecated(const std::string &name)
|
|||
|
||||
Builtins::Builtins()
|
||||
{
|
||||
this->globalscope.assignments.push_back(Assignment("$fn", boost::shared_ptr<Expression>(new Expression(Value(0.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$fs", boost::shared_ptr<Expression>(new Expression(Value(2.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$fa", boost::shared_ptr<Expression>(new Expression(Value(12.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$t", boost::shared_ptr<Expression>(new Expression(Value(0.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$fn", boost::shared_ptr<Expression>(new Expression(ValuePtr(0.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$fs", boost::shared_ptr<Expression>(new Expression(ValuePtr(2.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$fa", boost::shared_ptr<Expression>(new Expression(ValuePtr(12.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$t", boost::shared_ptr<Expression>(new Expression(ValuePtr(0.0)))));
|
||||
|
||||
Value::VectorType zero3;
|
||||
zero3.push_back(Value(0.0));
|
||||
zero3.push_back(Value(0.0));
|
||||
zero3.push_back(Value(0.0));
|
||||
Value zero3val(zero3);
|
||||
ValuePtr zero3val(zero3);
|
||||
this->globalscope.assignments.push_back(Assignment("$vpt", boost::shared_ptr<Expression>(new Expression(zero3val))));
|
||||
this->globalscope.assignments.push_back(Assignment("$vpr", boost::shared_ptr<Expression>(new Expression(zero3val))));
|
||||
this->globalscope.assignments.push_back(Assignment("$vpd", boost::shared_ptr<Expression>(new Expression(500))));
|
||||
this->globalscope.assignments.push_back(Assignment("$vpd", boost::shared_ptr<Expression>(new Expression(ValuePtr(500)))));
|
||||
}
|
||||
|
||||
Builtins::~Builtins()
|
||||
|
|
|
@ -63,7 +63,10 @@ AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstant
|
|||
Context c(ctx);
|
||||
c.setVariables(args, evalctx);
|
||||
|
||||
Value convexity, path, subdiv_type, level;
|
||||
ValuePtr convexity = ValuePtr::undefined;
|
||||
ValuePtr path = ValuePtr::undefined;
|
||||
ValuePtr subdiv_type = ValuePtr::undefined;
|
||||
ValuePtr level = ValuePtr::undefined;
|
||||
|
||||
if (type == MINKOWSKI) {
|
||||
convexity = c.lookup_variable("convexity", true);
|
||||
|
@ -81,31 +84,31 @@ AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstant
|
|||
}
|
||||
|
||||
if (type == RESIZE) {
|
||||
Value ns = c.lookup_variable("newsize");
|
||||
ValuePtr ns = c.lookup_variable("newsize");
|
||||
node->newsize << 0,0,0;
|
||||
if ( ns.type() == Value::VECTOR ) {
|
||||
Value::VectorType vs = ns.toVector();
|
||||
if ( ns->type() == Value::VECTOR ) {
|
||||
const Value::VectorType &vs = ns->toVector();
|
||||
if ( vs.size() >= 1 ) node->newsize[0] = vs[0].toDouble();
|
||||
if ( vs.size() >= 2 ) node->newsize[1] = vs[1].toDouble();
|
||||
if ( vs.size() >= 3 ) node->newsize[2] = vs[2].toDouble();
|
||||
}
|
||||
Value autosize = c.lookup_variable("auto");
|
||||
ValuePtr autosize = c.lookup_variable("auto");
|
||||
node->autosize << false, false, false;
|
||||
if ( autosize.type() == Value::VECTOR ) {
|
||||
Value::VectorType va = autosize.toVector();
|
||||
if ( autosize->type() == Value::VECTOR ) {
|
||||
const Value::VectorType &va = autosize->toVector();
|
||||
if ( va.size() >= 1 ) node->autosize[0] = va[0].toBool();
|
||||
if ( va.size() >= 2 ) node->autosize[1] = va[1].toBool();
|
||||
if ( va.size() >= 3 ) node->autosize[2] = va[2].toBool();
|
||||
}
|
||||
else if ( autosize.type() == Value::BOOL ) {
|
||||
node->autosize << autosize.toBool(),autosize.toBool(),autosize.toBool();
|
||||
else if ( autosize->type() == Value::BOOL ) {
|
||||
node->autosize << autosize->toBool(),autosize->toBool(),autosize->toBool();
|
||||
}
|
||||
}
|
||||
|
||||
node->convexity = (int)convexity.toDouble();
|
||||
node->convexity = (int)convexity->toDouble();
|
||||
node->path = path;
|
||||
node->subdiv_type = subdiv_type.toString();
|
||||
node->level = (int)level.toDouble();
|
||||
node->subdiv_type = subdiv_type->toString();
|
||||
node->level = (int)level->toDouble();
|
||||
|
||||
if (node->level <= 1)
|
||||
node->level = 1;
|
||||
|
@ -150,7 +153,7 @@ std::string CgaladvNode::toString() const
|
|||
stream << "(convexity = " << this->convexity << ")";
|
||||
break;
|
||||
case GLIDE:
|
||||
stream << "(path = " << this->path << ", convexity = " << this->convexity << ")";
|
||||
stream << "(path = " << *this->path << ", convexity = " << this->convexity << ")";
|
||||
break;
|
||||
case SUBDIV:
|
||||
stream << "(level = " << this->level << ", convexity = " << this->convexity << ")";
|
||||
|
|
|
@ -26,7 +26,7 @@ public:
|
|||
virtual std::string toString() const;
|
||||
virtual std::string name() const;
|
||||
|
||||
Value path;
|
||||
ValuePtr path;
|
||||
std::string subdiv_type;
|
||||
int convexity, level;
|
||||
Vector3d newsize;
|
||||
|
|
16
src/color.cc
16
src/color.cc
|
@ -219,15 +219,15 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia
|
|||
Context c(ctx);
|
||||
c.setVariables(args, evalctx);
|
||||
|
||||
Value v = c.lookup_variable("c");
|
||||
if (v.type() == Value::VECTOR) {
|
||||
ValuePtr v = c.lookup_variable("c");
|
||||
if (v->type() == Value::VECTOR) {
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
node->color[i] = i < v.toVector().size() ? v.toVector()[i].toDouble() : 1.0;
|
||||
node->color[i] = i < v->toVector().size() ? v->toVector()[i].toDouble() : 1.0;
|
||||
if (node->color[i] > 1)
|
||||
PRINTB_NOCACHE("WARNING: color() expects numbers between 0.0 and 1.0. Value of %.1f is too large.", node->color[i]);
|
||||
}
|
||||
} else if (v.type() == Value::STRING) {
|
||||
std::string colorname = v.toString();
|
||||
} else if (v->type() == Value::STRING) {
|
||||
std::string colorname = v->toString();
|
||||
boost::algorithm::to_lower(colorname);
|
||||
Color4f color;
|
||||
if (webcolors.find(colorname) != webcolors.end()) {
|
||||
|
@ -237,9 +237,9 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia
|
|||
PRINT_NOCACHE("WARNING: http://en.wikipedia.org/wiki/Web_colors");
|
||||
}
|
||||
}
|
||||
Value alpha = c.lookup_variable("alpha");
|
||||
if (alpha.type() == Value::NUMBER) {
|
||||
node->color[3] = alpha.toDouble();
|
||||
ValuePtr alpha = c.lookup_variable("alpha");
|
||||
if (alpha->type() == Value::NUMBER) {
|
||||
node->color[3] = alpha->toDouble();
|
||||
}
|
||||
|
||||
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx);
|
||||
|
|
|
@ -78,14 +78,14 @@ void Context::setVariables(const AssignmentList &args,
|
|||
const EvalContext *evalctx)
|
||||
{
|
||||
BOOST_FOREACH(const Assignment &arg, args) {
|
||||
set_variable(arg.first, arg.second ? arg.second->evaluate(this->parent) : Value());
|
||||
set_variable(arg.first, arg.second ? arg.second->evaluate(this->parent) : ValuePtr::undefined);
|
||||
}
|
||||
|
||||
if (evalctx) {
|
||||
size_t posarg = 0;
|
||||
for (size_t i=0; i<evalctx->numArgs(); i++) {
|
||||
const std::string &name = evalctx->getArgName(i);
|
||||
const Value &val = evalctx->getArgValue(i);
|
||||
ValuePtr val = evalctx->getArgValue(i);
|
||||
if (name.empty()) {
|
||||
if (posarg < args.size()) this->set_variable(args[posarg++].first, val);
|
||||
} else {
|
||||
|
@ -95,13 +95,18 @@ void Context::setVariables(const AssignmentList &args,
|
|||
}
|
||||
}
|
||||
|
||||
void Context::set_variable(const std::string &name, const Value &value)
|
||||
void Context::set_variable(const std::string &name, const ValuePtr &value)
|
||||
{
|
||||
if (is_config_variable(name)) this->config_variables[name] = value;
|
||||
else this->variables[name] = value;
|
||||
}
|
||||
|
||||
void Context::set_constant(const std::string &name, const Value &value)
|
||||
void Context::set_variable(const std::string &name, const Value &value)
|
||||
{
|
||||
set_variable(name, ValuePtr(value));
|
||||
}
|
||||
|
||||
void Context::set_constant(const std::string &name, const ValuePtr &value)
|
||||
{
|
||||
if (this->constants.find(name) != this->constants.end()) {
|
||||
PRINTB("WARNING: Attempt to modify constant '%s'.", name);
|
||||
|
@ -111,11 +116,16 @@ void Context::set_constant(const std::string &name, const Value &value)
|
|||
}
|
||||
}
|
||||
|
||||
Value Context::lookup_variable(const std::string &name, bool silent) const
|
||||
void Context::set_constant(const std::string &name, const Value &value)
|
||||
{
|
||||
set_constant(name, ValuePtr(value));
|
||||
}
|
||||
|
||||
ValuePtr Context::lookup_variable(const std::string &name, bool silent) const
|
||||
{
|
||||
if (!this->ctx_stack) {
|
||||
PRINT("ERROR: Context had null stack in lookup_variable()!!");
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
if (is_config_variable(name)) {
|
||||
for (int i = this->ctx_stack->size()-1; i >= 0; i--) {
|
||||
|
@ -123,7 +133,7 @@ Value Context::lookup_variable(const std::string &name, bool silent) const
|
|||
if (confvars.find(name) != confvars.end())
|
||||
return confvars.find(name)->second;
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
if (!this->parent && this->constants.find(name) != this->constants.end())
|
||||
return this->constants.find(name)->second;
|
||||
|
@ -133,7 +143,7 @@ Value Context::lookup_variable(const std::string &name, bool silent) const
|
|||
return this->parent->lookup_variable(name, silent);
|
||||
if (!silent)
|
||||
PRINTB("WARNING: Ignoring unknown variable '%s'.", name);
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
bool Context::has_local_variable(const std::string &name) const
|
||||
|
@ -145,11 +155,11 @@ bool Context::has_local_variable(const std::string &name) const
|
|||
return variables.find(name) != variables.end();
|
||||
}
|
||||
|
||||
Value Context::evaluate_function(const std::string &name, const EvalContext *evalctx) const
|
||||
ValuePtr Context::evaluate_function(const std::string &name, const EvalContext *evalctx) const
|
||||
{
|
||||
if (this->parent) return this->parent->evaluate_function(name, evalctx);
|
||||
PRINTB("WARNING: Ignoring unknown function '%s'.", name);
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
AbstractNode *Context::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const
|
||||
|
@ -190,7 +200,7 @@ std::string Context::dump(const AbstractModule *mod, const ModuleInstantiation *
|
|||
}
|
||||
}
|
||||
}
|
||||
typedef std::pair<std::string, Value> ValueMapType;
|
||||
typedef std::pair<std::string, ValuePtr> ValueMapType;
|
||||
s << " vars:";
|
||||
BOOST_FOREACH(const ValueMapType &v, constants) {
|
||||
s << boost::format(" %s = %s") % v.first % v.second;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <boost/unordered_map.hpp>
|
||||
#include "value.h"
|
||||
#include "typedefs.h"
|
||||
#include "memory.h"
|
||||
|
||||
class Context
|
||||
{
|
||||
|
@ -14,16 +15,18 @@ public:
|
|||
virtual ~Context();
|
||||
|
||||
const Context *getParent() const { return this->parent; }
|
||||
virtual Value evaluate_function(const std::string &name, const class EvalContext *evalctx) const;
|
||||
virtual ValuePtr evaluate_function(const std::string &name, const class EvalContext *evalctx) const;
|
||||
virtual class AbstractNode *instantiate_module(const class ModuleInstantiation &inst, const EvalContext *evalctx) const;
|
||||
|
||||
void setVariables(const AssignmentList &args,
|
||||
const class EvalContext *evalctx = NULL);
|
||||
|
||||
void set_variable(const std::string &name, const ValuePtr &value);
|
||||
void set_variable(const std::string &name, const Value &value);
|
||||
void set_constant(const std::string &name, const ValuePtr &value);
|
||||
void set_constant(const std::string &name, const Value &value);
|
||||
|
||||
Value lookup_variable(const std::string &name, bool silent = false) const;
|
||||
ValuePtr lookup_variable(const std::string &name, bool silent = false) const;
|
||||
bool has_local_variable(const std::string &name) const;
|
||||
|
||||
void setDocumentPath(const std::string &path) { this->document_path = path; }
|
||||
|
@ -36,7 +39,7 @@ protected:
|
|||
const Context *parent;
|
||||
Stack *ctx_stack;
|
||||
|
||||
typedef boost::unordered_map<std::string, Value> ValueMap;
|
||||
typedef boost::unordered_map<std::string, ValuePtr> ValueMap;
|
||||
ValueMap constants;
|
||||
ValueMap variables;
|
||||
ValueMap config_variables;
|
||||
|
|
|
@ -74,27 +74,27 @@ void ControlModule::for_eval(AbstractNode &node, const ModuleInstantiation &inst
|
|||
{
|
||||
if (evalctx->numArgs() > l) {
|
||||
const std::string &it_name = evalctx->getArgName(l);
|
||||
const Value &it_values = evalctx->getArgValue(l, ctx);
|
||||
ValuePtr it_values = evalctx->getArgValue(l, ctx);
|
||||
Context c(ctx);
|
||||
if (it_values.type() == Value::RANGE) {
|
||||
Value::RangeType range = it_values.toRange();
|
||||
if (it_values->type() == Value::RANGE) {
|
||||
Value::RangeType range = it_values->toRange();
|
||||
boost::uint32_t steps = range.nbsteps();
|
||||
if (steps >= 10000) {
|
||||
PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps);
|
||||
} else {
|
||||
for (Value::RangeType::iterator it = range.begin();it != range.end();it++) {
|
||||
c.set_variable(it_name, Value(*it));
|
||||
c.set_variable(it_name, ValuePtr(*it));
|
||||
for_eval(node, inst, l+1, &c, evalctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (it_values.type() == Value::VECTOR) {
|
||||
for (size_t i = 0; i < it_values.toVector().size(); i++) {
|
||||
c.set_variable(it_name, it_values.toVector()[i]);
|
||||
else if (it_values->type() == Value::VECTOR) {
|
||||
for (size_t i = 0; i < it_values->toVector().size(); i++) {
|
||||
c.set_variable(it_name, it_values->toVector()[i]);
|
||||
for_eval(node, inst, l+1, &c, evalctx);
|
||||
}
|
||||
}
|
||||
else if (it_values.type() != Value::UNDEFINED) {
|
||||
else if (it_values->type() != Value::UNDEFINED) {
|
||||
c.set_variable(it_name, it_values);
|
||||
for_eval(node, inst, l+1, &c, evalctx);
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
|||
int n = 0;
|
||||
if (evalctx->numArgs() > 0) {
|
||||
double v;
|
||||
if (evalctx->getArgValue(0).getDouble(v)) {
|
||||
if (evalctx->getArgValue(0)->getDouble(v)) {
|
||||
n = trunc(v);
|
||||
if (n < 0) {
|
||||
PRINTB("WARNING: Negative child index (%d) not allowed", n);
|
||||
|
@ -213,13 +213,13 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
|||
}
|
||||
else if (evalctx->numArgs()>0) {
|
||||
// one (or more ignored) parameter
|
||||
const Value& value = evalctx->getArgValue(0);
|
||||
if (value.type() == Value::NUMBER) {
|
||||
return getChild(value,modulectx);
|
||||
ValuePtr value = evalctx->getArgValue(0);
|
||||
if (value->type() == Value::NUMBER) {
|
||||
return getChild(*value, modulectx);
|
||||
}
|
||||
else if (value.type() == Value::VECTOR) {
|
||||
else if (value->type() == Value::VECTOR) {
|
||||
AbstractNode* node = new AbstractNode(inst);
|
||||
const Value::VectorType& vect = value.toVector();
|
||||
const Value::VectorType& vect = value->toVector();
|
||||
foreach (const Value::VectorType::value_type& vectvalue, vect) {
|
||||
AbstractNode* childnode = getChild(vectvalue,modulectx);
|
||||
if (childnode==NULL) continue; // error
|
||||
|
@ -227,9 +227,9 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
|||
}
|
||||
return node;
|
||||
}
|
||||
else if (value.type() == Value::RANGE) {
|
||||
else if (value->type() == Value::RANGE) {
|
||||
AbstractNode* node = new AbstractNode(inst);
|
||||
Value::RangeType range = value.toRange();
|
||||
Value::RangeType range = value->toRange();
|
||||
boost::uint32_t steps = range.nbsteps();
|
||||
if (steps >= 10000) {
|
||||
PRINTB("WARNING: Bad range parameter for children: too many elements (%lu).", steps);
|
||||
|
@ -245,7 +245,7 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
|||
else {
|
||||
// Invalid parameter
|
||||
// (e.g. first child of difference is invalid)
|
||||
PRINTB("WARNING: Bad parameter type (%s) for children, only accept: empty, number, vector, range.", value.toString());
|
||||
PRINTB("WARNING: Bad parameter type (%s) for children, only accept: empty, number, vector, range.", value->toString());
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -264,11 +264,11 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
|||
for (size_t i = 0; i < inst->arguments.size(); i++) {
|
||||
if (i > 0) msg << ", ";
|
||||
if (!evalctx->getArgName(i).empty()) msg << evalctx->getArgName(i) << " = ";
|
||||
Value val = evalctx->getArgValue(i);
|
||||
if (val.type() == Value::STRING) {
|
||||
msg << '"' << val.toString() << '"';
|
||||
ValuePtr val = evalctx->getArgValue(i);
|
||||
if (val->type() == Value::STRING) {
|
||||
msg << '"' << val->toString() << '"';
|
||||
} else {
|
||||
msg << val.toString();
|
||||
msg << val->toString();
|
||||
}
|
||||
}
|
||||
PRINTB("%s", msg.str());
|
||||
|
@ -293,7 +293,7 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
|||
if (type == IF)
|
||||
{
|
||||
const IfElseModuleInstantiation *ifelse = dynamic_cast<const IfElseModuleInstantiation*>(inst);
|
||||
if (evalctx->numArgs() > 0 && evalctx->getArgValue(0).toBool()) {
|
||||
if (evalctx->numArgs() > 0 && evalctx->getArgValue(0)->toBool()) {
|
||||
std::vector<AbstractNode *> instantiatednodes = ifelse->instantiateChildren(evalctx);
|
||||
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||
}
|
||||
|
|
|
@ -39,11 +39,11 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
boost::unordered_map<std::string,Value> dxf_dim_cache;
|
||||
boost::unordered_map<std::string,Value> dxf_cross_cache;
|
||||
boost::unordered_map<std::string, ValuePtr> dxf_dim_cache;
|
||||
boost::unordered_map<std::string, ValuePtr> dxf_cross_cache;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
Value builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx)
|
||||
ValuePtr builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx)
|
||||
{
|
||||
std::string filename;
|
||||
std::string layername;
|
||||
|
@ -56,17 +56,16 @@ Value builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx)
|
|||
// since the path is only available for ModuleInstantiations, not function expressions.
|
||||
// See issue #217
|
||||
for (size_t i = 0; i < evalctx->numArgs(); i++) {
|
||||
if (evalctx->getArgName(i) == "file")
|
||||
filename = lookup_file(evalctx->getArgValue(i).toString(),
|
||||
ValuePtr n = evalctx->getArgName(i);
|
||||
ValuePtr v = evalctx->getArgValue(i);
|
||||
if (evalctx->getArgName(i) == "file") {
|
||||
filename = lookup_file(v->toString(),
|
||||
evalctx->documentPath(), ctx->documentPath());
|
||||
if (evalctx->getArgName(i) == "layer")
|
||||
layername = evalctx->getArgValue(i).toString();
|
||||
if (evalctx->getArgName(i) == "origin")
|
||||
evalctx->getArgValue(i).getVec2(xorigin, yorigin);
|
||||
if (evalctx->getArgName(i) == "scale")
|
||||
evalctx->getArgValue(i).getDouble(scale);
|
||||
if (evalctx->getArgName(i) == "name")
|
||||
name = evalctx->getArgValue(i).toString();
|
||||
}
|
||||
if (n == "layer") layername = v->toString();
|
||||
if (n == "origin") v->getVec2(xorigin, yorigin);
|
||||
if (n == "scale") v->getDouble(scale);
|
||||
if (n == "name") name = v->toString();
|
||||
}
|
||||
|
||||
std::stringstream keystream;
|
||||
|
@ -100,46 +99,46 @@ Value builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx)
|
|||
double y = d->coords[4][1] - d->coords[3][1];
|
||||
double angle = d->angle;
|
||||
double distance_projected_on_line = fabs(x * cos(angle*M_PI/180) + y * sin(angle*M_PI/180));
|
||||
return dxf_dim_cache[key] = Value(distance_projected_on_line);
|
||||
return dxf_dim_cache[key] = ValuePtr(distance_projected_on_line);
|
||||
}
|
||||
else if (type == 1) {
|
||||
// Aligned
|
||||
double x = d->coords[4][0] - d->coords[3][0];
|
||||
double y = d->coords[4][1] - d->coords[3][1];
|
||||
return dxf_dim_cache[key] = Value(sqrt(x*x + y*y));
|
||||
return dxf_dim_cache[key] = ValuePtr(sqrt(x*x + y*y));
|
||||
}
|
||||
else if (type == 2) {
|
||||
// Angular
|
||||
double a1 = atan2(d->coords[0][0] - d->coords[5][0], d->coords[0][1] - d->coords[5][1]);
|
||||
double a2 = atan2(d->coords[4][0] - d->coords[3][0], d->coords[4][1] - d->coords[3][1]);
|
||||
return dxf_dim_cache[key] = Value(fabs(a1 - a2) * 180 / M_PI);
|
||||
return dxf_dim_cache[key] = ValuePtr(fabs(a1 - a2) * 180 / M_PI);
|
||||
}
|
||||
else if (type == 3 || type == 4) {
|
||||
// Diameter or Radius
|
||||
double x = d->coords[5][0] - d->coords[0][0];
|
||||
double y = d->coords[5][1] - d->coords[0][1];
|
||||
return dxf_dim_cache[key] = Value(sqrt(x*x + y*y));
|
||||
return dxf_dim_cache[key] = ValuePtr(sqrt(x*x + y*y));
|
||||
}
|
||||
else if (type == 5) {
|
||||
// Angular 3 Point
|
||||
}
|
||||
else if (type == 6) {
|
||||
// Ordinate
|
||||
return dxf_dim_cache[key] = Value((d->type & 64) ? d->coords[3][0] : d->coords[3][1]);
|
||||
return dxf_dim_cache[key] = ValuePtr((d->type & 64) ? d->coords[3][0] : d->coords[3][1]);
|
||||
}
|
||||
|
||||
PRINTB("WARNING: Dimension '%s' in '%s', layer '%s' has unsupported type!",
|
||||
name % filename % layername);
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
PRINTB("WARNING: Can't find dimension '%s' in '%s', layer '%s'!",
|
||||
name % filename % layername);
|
||||
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx)
|
||||
ValuePtr builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx)
|
||||
{
|
||||
std::string filename;
|
||||
std::string layername;
|
||||
|
@ -151,14 +150,12 @@ Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx)
|
|||
// since the path is only available for ModuleInstantiations, not function expressions.
|
||||
// See isse #217
|
||||
for (size_t i = 0; i < evalctx->numArgs(); i++) {
|
||||
if (evalctx->getArgName(i) == "file")
|
||||
filename = ctx->getAbsolutePath(evalctx->getArgValue(i).toString());
|
||||
if (evalctx->getArgName(i) == "layer")
|
||||
layername = evalctx->getArgValue(i).toString();
|
||||
if (evalctx->getArgName(i) == "origin")
|
||||
evalctx->getArgValue(i).getVec2(xorigin, yorigin);
|
||||
if (evalctx->getArgName(i) == "scale")
|
||||
evalctx->getArgValue(i).getDouble(scale);
|
||||
ValuePtr n = evalctx->getArgName(i);
|
||||
ValuePtr v = evalctx->getArgValue(i);
|
||||
if (n == "file") filename = ctx->getAbsolutePath(v->toString());
|
||||
if (n == "layer") layername = v->toString();
|
||||
if (n == "origin") v->getVec2(xorigin, yorigin);
|
||||
if (n == "scale") v->getDouble(scale);
|
||||
}
|
||||
|
||||
std::stringstream keystream;
|
||||
|
@ -174,8 +171,9 @@ Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx)
|
|||
<< "|" << filesize;
|
||||
std::string key = keystream.str();
|
||||
|
||||
if (dxf_cross_cache.find(key) != dxf_cross_cache.end())
|
||||
if (dxf_cross_cache.find(key) != dxf_cross_cache.end()) {
|
||||
return dxf_cross_cache.find(key)->second;
|
||||
}
|
||||
|
||||
DxfData dxf(36, 0, 0, filename, layername, xorigin, yorigin, scale);
|
||||
|
||||
|
@ -204,13 +202,13 @@ Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx)
|
|||
Value::VectorType ret;
|
||||
ret.push_back(Value(x));
|
||||
ret.push_back(Value(y));
|
||||
return dxf_cross_cache[key] = Value(ret);
|
||||
return dxf_cross_cache[key] = ValuePtr(ret);
|
||||
}
|
||||
}
|
||||
|
||||
PRINTB("WARNING: Can't find cross in '%s', layer '%s'!", filename % layername);
|
||||
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
void initialize_builtin_dxf_dim()
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
#include <boost/unordered_map.hpp>
|
||||
#include "value.h"
|
||||
|
||||
extern boost::unordered_map<std::string,Value> dxf_dim_cache;
|
||||
extern boost::unordered_map<std::string,Value> dxf_cross_cache;
|
||||
extern boost::unordered_map<std::string, ValuePtr> dxf_dim_cache;
|
||||
extern boost::unordered_map<std::string, ValuePtr> dxf_cross_cache;
|
||||
|
|
|
@ -14,11 +14,11 @@ const std::string &EvalContext::getArgName(size_t i) const
|
|||
return this->eval_arguments[i].first;
|
||||
}
|
||||
|
||||
Value EvalContext::getArgValue(size_t i, const Context *ctx) const
|
||||
ValuePtr EvalContext::getArgValue(size_t i, const Context *ctx) const
|
||||
{
|
||||
assert(i < this->eval_arguments.size());
|
||||
const Assignment &arg = this->eval_arguments[i];
|
||||
return arg.second ? arg.second->evaluate(ctx ? ctx : this) : Value();
|
||||
return arg.second ? arg.second->evaluate(ctx ? ctx : this) : ValuePtr::undefined;
|
||||
}
|
||||
|
||||
size_t EvalContext::numChildren() const
|
||||
|
@ -56,7 +56,7 @@ std::string EvalContext::dump(const AbstractModule *mod, const ModuleInstantiati
|
|||
if (m) {
|
||||
s << boost::format(" module args:");
|
||||
BOOST_FOREACH(const Assignment &arg, m->definition_arguments) {
|
||||
s << boost::format(" %s = %s") % arg.first % variables[arg.first];
|
||||
s << boost::format(" %s = %s") % arg.first % *(variables[arg.first]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ public:
|
|||
|
||||
size_t numArgs() const { return this->eval_arguments.size(); }
|
||||
const std::string &getArgName(size_t i) const;
|
||||
Value getArgValue(size_t i, const Context *ctx = NULL) const;
|
||||
ValuePtr getArgValue(size_t i, const Context *ctx = NULL) const;
|
||||
|
||||
size_t numChildren() const;
|
||||
ModuleInstantiation *getChild(size_t i) const;
|
||||
|
@ -29,6 +29,6 @@ public:
|
|||
|
||||
private:
|
||||
const AssignmentList &eval_arguments;
|
||||
std::vector<std::pair<std::string, Value> > eval_values;
|
||||
std::vector<std::pair<std::string, ValuePtr> > eval_values;
|
||||
const LocalScope *const scope;
|
||||
};
|
||||
|
|
94
src/expr.cc
94
src/expr.cc
|
@ -52,7 +52,7 @@ Expression::Expression(const std::string &type, Expression *expr)
|
|||
this->children.push_back(expr);
|
||||
}
|
||||
|
||||
Expression::Expression(const Value &val) : const_value(val), type("C"), recursioncount(0)
|
||||
Expression::Expression(const ValuePtr &val) : const_value(val), type("C"), recursioncount(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -61,62 +61,62 @@ Expression::~Expression()
|
|||
std::for_each(this->children.begin(), this->children.end(), del_fun<Expression>());
|
||||
}
|
||||
|
||||
Value Expression::sub_evaluate_range(const Context *context) const
|
||||
ValuePtr Expression::sub_evaluate_range(const Context *context) const
|
||||
{
|
||||
Value v1 = this->children[0]->evaluate(context);
|
||||
if (v1.type() == Value::NUMBER) {
|
||||
Value v2 = this->children[1]->evaluate(context);
|
||||
if (v2.type() == Value::NUMBER) {
|
||||
ValuePtr v1 = this->children[0]->evaluate(context);
|
||||
if (v1->type() == Value::NUMBER) {
|
||||
ValuePtr v2 = this->children[1]->evaluate(context);
|
||||
if (v2->type() == Value::NUMBER) {
|
||||
if (this->children.size() == 2) {
|
||||
Value::RangeType range(v1.toDouble(), v2.toDouble());
|
||||
return Value(range);
|
||||
Value::RangeType range(v1->toDouble(), v2->toDouble());
|
||||
return ValuePtr(range);
|
||||
} else {
|
||||
Value v3 = this->children[2]->evaluate(context);
|
||||
if (v3.type() == Value::NUMBER) {
|
||||
Value::RangeType range(v1.toDouble(), v2.toDouble(), v3.toDouble());
|
||||
return Value(range);
|
||||
ValuePtr v3 = this->children[2]->evaluate(context);
|
||||
if (v3->type() == Value::NUMBER) {
|
||||
Value::RangeType range(v1->toDouble(), v2->toDouble(), v3->toDouble());
|
||||
return ValuePtr(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value Expression::sub_evaluate_member(const Context *context) const
|
||||
ValuePtr Expression::sub_evaluate_member(const Context *context) const
|
||||
{
|
||||
Value v = this->children[0]->evaluate(context);
|
||||
ValuePtr v = this->children[0]->evaluate(context);
|
||||
|
||||
if (v.type() == Value::VECTOR) {
|
||||
if (v->type() == Value::VECTOR) {
|
||||
if (this->var_name == "x") return v[0];
|
||||
if (this->var_name == "y") return v[1];
|
||||
if (this->var_name == "z") return v[2];
|
||||
} else if (v.type() == Value::RANGE) {
|
||||
if (this->var_name == "begin") return Value(v[0]);
|
||||
if (this->var_name == "step") return Value(v[1]);
|
||||
if (this->var_name == "end") return Value(v[2]);
|
||||
} else if (v->type() == Value::RANGE) {
|
||||
if (this->var_name == "begin") return v[0];
|
||||
if (this->var_name == "step") return v[1];
|
||||
if (this->var_name == "end") return v[2];
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value Expression::sub_evaluate_vector(const Context *context) const
|
||||
ValuePtr Expression::sub_evaluate_vector(const Context *context) const
|
||||
{
|
||||
Value::VectorType vec;
|
||||
BOOST_FOREACH(const Expression *e, this->children) {
|
||||
vec.push_back(e->evaluate(context));
|
||||
vec.push_back(*(e->evaluate(context)));
|
||||
}
|
||||
return Value(vec);
|
||||
return ValuePtr(vec);
|
||||
}
|
||||
|
||||
Value Expression::sub_evaluate_function(const Context *context) const
|
||||
ValuePtr Expression::sub_evaluate_function(const Context *context) const
|
||||
{
|
||||
if (this->recursioncount >= 1000) {
|
||||
PRINTB("ERROR: Recursion detected calling function '%s'", this->call_funcname);
|
||||
// TO DO: throw function_recursion_detected();
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
this->recursioncount += 1;
|
||||
EvalContext c(context, this->call_arguments);
|
||||
const Value &result = context->evaluate_function(this->call_funcname, &c);
|
||||
ValuePtr result = context->evaluate_function(this->call_funcname, &c);
|
||||
this->recursioncount -= 1;
|
||||
return result;
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ namespace {
|
|||
|
||||
for (int i = 0; i < let_context.numArgs(); i++) {
|
||||
if (!allow_reassignment && context->has_local_variable(let_context.getArgName(i))) {
|
||||
PRINTB("WARNING: Ignoring duplicate variable assignment %s = %s", let_context.getArgName(i) % let_context.getArgValue(i, context).toString());
|
||||
PRINTB("WARNING: Ignoring duplicate variable assignment %s = %s", let_context.getArgName(i) % let_context.getArgValue(i, context)->toString());
|
||||
} else {
|
||||
// NOTE: iteratively evaluated list of arguments
|
||||
context->set_variable(let_context.getArgName(i), let_context.getArgValue(i, context));
|
||||
|
@ -170,7 +170,7 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
Value Expression::sub_evaluate_let_expression(const Context *context) const
|
||||
ValuePtr Expression::sub_evaluate_let_expression(const Context *context) const
|
||||
{
|
||||
Context c(context);
|
||||
evaluate_sequential_assignment(this->call_arguments, &c);
|
||||
|
@ -178,7 +178,7 @@ Value Expression::sub_evaluate_let_expression(const Context *context) const
|
|||
return this->children[0]->evaluate(&c);
|
||||
}
|
||||
|
||||
Value Expression::sub_evaluate_list_comprehension(const Context *context) const
|
||||
ValuePtr Expression::sub_evaluate_list_comprehension(const Context *context) const
|
||||
{
|
||||
Value::VectorType vec;
|
||||
|
||||
|
@ -187,10 +187,10 @@ Value Expression::sub_evaluate_list_comprehension(const Context *context) const
|
|||
if (this->children[1]->type == "c") {
|
||||
return this->children[1]->evaluate(context);
|
||||
} else {
|
||||
vec.push_back(this->children[1]->evaluate(context));
|
||||
vec.push_back((*this->children[1]->evaluate(context)));
|
||||
}
|
||||
}
|
||||
return vec;
|
||||
return ValuePtr(vec);
|
||||
} else if (this->call_funcname == "for") {
|
||||
EvalContext for_context(context, this->call_arguments);
|
||||
|
||||
|
@ -198,36 +198,36 @@ Value Expression::sub_evaluate_list_comprehension(const Context *context) const
|
|||
|
||||
// comprehension for statements are by the parser reduced to only contain one single element
|
||||
const std::string &it_name = for_context.getArgName(0);
|
||||
const Value &it_values = for_context.getArgValue(0, &assign_context);
|
||||
ValuePtr it_values = for_context.getArgValue(0, &assign_context);
|
||||
|
||||
Context c(context);
|
||||
|
||||
if (it_values.type() == Value::RANGE) {
|
||||
Value::RangeType range = it_values.toRange();
|
||||
if (it_values->type() == Value::RANGE) {
|
||||
Value::RangeType range = it_values->toRange();
|
||||
boost::uint32_t steps = range.nbsteps();
|
||||
if (steps >= 1000000) {
|
||||
PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps);
|
||||
} else {
|
||||
for (Value::RangeType::iterator it = range.begin();it != range.end();it++) {
|
||||
c.set_variable(it_name, Value(*it));
|
||||
vec.push_back(this->children[0]->evaluate(&c));
|
||||
c.set_variable(it_name, ValuePtr(*it));
|
||||
vec.push_back((*this->children[0]->evaluate(&c)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (it_values.type() == Value::VECTOR) {
|
||||
for (size_t i = 0; i < it_values.toVector().size(); i++) {
|
||||
c.set_variable(it_name, it_values.toVector()[i]);
|
||||
vec.push_back(this->children[0]->evaluate(&c));
|
||||
else if (it_values->type() == Value::VECTOR) {
|
||||
for (size_t i = 0; i < it_values->toVector().size(); i++) {
|
||||
c.set_variable(it_name, it_values->toVector()[i]);
|
||||
vec.push_back((*this->children[0]->evaluate(&c)));
|
||||
}
|
||||
}
|
||||
else if (it_values.type() != Value::UNDEFINED) {
|
||||
else if (it_values->type() != Value::UNDEFINED) {
|
||||
c.set_variable(it_name, it_values);
|
||||
vec.push_back(this->children[0]->evaluate(&c));
|
||||
vec.push_back((*this->children[0]->evaluate(&c)));
|
||||
}
|
||||
if (this->children[0]->type == "c") {
|
||||
return flatten(vec);
|
||||
return ValuePtr(flatten(vec));
|
||||
} else {
|
||||
return vec;
|
||||
return ValuePtr(vec);
|
||||
}
|
||||
} else if (this->call_funcname == "let") {
|
||||
Context c(context);
|
||||
|
@ -240,7 +240,7 @@ Value Expression::sub_evaluate_list_comprehension(const Context *context) const
|
|||
}
|
||||
|
||||
|
||||
Value Expression::evaluate(const Context *context) const
|
||||
ValuePtr Expression::evaluate(const Context *context) const
|
||||
{
|
||||
switch (type2int(this->type.c_str())) {
|
||||
case '!':
|
||||
|
@ -336,7 +336,7 @@ std::string Expression::toString() const
|
|||
stream << "!" << *this->children[0];
|
||||
}
|
||||
else if (this->type == "C") {
|
||||
stream << this->const_value;
|
||||
stream << *this->const_value;
|
||||
}
|
||||
else if (this->type == "R") {
|
||||
stream << "[" << *this->children[0] << " : " << *this->children[1];
|
||||
|
|
|
@ -10,7 +10,7 @@ class Expression
|
|||
public:
|
||||
std::vector<Expression*> children;
|
||||
|
||||
const Value const_value;
|
||||
ValuePtr const_value;
|
||||
std::string var_name;
|
||||
|
||||
std::string call_funcname;
|
||||
|
@ -35,12 +35,12 @@ public:
|
|||
std::string type;
|
||||
|
||||
Expression();
|
||||
Expression(const Value &val);
|
||||
Expression(const ValuePtr &val);
|
||||
Expression(const std::string &type, Expression *left, Expression *right);
|
||||
Expression(const std::string &type, Expression *expr);
|
||||
~Expression();
|
||||
|
||||
Value evaluate(const class Context *context) const;
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
|
@ -48,12 +48,12 @@ private:
|
|||
mutable int recursioncount;
|
||||
|
||||
// The following sub_* methods are needed to minimize stack usage only.
|
||||
Value sub_evaluate_function(const class Context *context) const;
|
||||
Value sub_evaluate_member(const class Context *context) const;
|
||||
Value sub_evaluate_range(const class Context *context) const;
|
||||
Value sub_evaluate_vector(const class Context *context) const;
|
||||
Value sub_evaluate_let_expression(const class Context *context) const;
|
||||
Value sub_evaluate_list_comprehension(const class Context *context) const;
|
||||
ValuePtr sub_evaluate_function(const class Context *context) const;
|
||||
ValuePtr sub_evaluate_member(const class Context *context) const;
|
||||
ValuePtr sub_evaluate_range(const class Context *context) const;
|
||||
ValuePtr sub_evaluate_vector(const class Context *context) const;
|
||||
ValuePtr sub_evaluate_let_expression(const class Context *context) const;
|
||||
ValuePtr sub_evaluate_list_comprehension(const class Context *context) const;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const Expression &expr);
|
||||
|
|
472
src/func.cc
472
src/func.cc
|
@ -69,10 +69,11 @@ AbstractFunction::~AbstractFunction()
|
|||
{
|
||||
}
|
||||
|
||||
Value AbstractFunction::evaluate(const Context*, const EvalContext *evalctx) const
|
||||
// FIXME: Is this needed?
|
||||
ValuePtr AbstractFunction::evaluate(const Context*, const EvalContext *evalctx) const
|
||||
{
|
||||
(void)evalctx; // unusued parameter
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
std::string AbstractFunction::dump(const std::string &indent, const std::string &name) const
|
||||
|
@ -87,9 +88,9 @@ Function::~Function()
|
|||
delete expr;
|
||||
}
|
||||
|
||||
Value Function::evaluate(const Context *ctx, const EvalContext *evalctx) const
|
||||
ValuePtr Function::evaluate(const Context *ctx, const EvalContext *evalctx) const
|
||||
{
|
||||
if (!expr) return Value();
|
||||
if (!expr) return ValuePtr::undefined;
|
||||
Context c(ctx);
|
||||
c.setVariables(definition_arguments, evalctx);
|
||||
return expr->evaluate(&c);
|
||||
|
@ -113,7 +114,7 @@ BuiltinFunction::~BuiltinFunction()
|
|||
{
|
||||
}
|
||||
|
||||
Value BuiltinFunction::evaluate(const Context *ctx, const EvalContext *evalctx) const
|
||||
ValuePtr BuiltinFunction::evaluate(const Context *ctx, const EvalContext *evalctx) const
|
||||
{
|
||||
return eval_func(ctx, evalctx);
|
||||
}
|
||||
|
@ -135,51 +136,51 @@ static inline double rad2deg(double x)
|
|||
return x * 180.0 / M_PI;
|
||||
}
|
||||
|
||||
Value builtin_abs(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_abs(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER)
|
||||
return Value(fabs(v.toDouble()));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER)
|
||||
return ValuePtr(fabs(v->toDouble()));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_sign(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_sign(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER) {
|
||||
register double x = v.toDouble();
|
||||
return Value((x<0) ? -1.0 : ((x>0) ? 1.0 : 0.0));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER) {
|
||||
register double x = v->toDouble();
|
||||
return ValuePtr((x<0) ? -1.0 : ((x>0) ? 1.0 : 0.0));
|
||||
}
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_rands(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_rands(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
size_t n = evalctx->numArgs();
|
||||
if (n == 3 || n == 4) {
|
||||
const Value &v0 = evalctx->getArgValue(0);
|
||||
if (v0.type() != Value::NUMBER) goto quit;
|
||||
double min = v0.toDouble();
|
||||
ValuePtr v0 = evalctx->getArgValue(0);
|
||||
if (v0->type() != Value::NUMBER) goto quit;
|
||||
double min = v0->toDouble();
|
||||
|
||||
const Value &v1 = evalctx->getArgValue(1);
|
||||
if (v1.type() != Value::NUMBER) goto quit;
|
||||
double max = v1.toDouble();
|
||||
ValuePtr v1 = evalctx->getArgValue(1);
|
||||
if (v1->type() != Value::NUMBER) goto quit;
|
||||
double max = v1->toDouble();
|
||||
if (max < min) {
|
||||
register double tmp = min; min = max; max = tmp;
|
||||
}
|
||||
const Value &v2 = evalctx->getArgValue(2);
|
||||
if (v2.type() != Value::NUMBER) goto quit;
|
||||
size_t numresults = std::max( 0, static_cast<int>( v2.toDouble() ) );
|
||||
ValuePtr v2 = evalctx->getArgValue(2);
|
||||
if (v2->type() != Value::NUMBER) goto quit;
|
||||
size_t numresults = std::max(0, static_cast<int>(v2->toDouble()));
|
||||
|
||||
bool deterministic = false;
|
||||
if (n > 3) {
|
||||
const Value &v3 = evalctx->getArgValue(3);
|
||||
if (v3.type() != Value::NUMBER) goto quit;
|
||||
deterministic_rng.seed( (unsigned int) v3.toDouble() );
|
||||
ValuePtr v3 = evalctx->getArgValue(3);
|
||||
if (v3->type() != Value::NUMBER) goto quit;
|
||||
deterministic_rng.seed((unsigned int) v3->toDouble());
|
||||
deterministic = true;
|
||||
}
|
||||
boost::uniform_real<> distributor( min, max );
|
||||
|
@ -196,77 +197,75 @@ Value builtin_rands(const Context *, const EvalContext *evalctx)
|
|||
}
|
||||
}
|
||||
}
|
||||
return Value(vec);
|
||||
return ValuePtr(vec);
|
||||
}
|
||||
quit:
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
|
||||
Value builtin_min(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_min(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
// preserve special handling of the first argument
|
||||
// as a template for vector processing
|
||||
size_t n = evalctx->numArgs();
|
||||
if (n >= 1) {
|
||||
const Value &v0 = evalctx->getArgValue(0);
|
||||
ValuePtr v0 = evalctx->getArgValue(0);
|
||||
|
||||
if (n == 1 && v0.type() == Value::VECTOR && !v0.toVector().empty()) {
|
||||
Value min = v0.toVector()[0];
|
||||
for (size_t i = 1; i < v0.toVector().size(); i++) {
|
||||
if (v0.toVector()[i] < min)
|
||||
min = v0.toVector()[i];
|
||||
if (n == 1 && v0->type() == Value::VECTOR && !v0->toVector().empty()) {
|
||||
Value min = v0->toVector()[0];
|
||||
for (size_t i = 1; i < v0->toVector().size(); i++) {
|
||||
if (v0->toVector()[i] < min) min = v0->toVector()[i];
|
||||
}
|
||||
return min;
|
||||
return ValuePtr(min);
|
||||
}
|
||||
if (v0.type() == Value::NUMBER) {
|
||||
double val = v0.toDouble();
|
||||
if (v0->type() == Value::NUMBER) {
|
||||
double val = v0->toDouble();
|
||||
for (size_t i = 1; i < n; ++i) {
|
||||
const Value &v = evalctx->getArgValue(i);
|
||||
ValuePtr v = evalctx->getArgValue(i);
|
||||
// 4/20/14 semantic change per discussion:
|
||||
// break on any non-number
|
||||
if (v.type() != Value::NUMBER) goto quit;
|
||||
register double x = v.toDouble();
|
||||
if (v->type() != Value::NUMBER) goto quit;
|
||||
register double x = v->toDouble();
|
||||
if (x < val) val = x;
|
||||
}
|
||||
return Value(val);
|
||||
return ValuePtr(val);
|
||||
}
|
||||
}
|
||||
quit:
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_max(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_max(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
// preserve special handling of the first argument
|
||||
// as a template for vector processing
|
||||
size_t n = evalctx->numArgs();
|
||||
if (n >= 1) {
|
||||
const Value &v0 = evalctx->getArgValue(0);
|
||||
ValuePtr v0 = evalctx->getArgValue(0);
|
||||
|
||||
if (n == 1 && v0.type() == Value::VECTOR && !v0.toVector().empty()) {
|
||||
Value max = v0.toVector()[0];
|
||||
for (size_t i = 1; i < v0.toVector().size(); i++) {
|
||||
if (v0.toVector()[i] > max)
|
||||
max = v0.toVector()[i];
|
||||
if (n == 1 && v0->type() == Value::VECTOR && !v0->toVector().empty()) {
|
||||
Value max = v0->toVector()[0];
|
||||
for (size_t i = 1; i < v0->toVector().size(); i++) {
|
||||
if (v0->toVector()[i] > max) max = v0->toVector()[i];
|
||||
}
|
||||
return max;
|
||||
return ValuePtr(max);
|
||||
}
|
||||
if (v0.type() == Value::NUMBER) {
|
||||
double val = v0.toDouble();
|
||||
if (v0->type() == Value::NUMBER) {
|
||||
double val = v0->toDouble();
|
||||
for (size_t i = 1; i < n; ++i) {
|
||||
const Value &v = evalctx->getArgValue(i);
|
||||
ValuePtr v = evalctx->getArgValue(i);
|
||||
// 4/20/14 semantic change per discussion:
|
||||
// break on any non-number
|
||||
if (v.type() != Value::NUMBER) goto quit;
|
||||
register double x = v.toDouble();
|
||||
if (v->type() != Value::NUMBER) goto quit;
|
||||
register double x = v->toDouble();
|
||||
if (x > val) val = x;
|
||||
}
|
||||
return Value(val);
|
||||
return ValuePtr(val);
|
||||
}
|
||||
}
|
||||
quit:
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
// this limit assumes 26+26=52 bits mantissa
|
||||
|
@ -307,14 +306,14 @@ double sin_degrees(register double x)
|
|||
return oppose ? -x : x;
|
||||
}
|
||||
|
||||
Value builtin_sin(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_sin(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER)
|
||||
return Value(sin_degrees(v.toDouble()));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER)
|
||||
return ValuePtr(sin_degrees(v->toDouble()));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
double cos_degrees(register double x)
|
||||
|
@ -354,220 +353,221 @@ double cos_degrees(register double x)
|
|||
return oppose ? -x : x;
|
||||
}
|
||||
|
||||
Value builtin_cos(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_cos(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER)
|
||||
return Value(cos_degrees(v.toDouble()));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER)
|
||||
return ValuePtr(cos_degrees(v->toDouble()));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_asin(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_asin(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER)
|
||||
return Value(rad2deg(asin(v.toDouble())));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER)
|
||||
return ValuePtr(rad2deg(asin(v->toDouble())));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_acos(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_acos(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER)
|
||||
return Value(rad2deg(acos(v.toDouble())));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER)
|
||||
return ValuePtr(rad2deg(acos(v->toDouble())));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_tan(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_tan(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER)
|
||||
return Value(tan(deg2rad(v.toDouble())));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER)
|
||||
return ValuePtr(tan(deg2rad(v->toDouble())));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_atan(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_atan(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER)
|
||||
return Value(rad2deg(atan(v.toDouble())));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER)
|
||||
return ValuePtr(rad2deg(atan(v->toDouble())));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_atan2(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_atan2(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 2) {
|
||||
Value v0 = evalctx->getArgValue(0), v1 = evalctx->getArgValue(1);
|
||||
if (v0.type() == Value::NUMBER && v1.type() == Value::NUMBER)
|
||||
return Value(rad2deg(atan2(v0.toDouble(), v1.toDouble())));
|
||||
ValuePtr v0 = evalctx->getArgValue(0), v1 = evalctx->getArgValue(1);
|
||||
if (v0->type() == Value::NUMBER && v1->type() == Value::NUMBER)
|
||||
return ValuePtr(rad2deg(atan2(v0->toDouble(), v1->toDouble())));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_pow(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_pow(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 2) {
|
||||
Value v0 = evalctx->getArgValue(0), v1 = evalctx->getArgValue(1);
|
||||
if (v0.type() == Value::NUMBER && v1.type() == Value::NUMBER)
|
||||
return Value(pow(v0.toDouble(), v1.toDouble()));
|
||||
ValuePtr v0 = evalctx->getArgValue(0), v1 = evalctx->getArgValue(1);
|
||||
if (v0->type() == Value::NUMBER && v1->type() == Value::NUMBER)
|
||||
return ValuePtr(pow(v0->toDouble(), v1->toDouble()));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_round(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_round(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER)
|
||||
return Value(round(v.toDouble()));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER)
|
||||
return ValuePtr(round(v->toDouble()));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_ceil(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_ceil(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER)
|
||||
return Value(ceil(v.toDouble()));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER)
|
||||
return ValuePtr(ceil(v->toDouble()));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_floor(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_floor(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER)
|
||||
return Value(floor(v.toDouble()));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER)
|
||||
return ValuePtr(floor(v->toDouble()));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_sqrt(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_sqrt(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER)
|
||||
return Value(sqrt(v.toDouble()));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER)
|
||||
return ValuePtr(sqrt(v->toDouble()));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_exp(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_exp(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER)
|
||||
return Value(exp(v.toDouble()));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER)
|
||||
return ValuePtr(exp(v->toDouble()));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_length(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_length(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::VECTOR) return Value(int(v.toVector().size()));
|
||||
if (v.type() == Value::STRING) {
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::VECTOR) return ValuePtr(int(v->toVector().size()));
|
||||
if (v->type() == Value::STRING) {
|
||||
//Unicode glyph count for the length -- rather than the string (num. of bytes) length.
|
||||
std::string text = v.toString();
|
||||
return Value(int( g_utf8_strlen( text.c_str(), text.size() ) ));
|
||||
std::string text = v->toString();
|
||||
return ValuePtr(int( g_utf8_strlen( text.c_str(), text.size() ) ));
|
||||
}
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_log(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_log(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
size_t n = evalctx->numArgs();
|
||||
if (n == 1 || n == 2) {
|
||||
const Value &v0 = evalctx->getArgValue(0);
|
||||
if (v0.type() == Value::NUMBER) {
|
||||
double x = 10.0, y = v0.toDouble();
|
||||
ValuePtr v0 = evalctx->getArgValue(0);
|
||||
if (v0->type() == Value::NUMBER) {
|
||||
double x = 10.0, y = v0->toDouble();
|
||||
if (n > 1) {
|
||||
const Value &v1 = evalctx->getArgValue(1);
|
||||
if (v1.type() != Value::NUMBER) goto quit;
|
||||
x = y; y = v1.toDouble();
|
||||
ValuePtr v1 = evalctx->getArgValue(1);
|
||||
if (v1->type() != Value::NUMBER) goto quit;
|
||||
x = y; y = v1->toDouble();
|
||||
}
|
||||
return Value(log(y) / log(x));
|
||||
return ValuePtr(log(y) / log(x));
|
||||
}
|
||||
}
|
||||
quit:
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_ln(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_ln(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() == Value::NUMBER)
|
||||
return Value(log(v.toDouble()));
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() == Value::NUMBER)
|
||||
return ValuePtr(log(v->toDouble()));
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_str(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_str(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
std::stringstream stream;
|
||||
|
||||
for (size_t i = 0; i < evalctx->numArgs(); i++) {
|
||||
stream << evalctx->getArgValue(i).toString();
|
||||
stream << evalctx->getArgValue(i)->toString();
|
||||
}
|
||||
return Value(stream.str());
|
||||
return ValuePtr(stream.str());
|
||||
}
|
||||
|
||||
Value builtin_chr(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_chr(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
std::stringstream stream;
|
||||
|
||||
for (size_t i = 0; i < evalctx->numArgs(); i++) {
|
||||
const Value v = evalctx->getArgValue(i);
|
||||
stream << v.chrString();
|
||||
ValuePtr v = evalctx->getArgValue(i);
|
||||
stream << v->chrString();
|
||||
}
|
||||
return Value(stream.str());
|
||||
return ValuePtr(stream.str());
|
||||
}
|
||||
|
||||
Value builtin_concat(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_concat(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
Value::VectorType result;
|
||||
|
||||
for (size_t i = 0; i < evalctx->numArgs(); i++) {
|
||||
const Value v = evalctx->getArgValue(i);
|
||||
if (v.type() == Value::VECTOR) {
|
||||
Value::VectorType vec = v.toVector();
|
||||
ValuePtr v = evalctx->getArgValue(i);
|
||||
if (v->type() == Value::VECTOR) {
|
||||
Value::VectorType vec = v->toVector();
|
||||
for (Value::VectorType::const_iterator it = vec.begin(); it != vec.end(); it++) {
|
||||
result.push_back(*it);
|
||||
}
|
||||
} else {
|
||||
result.push_back(v);
|
||||
result.push_back(*v);
|
||||
}
|
||||
}
|
||||
return Value(result);
|
||||
return ValuePtr(result);
|
||||
}
|
||||
|
||||
Value builtin_lookup(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_lookup(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
double p, low_p, low_v, high_p, high_v;
|
||||
if (evalctx->numArgs() < 2 || // Needs two args
|
||||
!evalctx->getArgValue(0).getDouble(p)) // First must be a number
|
||||
return Value();
|
||||
!evalctx->getArgValue(0)->getDouble(p)) // First must be a number
|
||||
return ValuePtr::undefined;
|
||||
|
||||
const Value::VectorType vec = evalctx->getArgValue(1).toVector();
|
||||
ValuePtr v1 = evalctx->getArgValue(1);
|
||||
const Value::VectorType &vec = v1->toVector();
|
||||
if (vec[0].toVector().size() < 2) // Second must be a vector of vectors
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
if (!vec[0].getVec2(low_p, low_v) || !vec[0].getVec2(high_p, high_v))
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
for (size_t i = 1; i < vec.size(); i++) {
|
||||
double this_p, this_v;
|
||||
if (vec[i].getVec2(this_p, this_v)) {
|
||||
|
@ -582,11 +582,11 @@ Value builtin_lookup(const Context *, const EvalContext *evalctx)
|
|||
}
|
||||
}
|
||||
if (p <= low_p)
|
||||
return Value(high_v);
|
||||
return ValuePtr(high_v);
|
||||
if (p >= high_p)
|
||||
return Value(low_v);
|
||||
return ValuePtr(low_v);
|
||||
double f = (p-low_p) / (high_p-low_p);
|
||||
return Value(high_v * f + low_v * (1-f));
|
||||
return ValuePtr(high_v * f + low_v * (1-f));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -715,48 +715,48 @@ static Value::VectorType search(const std::string &find, const Value::VectorType
|
|||
return returnvec;
|
||||
}
|
||||
|
||||
Value builtin_search(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_search(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() < 2) return Value();
|
||||
if (evalctx->numArgs() < 2) return ValuePtr::undefined;
|
||||
|
||||
const Value &findThis = evalctx->getArgValue(0);
|
||||
const Value &searchTable = evalctx->getArgValue(1);
|
||||
unsigned int num_returns_per_match = (evalctx->numArgs() > 2) ? evalctx->getArgValue(2).toDouble() : 1;
|
||||
unsigned int index_col_num = (evalctx->numArgs() > 3) ? evalctx->getArgValue(3).toDouble() : 0;
|
||||
ValuePtr findThis = evalctx->getArgValue(0);
|
||||
ValuePtr searchTable = evalctx->getArgValue(1);
|
||||
unsigned int num_returns_per_match = (evalctx->numArgs() > 2) ? evalctx->getArgValue(2)->toDouble() : 1;
|
||||
unsigned int index_col_num = (evalctx->numArgs() > 3) ? evalctx->getArgValue(3)->toDouble() : 0;
|
||||
|
||||
Value::VectorType returnvec;
|
||||
|
||||
if (findThis.type() == Value::NUMBER) {
|
||||
if (findThis->type() == Value::NUMBER) {
|
||||
unsigned int matchCount = 0;
|
||||
|
||||
for (size_t j = 0; j < searchTable.toVector().size(); j++) {
|
||||
const Value& search_element = searchTable.toVector()[j];
|
||||
for (size_t j = 0; j < searchTable->toVector().size(); j++) {
|
||||
const Value &search_element = searchTable->toVector()[j];
|
||||
|
||||
if ((index_col_num == 0 && findThis == search_element) ||
|
||||
if ((index_col_num == 0 && *findThis == search_element) ||
|
||||
(index_col_num < search_element.toVector().size() &&
|
||||
findThis == search_element.toVector()[index_col_num])) {
|
||||
*findThis == search_element.toVector()[index_col_num])) {
|
||||
returnvec.push_back(Value(double(j)));
|
||||
matchCount++;
|
||||
if (num_returns_per_match != 0 && matchCount >= num_returns_per_match) break;
|
||||
}
|
||||
}
|
||||
} else if (findThis.type() == Value::STRING) {
|
||||
if (searchTable.type() == Value::STRING) {
|
||||
returnvec = search(findThis.toString(), searchTable.toString(), num_returns_per_match, index_col_num);
|
||||
} else if (findThis->type() == Value::STRING) {
|
||||
if (searchTable->type() == Value::STRING) {
|
||||
returnvec = search(findThis->toString(), searchTable->toString(), num_returns_per_match, index_col_num);
|
||||
}
|
||||
else {
|
||||
returnvec = search(findThis.toString(), searchTable.toVector(), num_returns_per_match, index_col_num);
|
||||
returnvec = search(findThis->toString(), searchTable->toVector(), num_returns_per_match, index_col_num);
|
||||
}
|
||||
} else if (findThis.type() == Value::VECTOR) {
|
||||
for (size_t i = 0; i < findThis.toVector().size(); i++) {
|
||||
} else if (findThis->type() == Value::VECTOR) {
|
||||
for (size_t i = 0; i < findThis->toVector().size(); i++) {
|
||||
unsigned int matchCount = 0;
|
||||
Value::VectorType resultvec;
|
||||
|
||||
Value const& find_value = findThis.toVector()[i];
|
||||
Value const& find_value = findThis->toVector()[i];
|
||||
|
||||
for (size_t j = 0; j < searchTable.toVector().size(); j++) {
|
||||
for (size_t j = 0; j < searchTable->toVector().size(); j++) {
|
||||
|
||||
Value const& search_element = searchTable.toVector()[j];
|
||||
Value const& search_element = searchTable->toVector()[j];
|
||||
|
||||
if ((index_col_num == 0 && find_value == search_element) ||
|
||||
(index_col_num < search_element.toVector().size() &&
|
||||
|
@ -773,53 +773,53 @@ Value builtin_search(const Context *, const EvalContext *evalctx)
|
|||
}
|
||||
}
|
||||
if (num_returns_per_match == 1 && matchCount == 0) {
|
||||
if (findThis.toVector()[i].type() == Value::NUMBER) {
|
||||
PRINTB(" WARNING: search term not found: %s",findThis.toVector()[i].toDouble());
|
||||
if (findThis->toVector()[i].type() == Value::NUMBER) {
|
||||
PRINTB(" WARNING: search term not found: %s",findThis->toVector()[i].toDouble());
|
||||
}
|
||||
else if (findThis.toVector()[i].type() == Value::STRING) {
|
||||
PRINTB(" WARNING: search term not found: \"%s\"",findThis.toVector()[i].toString());
|
||||
else if (findThis->toVector()[i].type() == Value::STRING) {
|
||||
PRINTB(" WARNING: search term not found: \"%s\"",findThis->toVector()[i].toString());
|
||||
}
|
||||
returnvec.push_back(Value(resultvec));
|
||||
returnvec.push_back(resultvec);
|
||||
}
|
||||
if (num_returns_per_match == 0 || num_returns_per_match > 1) {
|
||||
returnvec.push_back(Value(resultvec));
|
||||
returnvec.push_back(resultvec);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PRINTB(" WARNING: search: none performed on input %s", findThis);
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
return Value(returnvec);
|
||||
return ValuePtr(returnvec);
|
||||
}
|
||||
|
||||
#define QUOTE(x__) # x__
|
||||
#define QUOTED(x__) QUOTE(x__)
|
||||
|
||||
Value builtin_version(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_version(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
(void)evalctx; // unusued parameter
|
||||
Value::VectorType val;
|
||||
val.push_back(Value(double(OPENSCAD_YEAR)));
|
||||
val.push_back(Value(double(OPENSCAD_MONTH)));
|
||||
val.push_back(double(OPENSCAD_YEAR));
|
||||
val.push_back(double(OPENSCAD_MONTH));
|
||||
#ifdef OPENSCAD_DAY
|
||||
val.push_back(Value(double(OPENSCAD_DAY)));
|
||||
val.push_back(double(OPENSCAD_DAY));
|
||||
#endif
|
||||
return Value(val);
|
||||
return ValuePtr(val);
|
||||
}
|
||||
|
||||
Value builtin_version_num(const Context *ctx, const EvalContext *evalctx)
|
||||
ValuePtr builtin_version_num(const Context *ctx, const EvalContext *evalctx)
|
||||
{
|
||||
Value val = (evalctx->numArgs() == 0) ? builtin_version(ctx, evalctx) : evalctx->getArgValue(0);
|
||||
ValuePtr val = (evalctx->numArgs() == 0) ? builtin_version(ctx, evalctx) : evalctx->getArgValue(0);
|
||||
double y, m, d = 0;
|
||||
if (!val.getVec3(y, m, d)) {
|
||||
if (!val.getVec2(y, m)) {
|
||||
return Value();
|
||||
if (!val->getVec3(y, m, d)) {
|
||||
if (!val->getVec2(y, m)) {
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
}
|
||||
return Value(y * 10000 + m * 100 + d);
|
||||
return ValuePtr(y * 10000 + m * 100 + d);
|
||||
}
|
||||
|
||||
Value builtin_parent_module(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_parent_module(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
int n;
|
||||
double d;
|
||||
|
@ -827,30 +827,30 @@ Value builtin_parent_module(const Context *, const EvalContext *evalctx)
|
|||
if (evalctx->numArgs() == 0)
|
||||
d=1; // parent module
|
||||
else if (evalctx->numArgs() == 1) {
|
||||
const Value &v = evalctx->getArgValue(0);
|
||||
if (v.type() != Value::NUMBER) return Value();
|
||||
v.getDouble(d);
|
||||
ValuePtr v = evalctx->getArgValue(0);
|
||||
if (v->type() != Value::NUMBER) return ValuePtr::undefined;
|
||||
v->getDouble(d);
|
||||
} else
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
n=trunc(d);
|
||||
if (n < 0) {
|
||||
PRINTB("WARNING: Negative parent module index (%d) not allowed", n);
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
if (n >= s) {
|
||||
PRINTB("WARNING: Parent module index (%d) greater than the number of modules on the stack", n);
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
return Value(Module::stack_element(s - 1 - n));
|
||||
return ValuePtr(Module::stack_element(s - 1 - n));
|
||||
}
|
||||
|
||||
Value builtin_norm(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_norm(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() == 1) {
|
||||
const Value &val = evalctx->getArgValue(0);
|
||||
if (val.type() == Value::VECTOR) {
|
||||
ValuePtr val = evalctx->getArgValue(0);
|
||||
if (val->type() == Value::VECTOR) {
|
||||
double sum = 0;
|
||||
Value::VectorType v = val.toVector();
|
||||
Value::VectorType v = val->toVector();
|
||||
size_t n = v.size();
|
||||
for (size_t i = 0; i < n; i++)
|
||||
if (v[i].type() == Value::NUMBER) {
|
||||
|
@ -859,48 +859,48 @@ Value builtin_norm(const Context *, const EvalContext *evalctx)
|
|||
sum += x*x;
|
||||
} else {
|
||||
PRINT(" WARNING: Incorrect arguments to norm()");
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
return Value(sqrt(sum));
|
||||
return ValuePtr(sqrt(sum));
|
||||
}
|
||||
}
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value builtin_cross(const Context *, const EvalContext *evalctx)
|
||||
ValuePtr builtin_cross(const Context *, const EvalContext *evalctx)
|
||||
{
|
||||
if (evalctx->numArgs() != 2) {
|
||||
PRINT("WARNING: Invalid number of parameters for cross()");
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value arg0 = evalctx->getArgValue(0);
|
||||
Value arg1 = evalctx->getArgValue(1);
|
||||
if ((arg0.type() != Value::VECTOR) || (arg1.type() != Value::VECTOR)) {
|
||||
ValuePtr arg0 = evalctx->getArgValue(0);
|
||||
ValuePtr arg1 = evalctx->getArgValue(1);
|
||||
if ((arg0->type() != Value::VECTOR) || (arg1->type() != Value::VECTOR)) {
|
||||
PRINT("WARNING: Invalid type of parameters for cross()");
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
Value::VectorType v0 = arg0.toVector();
|
||||
Value::VectorType v1 = arg1.toVector();
|
||||
Value::VectorType v0 = arg0->toVector();
|
||||
Value::VectorType v1 = arg1->toVector();
|
||||
if ((v0.size() != 3) || (v1.size() != 3)) {
|
||||
PRINT("WARNING: Invalid vector size of parameter for cross()");
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
for (unsigned int a = 0;a < 3;a++) {
|
||||
if ((v0[a].type() != Value::NUMBER) || (v1[a].type() != Value::NUMBER)) {
|
||||
PRINT("WARNING: Invalid value in parameter vector for cross()");
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
double d0 = v0[a].toDouble();
|
||||
double d1 = v1[a].toDouble();
|
||||
if (boost::math::isnan(d0) || boost::math::isnan(d1)) {
|
||||
PRINT("WARNING: Invalid value (NaN) in parameter vector for cross()");
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
if (boost::math::isinf(d0) || boost::math::isinf(d1)) {
|
||||
PRINT("WARNING: Invalid value (INF) in parameter vector for cross()");
|
||||
return Value();
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -912,7 +912,7 @@ Value builtin_cross(const Context *, const EvalContext *evalctx)
|
|||
result.push_back(Value(x));
|
||||
result.push_back(Value(y));
|
||||
result.push_back(Value(z));
|
||||
return Value(result);
|
||||
return ValuePtr(result);
|
||||
}
|
||||
|
||||
void register_builtin_functions()
|
||||
|
|
|
@ -18,21 +18,21 @@ public:
|
|||
virtual ~AbstractFunction();
|
||||
virtual bool is_experimental() const { return feature != NULL; }
|
||||
virtual bool is_enabled() const { return (feature == NULL) || feature->is_enabled(); }
|
||||
virtual Value evaluate(const class Context *ctx, const class EvalContext *evalctx) const;
|
||||
virtual ValuePtr evaluate(const class Context *ctx, const class EvalContext *evalctx) const;
|
||||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||
};
|
||||
|
||||
class BuiltinFunction : public AbstractFunction
|
||||
{
|
||||
public:
|
||||
typedef Value (*eval_func_t)(const Context *ctx, const EvalContext *evalctx);
|
||||
typedef ValuePtr (*eval_func_t)(const Context *ctx, const EvalContext *evalctx);
|
||||
eval_func_t eval_func;
|
||||
|
||||
BuiltinFunction(eval_func_t f) : eval_func(f) { }
|
||||
BuiltinFunction(eval_func_t f, const Feature& feature) : AbstractFunction(feature), eval_func(f) { }
|
||||
virtual ~BuiltinFunction();
|
||||
|
||||
virtual Value evaluate(const Context *ctx, const EvalContext *evalctx) const;
|
||||
virtual ValuePtr evaluate(const Context *ctx, const EvalContext *evalctx) const;
|
||||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||
};
|
||||
|
||||
|
@ -46,6 +46,6 @@ public:
|
|||
Function() { }
|
||||
virtual ~Function();
|
||||
|
||||
virtual Value evaluate(const Context *ctx, const EvalContext *evalctx) const;
|
||||
virtual ValuePtr evaluate(const Context *ctx, const EvalContext *evalctx) const;
|
||||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||
};
|
||||
|
|
|
@ -91,14 +91,14 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti
|
|||
c.dump(this, inst);
|
||||
#endif
|
||||
|
||||
Value v = c.lookup_variable("file");
|
||||
if (v.isUndefined()) {
|
||||
ValuePtr v = c.lookup_variable("file");
|
||||
if (v->isUndefined()) {
|
||||
v = c.lookup_variable("filename");
|
||||
if (!v.isUndefined()) {
|
||||
if (!v->isUndefined()) {
|
||||
printDeprecation("DEPRECATED: filename= is deprecated. Please use file=");
|
||||
}
|
||||
}
|
||||
std::string filename = lookup_file(v.isUndefined() ? "" : v.toString(), inst->path(), ctx->documentPath());
|
||||
std::string filename = lookup_file(v->isUndefined() ? "" : v->toString(), inst->path(), ctx->documentPath());
|
||||
import_type_e actualtype = this->type;
|
||||
if (actualtype == TYPE_UNKNOWN) {
|
||||
std::string extraw = boosty::extension_str(fs::path(filename));
|
||||
|
@ -110,31 +110,30 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti
|
|||
|
||||
ImportNode *node = new ImportNode(inst, actualtype);
|
||||
|
||||
node->fn = c.lookup_variable("$fn").toDouble();
|
||||
node->fs = c.lookup_variable("$fs").toDouble();
|
||||
node->fa = c.lookup_variable("$fa").toDouble();
|
||||
node->fn = c.lookup_variable("$fn")->toDouble();
|
||||
node->fs = c.lookup_variable("$fs")->toDouble();
|
||||
node->fa = c.lookup_variable("$fa")->toDouble();
|
||||
|
||||
node->filename = filename;
|
||||
Value layerval = c.lookup_variable("layer", true);
|
||||
Value layerval = *c.lookup_variable("layer", true);
|
||||
if (layerval.isUndefined()) {
|
||||
layerval = c.lookup_variable("layername");
|
||||
layerval = *c.lookup_variable("layername");
|
||||
if (!layerval.isUndefined()) {
|
||||
printDeprecation("DEPRECATED: layername= is deprecated. Please use layer=");
|
||||
}
|
||||
}
|
||||
node->layername = layerval.isUndefined() ? "" : layerval.toString();
|
||||
node->convexity = c.lookup_variable("convexity", true).toDouble();
|
||||
node->convexity = c.lookup_variable("convexity", true)->toDouble();
|
||||
|
||||
if (node->convexity <= 0) node->convexity = 1;
|
||||
|
||||
Value origin = c.lookup_variable("origin", true);
|
||||
ValuePtr origin = c.lookup_variable("origin", true);
|
||||
node->origin_x = node->origin_y = 0;
|
||||
origin.getVec2(node->origin_x, node->origin_y);
|
||||
origin->getVec2(node->origin_x, node->origin_y);
|
||||
|
||||
node->scale = c.lookup_variable("scale", true).toDouble();
|
||||
node->scale = c.lookup_variable("scale", true)->toDouble();
|
||||
|
||||
if (node->scale <= 0)
|
||||
node->scale = 1;
|
||||
if (node->scale <= 0) node->scale = 1;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
|
|
@ -59,46 +59,46 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI
|
|||
Context c(ctx);
|
||||
c.setVariables(args, evalctx);
|
||||
|
||||
node->fn = c.lookup_variable("$fn").toDouble();
|
||||
node->fs = c.lookup_variable("$fs").toDouble();
|
||||
node->fa = c.lookup_variable("$fa").toDouble();
|
||||
node->fn = c.lookup_variable("$fn")->toDouble();
|
||||
node->fs = c.lookup_variable("$fs")->toDouble();
|
||||
node->fa = c.lookup_variable("$fa")->toDouble();
|
||||
|
||||
Value file = c.lookup_variable("file");
|
||||
Value layer = c.lookup_variable("layer", true);
|
||||
Value height = c.lookup_variable("height", true);
|
||||
Value convexity = c.lookup_variable("convexity", true);
|
||||
Value origin = c.lookup_variable("origin", true);
|
||||
Value scale = c.lookup_variable("scale", true);
|
||||
Value center = c.lookup_variable("center", true);
|
||||
Value twist = c.lookup_variable("twist", true);
|
||||
Value slices = c.lookup_variable("slices", true);
|
||||
ValuePtr file = c.lookup_variable("file");
|
||||
ValuePtr layer = c.lookup_variable("layer", true);
|
||||
ValuePtr height = c.lookup_variable("height", true);
|
||||
ValuePtr convexity = c.lookup_variable("convexity", true);
|
||||
ValuePtr origin = c.lookup_variable("origin", true);
|
||||
ValuePtr scale = c.lookup_variable("scale", true);
|
||||
ValuePtr center = c.lookup_variable("center", true);
|
||||
ValuePtr twist = c.lookup_variable("twist", true);
|
||||
ValuePtr slices = c.lookup_variable("slices", true);
|
||||
|
||||
if (!file.isUndefined() && file.type() == Value::STRING) {
|
||||
if (!file->isUndefined() && file->type() == Value::STRING) {
|
||||
printDeprecation("DEPRECATED: Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead.");
|
||||
node->filename = lookup_file(file.toString(), inst->path(), c.documentPath());
|
||||
node->filename = lookup_file(file->toString(), inst->path(), c.documentPath());
|
||||
}
|
||||
|
||||
// if height not given, and first argument is a number,
|
||||
// then assume it should be the height.
|
||||
if (c.lookup_variable("height").isUndefined() &&
|
||||
if (c.lookup_variable("height")->isUndefined() &&
|
||||
evalctx->numArgs() > 0 &&
|
||||
evalctx->getArgName(0) == "") {
|
||||
const Value &val = evalctx->getArgValue(0);
|
||||
if (val.type() == Value::NUMBER) height = val;
|
||||
ValuePtr val = evalctx->getArgValue(0);
|
||||
if (val->type() == Value::NUMBER) height = val;
|
||||
}
|
||||
|
||||
node->layername = layer.isUndefined() ? "" : layer.toString();
|
||||
node->layername = layer->isUndefined() ? "" : layer->toString();
|
||||
node->height = 100;
|
||||
height.getDouble(node->height);
|
||||
node->convexity = (int)convexity.toDouble();
|
||||
origin.getVec2(node->origin_x, node->origin_y);
|
||||
height->getDouble(node->height);
|
||||
node->convexity = (int)convexity->toDouble();
|
||||
origin->getVec2(node->origin_x, node->origin_y);
|
||||
node->scale_x = node->scale_y = 1;
|
||||
scale.getDouble(node->scale_x);
|
||||
scale.getDouble(node->scale_y);
|
||||
scale.getVec2(node->scale_x, node->scale_y);
|
||||
scale->getDouble(node->scale_x);
|
||||
scale->getDouble(node->scale_y);
|
||||
scale->getVec2(node->scale_x, node->scale_y);
|
||||
|
||||
if (center.type() == Value::BOOL)
|
||||
node->center = center.toBool();
|
||||
if (center->type() == Value::BOOL)
|
||||
node->center = center->toBool();
|
||||
|
||||
if (node->height <= 0) node->height = 0;
|
||||
|
||||
|
@ -108,10 +108,10 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI
|
|||
if (node->scale_x < 0) node->scale_x = 0;
|
||||
if (node->scale_y < 0) node->scale_y = 0;
|
||||
|
||||
if (slices.type() == Value::NUMBER) node->slices = (int)slices.toDouble();
|
||||
if (slices->type() == Value::NUMBER) node->slices = (int)slices->toDouble();
|
||||
|
||||
if (twist.type() == Value::NUMBER) {
|
||||
node->twist = twist.toDouble();
|
||||
if (twist->type() == Value::NUMBER) {
|
||||
node->twist = twist->toDouble();
|
||||
if (node->twist != 0.0) {
|
||||
if (node->slices == 0) {
|
||||
node->slices = (int)fmax(2, fabs(Calc::get_fragments_from_r(node->height,
|
||||
|
|
|
@ -1485,7 +1485,7 @@ bool MainWindow::eventFilter(QObject* obj, QEvent *event)
|
|||
|
||||
void MainWindow::updateTemporalVariables()
|
||||
{
|
||||
this->top_ctx.set_variable("$t", Value(this->e_tval->text().toDouble()));
|
||||
this->top_ctx.set_variable("$t", ValuePtr(this->e_tval->text().toDouble()));
|
||||
|
||||
Value::VectorType vpt;
|
||||
vpt.push_back(Value(-qglview->cam.object_trans.x()));
|
||||
|
@ -1497,9 +1497,9 @@ void MainWindow::updateTemporalVariables()
|
|||
vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.x() + 90, 360)));
|
||||
vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.y(), 360)));
|
||||
vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.z(), 360)));
|
||||
top_ctx.set_variable("$vpr", Value(vpr));
|
||||
top_ctx.set_variable("$vpr", ValuePtr(vpr));
|
||||
|
||||
top_ctx.set_variable("$vpd", Value(qglview->cam.viewer_distance));
|
||||
top_ctx.set_variable("$vpd", ValuePtr(qglview->cam.viewer_distance));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1531,25 +1531,25 @@ void MainWindow::updateCamera()
|
|||
BOOST_FOREACH(const Assignment &a, root_module->scope.assignments) {
|
||||
double x, y, z;
|
||||
if ("$vpr" == a.first) {
|
||||
const Value vpr = a.second.get()->evaluate(&mc);
|
||||
if (vpr.getVec3(x, y, z)) {
|
||||
ValuePtr vpr = a.second.get()->evaluate(&mc);
|
||||
if (vpr->getVec3(x, y, z)) {
|
||||
rx = x;
|
||||
ry = y;
|
||||
rz = z;
|
||||
camera_set = true;
|
||||
}
|
||||
} else if ("$vpt" == a.first) {
|
||||
const Value vpt = a.second.get()->evaluate(&mc);
|
||||
if (vpt.getVec3(x, y, z)) {
|
||||
ValuePtr vpt = a.second.get()->evaluate(&mc);
|
||||
if (vpt->getVec3(x, y, z)) {
|
||||
tx = x;
|
||||
ty = y;
|
||||
tz = z;
|
||||
camera_set = true;
|
||||
}
|
||||
} else if ("$vpd" == a.first) {
|
||||
const Value vpd = a.second.get()->evaluate(&mc);
|
||||
if (vpd.type() == Value::NUMBER) {
|
||||
d = vpd.toDouble();
|
||||
ValuePtr vpd = a.second.get()->evaluate(&mc);
|
||||
if (vpd->type() == Value::NUMBER) {
|
||||
d = vpd->toDouble();
|
||||
camera_set = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
using boost::shared_ptr;
|
||||
using boost::make_shared;
|
||||
using boost::dynamic_pointer_cast;
|
||||
using boost::static_pointer_cast;
|
||||
|
|
|
@ -24,8 +24,8 @@ void ModuleContext::evaluateAssignments(const AssignmentList &assignments)
|
|||
// First, assign all simple variables
|
||||
std::list<std::string> undefined_vars;
|
||||
BOOST_FOREACH(const Assignment &ass, assignments) {
|
||||
Value tmpval = ass.second->evaluate(this);
|
||||
if (tmpval.isUndefined()) undefined_vars.push_back(ass.first);
|
||||
ValuePtr tmpval = ass.second->evaluate(this);
|
||||
if (tmpval->isUndefined()) undefined_vars.push_back(ass.first);
|
||||
else this->set_variable(ass.first, tmpval);
|
||||
}
|
||||
|
||||
|
@ -46,12 +46,12 @@ void ModuleContext::evaluateAssignments(const AssignmentList &assignments)
|
|||
boost::unordered_map<std::string, Expression *>::iterator found = tmpass.find(*curr);
|
||||
if (found != tmpass.end()) {
|
||||
const Expression *expr = found->second;
|
||||
Value tmpval = expr->evaluate(this);
|
||||
ValuePtr tmpval = expr->evaluate(this);
|
||||
// FIXME: it's not enough to check for undefined;
|
||||
// we need to check for any undefined variable in the subexpression
|
||||
// For now, ignore this and revisit the validity and order of variable
|
||||
// assignments later
|
||||
if (!tmpval.isUndefined()) {
|
||||
if (!tmpval->isUndefined()) {
|
||||
changed = true;
|
||||
this->set_variable(*curr, tmpval);
|
||||
undefined_vars.erase(curr);
|
||||
|
@ -89,7 +89,7 @@ void ModuleContext::registerBuiltin()
|
|||
this->set_variable(ass.first, ass.second->evaluate(this));
|
||||
}
|
||||
|
||||
this->set_constant("PI",Value(M_PI));
|
||||
this->set_constant("PI", ValuePtr(M_PI));
|
||||
}
|
||||
|
||||
const AbstractFunction *ModuleContext::findLocalFunction(const std::string &name) const
|
||||
|
@ -122,7 +122,8 @@ const AbstractModule *ModuleContext::findLocalModule(const std::string &name) co
|
|||
return NULL;
|
||||
}
|
||||
|
||||
Value ModuleContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const
|
||||
ValuePtr ModuleContext::evaluate_function(const std::string &name,
|
||||
const EvalContext *evalctx) const
|
||||
{
|
||||
const AbstractFunction *foundf = findLocalFunction(name);
|
||||
if (foundf) return foundf->evaluate(this, evalctx);
|
||||
|
@ -156,7 +157,7 @@ std::string ModuleContext::dump(const AbstractModule *mod, const ModuleInstantia
|
|||
}
|
||||
}
|
||||
}
|
||||
typedef std::pair<std::string, Value> ValueMapType;
|
||||
typedef std::pair<std::string, ValuePtr> ValueMapType;
|
||||
s << " vars:";
|
||||
BOOST_FOREACH(const ValueMapType &v, constants) {
|
||||
s << boost::format(" %s = %s") % v.first % v.second;
|
||||
|
@ -177,8 +178,8 @@ FileContext::FileContext(const class FileModule &module, const Context *parent)
|
|||
if (!module.modulePath().empty()) this->document_path = module.modulePath();
|
||||
}
|
||||
|
||||
Value FileContext::sub_evaluate_function(const std::string &name, const EvalContext *evalctx,
|
||||
|
||||
ValuePtr FileContext::sub_evaluate_function(const std::string &name,
|
||||
const EvalContext *evalctx,
|
||||
FileModule *usedmod) const
|
||||
|
||||
{
|
||||
|
@ -192,7 +193,8 @@ Value FileContext::sub_evaluate_function(const std::string &name, const EvalCont
|
|||
return usedmod->scope.functions[name]->evaluate(&ctx, evalctx);
|
||||
}
|
||||
|
||||
Value FileContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const
|
||||
ValuePtr FileContext::evaluate_function(const std::string &name,
|
||||
const EvalContext *evalctx) const
|
||||
{
|
||||
const AbstractFunction *foundf = findLocalFunction(name);
|
||||
if (foundf) return foundf->evaluate(this, evalctx);
|
||||
|
|
|
@ -18,7 +18,7 @@ public:
|
|||
|
||||
void initializeModule(const Module &m);
|
||||
void registerBuiltin();
|
||||
virtual Value evaluate_function(const std::string &name,
|
||||
virtual ValuePtr evaluate_function(const std::string &name,
|
||||
const EvalContext *evalctx) const;
|
||||
virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst,
|
||||
const EvalContext *evalctx) const;
|
||||
|
@ -45,7 +45,8 @@ class FileContext : public ModuleContext
|
|||
public:
|
||||
FileContext(const class FileModule &module, const Context *parent);
|
||||
virtual ~FileContext() {}
|
||||
virtual Value evaluate_function(const std::string &name, const EvalContext *evalctx) const;
|
||||
virtual ValuePtr evaluate_function(const std::string &name,
|
||||
const EvalContext *evalctx) const;
|
||||
virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst,
|
||||
const EvalContext *evalctx) const;
|
||||
|
||||
|
@ -53,5 +54,7 @@ private:
|
|||
const FileModule::ModuleContainer &usedlibs;
|
||||
|
||||
// This sub_* method is needed to minimize stack usage only.
|
||||
Value sub_evaluate_function(const std::string &name, const EvalContext *evalctx, FileModule *usedmod) const;
|
||||
ValuePtr sub_evaluate_function(const std::string &name,
|
||||
const EvalContext *evalctx,
|
||||
FileModule *usedmod) const;
|
||||
};
|
||||
|
|
|
@ -59,14 +59,14 @@ AbstractNode *AbstractModule::instantiate(const Context *ctx, const ModuleInstan
|
|||
|
||||
double AbstractModule::lookup_double_variable_with_default(Context &c, std::string variable, double def) const
|
||||
{
|
||||
const Value v = c.lookup_variable(variable, true);
|
||||
return (v.type() == Value::NUMBER) ? v.toDouble() : def;
|
||||
ValuePtr v = c.lookup_variable(variable, true);
|
||||
return (v->type() == Value::NUMBER) ? v->toDouble() : def;
|
||||
}
|
||||
|
||||
std::string AbstractModule::lookup_string_variable_with_default(Context &c, std::string variable, std::string def) const
|
||||
{
|
||||
const Value v = c.lookup_variable(variable, true);
|
||||
return (v.type() == Value::STRING) ? v.toString() : def;
|
||||
ValuePtr v = c.lookup_variable(variable, true);
|
||||
return (v->type() == Value::STRING) ? v->toString() : def;
|
||||
}
|
||||
|
||||
std::string AbstractModule::dump(const std::string &indent, const std::string &name) const
|
||||
|
@ -195,9 +195,9 @@ AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation
|
|||
|
||||
ModuleContext c(ctx, evalctx);
|
||||
// set $children first since we might have variables depending on it
|
||||
c.set_variable("$children", Value(double(inst->scope.children.size())));
|
||||
c.set_variable("$children", ValuePtr(double(inst->scope.children.size())));
|
||||
module_stack.push_back(inst->name());
|
||||
c.set_variable("$parent_modules", Value(double(module_stack.size())));
|
||||
c.set_variable("$parent_modules", ValuePtr(double(module_stack.size())));
|
||||
c.initializeModule(*this);
|
||||
// FIXME: Set document path to the path of the module
|
||||
#if 0 && DEBUG
|
||||
|
|
|
@ -59,21 +59,21 @@ AbstractNode *OffsetModule::instantiate(const Context *ctx, const ModuleInstanti
|
|||
Context c(ctx);
|
||||
c.setVariables(args, evalctx);
|
||||
|
||||
node->fn = c.lookup_variable("$fn").toDouble();
|
||||
node->fs = c.lookup_variable("$fs").toDouble();
|
||||
node->fa = c.lookup_variable("$fa").toDouble();
|
||||
node->fn = c.lookup_variable("$fn")->toDouble();
|
||||
node->fs = c.lookup_variable("$fs")->toDouble();
|
||||
node->fa = c.lookup_variable("$fa")->toDouble();
|
||||
|
||||
Value delta = c.lookup_variable("delta");
|
||||
ValuePtr delta = c.lookup_variable("delta");
|
||||
node->delta = 1;
|
||||
delta.getDouble(node->delta);
|
||||
delta->getDouble(node->delta);
|
||||
|
||||
Value miter_limit = c.lookup_variable("miter_limit", true);
|
||||
ValuePtr miter_limit = c.lookup_variable("miter_limit", true);
|
||||
node->miter_limit = 2;
|
||||
miter_limit.getDouble(node->miter_limit);
|
||||
miter_limit->getDouble(node->miter_limit);
|
||||
|
||||
Value join_type = c.lookup_variable("join_type", true);
|
||||
if (join_type.type() == Value::STRING) {
|
||||
std::string jt = join_type.toString();
|
||||
ValuePtr join_type = c.lookup_variable("join_type", true);
|
||||
if (join_type->type() == Value::STRING) {
|
||||
std::string jt = join_type->toString();
|
||||
if (std::string("bevel") == jt) {
|
||||
node->join_type = ClipperLib::jtSquare;
|
||||
} else if (std::string("round") == jt) {
|
||||
|
@ -84,7 +84,7 @@ AbstractNode *OffsetModule::instantiate(const Context *ctx, const ModuleInstanti
|
|||
PRINTB("WARNING: Unknown join_type for offset(): '%s'", jt);
|
||||
}
|
||||
|
||||
if ((node->join_type != ClipperLib::jtMiter) && !miter_limit.isUndefined()) {
|
||||
if ((node->join_type != ClipperLib::jtMiter) && !miter_limit->isUndefined()) {
|
||||
PRINTB("WARNING: miter_limit is ignored in offset() for join_type: '%s'", jt);
|
||||
}
|
||||
}
|
||||
|
|
12
src/parser.y
12
src/parser.y
|
@ -308,15 +308,15 @@ single_module_instantiation:
|
|||
expr:
|
||||
TOK_TRUE
|
||||
{
|
||||
$$ = new Expression(Value(true));
|
||||
$$ = new Expression(ValuePtr(true));
|
||||
}
|
||||
| TOK_FALSE
|
||||
{
|
||||
$$ = new Expression(Value(false));
|
||||
$$ = new Expression(ValuePtr(false));
|
||||
}
|
||||
| TOK_UNDEF
|
||||
{
|
||||
$$ = new Expression(Value::undefined);
|
||||
$$ = new Expression(ValuePtr::undefined);
|
||||
}
|
||||
| TOK_ID
|
||||
{
|
||||
|
@ -333,12 +333,12 @@ expr:
|
|||
}
|
||||
| TOK_STRING
|
||||
{
|
||||
$$ = new Expression(Value(std::string($1)));
|
||||
$$ = new Expression(ValuePtr(std::string($1)));
|
||||
free($1);
|
||||
}
|
||||
| TOK_NUMBER
|
||||
{
|
||||
$$ = new Expression(Value($1));
|
||||
$$ = new Expression(ValuePtr($1));
|
||||
}
|
||||
| TOK_LET '(' arguments_call ')' expr %prec LET
|
||||
{
|
||||
|
@ -371,7 +371,7 @@ expr:
|
|||
}
|
||||
| '[' optional_commas ']'
|
||||
{
|
||||
$$ = new Expression(Value(Value::VectorType()));
|
||||
$$ = new Expression(ValuePtr(Value::VectorType()));
|
||||
}
|
||||
| '[' vector_expr optional_commas ']'
|
||||
{
|
||||
|
|
|
@ -108,7 +108,7 @@ public:
|
|||
double fn, fs, fa;
|
||||
primitive_type_e type;
|
||||
int convexity;
|
||||
Value points, paths, faces;
|
||||
ValuePtr points, paths, faces;
|
||||
virtual Geometry *createGeometry() const;
|
||||
};
|
||||
|
||||
|
@ -125,19 +125,19 @@ public:
|
|||
*/
|
||||
Value PrimitiveModule::lookup_radius(const Context &ctx, const std::string &diameter_var, const std::string &radius_var) const
|
||||
{
|
||||
const Value d = ctx.lookup_variable(diameter_var, true);
|
||||
const Value r = ctx.lookup_variable(radius_var, true);
|
||||
const bool r_defined = (r.type() == Value::NUMBER);
|
||||
ValuePtr d = ctx.lookup_variable(diameter_var, true);
|
||||
ValuePtr r = ctx.lookup_variable(radius_var, true);
|
||||
const bool r_defined = (r->type() == Value::NUMBER);
|
||||
|
||||
if (d.type() == Value::NUMBER) {
|
||||
if (d->type() == Value::NUMBER) {
|
||||
if (r_defined) {
|
||||
PRINTB("WARNING: Ignoring radius variable '%s' as diameter '%s' is defined too.", radius_var % diameter_var);
|
||||
}
|
||||
return Value(d.toDouble() / 2.0);
|
||||
return Value(d->toDouble() / 2.0);
|
||||
} else if (r_defined) {
|
||||
return r;
|
||||
return *r;
|
||||
} else {
|
||||
return Value();
|
||||
return Value::undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,9 +179,9 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
|
|||
Context c(ctx);
|
||||
c.setVariables(args, evalctx);
|
||||
|
||||
node->fn = c.lookup_variable("$fn").toDouble();
|
||||
node->fs = c.lookup_variable("$fs").toDouble();
|
||||
node->fa = c.lookup_variable("$fa").toDouble();
|
||||
node->fn = c.lookup_variable("$fn")->toDouble();
|
||||
node->fs = c.lookup_variable("$fs")->toDouble();
|
||||
node->fa = c.lookup_variable("$fa")->toDouble();
|
||||
|
||||
if (node->fs < F_MINIMUM) {
|
||||
PRINTB("WARNING: $fs too small - clamping to %f", F_MINIMUM);
|
||||
|
@ -194,14 +194,14 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
|
|||
|
||||
switch (this->type) {
|
||||
case CUBE: {
|
||||
Value size = c.lookup_variable("size");
|
||||
Value center = c.lookup_variable("center");
|
||||
size.getDouble(node->x);
|
||||
size.getDouble(node->y);
|
||||
size.getDouble(node->z);
|
||||
size.getVec3(node->x, node->y, node->z);
|
||||
if (center.type() == Value::BOOL) {
|
||||
node->center = center.toBool();
|
||||
ValuePtr size = c.lookup_variable("size");
|
||||
ValuePtr center = c.lookup_variable("center");
|
||||
size->getDouble(node->x);
|
||||
size->getDouble(node->y);
|
||||
size->getDouble(node->z);
|
||||
size->getVec3(node->x, node->y, node->z);
|
||||
if (center->type() == Value::BOOL) {
|
||||
node->center = center->toBool();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -213,9 +213,9 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
|
|||
break;
|
||||
}
|
||||
case CYLINDER: {
|
||||
const Value h = c.lookup_variable("h");
|
||||
if (h.type() == Value::NUMBER) {
|
||||
node->h = h.toDouble();
|
||||
ValuePtr h = c.lookup_variable("h");
|
||||
if (h->type() == Value::NUMBER) {
|
||||
node->h = h->toDouble();
|
||||
}
|
||||
|
||||
const Value r = lookup_radius(c, "d", "r");
|
||||
|
@ -232,32 +232,32 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
|
|||
node->r2 = r2.toDouble();
|
||||
}
|
||||
|
||||
const Value center = c.lookup_variable("center");
|
||||
if (center.type() == Value::BOOL) {
|
||||
node->center = center.toBool();
|
||||
ValuePtr center = c.lookup_variable("center");
|
||||
if (center->type() == Value::BOOL) {
|
||||
node->center = center->toBool();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case POLYHEDRON: {
|
||||
node->points = c.lookup_variable("points");
|
||||
node->faces = c.lookup_variable("faces");
|
||||
if (node->faces.type() == Value::UNDEFINED) {
|
||||
if (node->faces->type() == Value::UNDEFINED) {
|
||||
// backwards compatible
|
||||
node->faces = c.lookup_variable("triangles", true);
|
||||
if (node->faces.type() != Value::UNDEFINED) {
|
||||
if (node->faces->type() != Value::UNDEFINED) {
|
||||
printDeprecation("DEPRECATED: polyhedron(triangles=[]) will be removed in future releases. Use polyhedron(faces=[]) instead.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SQUARE: {
|
||||
Value size = c.lookup_variable("size");
|
||||
Value center = c.lookup_variable("center");
|
||||
size.getDouble(node->x);
|
||||
size.getDouble(node->y);
|
||||
size.getVec2(node->x, node->y);
|
||||
if (center.type() == Value::BOOL) {
|
||||
node->center = center.toBool();
|
||||
ValuePtr size = c.lookup_variable("size");
|
||||
ValuePtr center = c.lookup_variable("center");
|
||||
size->getDouble(node->x);
|
||||
size->getDouble(node->y);
|
||||
size->getVec2(node->x, node->y);
|
||||
if (center->type() == Value::BOOL) {
|
||||
node->center = center->toBool();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
|
|||
}
|
||||
}
|
||||
|
||||
node->convexity = c.lookup_variable("convexity", true).toDouble();
|
||||
node->convexity = c.lookup_variable("convexity", true)->toDouble();
|
||||
if (node->convexity < 1)
|
||||
node->convexity = 1;
|
||||
|
||||
|
@ -505,15 +505,15 @@ Geometry *PrimitiveNode::createGeometry() const
|
|||
PolySet *p = new PolySet(3);
|
||||
g = p;
|
||||
p->setConvexity(this->convexity);
|
||||
for (size_t i=0; i<this->faces.toVector().size(); i++)
|
||||
for (size_t i=0; i<this->faces->toVector().size(); i++)
|
||||
{
|
||||
p->append_poly();
|
||||
const Value::VectorType &vec = this->faces.toVector()[i].toVector();
|
||||
const Value::VectorType &vec = this->faces->toVector()[i].toVector();
|
||||
for (size_t j=0; j<vec.size(); j++) {
|
||||
size_t pt = vec[j].toDouble();
|
||||
if (pt < this->points.toVector().size()) {
|
||||
if (pt < this->points->toVector().size()) {
|
||||
double px, py, pz;
|
||||
if (!this->points.toVector()[pt].getVec3(px, py, pz) ||
|
||||
if (!this->points->toVector()[pt].getVec3(px, py, pz) ||
|
||||
isinf(px) || isinf(py) || isinf(pz)) {
|
||||
PRINTB("ERROR: Unable to convert point at index %d to a vec3 of numbers", j);
|
||||
delete p;
|
||||
|
@ -571,7 +571,7 @@ Geometry *PrimitiveNode::createGeometry() const
|
|||
|
||||
Outline2d outline;
|
||||
double x,y;
|
||||
const Value::VectorType &vec = this->points.toVector();
|
||||
const Value::VectorType &vec = this->points->toVector();
|
||||
for (unsigned int i=0;i<vec.size();i++) {
|
||||
const Value &val = vec[i];
|
||||
if (!val.getVec2(x, y) ||
|
||||
|
@ -584,11 +584,11 @@ Geometry *PrimitiveNode::createGeometry() const
|
|||
outline.vertices.push_back(Vector2d(x, y));
|
||||
}
|
||||
|
||||
if (this->paths.toVector().size() == 0 && outline.vertices.size() > 2) {
|
||||
if (this->paths->toVector().size() == 0 && outline.vertices.size() > 2) {
|
||||
p->addOutline(outline);
|
||||
}
|
||||
else {
|
||||
BOOST_FOREACH(const Value &polygon, this->paths.toVector()) {
|
||||
BOOST_FOREACH(const Value &polygon, this->paths->toVector()) {
|
||||
Outline2d curroutline;
|
||||
BOOST_FOREACH(const Value &index, polygon.toVector()) {
|
||||
unsigned int idx = index.toDouble();
|
||||
|
@ -635,8 +635,8 @@ std::string PrimitiveNode::toString() const
|
|||
<< ", r2 = " << this->r2 << ", center = " << (center ? "true" : "false") << ")";
|
||||
break;
|
||||
case POLYHEDRON:
|
||||
stream << "(points = " << this->points
|
||||
<< ", faces = " << this->faces
|
||||
stream << "(points = " << *this->points
|
||||
<< ", faces = " << *this->faces
|
||||
<< ", convexity = " << this->convexity << ")";
|
||||
break;
|
||||
case SQUARE:
|
||||
|
@ -648,7 +648,7 @@ std::string PrimitiveNode::toString() const
|
|||
<< ", $fs = " << this->fs << ", r = " << this->r1 << ")";
|
||||
break;
|
||||
case POLYGON:
|
||||
stream << "(points = " << this->points << ", paths = " << this->paths << ", convexity = " << this->convexity << ")";
|
||||
stream << "(points = " << *this->points << ", paths = " << *this->paths << ", convexity = " << this->convexity << ")";
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
|
|
|
@ -54,13 +54,13 @@ AbstractNode *ProjectionModule::instantiate(const Context *ctx, const ModuleInst
|
|||
Context c(ctx);
|
||||
c.setVariables(args, evalctx);
|
||||
|
||||
Value convexity = c.lookup_variable("convexity", true);
|
||||
Value cut = c.lookup_variable("cut", true);
|
||||
ValuePtr convexity = c.lookup_variable("convexity", true);
|
||||
ValuePtr cut = c.lookup_variable("cut", true);
|
||||
|
||||
node->convexity = (int)convexity.toDouble();
|
||||
node->convexity = (int)convexity->toDouble();
|
||||
|
||||
if (cut.type() == Value::BOOL)
|
||||
node->cut_mode = cut.toBool();
|
||||
if (cut->type() == Value::BOOL)
|
||||
node->cut_mode = cut->toBool();
|
||||
|
||||
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx);
|
||||
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||
|
|
|
@ -51,9 +51,9 @@ AbstractNode *RenderModule::instantiate(const Context *ctx, const ModuleInstanti
|
|||
Context c(ctx);
|
||||
c.setVariables(args, evalctx);
|
||||
|
||||
Value v = c.lookup_variable("convexity");
|
||||
if (v.type() == Value::NUMBER)
|
||||
node->convexity = (int)v.toDouble();
|
||||
ValuePtr v = c.lookup_variable("convexity");
|
||||
if (v->type() == Value::NUMBER)
|
||||
node->convexity = (int)v->toDouble();
|
||||
|
||||
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx);
|
||||
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||
|
|
|
@ -57,25 +57,25 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI
|
|||
Context c(ctx);
|
||||
c.setVariables(args, evalctx);
|
||||
|
||||
node->fn = c.lookup_variable("$fn").toDouble();
|
||||
node->fs = c.lookup_variable("$fs").toDouble();
|
||||
node->fa = c.lookup_variable("$fa").toDouble();
|
||||
node->fn = c.lookup_variable("$fn")->toDouble();
|
||||
node->fs = c.lookup_variable("$fs")->toDouble();
|
||||
node->fa = c.lookup_variable("$fa")->toDouble();
|
||||
|
||||
Value file = c.lookup_variable("file");
|
||||
Value layer = c.lookup_variable("layer", true);
|
||||
Value convexity = c.lookup_variable("convexity", true);
|
||||
Value origin = c.lookup_variable("origin", true);
|
||||
Value scale = c.lookup_variable("scale", true);
|
||||
ValuePtr file = c.lookup_variable("file");
|
||||
ValuePtr layer = c.lookup_variable("layer", true);
|
||||
ValuePtr convexity = c.lookup_variable("convexity", true);
|
||||
ValuePtr origin = c.lookup_variable("origin", true);
|
||||
ValuePtr scale = c.lookup_variable("scale", true);
|
||||
|
||||
if (!file.isUndefined()) {
|
||||
if (!file->isUndefined()) {
|
||||
printDeprecation("DEPRECATED: Support for reading files in rotate_extrude will be removed in future releases. Use a child import() instead.");
|
||||
node->filename = lookup_file(file.toString(), inst->path(), c.documentPath());
|
||||
node->filename = lookup_file(file->toString(), inst->path(), c.documentPath());
|
||||
}
|
||||
|
||||
node->layername = layer.isUndefined() ? "" : layer.toString();
|
||||
node->convexity = (int)convexity.toDouble();
|
||||
origin.getVec2(node->origin_x, node->origin_y);
|
||||
node->scale = scale.toDouble();
|
||||
node->layername = layer->isUndefined() ? "" : layer->toString();
|
||||
node->convexity = (int)convexity->toDouble();
|
||||
origin->getVec2(node->origin_x, node->origin_y);
|
||||
node->scale = scale->toDouble();
|
||||
|
||||
if (node->convexity <= 0)
|
||||
node->convexity = 1;
|
||||
|
|
|
@ -93,22 +93,22 @@ AbstractNode *SurfaceModule::instantiate(const Context *ctx, const ModuleInstant
|
|||
Context c(ctx);
|
||||
c.setVariables(args, evalctx);
|
||||
|
||||
Value fileval = c.lookup_variable("file");
|
||||
node->filename = lookup_file(fileval.isUndefined() ? "" : fileval.toString(), inst->path(), c.documentPath());
|
||||
ValuePtr fileval = c.lookup_variable("file");
|
||||
node->filename = lookup_file(fileval->isUndefined() ? "" : fileval->toString(), inst->path(), c.documentPath());
|
||||
|
||||
Value center = c.lookup_variable("center", true);
|
||||
if (center.type() == Value::BOOL) {
|
||||
node->center = center.toBool();
|
||||
ValuePtr center = c.lookup_variable("center", true);
|
||||
if (center->type() == Value::BOOL) {
|
||||
node->center = center->toBool();
|
||||
}
|
||||
|
||||
Value convexity = c.lookup_variable("convexity", true);
|
||||
if (convexity.type() == Value::NUMBER) {
|
||||
node->convexity = (int)convexity.toDouble();
|
||||
ValuePtr convexity = c.lookup_variable("convexity", true);
|
||||
if (convexity->type() == Value::NUMBER) {
|
||||
node->convexity = (int)convexity->toDouble();
|
||||
}
|
||||
|
||||
Value invert = c.lookup_variable("invert", true);
|
||||
if (invert.type() == Value::BOOL) {
|
||||
node->invert = invert.toBool();
|
||||
ValuePtr invert = c.lookup_variable("invert", true);
|
||||
if (invert->type() == Value::BOOL) {
|
||||
node->invert = invert->toBool();
|
||||
}
|
||||
|
||||
return node;
|
||||
|
|
|
@ -54,9 +54,9 @@ AbstractNode *TextModule::instantiate(const Context *ctx, const ModuleInstantiat
|
|||
Context c(ctx);
|
||||
c.setVariables(args, evalctx);
|
||||
|
||||
double fn = c.lookup_variable("$fn").toDouble();
|
||||
double fa = c.lookup_variable("$fa").toDouble();
|
||||
double fs = c.lookup_variable("$fs").toDouble();
|
||||
double fn = c.lookup_variable("$fn")->toDouble();
|
||||
double fa = c.lookup_variable("$fa")->toDouble();
|
||||
double fs = c.lookup_variable("$fs")->toDouble();
|
||||
|
||||
node->params.set_fn(fn);
|
||||
node->params.set_fa(fa);
|
||||
|
|
|
@ -87,45 +87,45 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta
|
|||
if (this->type == SCALE)
|
||||
{
|
||||
Vector3d scalevec(1,1,1);
|
||||
Value v = c.lookup_variable("v");
|
||||
if (!v.getVec3(scalevec[0], scalevec[1], scalevec[2], 1.0)) {
|
||||
ValuePtr v = c.lookup_variable("v");
|
||||
if (!v->getVec3(scalevec[0], scalevec[1], scalevec[2], 1.0)) {
|
||||
double num;
|
||||
if (v.getDouble(num)) scalevec.setConstant(num);
|
||||
if (v->getDouble(num)) scalevec.setConstant(num);
|
||||
}
|
||||
node->matrix.scale(scalevec);
|
||||
}
|
||||
else if (this->type == ROTATE)
|
||||
{
|
||||
Value val_a = c.lookup_variable("a");
|
||||
if (val_a.type() == Value::VECTOR)
|
||||
ValuePtr val_a = c.lookup_variable("a");
|
||||
if (val_a->type() == Value::VECTOR)
|
||||
{
|
||||
Eigen::AngleAxisd rotx(0, Vector3d::UnitX());
|
||||
Eigen::AngleAxisd roty(0, Vector3d::UnitY());
|
||||
Eigen::AngleAxisd rotz(0, Vector3d::UnitZ());
|
||||
double a;
|
||||
if (val_a.toVector().size() > 0) {
|
||||
val_a.toVector()[0].getDouble(a);
|
||||
if (val_a->toVector().size() > 0) {
|
||||
val_a->toVector()[0].getDouble(a);
|
||||
rotx = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitX());
|
||||
}
|
||||
if (val_a.toVector().size() > 1) {
|
||||
val_a.toVector()[1].getDouble(a);
|
||||
if (val_a->toVector().size() > 1) {
|
||||
val_a->toVector()[1].getDouble(a);
|
||||
roty = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitY());
|
||||
}
|
||||
if (val_a.toVector().size() > 2) {
|
||||
val_a.toVector()[2].getDouble(a);
|
||||
if (val_a->toVector().size() > 2) {
|
||||
val_a->toVector()[2].getDouble(a);
|
||||
rotz = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitZ());
|
||||
}
|
||||
node->matrix.rotate(rotz * roty * rotx);
|
||||
}
|
||||
else
|
||||
{
|
||||
Value val_v = c.lookup_variable("v");
|
||||
ValuePtr val_v = c.lookup_variable("v");
|
||||
double a = 0;
|
||||
|
||||
val_a.getDouble(a);
|
||||
val_a->getDouble(a);
|
||||
|
||||
Vector3d axis(0,0,1);
|
||||
if (val_v.getVec3(axis[0], axis[1], axis[2])) {
|
||||
if (val_v->getVec3(axis[0], axis[1], axis[2])) {
|
||||
if (axis.squaredNorm() > 0) axis.normalize();
|
||||
}
|
||||
|
||||
|
@ -136,10 +136,10 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta
|
|||
}
|
||||
else if (this->type == MIRROR)
|
||||
{
|
||||
Value val_v = c.lookup_variable("v");
|
||||
ValuePtr val_v = c.lookup_variable("v");
|
||||
double x = 1, y = 0, z = 0;
|
||||
|
||||
if (val_v.getVec3(x, y, z)) {
|
||||
if (val_v->getVec3(x, y, z)) {
|
||||
if (x != 0.0 || y != 0.0 || z != 0.0) {
|
||||
double sn = 1.0 / sqrt(x*x + y*y + z*z);
|
||||
x *= sn, y *= sn, z *= sn;
|
||||
|
@ -158,19 +158,20 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta
|
|||
}
|
||||
else if (this->type == TRANSLATE)
|
||||
{
|
||||
Value v = c.lookup_variable("v");
|
||||
ValuePtr v = c.lookup_variable("v");
|
||||
Vector3d translatevec(0,0,0);
|
||||
v.getVec3(translatevec[0], translatevec[1], translatevec[2]);
|
||||
v->getVec3(translatevec[0], translatevec[1], translatevec[2]);
|
||||
node->matrix.translate(translatevec);
|
||||
}
|
||||
else if (this->type == MULTMATRIX)
|
||||
{
|
||||
Value v = c.lookup_variable("m");
|
||||
if (v.type() == Value::VECTOR) {
|
||||
ValuePtr v = c.lookup_variable("m");
|
||||
if (v->type() == Value::VECTOR) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
size_t x = i / 4, y = i % 4;
|
||||
if (y < v.toVector().size() && v.toVector()[y].type() == Value::VECTOR && x < v.toVector()[y].toVector().size())
|
||||
v.toVector()[y].toVector()[x].getDouble(node->matrix(y, x));
|
||||
if (y < v->toVector().size() && v->toVector()[y].type() ==
|
||||
Value::VECTOR && x < v->toVector()[y].toVector().size())
|
||||
v->toVector()[y].toVector()[x].getDouble(node->matrix(y, x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
123
src/value.cc
123
src/value.cc
|
@ -41,6 +41,9 @@
|
|||
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
|
||||
Value Value::undefined;
|
||||
ValuePtr ValuePtr::undefined;
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const Filename &filename)
|
||||
{
|
||||
fs::path fnpath = fs::path( (std::string)filename );
|
||||
|
@ -77,8 +80,6 @@ std::ostream &operator<<(std::ostream &stream, const QuotedString &s)
|
|||
return stream;
|
||||
}
|
||||
|
||||
Value Value::undefined;
|
||||
|
||||
Value::Value() : value(boost::blank())
|
||||
{
|
||||
// std::cout << "creating undef\n";
|
||||
|
@ -688,7 +689,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
Value Value::operator[](const Value &v)
|
||||
Value Value::operator[](const Value &v) const
|
||||
{
|
||||
return boost::apply_visitor(bracket_visitor(), this->value, v.value);
|
||||
}
|
||||
|
@ -790,3 +791,119 @@ bool Value::RangeType::iterator::operator!=(const self_type &other) const
|
|||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
ValuePtr::ValuePtr()
|
||||
{
|
||||
this->reset(new Value());
|
||||
}
|
||||
|
||||
ValuePtr::ValuePtr(const Value &v)
|
||||
{
|
||||
this->reset(new Value(v));
|
||||
}
|
||||
|
||||
ValuePtr::ValuePtr(bool v)
|
||||
{
|
||||
this->reset(new Value(v));
|
||||
}
|
||||
|
||||
ValuePtr::ValuePtr(int v)
|
||||
{
|
||||
this->reset(new Value(v));
|
||||
}
|
||||
|
||||
ValuePtr::ValuePtr(double v)
|
||||
{
|
||||
this->reset(new Value(v));
|
||||
}
|
||||
|
||||
ValuePtr::ValuePtr(const std::string &v)
|
||||
{
|
||||
this->reset(new Value(v));
|
||||
}
|
||||
|
||||
ValuePtr::ValuePtr(const char *v)
|
||||
{
|
||||
this->reset(new Value(v));
|
||||
}
|
||||
|
||||
ValuePtr::ValuePtr(const char v)
|
||||
{
|
||||
this->reset(new Value(v));
|
||||
}
|
||||
|
||||
ValuePtr::ValuePtr(const Value::VectorType &v)
|
||||
{
|
||||
this->reset(new Value(v));
|
||||
}
|
||||
|
||||
ValuePtr::ValuePtr(const Value::RangeType &v)
|
||||
{
|
||||
this->reset(new Value(v));
|
||||
}
|
||||
|
||||
bool ValuePtr::operator==(const ValuePtr &v) const
|
||||
{
|
||||
return ValuePtr(**this == *v);
|
||||
}
|
||||
|
||||
bool ValuePtr::operator!=(const ValuePtr &v) const
|
||||
{
|
||||
return ValuePtr(**this != *v);
|
||||
}
|
||||
|
||||
bool ValuePtr::operator<(const ValuePtr &v) const
|
||||
{
|
||||
return ValuePtr(**this < *v);
|
||||
}
|
||||
|
||||
bool ValuePtr::operator<=(const ValuePtr &v) const
|
||||
{
|
||||
return ValuePtr(**this <= *v);
|
||||
}
|
||||
|
||||
bool ValuePtr::operator>=(const ValuePtr &v) const
|
||||
{
|
||||
return ValuePtr(**this >= *v);
|
||||
}
|
||||
|
||||
bool ValuePtr::operator>(const ValuePtr &v) const
|
||||
{
|
||||
return ValuePtr(**this > *v);
|
||||
}
|
||||
|
||||
ValuePtr ValuePtr::operator-() const
|
||||
{
|
||||
return ValuePtr(-**this);
|
||||
}
|
||||
|
||||
ValuePtr ValuePtr::operator[](const ValuePtr &v) const
|
||||
{
|
||||
return ValuePtr((**this)[*v]);
|
||||
}
|
||||
|
||||
ValuePtr ValuePtr::operator+(const ValuePtr &v) const
|
||||
{
|
||||
return ValuePtr(**this + *v);
|
||||
}
|
||||
|
||||
ValuePtr ValuePtr::operator-(const ValuePtr &v) const
|
||||
{
|
||||
return ValuePtr(**this - *v);
|
||||
}
|
||||
|
||||
ValuePtr ValuePtr::operator*(const ValuePtr &v) const
|
||||
{
|
||||
return ValuePtr(**this * *v);
|
||||
}
|
||||
|
||||
ValuePtr ValuePtr::operator/(const ValuePtr &v) const
|
||||
{
|
||||
return ValuePtr(**this / *v);
|
||||
}
|
||||
|
||||
ValuePtr ValuePtr::operator%(const ValuePtr &v) const
|
||||
{
|
||||
return ValuePtr(**this % *v);
|
||||
}
|
||||
|
||||
|
|
40
src/value.h
40
src/value.h
|
@ -11,6 +11,7 @@
|
|||
#include <boost/lexical_cast.hpp>
|
||||
#endif
|
||||
#include <boost/cstdint.hpp>
|
||||
#include "memory.h"
|
||||
|
||||
class QuotedString : public std::string
|
||||
{
|
||||
|
@ -138,7 +139,7 @@ public:
|
|||
bool operator>=(const Value &v) const;
|
||||
bool operator>(const Value &v) const;
|
||||
Value operator-() const;
|
||||
Value operator[](const Value &v);
|
||||
Value operator[](const Value &v) const;
|
||||
Value operator+(const Value &v) const;
|
||||
Value operator-(const Value &v) const;
|
||||
Value operator*(const Value &v) const;
|
||||
|
@ -160,3 +161,40 @@ private:
|
|||
|
||||
Variant value;
|
||||
};
|
||||
|
||||
class ValuePtr : public shared_ptr<const Value>
|
||||
{
|
||||
public:
|
||||
static ValuePtr undefined;
|
||||
|
||||
ValuePtr();
|
||||
explicit ValuePtr(const Value &v);
|
||||
ValuePtr(bool v);
|
||||
ValuePtr(int v);
|
||||
ValuePtr(double v);
|
||||
ValuePtr(const std::string &v);
|
||||
ValuePtr(const char *v);
|
||||
ValuePtr(const char v);
|
||||
ValuePtr(const Value::VectorType &v);
|
||||
ValuePtr(const Value::RangeType &v);
|
||||
|
||||
operator bool() const { return **this; }
|
||||
|
||||
bool operator==(const ValuePtr &v) const;
|
||||
bool operator!=(const ValuePtr &v) const;
|
||||
bool operator<(const ValuePtr &v) const;
|
||||
bool operator<=(const ValuePtr &v) const;
|
||||
bool operator>=(const ValuePtr &v) const;
|
||||
bool operator>(const ValuePtr &v) const;
|
||||
ValuePtr operator-() const;
|
||||
ValuePtr operator[](const ValuePtr &v) const;
|
||||
ValuePtr operator+(const ValuePtr &v) const;
|
||||
ValuePtr operator-(const ValuePtr &v) const;
|
||||
ValuePtr operator*(const ValuePtr &v) const;
|
||||
ValuePtr operator/(const ValuePtr &v) const;
|
||||
ValuePtr operator%(const ValuePtr &v) const;
|
||||
|
||||
const Value &operator*() const { return *this->get(); }
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue