openscad/src/value.cc

347 lines
6.7 KiB
C++

/*
* OpenSCAD (www.openscad.at)
* Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "openscad.h"
Value::Value()
{
reset_undef();
}
Value::~Value()
{
for (int i = 0; i < vec.size(); i++)
delete vec[i];
vec.clear();
}
Value::Value(bool v)
{
reset_undef();
type = BOOL;
b = v;
}
Value::Value(double v)
{
reset_undef();
type = NUMBER;
num = v;
}
Value::Value(const QString &t)
{
reset_undef();
type = STRING;
text = t;
}
Value::Value(const Value &v)
{
*this = v;
}
Value& Value::operator = (const Value &v)
{
reset_undef();
type = v.type;
b = v.b;
num = v.num;
for (int i = 0; i < v.vec.size(); i++)
vec.append(new Value(*v.vec[i]));
range_begin = v.range_begin;
range_step = v.range_step;
range_end = v.range_end;
text = v.text;
return *this;
}
Value Value::operator ! () const
{
if (type == BOOL) {
return Value(!b);
}
return Value();
}
Value Value::operator && (const Value &v) const
{
if (type == BOOL && v.type == BOOL) {
return Value(b && v.b);
}
return Value();
}
Value Value::operator || (const Value &v) const
{
if (type == BOOL && v.type == BOOL) {
return Value(b || v.b);
}
return Value();
}
Value Value::operator + (const Value &v) const
{
if (type == VECTOR && v.type == VECTOR) {
Value r;
r.type = VECTOR;
for (int i = 0; i < vec.size() && i < v.vec.size(); i++)
r.vec.append(new Value(*vec[i] + *v.vec[i]));
return r;
}
if (type == NUMBER && v.type == NUMBER) {
return Value(num + v.num);
}
return Value();
}
Value Value::operator - (const Value &v) const
{
if (type == VECTOR && v.type == VECTOR) {
Value r;
r.type = VECTOR;
for (int i = 0; i < vec.size() && i < v.vec.size(); i++)
r.vec.append(new Value(*vec[i] - *v.vec[i]));
return r;
}
if (type == NUMBER && v.type == NUMBER) {
return Value(num - v.num);
}
return Value();
}
Value Value::operator * (const Value &v) const
{
if (type == VECTOR && v.type == NUMBER) {
Value r;
r.type = VECTOR;
for (int i = 0; i < vec.size(); i++)
r.vec.append(new Value(*vec[i] * v));
return r;
}
if (type == NUMBER && v.type == VECTOR) {
Value r;
r.type = VECTOR;
for (int i = 0; i < v.vec.size(); i++)
r.vec.append(new Value(v * *v.vec[i]));
return r;
}
if (type == NUMBER && v.type == NUMBER) {
return Value(num * v.num);
}
return Value();
}
Value Value::operator / (const Value &v) const
{
if (type == VECTOR && v.type == NUMBER) {
Value r;
r.type = VECTOR;
for (int i = 0; i < vec.size(); i++)
r.vec.append(new Value(*vec[i] / v));
return r;
}
if (type == NUMBER && v.type == VECTOR) {
Value r;
r.type = VECTOR;
for (int i = 0; i < v.vec.size(); i++)
r.vec.append(new Value(v / *v.vec[i]));
return r;
}
if (type == NUMBER && v.type == NUMBER) {
return Value(num / v.num);
}
return Value();
}
Value Value::operator % (const Value &v) const
{
if (type == NUMBER && v.type == NUMBER) {
return Value(fmod(num, v.num));
}
return Value();
}
Value Value::operator < (const Value &v) const
{
if (type == NUMBER && v.type == NUMBER) {
return Value(num < v.num);
}
return Value();
}
Value Value::operator <= (const Value &v) const
{
if (type == NUMBER && v.type == NUMBER) {
return Value(num <= v.num);
}
return Value();
}
Value Value::operator == (const Value &v) const
{
if (type == BOOL && v.type == BOOL) {
return Value(b == v.b);
}
if (type == NUMBER && v.type == NUMBER) {
return Value(num == v.num);
}
if (type == RANGE && v.type == RANGE) {
return Value(range_begin == v.range_begin && range_step == v.range_step && range_end == v.range_end);
}
if (type == VECTOR && v.type == VECTOR) {
if (vec.size() != v.vec.size())
return Value(false);
for (int i=0; i<vec.size(); i++)
if (!(*vec[i] == *v.vec[i]).b)
return Value(false);
return Value(true);
}
if (type == STRING && v.type == STRING) {
return Value(text == v.text);
}
return Value(false);
}
Value Value::operator != (const Value &v) const
{
Value eq = *this == v;
return Value(!eq.b);
}
Value Value::operator >= (const Value &v) const
{
if (type == NUMBER && v.type == NUMBER) {
return Value(num >= v.num);
}
return Value();
}
Value Value::operator > (const Value &v) const
{
if (type == NUMBER && v.type == NUMBER) {
return Value(num > v.num);
}
return Value();
}
Value Value::inv() const
{
if (type == VECTOR) {
Value r;
r.type = VECTOR;
for (int i = 0; i < vec.size(); i++)
r.vec.append(new Value(vec[i]->inv()));
return r;
}
if (type == NUMBER)
return Value(-num);
return Value();
}
bool Value::getnum(double &v) const
{
if (type != NUMBER)
return false;
v = num;
return true;
}
bool Value::getv2(double &x, double &y) const
{
if (type != VECTOR || vec.size() != 2)
return false;
if (vec[0]->type != NUMBER)
return false;
if (vec[1]->type != NUMBER)
return false;
x = vec[0]->num;
y = vec[1]->num;
return true;
}
bool Value::getv3(double &x, double &y, double &z) const
{
if (type == VECTOR && vec.size() == 2) {
if (getv2(x, y)) {
z = 0;
return true;
}
return false;
}
if (type != VECTOR || vec.size() != 3)
return false;
if (vec[0]->type != NUMBER)
return false;
if (vec[1]->type != NUMBER)
return false;
if (vec[2]->type != NUMBER)
return false;
x = vec[0]->num;
y = vec[1]->num;
z = vec[2]->num;
return true;
}
QString Value::dump() const
{
if (type == STRING) {
return QString("\"") + text + QString("\"");
}
if (type == VECTOR) {
QString text = "[";
for (int i = 0; i < vec.size(); i++) {
if (i > 0)
text += ", ";
text += vec[i]->dump();
}
return text + "]";
}
if (type == RANGE) {
QString text;
text.sprintf("[ %g : %g : %g ]", range_begin, range_step, range_end);
return text;
}
if (type == NUMBER) {
QString text;
text.sprintf("%g", num);
return text;
}
if (type == BOOL) {
return QString(b ? "true" : "false");
}
return QString("undef");
}
void Value::reset_undef()
{
type = UNDEFINED;
b = false;
num = 0;
for (int i = 0; i < vec.size(); i++)
delete vec[i];
vec.clear();
range_begin = 0;
range_step = 0;
range_end = 0;
text = QString();
}