diff options
author | kintel <kintel@b57f626f-c46c-0410-a088-ec61d464b74c> | 2010-01-30 04:17:05 (GMT) |
---|---|---|
committer | kintel <kintel@b57f626f-c46c-0410-a088-ec61d464b74c> | 2010-01-30 04:17:05 (GMT) |
commit | 6940d171812565209efe679a5d923417c3f47d4a (patch) | |
tree | 2a05d2f8865ff1127f854db41bf31143f64ccf2d /src/openscad.h | |
parent | 2b19f33ee1ddce246c2bfe0a05fe379d0117a741 (diff) |
reorganized file structure layout. more to follow...
git-svn-id: http://svn.clifford.at/openscad/trunk@364 b57f626f-c46c-0410-a088-ec61d464b74c
Diffstat (limited to 'src/openscad.h')
-rw-r--r-- | src/openscad.h | 738 |
1 files changed, 738 insertions, 0 deletions
diff --git a/src/openscad.h b/src/openscad.h new file mode 100644 index 0000000..03ea1cb --- /dev/null +++ b/src/openscad.h @@ -0,0 +1,738 @@ +/* + * 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 + +#ifdef ENABLE_OPENCSG +// this must be included before the GL headers +# include <GL/glew.h> +#endif + +#include <qgl.h> + +#include <QHash> +#include <QCache> +#include <QVector> +#include <QProgressDialog> +#include <QSyntaxHighlighter> +#include <QPointer> + +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <math.h> + +#include <fstream> +#include <iostream> + +// for win32 and maybe others.. +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +class Value; +class Expression; + +class AbstractFunction; +class BuiltinFunction; +class Function; + +class AbstractModule; +class ModuleInstantiation; +class Module; + +class Context; +class PolySet; +class CSGTerm; +class CSGChain; +class AbstractNode; +class AbstractIntersectionNode; +class AbstractPolyNode; +struct CGAL_Nef_polyhedron; + +const double GRID_COARSE = 0.001; +const double GRID_FINE = 0.000001; + +template <typename T> +class Grid2d +{ +public: + double res; + QHash<QPair<int64_t,int64_t>, T> db; + + Grid2d(double resolution) { + res = resolution; + } + /*! + Aligns x,y to the grid or to existing point if one close enough exists. + Returns the value stored if a point already existing or an uninitialized new value + if not. + */ + T &align(double &x, double &y) { + int64_t ix = (int64_t)round(x / res); + int64_t iy = (int64_t)round(y / res); + if (!db.contains(QPair<int64_t,int64_t>(ix, iy))) { + int dist = 10; + for (int64_t jx = ix - 1; jx <= ix + 1; jx++) { + for (int64_t jy = iy - 1; jy <= iy + 1; jy++) { + if (!db.contains(QPair<int64_t,int64_t>(jx, jy))) + continue; + if (abs(ix-jx) + abs(iy-jy) < dist) { + dist = abs(ix-jx) + abs(iy-jy); + ix = jx; + iy = jy; + } + } + } + } + x = ix * res, y = iy * res; + return db[QPair<int64_t,int64_t>(ix, iy)]; + } + bool has(double x, double y) const { + int64_t ix = (int64_t)round(x / res); + int64_t iy = (int64_t)round(y / res); + if (db.contains(QPair<int64_t,int64_t>(ix, iy))) + return true; + for (int64_t jx = ix - 1; jx <= ix + 1; jx++) + for (int64_t jy = iy - 1; jy <= iy + 1; jy++) { + if (db.contains(QPair<int64_t,int64_t>(jx, jy))) + return true; + } + return false; + } + bool eq(double x1, double y1, double x2, double y2) { + align(x1, y1); + align(x2, y2); + if (fabs(x1 - x2) < res && fabs(y1 - y2) < res) + return true; + return false; + } + T &data(double x, double y) { + return align(x, y); + } + T &operator()(double x, double y) { + return align(x, y); + } +}; + +template <typename T> +class Grid3d +{ +public: + double res; + QHash<QPair<QPair<int64_t,int64_t>,int64_t>, T> db; + + Grid3d(double resolution) { + res = resolution; + } + T &align(double &x, double &y, double &z) { + int64_t ix = (int64_t)round(x / res); + int64_t iy = (int64_t)round(y / res); + int64_t iz = (int64_t)round(z / res); + if (!db.contains(QPair<QPair<int64_t,int64_t>,int64_t>(QPair<int64_t,int64_t>(ix, iy), iz))) { + int dist = 10; + for (int64_t jx = ix - 1; jx <= ix + 1; jx++) { + for (int64_t jy = iy - 1; jy <= iy + 1; jy++) { + for (int64_t jz = iz - 1; jz <= iz + 1; jz++) { + if (!db.contains(QPair<QPair<int64_t,int64_t>,int64_t>(QPair<int64_t,int64_t>(jx, jy), jz))) + continue; + if (abs(ix-jx) + abs(iy-jy) + abs(iz-jz) < dist) { + dist = abs(ix-jx) + abs(iy-jy) + abs(iz-jz); + ix = jx; + iy = jy; + iz = jz; + } + } + } + } + } + x = ix * res, y = iy * res, z = iz * res; + return db[QPair<QPair<int64_t,int64_t>,int64_t>(QPair<int64_t,int64_t>(ix, iy), iz)]; + } + bool has(double x, double y, double z) { + int64_t ix = (int64_t)round(x / res); + int64_t iy = (int64_t)round(y / res); + int64_t iz = (int64_t)round(z / res); + if (db.contains(QPair<QPair<int64_t,int64_t>,int64_t>(QPair<int64_t,int64_t>(ix, iy), iz))) + return true; + for (int64_t jx = ix - 1; jx <= ix + 1; jx++) + for (int64_t jy = iy - 1; jy <= iy + 1; jy++) + for (int64_t jz = iz - 1; jz <= iz + 1; jz++) { + if (db.contains(QPair<QPair<int64_t,int64_t>,int64_t>(QPair<int64_t,int64_t>(jx, jy), jz))) + return true; + } + return false; + + } + bool eq(double x1, double y1, double z1, double x2, double y2, double z2) { + align(x1, y1, z1); + align(x2, y2, z2); + if (fabs(x1 - x2) < res && fabs(y1 - y2) < res && fabs(z1 - z2) < res) + return true; + return false; + } + T &data(double x, double y, double z) { + return align(x, y, z); + } + T &operator()(double x, double y, double z) { + return align(x, y, z); + } +}; + +class Value +{ +public: + enum type_e { + UNDEFINED, + BOOL, + NUMBER, + RANGE, + VECTOR, + STRING + }; + + enum type_e type; + + bool b; + double num; + QVector<Value*> vec; + double range_begin; + double range_step; + double range_end; + QString text; + + Value(); + ~Value(); + + Value(bool v); + Value(double v); + Value(const QString &t); + + Value(const Value &v); + Value& operator = (const Value &v); + + Value operator ! () 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 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 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; + + bool getnum(double &v) const; + bool getv2(double &x, double &y) const; + bool getv3(double &x, double &y, double &z) const; + + QString dump() const; + +private: + void reset_undef(); +}; + +class Expression +{ +public: + QVector<Expression*> children; + + Value *const_value; + QString var_name; + + QString call_funcname; + QVector<QString> call_argnames; + + // Boolean: ! && || + // Operators: * / % + - + // Relations: < <= == != >= > + // Vector element: [] + // Condition operator: ?: + // Invert (prefix '-'): I + // Constant value: C + // Create Range: R + // Create Vector: V + // Create Matrix: M + // Lookup Variable: L + // Lookup member per name: N + // Function call: F + QString type; + + Expression(); + ~Expression(); + + Value evaluate(const Context *context) const; + QString dump() const; +}; + +class AbstractFunction +{ +public: + virtual ~AbstractFunction(); + 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; +}; + +class BuiltinFunction : public AbstractFunction +{ +public: + typedef Value (*eval_func_t)(const QVector<QString> &argnames, const QVector<Value> &args); + eval_func_t eval_func; + + BuiltinFunction(eval_func_t f) : eval_func(f) { } + virtual ~BuiltinFunction(); + + 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; +}; + +class Function : public AbstractFunction +{ +public: + QVector<QString> argnames; + QVector<Expression*> argexpr; + + Expression *expr; + + Function() { } + virtual ~Function(); + + 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; +}; + +extern QHash<QString, AbstractFunction*> builtin_functions; +extern void initialize_builtin_functions(); +extern void initialize_builtin_dxf_dim(); +extern void destroy_builtin_functions(); + +class AbstractModule +{ +public: + virtual ~AbstractModule(); + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual QString dump(QString indent, QString name) const; +}; + +class ModuleInstantiation +{ +public: + QString label; + QString modname; + QVector<QString> argnames; + QVector<Expression*> argexpr; + QVector<Value> argvalues; + QVector<ModuleInstantiation*> children; + + bool tag_root; + bool tag_highlight; + bool tag_background; + const Context *ctx; + + ModuleInstantiation() : tag_root(false), tag_highlight(false), tag_background(false), ctx(NULL) { } + ~ModuleInstantiation(); + + QString dump(QString indent) const; + AbstractNode *evaluate(const Context *ctx) const; +}; + +class Module : public AbstractModule +{ +public: + QVector<QString> argnames; + QVector<Expression*> argexpr; + + QVector<QString> assignments_var; + QVector<Expression*> assignments_expr; + + QHash<QString, AbstractFunction*> functions; + QHash<QString, AbstractModule*> modules; + + QVector<ModuleInstantiation*> children; + + Module() { } + virtual ~Module(); + + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const; + virtual QString dump(QString indent, QString name) const; +}; + +extern QHash<QString, AbstractModule*> builtin_modules; +extern void initialize_builtin_modules(); +extern void destroy_builtin_modules(); + +extern void register_builtin_csgops(); +extern void register_builtin_transform(); +extern void register_builtin_primitives(); +extern void register_builtin_surface(); +extern void register_builtin_control(); +extern void register_builtin_render(); +extern void register_builtin_import(); +extern void register_builtin_dxf_linear_extrude(); +extern void register_builtin_dxf_rotate_extrude(); + +class Context +{ +public: + const Context *parent; + QHash<QString, Value> variables; + QHash<QString, Value> config_variables; + const QHash<QString, AbstractFunction*> *functions_p; + const QHash<QString, AbstractModule*> *modules_p; + const ModuleInstantiation *inst_p; + + static QVector<const Context*> ctx_stack; + + Context(const Context *parent = NULL); + ~Context(); + + void args(const QVector<QString> &argnames, const QVector<Expression*> &argexpr, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues); + + void set_variable(QString name, Value value); + Value lookup_variable(QString name, bool silent = false) const; + + Value evaluate_function(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const; + AbstractNode *evaluate_module(const ModuleInstantiation *inst) const; +}; + +class DxfData +{ +public: + struct Point { + double x, y; + Point() : x(0), y(0) { } + Point(double x, double y) : x(x), y(y) { } + }; + struct Path { + QList<Point*> points; + bool is_closed, is_inner; + Path() : is_closed(false), is_inner(false) { } + }; + struct Dim { + unsigned int type; + double coords[7][2]; + double angle; + double length; + QString name; + Dim() { + for (int i = 0; i < 7; i++) + for (int j = 0; j < 2; j++) + coords[i][j] = 0; + type = 0; + angle = 0; + length = 0; + } + }; + + QList<Point> points; + QList<Path> paths; + QList<Dim> dims; + + DxfData(); + DxfData(double fn, double fs, double fa, QString filename, QString layername = QString(), double xorigin = 0.0, double yorigin = 0.0, double scale = 1.0); + DxfData(const struct CGAL_Nef_polyhedron &N); + + Point *addPoint(double x, double y); + +private: + void fixup_path_direction(); +}; + +// 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 + +#ifdef ENABLE_CGAL + +#include <CGAL/Gmpq.h> +#include <CGAL/Extended_cartesian.h> +#include <CGAL/Nef_polyhedron_2.h> +#include <CGAL/Cartesian.h> +#include <CGAL/Polyhedron_3.h> +#include <CGAL/Nef_polyhedron_3.h> +#include <CGAL/IO/Polyhedron_iostream.h> + +typedef CGAL::Extended_cartesian<CGAL::Gmpq> CGAL_Kernel2; +typedef CGAL::Nef_polyhedron_2<CGAL_Kernel2> CGAL_Nef_polyhedron2; +typedef CGAL_Kernel2::Aff_transformation_2 CGAL_Aff_transformation2; + +typedef CGAL::Cartesian<CGAL::Gmpq> CGAL_Kernel3; +typedef CGAL::Polyhedron_3<CGAL_Kernel3> CGAL_Polyhedron; +typedef CGAL_Polyhedron::HalfedgeDS CGAL_HDS; +typedef CGAL::Polyhedron_incremental_builder_3<CGAL_HDS> CGAL_Polybuilder; +typedef CGAL::Nef_polyhedron_3<CGAL_Kernel3> CGAL_Nef_polyhedron3; +typedef CGAL_Nef_polyhedron3::Aff_transformation_3 CGAL_Aff_transformation; +typedef CGAL_Nef_polyhedron3::Vector_3 CGAL_Vector; +typedef CGAL_Nef_polyhedron3::Plane_3 CGAL_Plane; +typedef CGAL_Nef_polyhedron3::Point_3 CGAL_Point; + +struct CGAL_Nef_polyhedron +{ + int dim; + CGAL_Nef_polyhedron2 p2; + CGAL_Nef_polyhedron3 p3; + + CGAL_Nef_polyhedron() { + dim = 0; + } + + CGAL_Nef_polyhedron(const CGAL_Nef_polyhedron2 &p) { + dim = 2; + p2 = p; + } + + CGAL_Nef_polyhedron(const CGAL_Nef_polyhedron3 &p) { + dim = 3; + p3 = p; + } + + int weight() { + if (dim == 2) + return p2.explorer().number_of_vertices(); + if (dim == 3) + return p3.number_of_vertices(); + return 0; + } +}; + +#endif /* ENABLE_CGAL */ + +#ifdef ENABLE_OPENCSG +# include <opencsg.h> +#endif + +class PolySet +{ +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 QList<Point> Polygon; + QVector<Polygon> polygons; + QVector<Polygon> borders; + Grid3d<void*> grid; + + bool is2d; + int convexity; + + PolySet(); + ~PolySet(); + + void append_poly(); + void append_vertex(double x, double y, double z); + void insert_vertex(double x, double y, double z); + + void append_vertex(double x, double y) { + append_vertex(x, y, 0.0); + } + void insert_vertex(double x, double y) { + insert_vertex(x, y, 0.0); + } + + enum colormode_e { + COLORMODE_NONE, + COLORMODE_MATERIAL, + COLORMODE_CUTOUT, + COLORMODE_HIGHLIGHT, + COLORMODE_BACKGROUND + }; + + enum csgmode_e { + CSGMODE_NONE, + CSGMODE_NORMAL = 1, + CSGMODE_DIFFERENCE = 2, + CSGMODE_BACKGROUND = 11, + CSGMODE_BACKGROUND_DIFFERENCE = 12, + CSGMODE_HIGHLIGHT = 21, + CSGMODE_HIGHLIGHT_DIFFERENCE = 22 + }; + + struct ps_cache_entry { + PolySet *ps; + QString msg; + ps_cache_entry(PolySet *ps); + ~ps_cache_entry(); + }; + + static QCache<QString,ps_cache_entry> ps_cache; + + void render_surface(colormode_e colormode, csgmode_e csgmode, double *m, GLint *shaderinfo = NULL) const; + void render_edges(colormode_e colormode, csgmode_e csgmode) const; + +#ifdef ENABLE_CGAL + CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; +#endif + + int refcount; + PolySet *link(); + void unlink(); +}; + +class CSGTerm +{ +public: + enum type_e { + TYPE_PRIMITIVE, + TYPE_UNION, + TYPE_INTERSECTION, + TYPE_DIFFERENCE + }; + + type_e type; + PolySet *polyset; + QString label; + CSGTerm *left; + CSGTerm *right; + double m[20]; + int refcounter; + + CSGTerm(PolySet *polyset, double m[20], QString label); + CSGTerm(type_e type, CSGTerm *left, CSGTerm *right); + + CSGTerm *normalize(); + CSGTerm *normalize_tail(); + + CSGTerm *link(); + void unlink(); + QString dump(); +}; + +class CSGChain +{ +public: + QVector<PolySet*> polysets; + QVector<double*> matrices; + QVector<CSGTerm::type_e> types; + QVector<QString> labels; + + CSGChain(); + + void add(PolySet *polyset, double *m, CSGTerm::type_e type, QString label); + void import(CSGTerm *term, CSGTerm::type_e type = CSGTerm::TYPE_UNION); + QString dump(); +}; + +class AbstractNode +{ +public: + QVector<AbstractNode*> children; + const ModuleInstantiation *modinst; + + int progress_mark; + void progress_prepare(); + void progress_report() const; + + int idx; + static int idx_counter; + QString dump_cache; + + AbstractNode(const ModuleInstantiation *mi); + virtual ~AbstractNode(); + virtual QString mk_cache_id() const; +#ifdef ENABLE_CGAL + struct cgal_nef_cache_entry { + CGAL_Nef_polyhedron N; + QString msg; + cgal_nef_cache_entry(CGAL_Nef_polyhedron N); + }; + static QCache<QString, cgal_nef_cache_entry> cgal_nef_cache; + virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; +#endif + virtual CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const; + virtual QString dump(QString indent) const; +}; + +class AbstractIntersectionNode : public AbstractNode +{ +public: + AbstractIntersectionNode(const ModuleInstantiation *mi) : AbstractNode(mi) { }; +#ifdef ENABLE_CGAL + virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; +#endif + virtual CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const; + virtual QString dump(QString indent) const; +}; + +class AbstractPolyNode : public AbstractNode +{ +public: + enum render_mode_e { + RENDER_CGAL, + RENDER_OPENCSG + }; + AbstractPolyNode(const ModuleInstantiation *mi) : AbstractNode(mi) { }; + virtual PolySet *render_polyset(render_mode_e mode) const; +#ifdef ENABLE_CGAL + virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; +#endif + virtual CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const; + static CSGTerm *render_csg_term_from_ps(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, PolySet *ps, const ModuleInstantiation *modinst, int idx); +}; + +extern QHash<QString,Value> dxf_dim_cache; +extern QHash<QString,Value> dxf_cross_cache; + +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(); + +void dxf_tesselate(PolySet *ps, DxfData *dxf, double rot, bool up, bool do_triangle_splitting, double h); +void dxf_border_to_ps(PolySet *ps, DxfData *dxf); + +#endif /* INCLUDE_ABSTRACT_NODE_DETAILS */ + +class Highlighter : public QSyntaxHighlighter +{ +public: + Highlighter(QTextDocument *parent); + void highlightBlock(const QString &text); +}; + +extern AbstractModule *parse(const char *text, int debug); +extern int get_fragments_from_r(double r, double fn, double fs, double fa); + +extern QString commandline_commands; +extern int parser_error_pos; + +#ifdef ENABLE_CGAL +void export_stl(CGAL_Nef_polyhedron *root_N, QString filename, QProgressDialog *pd); +void export_off(CGAL_Nef_polyhedron *root_N, QString filename, QProgressDialog *pd); +void export_dxf(CGAL_Nef_polyhedron *root_N, QString filename, QProgressDialog *pd); +#endif +extern void handle_dep(QString filename); + +#endif + |