Merge pull request #656 from openscad/vector-norm-cross

Add vector norm() and cross().
issue406^2
Marius Kintel 2014-02-16 22:26:06 -05:00
commit d2024c12bb
5 changed files with 168 additions and 0 deletions

View File

@ -36,6 +36,10 @@
#include "printutils.h"
#include <boost/foreach.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
using boost::math::isnan;
using boost::math::isinf;
/*
Random numbers
@ -598,6 +602,71 @@ Value builtin_parent_module(const Context *, const EvalContext *evalctx)
return Value(Module::stack_element(s - 1 - n));
}
Value builtin_norm(const Context *, const EvalContext *evalctx)
{
if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::VECTOR) {
double sum = 0;
Value::VectorType v = evalctx->getArgValue(0).toVector();
for (size_t i = 0; i < v.size(); i++)
if (v[i].type() == Value::NUMBER)
sum += pow(v[i].toDouble(),2);
else {
PRINT(" WARNING: Incorrect arguments to norm()");
return Value();
}
return Value(sqrt(sum));
}
return Value();
}
Value builtin_cross(const Context *, const EvalContext *evalctx)
{
if (evalctx->numArgs() != 2) {
PRINT("WARNING: Invalid number of parameters for cross()");
return Value();
}
Value arg0 = evalctx->getArgValue(0);
Value arg1 = evalctx->getArgValue(1);
if ((arg0.type() != Value::VECTOR) || (arg1.type() != Value::VECTOR)) {
PRINT("WARNING: Invalid type of parameters for cross()");
return Value();
}
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();
}
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();
}
double d0 = v0[a].toDouble();
double d1 = v1[a].toDouble();
if (isnan(d0) || isnan(d1)) {
PRINT("WARNING: Invalid value (NaN) in parameter vector for cross()");
return Value();
}
if (isinf(d0) || isinf(d1)) {
PRINT("WARNING: Invalid value (INF) in parameter vector for cross()");
return Value();
}
}
double x = v0[1].toDouble() * v1[2].toDouble() - v0[2].toDouble() * v1[1].toDouble();
double y = v0[2].toDouble() * v1[0].toDouble() - v0[0].toDouble() * v1[2].toDouble();
double z = v0[0].toDouble() * v1[1].toDouble() - v0[1].toDouble() * v1[0].toDouble();
Value::VectorType result;
result.push_back(Value(x));
result.push_back(Value(y));
result.push_back(Value(z));
return Value(result);
}
void register_builtin_functions()
{
Builtins::init("abs", new BuiltinFunction(&builtin_abs));
@ -627,5 +696,7 @@ void register_builtin_functions()
Builtins::init("search", new BuiltinFunction(&builtin_search));
Builtins::init("version", new BuiltinFunction(&builtin_version));
Builtins::init("version_num", new BuiltinFunction(&builtin_version_num));
Builtins::init("norm", new BuiltinFunction(&builtin_norm));
Builtins::init("cross", new BuiltinFunction(&builtin_cross));
Builtins::init("parent_module", new BuiltinFunction(&builtin_parent_module));
}

View File

@ -0,0 +1,17 @@
echo(cross([2, 3, 4], [5, 6, 7]));
echo(cross([2, 1, -3], [0, 4, 5]));
echo(cross([2, 1, -3], cross([2, 3, 4], [5, 6, 7])));
echo(cross([2, 0/0, -3], [0, 4, 5]));
echo(cross([2, 1/0, -3], [0, 4, 5]));
echo(cross([2, -1/0, -3], [0, 4, 5]));
echo(cross(0));
echo(cross(0, 1));
echo(cross(0, "a"));
echo(cross(0, 1, 3));
echo(cross([0], [1]));
echo(cross([1, 2, 3], [1, 2]));
echo(cross([1, 2, 3], [1, 2, "a"]));
echo(cross([1, 2, 3], [1, 2, [0]]));
echo(cross([1, 2, 3], [1, 2, [1:2]]));

27
testdata/scad/functions/norm-tests.scad vendored Normal file
View File

@ -0,0 +1,27 @@
u=undef;
echo(norm([]));
echo(norm([1]));
echo(norm([1,2]));
echo(norm([1,2,3]));
echo(norm([1,2,3,4]));
echo(norm());
echo(norm([1,2,0/0]));
echo(norm([1,2,1/0]));
echo(norm([1,2,-1/0]));
echo(norm(""));
echo(norm("abcd"));
echo(norm(true));
echo(norm([1:4]));
echo(norm([1, 2, "a"]));
echo(norm([1, 2, []]));
echo(norm([1, 2, [1]]));
echo(norm([1, 2, [1:3]]));
echo(norm([[1,2,3,4],[1,2,3],[1,2],[1]]));
echo(norm(u));
echo(norm(u, u));
echo(norm(a, a));

View File

@ -0,0 +1,27 @@
ECHO: [-3, 6, -3]
ECHO: [17, -10, 8]
ECHO: [15, 15, 15]
WARNING: Invalid value (NaN) in parameter vector for cross()
ECHO: undef
WARNING: Invalid value (INF) in parameter vector for cross()
ECHO: undef
WARNING: Invalid value (INF) in parameter vector for cross()
ECHO: undef
WARNING: Invalid number of parameters for cross()
ECHO: undef
WARNING: Invalid type of parameters for cross()
ECHO: undef
WARNING: Invalid type of parameters for cross()
ECHO: undef
WARNING: Invalid number of parameters for cross()
ECHO: undef
WARNING: Invalid vector size of parameter for cross()
ECHO: undef
WARNING: Invalid vector size of parameter for cross()
ECHO: undef
WARNING: Invalid value in parameter vector for cross()
ECHO: undef
WARNING: Invalid value in parameter vector for cross()
ECHO: undef
WARNING: Invalid value in parameter vector for cross()
ECHO: undef

View File

@ -0,0 +1,26 @@
ECHO: 0
ECHO: 1
ECHO: 2.2360679775
ECHO: 3.74165738677
ECHO: 5.47722557505
ECHO: undef
ECHO: nan
ECHO: inf
ECHO: inf
ECHO: undef
ECHO: undef
ECHO: undef
ECHO: undef
WARNING: Incorrect arguments to norm()
ECHO: undef
WARNING: Incorrect arguments to norm()
ECHO: undef
WARNING: Incorrect arguments to norm()
ECHO: undef
WARNING: Incorrect arguments to norm()
ECHO: undef
WARNING: Incorrect arguments to norm()
ECHO: undef
ECHO: undef
ECHO: undef
ECHO: undef