2009-06-20 16:10:55 +04:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef OPENSCAD_H
|
|
|
|
#define OPENSCAD_H
|
|
|
|
|
2009-06-20 23:00:19 +04:00
|
|
|
#include <QHash>
|
|
|
|
#include <QVector>
|
2009-06-23 23:56:46 +04:00
|
|
|
#include <QMainWindow>
|
|
|
|
#include <QSplitter>
|
|
|
|
#include <QTextEdit>
|
|
|
|
#include <QGLWidget>
|
|
|
|
|
2009-06-21 10:53:46 +04:00
|
|
|
#include <stdio.h>
|
2009-06-23 23:56:46 +04:00
|
|
|
#include <errno.h>
|
2009-06-21 10:53:46 +04:00
|
|
|
#include <stdlib.h>
|
2009-06-23 23:56:46 +04:00
|
|
|
#include <string.h>
|
2009-06-21 10:53:46 +04:00
|
|
|
#include <math.h>
|
2009-06-20 23:00:19 +04:00
|
|
|
|
2009-06-21 20:41:38 +04:00
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
|
|
|
|
2009-06-20 23:00:19 +04:00
|
|
|
class Value;
|
|
|
|
class Expression;
|
|
|
|
|
|
|
|
class AbstractFunction;
|
|
|
|
class BuiltinFunction;
|
|
|
|
class Function;
|
|
|
|
|
|
|
|
class AbstractModule;
|
|
|
|
class ModuleInstanciation;
|
|
|
|
class Module;
|
|
|
|
|
|
|
|
class Context;
|
|
|
|
class AbstractNode;
|
|
|
|
|
|
|
|
class Value
|
|
|
|
{
|
|
|
|
public:
|
2009-06-23 14:31:25 +04:00
|
|
|
enum type_e {
|
|
|
|
UNDEFINED,
|
|
|
|
BOOL,
|
|
|
|
NUMBER,
|
|
|
|
RANGE,
|
|
|
|
VECTOR,
|
|
|
|
MATRIX,
|
|
|
|
STRING
|
|
|
|
};
|
|
|
|
|
|
|
|
enum type_e type;
|
|
|
|
|
|
|
|
bool b;
|
|
|
|
double num;
|
2009-06-20 23:00:19 +04:00
|
|
|
double x, y, z;
|
2009-06-23 14:31:25 +04:00
|
|
|
double r_begin;
|
|
|
|
double r_step;
|
|
|
|
double r_end;
|
|
|
|
double m[16];
|
2009-06-21 12:59:53 +04:00
|
|
|
QString text;
|
2009-06-20 23:00:19 +04:00
|
|
|
|
2009-06-23 14:31:25 +04:00
|
|
|
Value();
|
|
|
|
Value(bool v);
|
|
|
|
Value(double v);
|
|
|
|
Value(double v1, double v2, double v3);
|
|
|
|
Value(double m[16]);
|
|
|
|
Value(const QString &t);
|
|
|
|
|
|
|
|
Value(const Value &v);
|
2009-06-20 23:00:19 +04:00
|
|
|
Value& operator = (const Value &v);
|
2009-06-23 14:31:25 +04:00
|
|
|
|
2009-06-20 23:00:19 +04:00
|
|
|
Value operator + (const Value &v) const;
|
|
|
|
Value operator - (const Value &v) const;
|
|
|
|
Value operator * (const Value &v) const;
|
|
|
|
Value operator / (const Value &v) const;
|
|
|
|
Value operator % (const Value &v) const;
|
|
|
|
Value inv() const;
|
2009-06-21 10:53:46 +04:00
|
|
|
|
|
|
|
QString dump() const;
|
2009-06-23 14:31:25 +04:00
|
|
|
|
|
|
|
private:
|
|
|
|
void reset_undef();
|
2009-06-20 23:00:19 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
class Expression
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
QVector<Expression*> children;
|
|
|
|
|
|
|
|
Value const_value;
|
|
|
|
QString var_name;
|
|
|
|
|
|
|
|
QString call_funcname;
|
|
|
|
QVector<QString> call_argnames;
|
|
|
|
|
|
|
|
// Math operators: * / % + -
|
2009-06-23 14:31:25 +04:00
|
|
|
// Condition (?: operator): ?
|
2009-06-20 23:00:19 +04:00
|
|
|
// Invert (prefix '-'): I
|
|
|
|
// Constant value: C
|
2009-06-23 14:31:25 +04:00
|
|
|
// Create Range: R
|
2009-06-21 10:53:46 +04:00
|
|
|
// Create Vector: V
|
2009-06-23 14:31:25 +04:00
|
|
|
// Create Matrix: M
|
2009-06-21 10:53:46 +04:00
|
|
|
// Lookup Variable: L
|
2009-06-23 14:31:25 +04:00
|
|
|
// Lookup member per name: N
|
2009-06-20 23:00:19 +04:00
|
|
|
// Function call: F
|
|
|
|
char type;
|
|
|
|
|
|
|
|
Expression();
|
|
|
|
~Expression();
|
|
|
|
|
2009-06-21 10:53:46 +04:00
|
|
|
Value evaluate(const Context *context) const;
|
|
|
|
QString dump() const;
|
2009-06-20 23:00:19 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
class AbstractFunction
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual ~AbstractFunction();
|
2009-06-21 10:53:46 +04:00
|
|
|
virtual Value evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const;
|
|
|
|
virtual QString dump(QString indent, QString name) const;
|
2009-06-20 23:00:19 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
class BuiltinFunction : public AbstractFunction
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef Value (*eval_func_t)(const QVector<Value> &args);
|
|
|
|
eval_func_t eval_func;
|
|
|
|
|
|
|
|
BuiltinFunction(eval_func_t f) : eval_func(f) { }
|
|
|
|
virtual ~BuiltinFunction();
|
|
|
|
|
2009-06-21 10:53:46 +04:00
|
|
|
virtual Value evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const;
|
|
|
|
virtual QString dump(QString indent, QString name) const;
|
2009-06-20 23:00:19 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
class Function : public AbstractFunction
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
QVector<QString> argnames;
|
|
|
|
QVector<Expression*> argexpr;
|
|
|
|
|
2009-06-21 10:53:46 +04:00
|
|
|
Expression *expr;
|
2009-06-20 23:00:19 +04:00
|
|
|
|
|
|
|
Function() { }
|
|
|
|
virtual ~Function();
|
|
|
|
|
2009-06-21 10:53:46 +04:00
|
|
|
virtual Value evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const;
|
|
|
|
virtual QString dump(QString indent, QString name) const;
|
2009-06-20 23:00:19 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
extern QHash<QString, AbstractFunction*> builtin_functions;
|
|
|
|
extern void initialize_builtin_functions();
|
|
|
|
extern void destroy_builtin_functions();
|
|
|
|
|
|
|
|
class AbstractModule
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual ~AbstractModule();
|
2009-06-21 15:41:11 +04:00
|
|
|
virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const;
|
2009-06-21 10:53:46 +04:00
|
|
|
virtual QString dump(QString indent, QString name) const;
|
2009-06-20 23:00:19 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
class ModuleInstanciation
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
QString label;
|
|
|
|
QString modname;
|
|
|
|
QVector<QString> argnames;
|
|
|
|
QVector<Expression*> argexpr;
|
2009-06-21 10:53:46 +04:00
|
|
|
QVector<ModuleInstanciation*> children;
|
2009-06-20 23:00:19 +04:00
|
|
|
|
|
|
|
ModuleInstanciation() { }
|
|
|
|
~ModuleInstanciation();
|
2009-06-21 10:53:46 +04:00
|
|
|
|
2009-06-21 12:59:53 +04:00
|
|
|
QString dump(QString indent) const;
|
|
|
|
AbstractNode *evaluate(const Context *ctx) const;
|
2009-06-20 23:00:19 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
class Module : public AbstractModule
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
QVector<QString> argnames;
|
|
|
|
QVector<Expression*> argexpr;
|
|
|
|
|
2009-06-21 15:41:11 +04:00
|
|
|
QVector<QString> assignments_var;
|
|
|
|
QVector<Expression*> assignments_expr;
|
|
|
|
|
2009-06-20 23:00:19 +04:00
|
|
|
QHash<QString, AbstractFunction*> functions;
|
|
|
|
QHash<QString, AbstractModule*> modules;
|
|
|
|
|
2009-06-21 10:53:46 +04:00
|
|
|
QVector<ModuleInstanciation*> children;
|
2009-06-20 23:00:19 +04:00
|
|
|
|
|
|
|
Module() { }
|
|
|
|
virtual ~Module();
|
|
|
|
|
2009-06-21 15:41:11 +04:00
|
|
|
virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const;
|
2009-06-21 10:53:46 +04:00
|
|
|
virtual QString dump(QString indent, QString name) const;
|
2009-06-20 23:00:19 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
extern QHash<QString, AbstractModule*> builtin_modules;
|
|
|
|
extern void initialize_builtin_modules();
|
|
|
|
extern void destroy_builtin_modules();
|
|
|
|
|
2009-06-23 02:36:36 +04:00
|
|
|
extern void register_builtin_csg();
|
2009-06-21 15:41:11 +04:00
|
|
|
extern void register_builtin_trans();
|
2009-06-23 02:36:36 +04:00
|
|
|
extern void register_builtin_primitive();
|
2009-06-21 15:41:11 +04:00
|
|
|
|
2009-06-20 23:00:19 +04:00
|
|
|
class Context
|
|
|
|
{
|
|
|
|
public:
|
2009-06-21 10:53:46 +04:00
|
|
|
const Context *parent;
|
2009-06-20 23:00:19 +04:00
|
|
|
QHash<QString, Value> variables;
|
2009-06-21 15:41:11 +04:00
|
|
|
const QHash<QString, AbstractFunction*> *functions_p;
|
|
|
|
const QHash<QString, AbstractModule*> *modules_p;
|
2009-06-20 23:00:19 +04:00
|
|
|
|
2009-06-23 23:56:46 +04:00
|
|
|
Context(const Context *parent = NULL) : parent(parent) { }
|
2009-06-20 23:00:19 +04:00
|
|
|
void args(const QVector<QString> &argnames, const QVector<Expression*> &argexpr, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues);
|
|
|
|
|
2009-06-21 10:53:46 +04:00
|
|
|
Value lookup_variable(QString name) const;
|
|
|
|
Value evaluate_function(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const;
|
2009-06-21 15:41:11 +04:00
|
|
|
AbstractNode *evaluate_module(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues, const QVector<AbstractNode*> child_nodes) const;
|
2009-06-20 23:00:19 +04:00
|
|
|
};
|
|
|
|
|
2009-06-21 15:41:11 +04:00
|
|
|
// The CGAL template magic slows down the compilation process by a factor of 5.
|
|
|
|
// So we only include the declaration of AbstractNode where it is needed...
|
|
|
|
#ifdef INCLUDE_ABSTRACT_NODE_DETAILS
|
|
|
|
|
2009-06-23 23:56:46 +04:00
|
|
|
#ifdef ENABLE_CGAL
|
|
|
|
|
2009-06-21 15:41:11 +04:00
|
|
|
#include <CGAL/Gmpq.h>
|
|
|
|
#include <CGAL/Cartesian.h>
|
|
|
|
#include <CGAL/Polyhedron_3.h>
|
|
|
|
#include <CGAL/Nef_polyhedron_3.h>
|
2009-06-21 20:41:38 +04:00
|
|
|
#include <CGAL/IO/Polyhedron_iostream.h>
|
2009-06-21 15:41:11 +04:00
|
|
|
|
2009-06-21 20:41:38 +04:00
|
|
|
typedef CGAL::Cartesian<CGAL::Gmpq> CGAL_Kernel;
|
2009-06-21 15:41:11 +04:00
|
|
|
typedef CGAL::Polyhedron_3<CGAL_Kernel> CGAL_Polyhedron;
|
2009-06-21 20:41:38 +04:00
|
|
|
typedef CGAL_Polyhedron::HalfedgeDS CGAL_HDS;
|
|
|
|
typedef CGAL::Polyhedron_incremental_builder_3<CGAL_HDS> CGAL_Polybuilder;
|
2009-06-21 15:41:11 +04:00
|
|
|
typedef CGAL::Nef_polyhedron_3<CGAL_Kernel> CGAL_Nef_polyhedron;
|
|
|
|
typedef CGAL_Nef_polyhedron::Aff_transformation_3 CGAL_Aff_transformation;
|
|
|
|
typedef CGAL_Nef_polyhedron::Vector_3 CGAL_Vector;
|
|
|
|
typedef CGAL_Nef_polyhedron::Plane_3 CGAL_Plane;
|
|
|
|
typedef CGAL_Nef_polyhedron::Point_3 CGAL_Point;
|
|
|
|
|
2009-06-23 23:56:46 +04:00
|
|
|
#endif /* ENABLE_CGAL */
|
|
|
|
|
2009-06-20 23:00:19 +04:00
|
|
|
class AbstractNode
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
QVector<AbstractNode*> children;
|
2009-06-21 15:41:11 +04:00
|
|
|
|
2009-06-21 16:43:52 +04:00
|
|
|
int progress_mark;
|
|
|
|
void progress_prepare();
|
|
|
|
void progress_report() const;
|
|
|
|
|
2009-06-21 15:41:11 +04:00
|
|
|
virtual ~AbstractNode();
|
2009-06-23 23:56:46 +04:00
|
|
|
#ifdef ENABLE_CGAL
|
2009-06-21 15:41:11 +04:00
|
|
|
virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
|
2009-06-23 23:56:46 +04:00
|
|
|
#endif
|
2009-06-21 15:41:11 +04:00
|
|
|
virtual QString dump(QString indent) const;
|
2009-06-20 23:00:19 +04:00
|
|
|
};
|
|
|
|
|
2009-06-21 16:43:52 +04:00
|
|
|
extern int progress_report_count;
|
|
|
|
extern void (*progress_report_f)(const class AbstractNode*, void*, int);
|
|
|
|
extern void *progress_report_vp;
|
|
|
|
|
|
|
|
void progress_report_prep(AbstractNode *root, void (*f)(const class AbstractNode *node, void *vp, int mark), void *vp);
|
|
|
|
void progress_report_fin();
|
|
|
|
|
2009-06-23 23:56:46 +04:00
|
|
|
#else
|
|
|
|
|
|
|
|
// this is a bit hackish - but a pointer is a pointer..
|
|
|
|
struct CGAL_Nef_polyhedron;
|
|
|
|
|
2009-06-21 15:41:11 +04:00
|
|
|
#endif /* HIDE_ABSTRACT_NODE_DETAILS */
|
|
|
|
|
2009-06-23 23:56:46 +04:00
|
|
|
class GLView : public QGLWidget
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
|
|
|
struct Point {
|
|
|
|
double x, y, z;
|
|
|
|
Point() : x(0), y(0), z(0) { }
|
|
|
|
Point(double x, double y, double z) : x(x), y(y), z(z) { }
|
|
|
|
};
|
|
|
|
typedef QVector<Point> Polygon;
|
|
|
|
QVector<Polygon> polygons;
|
|
|
|
|
|
|
|
void (*renderfunc)(void*);
|
|
|
|
void *renderfunc_vp;
|
|
|
|
|
|
|
|
double viewer_distance;
|
|
|
|
double object_rot_y;
|
|
|
|
double object_rot_z;
|
|
|
|
|
|
|
|
GLView(QWidget *parent = NULL);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
bool mouse_drag_active;
|
|
|
|
int last_mouse_x;
|
|
|
|
int last_mouse_y;
|
|
|
|
|
|
|
|
void wheelEvent(QWheelEvent *event);
|
|
|
|
void mousePressEvent(QMouseEvent *event);
|
|
|
|
void mouseMoveEvent(QMouseEvent *event);
|
|
|
|
void mouseReleaseEvent(QMouseEvent *event);
|
|
|
|
|
|
|
|
void initializeGL();
|
|
|
|
void resizeGL(int w, int h);
|
|
|
|
void paintGL();
|
|
|
|
};
|
|
|
|
|
|
|
|
class MainWindow : public QMainWindow
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
|
|
|
QString filename;
|
|
|
|
QSplitter *s1, *s2;
|
|
|
|
QTextEdit *editor;
|
|
|
|
GLView *screen;
|
|
|
|
QTextEdit *console;
|
|
|
|
|
|
|
|
Context root_ctx;
|
|
|
|
AbstractModule *root_module;
|
|
|
|
AbstractNode *root_node;
|
|
|
|
#ifdef ENABLE_CGAL
|
|
|
|
CGAL_Nef_polyhedron *root_N;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
MainWindow(const char *filename = 0);
|
|
|
|
~MainWindow();
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void actionNew();
|
|
|
|
void actionOpen();
|
|
|
|
void actionSave();
|
|
|
|
void actionSaveAs();
|
|
|
|
void actionCompile();
|
|
|
|
#ifdef ENABLE_CGAL
|
|
|
|
void actionRenderCGAL();
|
|
|
|
#endif
|
|
|
|
void actionDisplayAST();
|
|
|
|
void actionDisplayCSG();
|
|
|
|
void actionExportSTL();
|
|
|
|
void actionExportOFF();
|
|
|
|
};
|
|
|
|
|
|
|
|
extern AbstractModule *parse(const char *text, int debug);
|
2009-06-21 10:53:46 +04:00
|
|
|
|
2009-06-20 16:10:55 +04:00
|
|
|
#endif
|
|
|
|
|