2009-06-23 02:36:36 +04:00
|
|
|
/*
|
2011-01-21 04:21:09 +03:00
|
|
|
* OpenSCAD (www.openscad.org)
|
|
|
|
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
|
|
|
* Marius Kintel <marius@kintel.net>
|
2009-06-23 02:36:36 +04:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
2010-02-01 12:34:18 +03:00
|
|
|
* As a special exception, you have permission to link this program
|
|
|
|
* with the CGAL library and distribute executables, as long as you
|
|
|
|
* follow the requirements of the GNU GPL in regard to all of the
|
|
|
|
* software in the executable aside from CGAL.
|
|
|
|
*
|
2009-06-23 02:36:36 +04:00
|
|
|
* 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
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2010-01-30 07:26:05 +03:00
|
|
|
#include "module.h"
|
|
|
|
#include "node.h"
|
|
|
|
#include "polyset.h"
|
|
|
|
#include "context.h"
|
|
|
|
#include "dxfdata.h"
|
|
|
|
#include "dxftess.h"
|
|
|
|
#include "builtin.h"
|
2010-06-14 23:23:38 +04:00
|
|
|
#include "printutils.h"
|
2010-03-02 21:22:31 +03:00
|
|
|
#include "visitor.h"
|
|
|
|
#include <sstream>
|
2010-03-28 19:57:39 +04:00
|
|
|
#include <assert.h>
|
2011-09-03 08:10:36 +04:00
|
|
|
#include <boost/assign/std/vector.hpp>
|
|
|
|
using namespace boost::assign; // bring 'operator+=()' into scope
|
2009-06-23 02:36:36 +04:00
|
|
|
|
2011-06-05 21:55:50 +04:00
|
|
|
#define F_MINIMUM 0.01
|
|
|
|
|
2009-06-23 02:36:36 +04:00
|
|
|
enum primitive_type_e {
|
|
|
|
CUBE,
|
|
|
|
SPHERE,
|
2009-10-05 13:38:48 +04:00
|
|
|
CYLINDER,
|
2009-12-29 14:08:27 +03:00
|
|
|
POLYHEDRON,
|
2010-01-04 20:36:47 +03:00
|
|
|
SQUARE,
|
2010-01-06 22:58:54 +03:00
|
|
|
CIRCLE,
|
|
|
|
POLYGON
|
2009-06-23 02:36:36 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
class PrimitiveModule : public AbstractModule
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
primitive_type_e type;
|
|
|
|
PrimitiveModule(primitive_type_e type) : type(type) { }
|
2010-01-06 22:38:45 +03:00
|
|
|
virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
|
2009-06-23 02:36:36 +04:00
|
|
|
};
|
|
|
|
|
2009-06-24 14:59:15 +04:00
|
|
|
class PrimitiveNode : public AbstractPolyNode
|
2009-06-23 02:36:36 +04:00
|
|
|
{
|
|
|
|
public:
|
2010-03-02 21:22:31 +03:00
|
|
|
PrimitiveNode(const ModuleInstantiation *mi, primitive_type_e type) : AbstractPolyNode(mi), type(type) { }
|
2010-08-28 19:34:22 +04:00
|
|
|
virtual Response accept(class State &state, Visitor &visitor) const {
|
2010-03-02 21:22:31 +03:00
|
|
|
return visitor.visit(state, *this);
|
|
|
|
}
|
|
|
|
virtual std::string toString() const;
|
2010-08-28 23:21:44 +04:00
|
|
|
virtual std::string name() const {
|
|
|
|
switch (this->type) {
|
|
|
|
case CUBE:
|
|
|
|
return "cube";
|
|
|
|
break;
|
|
|
|
case SPHERE:
|
|
|
|
return "sphere";
|
|
|
|
break;
|
|
|
|
case CYLINDER:
|
|
|
|
return "cylinder";
|
|
|
|
break;
|
|
|
|
case POLYHEDRON:
|
|
|
|
return "polyhedron";
|
|
|
|
break;
|
|
|
|
case SQUARE:
|
|
|
|
return "square";
|
|
|
|
break;
|
|
|
|
case CIRCLE:
|
|
|
|
return "circle";
|
|
|
|
break;
|
|
|
|
case POLYGON:
|
|
|
|
return "polygon";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(false && "PrimitiveNode::name(): Unknown primitive type");
|
|
|
|
return AbstractPolyNode::name();
|
|
|
|
}
|
|
|
|
}
|
2010-03-02 21:22:31 +03:00
|
|
|
|
2009-06-23 02:36:36 +04:00
|
|
|
bool center;
|
|
|
|
double x, y, z, h, r1, r2;
|
2009-06-30 22:05:10 +04:00
|
|
|
double fn, fs, fa;
|
2009-06-23 02:36:36 +04:00
|
|
|
primitive_type_e type;
|
2010-01-06 22:58:54 +03:00
|
|
|
int convexity;
|
|
|
|
Value points, paths, triangles;
|
2011-09-09 07:53:05 +04:00
|
|
|
virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const;
|
2009-06-23 02:36:36 +04:00
|
|
|
};
|
|
|
|
|
2010-01-06 22:38:45 +03:00
|
|
|
AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
|
2009-06-23 02:36:36 +04:00
|
|
|
{
|
2010-08-28 23:21:44 +04:00
|
|
|
PrimitiveNode *node = new PrimitiveNode(inst, this->type);
|
2009-06-23 02:36:36 +04:00
|
|
|
|
|
|
|
node->center = false;
|
|
|
|
node->x = node->y = node->z = node->h = node->r1 = node->r2 = 1;
|
|
|
|
|
2011-09-03 08:10:36 +04:00
|
|
|
std::vector<std::string> argnames;
|
|
|
|
std::vector<Expression*> argexpr;
|
2009-06-23 02:36:36 +04:00
|
|
|
|
2010-08-28 23:21:44 +04:00
|
|
|
switch (this->type) {
|
|
|
|
case CUBE:
|
2011-09-03 08:10:36 +04:00
|
|
|
argnames += "size", "center";
|
2010-08-28 23:21:44 +04:00
|
|
|
break;
|
|
|
|
case SPHERE:
|
2011-09-03 08:10:36 +04:00
|
|
|
argnames += "r";
|
2010-08-28 23:21:44 +04:00
|
|
|
break;
|
|
|
|
case CYLINDER:
|
2011-09-03 08:10:36 +04:00
|
|
|
argnames += "h", "r1", "r2", "center";
|
2010-08-28 23:21:44 +04:00
|
|
|
break;
|
|
|
|
case POLYHEDRON:
|
2011-09-03 08:10:36 +04:00
|
|
|
argnames += "points", "triangles", "convexity";
|
2010-08-28 23:21:44 +04:00
|
|
|
break;
|
|
|
|
case SQUARE:
|
2011-09-03 08:10:36 +04:00
|
|
|
argnames += "size", "center";
|
2010-08-28 23:21:44 +04:00
|
|
|
break;
|
|
|
|
case CIRCLE:
|
2011-09-03 08:10:36 +04:00
|
|
|
argnames += "r";
|
2010-08-28 23:21:44 +04:00
|
|
|
break;
|
|
|
|
case POLYGON:
|
2011-09-03 08:10:36 +04:00
|
|
|
argnames += "points", "paths", "convexity";
|
2010-08-28 23:21:44 +04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(false && "PrimitiveModule::evaluate(): Unknown node type");
|
2010-01-06 22:58:54 +03:00
|
|
|
}
|
2009-06-23 02:36:36 +04:00
|
|
|
|
|
|
|
Context c(ctx);
|
2009-07-01 13:48:25 +04:00
|
|
|
c.args(argnames, argexpr, inst->argnames, inst->argvalues);
|
2009-06-23 02:36:36 +04:00
|
|
|
|
2009-06-30 22:05:10 +04:00
|
|
|
node->fn = c.lookup_variable("$fn").num;
|
2009-06-27 02:09:50 +04:00
|
|
|
node->fs = c.lookup_variable("$fs").num;
|
|
|
|
node->fa = c.lookup_variable("$fa").num;
|
2009-06-26 08:32:52 +04:00
|
|
|
|
2011-06-05 21:55:50 +04:00
|
|
|
if (node->fs < F_MINIMUM) {
|
|
|
|
PRINTF("WARNING: $fs too small - clamping to %f", F_MINIMUM);
|
|
|
|
node->fs = F_MINIMUM;
|
2011-04-08 02:36:13 +04:00
|
|
|
}
|
2011-06-05 21:55:50 +04:00
|
|
|
if (node->fa < F_MINIMUM) {
|
|
|
|
PRINTF("WARNING: $fa too small - clamping to %f", F_MINIMUM);
|
|
|
|
node->fa = F_MINIMUM;
|
2011-04-08 02:36:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-23 02:36:36 +04:00
|
|
|
if (type == CUBE) {
|
|
|
|
Value size = c.lookup_variable("size");
|
|
|
|
Value center = c.lookup_variable("center");
|
2009-06-30 22:05:10 +04:00
|
|
|
size.getnum(node->x);
|
|
|
|
size.getnum(node->y);
|
|
|
|
size.getnum(node->z);
|
|
|
|
size.getv3(node->x, node->y, node->z);
|
2009-06-23 14:31:25 +04:00
|
|
|
if (center.type == Value::BOOL) {
|
|
|
|
node->center = center.b;
|
2009-06-23 02:36:36 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type == SPHERE) {
|
|
|
|
Value r = c.lookup_variable("r");
|
2009-06-23 14:31:25 +04:00
|
|
|
if (r.type == Value::NUMBER) {
|
|
|
|
node->r1 = r.num;
|
2009-06-23 02:36:36 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type == CYLINDER) {
|
|
|
|
Value h = c.lookup_variable("h");
|
2009-06-30 22:05:10 +04:00
|
|
|
Value r, r1, r2;
|
|
|
|
r1 = c.lookup_variable("r1");
|
|
|
|
r2 = c.lookup_variable("r2");
|
2011-09-02 04:32:07 +04:00
|
|
|
r = c.lookup_variable("r", true); // silence warning since r has no default value
|
2009-06-23 02:36:36 +04:00
|
|
|
Value center = c.lookup_variable("center");
|
2009-06-23 14:31:25 +04:00
|
|
|
if (h.type == Value::NUMBER) {
|
|
|
|
node->h = h.num;
|
2009-06-23 02:36:36 +04:00
|
|
|
}
|
2009-06-23 14:31:25 +04:00
|
|
|
if (r.type == Value::NUMBER) {
|
|
|
|
node->r1 = r.num;
|
|
|
|
node->r2 = r.num;
|
2009-06-23 02:36:36 +04:00
|
|
|
}
|
2009-06-23 14:31:25 +04:00
|
|
|
if (r1.type == Value::NUMBER) {
|
|
|
|
node->r1 = r1.num;
|
2009-06-23 02:36:36 +04:00
|
|
|
}
|
2009-06-23 14:31:25 +04:00
|
|
|
if (r2.type == Value::NUMBER) {
|
2009-06-23 15:28:35 +04:00
|
|
|
node->r2 = r2.num;
|
2009-06-23 02:36:36 +04:00
|
|
|
}
|
2009-06-23 14:31:25 +04:00
|
|
|
if (center.type == Value::BOOL) {
|
|
|
|
node->center = center.b;
|
2009-06-23 02:36:36 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-19 23:50:00 +04:00
|
|
|
if (type == POLYHEDRON) {
|
2009-10-05 13:38:48 +04:00
|
|
|
node->points = c.lookup_variable("points");
|
|
|
|
node->triangles = c.lookup_variable("triangles");
|
|
|
|
}
|
|
|
|
|
2009-12-29 14:08:27 +03:00
|
|
|
if (type == SQUARE) {
|
|
|
|
Value size = c.lookup_variable("size");
|
|
|
|
Value center = c.lookup_variable("center");
|
|
|
|
size.getnum(node->x);
|
|
|
|
size.getnum(node->y);
|
|
|
|
size.getv2(node->x, node->y);
|
|
|
|
if (center.type == Value::BOOL) {
|
|
|
|
node->center = center.b;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-04 20:36:47 +03:00
|
|
|
if (type == CIRCLE) {
|
|
|
|
Value r = c.lookup_variable("r");
|
|
|
|
if (r.type == Value::NUMBER) {
|
|
|
|
node->r1 = r.num;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-06 22:58:54 +03:00
|
|
|
if (type == POLYGON) {
|
|
|
|
node->points = c.lookup_variable("points");
|
|
|
|
node->paths = c.lookup_variable("paths");
|
|
|
|
}
|
|
|
|
|
|
|
|
node->convexity = c.lookup_variable("convexity", true).num;
|
|
|
|
if (node->convexity < 1)
|
|
|
|
node->convexity = 1;
|
|
|
|
|
2009-06-23 02:36:36 +04:00
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2010-01-08 17:23:14 +03:00
|
|
|
/*!
|
|
|
|
Returns the number of subdivision of a whole circle, given radius and
|
|
|
|
the three special variables $fn, $fs and $fa
|
|
|
|
*/
|
2009-06-30 22:05:10 +04:00
|
|
|
int get_fragments_from_r(double r, double fn, double fs, double fa)
|
2009-06-25 23:53:12 +04:00
|
|
|
{
|
2010-01-30 23:08:50 +03:00
|
|
|
if (r < GRID_FINE) return 0;
|
2009-06-30 22:05:10 +04:00
|
|
|
if (fn > 0.0)
|
2009-08-10 11:18:35 +04:00
|
|
|
return (int)fn;
|
2009-06-26 14:56:50 +04:00
|
|
|
return (int)ceil(fmax(fmin(360.0 / fa, r*M_PI / fs), 5));
|
2009-06-25 23:53:12 +04:00
|
|
|
}
|
2009-06-23 23:56:46 +04:00
|
|
|
|
2011-04-13 16:30:55 +04:00
|
|
|
struct point2d {
|
|
|
|
double x, y;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void generate_circle(point2d *circle, double r, int fragments)
|
|
|
|
{
|
|
|
|
for (int i=0; i<fragments; i++) {
|
2011-06-05 19:40:53 +04:00
|
|
|
double phi = (M_PI*2*i) / fragments;
|
2011-04-13 16:30:55 +04:00
|
|
|
circle[i].x = r*cos(phi);
|
|
|
|
circle[i].y = r*sin(phi);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-09 07:53:05 +04:00
|
|
|
PolySet *PrimitiveNode::evaluate_polyset(class PolySetEvaluator *) const
|
2009-06-23 02:36:36 +04:00
|
|
|
{
|
2009-06-24 14:59:15 +04:00
|
|
|
PolySet *p = new PolySet();
|
|
|
|
|
2010-08-28 23:21:44 +04:00
|
|
|
if (this->type == CUBE && this->x > 0 && this->y > 0 && this->z > 0)
|
2009-06-24 14:59:15 +04:00
|
|
|
{
|
|
|
|
double x1, x2, y1, y2, z1, z2;
|
2010-08-28 23:21:44 +04:00
|
|
|
if (this->center) {
|
|
|
|
x1 = -this->x/2;
|
|
|
|
x2 = +this->x/2;
|
|
|
|
y1 = -this->y/2;
|
|
|
|
y2 = +this->y/2;
|
|
|
|
z1 = -this->z/2;
|
|
|
|
z2 = +this->z/2;
|
2009-06-24 14:59:15 +04:00
|
|
|
} else {
|
|
|
|
x1 = y1 = z1 = 0;
|
2010-08-28 23:21:44 +04:00
|
|
|
x2 = this->x;
|
|
|
|
y2 = this->y;
|
|
|
|
z2 = this->z;
|
2009-06-24 14:59:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
p->append_poly(); // top
|
|
|
|
p->append_vertex(x1, y1, z2);
|
|
|
|
p->append_vertex(x2, y1, z2);
|
|
|
|
p->append_vertex(x2, y2, z2);
|
|
|
|
p->append_vertex(x1, y2, z2);
|
|
|
|
|
|
|
|
p->append_poly(); // bottom
|
|
|
|
p->append_vertex(x1, y2, z1);
|
|
|
|
p->append_vertex(x2, y2, z1);
|
|
|
|
p->append_vertex(x2, y1, z1);
|
|
|
|
p->append_vertex(x1, y1, z1);
|
|
|
|
|
|
|
|
p->append_poly(); // side1
|
|
|
|
p->append_vertex(x1, y1, z1);
|
|
|
|
p->append_vertex(x2, y1, z1);
|
|
|
|
p->append_vertex(x2, y1, z2);
|
|
|
|
p->append_vertex(x1, y1, z2);
|
|
|
|
|
|
|
|
p->append_poly(); // side2
|
|
|
|
p->append_vertex(x2, y1, z1);
|
|
|
|
p->append_vertex(x2, y2, z1);
|
|
|
|
p->append_vertex(x2, y2, z2);
|
|
|
|
p->append_vertex(x2, y1, z2);
|
|
|
|
|
|
|
|
p->append_poly(); // side3
|
|
|
|
p->append_vertex(x2, y2, z1);
|
|
|
|
p->append_vertex(x1, y2, z1);
|
|
|
|
p->append_vertex(x1, y2, z2);
|
|
|
|
p->append_vertex(x2, y2, z2);
|
|
|
|
|
|
|
|
p->append_poly(); // side4
|
|
|
|
p->append_vertex(x1, y2, z1);
|
|
|
|
p->append_vertex(x1, y1, z1);
|
|
|
|
p->append_vertex(x1, y1, z2);
|
|
|
|
p->append_vertex(x1, y2, z2);
|
|
|
|
}
|
2009-06-23 02:36:36 +04:00
|
|
|
|
2010-08-28 23:21:44 +04:00
|
|
|
if (this->type == SPHERE && this->r1 > 0)
|
2009-06-24 14:59:15 +04:00
|
|
|
{
|
2009-06-25 23:53:12 +04:00
|
|
|
struct ring_s {
|
|
|
|
point2d *points;
|
2011-03-22 23:38:48 +03:00
|
|
|
double z;
|
2009-06-25 23:53:12 +04:00
|
|
|
};
|
|
|
|
|
2011-03-22 23:38:48 +03:00
|
|
|
int fragments = get_fragments_from_r(r1, fn, fs, fa);
|
|
|
|
int rings = fragments/2;
|
2011-04-13 16:30:55 +04:00
|
|
|
// Uncomment the following three lines to enable experimental sphere tesselation
|
|
|
|
// if (rings % 2 == 0) rings++; // To ensure that the middle ring is at phi == 0 degrees
|
2011-04-08 02:34:57 +04:00
|
|
|
|
2011-01-19 02:17:31 +03:00
|
|
|
ring_s *ring = new ring_s[rings];
|
2009-06-25 23:53:12 +04:00
|
|
|
|
2011-04-13 16:30:55 +04:00
|
|
|
// double offset = 0.5 * ((fragments / 2) % 2);
|
2009-06-25 23:53:12 +04:00
|
|
|
for (int i = 0; i < rings; i++) {
|
2011-04-13 16:30:55 +04:00
|
|
|
// double phi = (M_PI * (i + offset)) / (fragments/2);
|
2009-06-25 23:53:12 +04:00
|
|
|
double phi = (M_PI * (i + 0.5)) / rings;
|
2011-03-22 23:38:48 +03:00
|
|
|
double r = r1 * sin(phi);
|
2009-06-25 23:53:12 +04:00
|
|
|
ring[i].z = r1 * cos(phi);
|
2011-03-22 23:38:48 +03:00
|
|
|
ring[i].points = new point2d[fragments];
|
2011-04-13 16:30:55 +04:00
|
|
|
generate_circle(ring[i].points, r, fragments);
|
2009-06-25 23:53:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
p->append_poly();
|
2011-03-22 23:38:48 +03:00
|
|
|
for (int i = 0; i < fragments; i++)
|
2009-06-26 14:56:50 +04:00
|
|
|
p->append_vertex(ring[0].points[i].x, ring[0].points[i].y, ring[0].z);
|
2009-06-25 23:53:12 +04:00
|
|
|
|
|
|
|
for (int i = 0; i < rings-1; i++) {
|
|
|
|
ring_s *r1 = &ring[i];
|
|
|
|
ring_s *r2 = &ring[i+1];
|
|
|
|
int r1i = 0, r2i = 0;
|
2011-03-22 23:38:48 +03:00
|
|
|
while (r1i < fragments || r2i < fragments)
|
2009-06-25 23:53:12 +04:00
|
|
|
{
|
2011-03-22 23:38:48 +03:00
|
|
|
if (r1i >= fragments)
|
2009-06-25 23:53:12 +04:00
|
|
|
goto sphere_next_r2;
|
2011-03-22 23:38:48 +03:00
|
|
|
if (r2i >= fragments)
|
2009-06-25 23:53:12 +04:00
|
|
|
goto sphere_next_r1;
|
2011-03-22 23:38:48 +03:00
|
|
|
if ((double)r1i / fragments <
|
|
|
|
(double)r2i / fragments)
|
2009-06-25 23:53:12 +04:00
|
|
|
{
|
|
|
|
sphere_next_r1:
|
|
|
|
p->append_poly();
|
2011-03-22 23:38:48 +03:00
|
|
|
int r1j = (r1i+1) % fragments;
|
2009-06-26 14:56:50 +04:00
|
|
|
p->insert_vertex(r1->points[r1i].x, r1->points[r1i].y, r1->z);
|
|
|
|
p->insert_vertex(r1->points[r1j].x, r1->points[r1j].y, r1->z);
|
2011-03-22 23:38:48 +03:00
|
|
|
p->insert_vertex(r2->points[r2i % fragments].x, r2->points[r2i % fragments].y, r2->z);
|
2009-06-25 23:53:12 +04:00
|
|
|
r1i++;
|
|
|
|
} else {
|
|
|
|
sphere_next_r2:
|
|
|
|
p->append_poly();
|
2011-03-22 23:38:48 +03:00
|
|
|
int r2j = (r2i+1) % fragments;
|
2009-06-25 23:53:12 +04:00
|
|
|
p->append_vertex(r2->points[r2i].x, r2->points[r2i].y, r2->z);
|
|
|
|
p->append_vertex(r2->points[r2j].x, r2->points[r2j].y, r2->z);
|
2011-03-22 23:38:48 +03:00
|
|
|
p->append_vertex(r1->points[r1i % fragments].x, r1->points[r1i % fragments].y, r1->z);
|
2009-06-25 23:53:12 +04:00
|
|
|
r2i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
p->append_poly();
|
2011-03-22 23:38:48 +03:00
|
|
|
for (int i = 0; i < fragments; i++)
|
2009-06-26 14:56:50 +04:00
|
|
|
p->insert_vertex(ring[rings-1].points[i].x, ring[rings-1].points[i].y, ring[rings-1].z);
|
2011-01-19 02:17:31 +03:00
|
|
|
|
|
|
|
delete[] ring;
|
2009-06-24 14:59:15 +04:00
|
|
|
}
|
2009-06-23 02:36:36 +04:00
|
|
|
|
2010-08-28 23:21:44 +04:00
|
|
|
if (this->type == CYLINDER &&
|
|
|
|
this->h > 0 && this->r1 >=0 && this->r2 >= 0 && (this->r1 > 0 || this->r2 > 0))
|
2009-06-23 02:36:36 +04:00
|
|
|
{
|
2010-08-28 23:21:44 +04:00
|
|
|
int fragments = get_fragments_from_r(fmax(this->r1, this->r2), this->fn, this->fs, this->fa);
|
2009-06-24 14:59:15 +04:00
|
|
|
|
|
|
|
double z1, z2;
|
2010-08-28 23:21:44 +04:00
|
|
|
if (this->center) {
|
|
|
|
z1 = -this->h/2;
|
|
|
|
z2 = +this->h/2;
|
2009-06-24 14:59:15 +04:00
|
|
|
} else {
|
|
|
|
z1 = 0;
|
2010-08-28 23:21:44 +04:00
|
|
|
z2 = this->h;
|
2009-06-24 14:59:15 +04:00
|
|
|
}
|
|
|
|
|
2011-01-19 02:17:31 +03:00
|
|
|
point2d *circle1 = new point2d[fragments];
|
|
|
|
point2d *circle2 = new point2d[fragments];
|
2009-06-24 14:59:15 +04:00
|
|
|
|
2011-04-13 16:30:55 +04:00
|
|
|
generate_circle(circle1, r1, fragments);
|
|
|
|
generate_circle(circle2, r2, fragments);
|
2009-06-24 14:59:15 +04:00
|
|
|
|
|
|
|
for (int i=0; i<fragments; i++) {
|
|
|
|
int j = (i+1) % fragments;
|
2011-03-22 22:50:59 +03:00
|
|
|
if (r1 == r2) {
|
2009-06-30 22:19:57 +04:00
|
|
|
p->append_poly();
|
|
|
|
p->insert_vertex(circle1[i].x, circle1[i].y, z1);
|
|
|
|
p->insert_vertex(circle2[i].x, circle2[i].y, z2);
|
|
|
|
p->insert_vertex(circle2[j].x, circle2[j].y, z2);
|
|
|
|
p->insert_vertex(circle1[j].x, circle1[j].y, z1);
|
2011-03-22 22:50:59 +03:00
|
|
|
} else {
|
|
|
|
if (r1 > 0) {
|
|
|
|
p->append_poly();
|
|
|
|
p->insert_vertex(circle1[i].x, circle1[i].y, z1);
|
|
|
|
p->insert_vertex(circle2[i].x, circle2[i].y, z2);
|
|
|
|
p->insert_vertex(circle1[j].x, circle1[j].y, z1);
|
|
|
|
}
|
|
|
|
if (r2 > 0) {
|
|
|
|
p->append_poly();
|
|
|
|
p->insert_vertex(circle2[i].x, circle2[i].y, z2);
|
|
|
|
p->insert_vertex(circle2[j].x, circle2[j].y, z2);
|
|
|
|
p->insert_vertex(circle1[j].x, circle1[j].y, z1);
|
|
|
|
}
|
2009-06-30 22:19:57 +04:00
|
|
|
}
|
2009-06-23 02:36:36 +04:00
|
|
|
}
|
|
|
|
|
2010-08-28 23:21:44 +04:00
|
|
|
if (this->r1 > 0) {
|
2009-06-24 14:59:15 +04:00
|
|
|
p->append_poly();
|
|
|
|
for (int i=0; i<fragments; i++)
|
2009-06-25 13:49:28 +04:00
|
|
|
p->insert_vertex(circle1[i].x, circle1[i].y, z1);
|
2009-06-23 02:36:36 +04:00
|
|
|
}
|
|
|
|
|
2010-08-28 23:21:44 +04:00
|
|
|
if (this->r2 > 0) {
|
2009-06-24 14:59:15 +04:00
|
|
|
p->append_poly();
|
|
|
|
for (int i=0; i<fragments; i++)
|
2009-06-25 13:49:28 +04:00
|
|
|
p->append_vertex(circle2[i].x, circle2[i].y, z2);
|
2009-06-23 02:36:36 +04:00
|
|
|
}
|
2011-01-19 02:17:31 +03:00
|
|
|
|
|
|
|
delete[] circle1;
|
|
|
|
delete[] circle2;
|
2009-06-23 02:36:36 +04:00
|
|
|
}
|
|
|
|
|
2010-08-28 23:21:44 +04:00
|
|
|
if (this->type == POLYHEDRON)
|
2009-10-05 13:38:48 +04:00
|
|
|
{
|
2010-08-28 23:21:44 +04:00
|
|
|
p->convexity = this->convexity;
|
2011-04-29 01:36:56 +04:00
|
|
|
for (size_t i=0; i<this->triangles.vec.size(); i++)
|
2009-10-05 13:38:48 +04:00
|
|
|
{
|
|
|
|
p->append_poly();
|
2011-04-29 01:36:56 +04:00
|
|
|
for (size_t j=0; j<this->triangles.vec[i]->vec.size(); j++) {
|
2011-09-03 08:10:36 +04:00
|
|
|
size_t pt = this->triangles.vec[i]->vec[j]->num;
|
2010-08-28 23:21:44 +04:00
|
|
|
if (pt < this->points.vec.size()) {
|
2010-01-09 15:23:49 +03:00
|
|
|
double px, py, pz;
|
2010-08-28 23:21:44 +04:00
|
|
|
if (this->points.vec[pt]->getv3(px, py, pz))
|
2010-01-09 15:23:49 +03:00
|
|
|
p->insert_vertex(px, py, pz);
|
|
|
|
}
|
2009-10-05 13:38:48 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-25 19:46:21 +04:00
|
|
|
if (this->type == SQUARE && x > 0 && y > 0)
|
2009-12-29 14:08:27 +03:00
|
|
|
{
|
|
|
|
double x1, x2, y1, y2;
|
2010-08-28 23:21:44 +04:00
|
|
|
if (this->center) {
|
|
|
|
x1 = -this->x/2;
|
|
|
|
x2 = +this->x/2;
|
|
|
|
y1 = -this->y/2;
|
|
|
|
y2 = +this->y/2;
|
2009-12-29 14:08:27 +03:00
|
|
|
} else {
|
|
|
|
x1 = y1 = 0;
|
2010-08-28 23:21:44 +04:00
|
|
|
x2 = this->x;
|
|
|
|
y2 = this->y;
|
2009-12-29 14:08:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
p->is2d = true;
|
|
|
|
p->append_poly();
|
|
|
|
p->append_vertex(x1, y1);
|
|
|
|
p->append_vertex(x2, y1);
|
|
|
|
p->append_vertex(x2, y2);
|
|
|
|
p->append_vertex(x1, y2);
|
|
|
|
}
|
|
|
|
|
2010-08-28 23:21:44 +04:00
|
|
|
if (this->type == CIRCLE)
|
2010-01-04 20:36:47 +03:00
|
|
|
{
|
2010-08-28 23:21:44 +04:00
|
|
|
int fragments = get_fragments_from_r(this->r1, this->fn, this->fs, this->fa);
|
2010-01-04 20:36:47 +03:00
|
|
|
|
2011-01-19 02:17:31 +03:00
|
|
|
p->is2d = true;
|
|
|
|
p->append_poly();
|
2010-01-04 20:36:47 +03:00
|
|
|
|
2011-01-19 02:17:31 +03:00
|
|
|
for (int i=0; i < fragments; i++) {
|
2010-01-04 20:36:47 +03:00
|
|
|
double phi = (M_PI*2*i) / fragments;
|
2011-04-12 22:35:44 +04:00
|
|
|
p->append_vertex(this->r1*cos(phi), this->r1*sin(phi));
|
2010-01-04 20:36:47 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-28 23:21:44 +04:00
|
|
|
if (this->type == POLYGON)
|
2010-01-06 22:58:54 +03:00
|
|
|
{
|
|
|
|
DxfData dd;
|
|
|
|
|
2011-04-29 01:36:56 +04:00
|
|
|
for (size_t i=0; i<this->points.vec.size(); i++) {
|
2010-06-14 23:23:38 +04:00
|
|
|
double x,y;
|
2010-08-28 23:21:44 +04:00
|
|
|
if (!this->points.vec[i]->getv2(x, y)) {
|
2010-06-14 23:23:38 +04:00
|
|
|
PRINTF("ERROR: Unable to convert point at index %d to a vec2 of numbers", i);
|
2011-09-09 07:53:05 +04:00
|
|
|
delete p;
|
2010-11-08 01:50:57 +03:00
|
|
|
return NULL;
|
2010-06-14 23:23:38 +04:00
|
|
|
}
|
2011-09-04 00:44:41 +04:00
|
|
|
dd.points.push_back(Vector2d(x, y));
|
2010-01-06 22:58:54 +03:00
|
|
|
}
|
|
|
|
|
2010-08-28 23:21:44 +04:00
|
|
|
if (this->paths.vec.size() == 0)
|
2010-01-06 22:58:54 +03:00
|
|
|
{
|
2011-09-04 00:44:41 +04:00
|
|
|
dd.paths.push_back(DxfData::Path());
|
2011-04-29 01:36:56 +04:00
|
|
|
for (size_t i=0; i<this->points.vec.size(); i++) {
|
2010-04-05 14:28:41 +04:00
|
|
|
assert(i < dd.points.size()); // FIXME: Not needed, but this used to be an 'if'
|
2011-09-04 00:44:41 +04:00
|
|
|
dd.paths.back().indices.push_back(i);
|
2010-01-09 15:23:49 +03:00
|
|
|
}
|
2011-09-04 00:44:41 +04:00
|
|
|
if (dd.paths.back().indices.size() > 0) {
|
|
|
|
dd.paths.back().indices.push_back(dd.paths.back().indices.front());
|
|
|
|
dd.paths.back().is_closed = true;
|
2010-01-06 22:58:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-04-29 01:36:56 +04:00
|
|
|
for (size_t i=0; i<this->paths.vec.size(); i++)
|
2010-01-06 22:58:54 +03:00
|
|
|
{
|
2011-09-04 00:44:41 +04:00
|
|
|
dd.paths.push_back(DxfData::Path());
|
2011-04-29 01:36:56 +04:00
|
|
|
for (size_t j=0; j<this->paths.vec[i]->vec.size(); j++) {
|
2010-08-28 23:21:44 +04:00
|
|
|
int idx = this->paths.vec[i]->vec[j]->num;
|
2010-01-13 13:48:30 +03:00
|
|
|
if (idx < dd.points.size()) {
|
2011-09-04 00:44:41 +04:00
|
|
|
dd.paths.back().indices.push_back(idx);
|
2010-01-13 13:48:30 +03:00
|
|
|
}
|
|
|
|
}
|
2011-09-04 00:44:41 +04:00
|
|
|
if (dd.paths.back().indices.empty()) {
|
|
|
|
dd.paths.pop_back();
|
2010-01-13 13:48:30 +03:00
|
|
|
} else {
|
2011-09-04 00:44:41 +04:00
|
|
|
dd.paths.back().indices.push_back(dd.paths.back().indices.front());
|
|
|
|
dd.paths.back().is_closed = true;
|
2010-01-06 22:58:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
p->is2d = true;
|
|
|
|
p->convexity = convexity;
|
2011-09-01 19:03:34 +04:00
|
|
|
dxf_tesselate(p, dd, 0, true, false, 0);
|
2011-09-04 00:44:41 +04:00
|
|
|
dxf_border_to_ps(p, dd);
|
2010-01-06 22:58:54 +03:00
|
|
|
}
|
|
|
|
|
2009-06-24 14:59:15 +04:00
|
|
|
return p;
|
2009-06-23 02:36:36 +04:00
|
|
|
}
|
|
|
|
|
2010-03-02 21:22:31 +03:00
|
|
|
std::string PrimitiveNode::toString() const
|
|
|
|
{
|
|
|
|
std::stringstream stream;
|
|
|
|
|
2010-08-28 23:21:44 +04:00
|
|
|
stream << this->name();
|
|
|
|
|
2010-03-02 21:22:31 +03:00
|
|
|
switch (this->type) {
|
|
|
|
case CUBE:
|
2010-08-28 23:21:44 +04:00
|
|
|
stream << "(size = [" << this->x << ", " << this->y << ", " << this->z << "], "
|
2010-03-02 21:22:31 +03:00
|
|
|
<< "center = " << (center ? "true" : "false") << ")";
|
|
|
|
break;
|
|
|
|
case SPHERE:
|
2010-08-28 23:21:44 +04:00
|
|
|
stream << "($fn = " << this->fn << ", $fa = " << this->fa
|
2010-03-02 21:22:31 +03:00
|
|
|
<< ", $fs = " << this->fs << ", r = " << this->r1 << ")";
|
|
|
|
break;
|
|
|
|
case CYLINDER:
|
2010-08-28 23:21:44 +04:00
|
|
|
stream << "($fn = " << this->fn << ", $fa = " << this->fa
|
2010-03-02 21:22:31 +03:00
|
|
|
<< ", $fs = " << this->fs << ", h = " << this->h << ", r1 = " << this->r1
|
|
|
|
<< ", r2 = " << this->r2 << ", center = " << (center ? "true" : "false") << ")";
|
|
|
|
break;
|
|
|
|
case POLYHEDRON:
|
2010-11-08 00:29:34 +03:00
|
|
|
stream << "(points = " << this->points
|
|
|
|
<< ", triangles = " << this->triangles
|
2010-03-02 21:22:31 +03:00
|
|
|
<< ", convexity = " << this->convexity << ")";
|
|
|
|
break;
|
|
|
|
case SQUARE:
|
2010-08-28 23:21:44 +04:00
|
|
|
stream << "(size = [" << this->x << ", " << this->y << "], "
|
2010-03-02 21:22:31 +03:00
|
|
|
<< "center = " << (center ? "true" : "false") << ")";
|
|
|
|
break;
|
|
|
|
case CIRCLE:
|
2010-08-28 23:21:44 +04:00
|
|
|
stream << "($fn = " << this->fn << ", $fa = " << this->fa
|
2010-03-02 21:22:31 +03:00
|
|
|
<< ", $fs = " << this->fs << ", r = " << this->r1 << ")";
|
|
|
|
break;
|
|
|
|
case POLYGON:
|
2010-11-08 00:29:34 +03:00
|
|
|
stream << "(points = " << this->points << ", paths = " << this->paths << ", convexity = " << this->convexity << ")";
|
2010-03-02 21:22:31 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
return stream.str();
|
|
|
|
}
|
2011-11-06 21:37:12 +04:00
|
|
|
|
|
|
|
void register_builtin_primitives()
|
|
|
|
{
|
|
|
|
Builtins::init("cube", new PrimitiveModule(CUBE));
|
|
|
|
Builtins::init("sphere", new PrimitiveModule(SPHERE));
|
|
|
|
Builtins::init("cylinder", new PrimitiveModule(CYLINDER));
|
|
|
|
Builtins::init("polyhedron", new PrimitiveModule(POLYHEDRON));
|
|
|
|
Builtins::init("square", new PrimitiveModule(SQUARE));
|
|
|
|
Builtins::init("circle", new PrimitiveModule(CIRCLE));
|
|
|
|
Builtins::init("polygon", new PrimitiveModule(POLYGON));
|
|
|
|
}
|