diff --git a/openscad.pro b/openscad.pro index 6d8282a6..5c39928d 100644 --- a/openscad.pro +++ b/openscad.pro @@ -206,6 +206,7 @@ HEADERS += src/typedefs.h \ src/OpenCSGWarningDialog.h \ src/AboutDialog.h \ src/builtin.h \ + src/calc.h \ src/context.h \ src/modcontext.h \ src/evalcontext.h \ @@ -324,6 +325,7 @@ SOURCES += src/version_check.cc \ src/AutoUpdater.cc \ \ src/builtin.cc \ + src/calc.cc \ src/export.cc \ src/export_png.cc \ src/import.cc \ diff --git a/src/PolySetCGALEvaluator.cc b/src/PolySetCGALEvaluator.cc index a2d896d8..0b57de16 100644 --- a/src/PolySetCGALEvaluator.cc +++ b/src/PolySetCGALEvaluator.cc @@ -13,10 +13,10 @@ #include "dxfdata.h" #include "dxftess.h" #include "module.h" +#include "calc.h" #include "svg.h" #include "printutils.h" -#include "openscad.h" // get_fragments_from_r() #include #include @@ -469,7 +469,7 @@ PolySet *PolySetCGALEvaluator::rotateDxfData(const RotateExtrudeNode &node, DxfD } } - int fragments = get_fragments_from_r(max_x-min_x, node.fn, node.fs, node.fa); + int fragments = Calc::get_fragments_from_r(max_x-min_x, node.fn, node.fs, node.fa); double ***points; points = new double**[fragments]; diff --git a/src/calc.cc b/src/calc.cc new file mode 100644 index 00000000..bdae0859 --- /dev/null +++ b/src/calc.cc @@ -0,0 +1,40 @@ +/* + * OpenSCAD (www.openscad.org) + * Copyright (C) 2009-2011 Clifford Wolf and + * Marius Kintel + * + * 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. + * + * 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. + * + * 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 "calc.h" +#include "grid.h" + +/*! + Returns the number of subdivision of a whole circle, given radius and + the three special variables $fn, $fs and $fa +*/ +int Calc::get_fragments_from_r(double r, double fn, double fs, double fa) +{ + if (r < GRID_FINE) return 3; + if (fn > 0.0) return (int)(fn >= 3 ? fn : 3); + return (int)ceil(fmax(fmin(360.0 / fa, r*2*M_PI / fs), 5)); +} + diff --git a/src/calc.h b/src/calc.h new file mode 100644 index 00000000..ce19e5b5 --- /dev/null +++ b/src/calc.h @@ -0,0 +1,9 @@ +#ifndef CALC_H_ +#define CALC_H_ + +class Calc { +public: + static int get_fragments_from_r(double r, double fn, double fs, double fa); +}; + +#endif diff --git a/src/dxfdata.cc b/src/dxfdata.cc index 84152286..9b61b939 100644 --- a/src/dxfdata.cc +++ b/src/dxfdata.cc @@ -28,7 +28,7 @@ #include "grid.h" #include "printutils.h" #include "handle_dep.h" -#include "openscad.h" // get_fragments_from_r() +#include "calc.h" #include #include "mathc99.h" @@ -189,7 +189,7 @@ DxfData::DxfData(double fn, double fs, double fa, } } else if (mode == "CIRCLE") { - int n = get_fragments_from_r(radius, fn, fs, fa); + int n = Calc::get_fragments_from_r(radius, fn, fs, fa); Vector2d center(xverts[0], yverts[0]); for (int i = 0; i < n; i++) { double a1 = (2*M_PI*i)/n; @@ -200,7 +200,7 @@ DxfData::DxfData(double fn, double fs, double fa, } else if (mode == "ARC") { Vector2d center(xverts[0], yverts[0]); - int n = get_fragments_from_r(radius, fn, fs, fa); + int n = Calc::get_fragments_from_r(radius, fn, fs, fa); while (arc_start_angle > arc_stop_angle) arc_stop_angle += 360.0; n = (int)ceil(n * (arc_stop_angle-arc_start_angle) / 360); @@ -237,7 +237,7 @@ DxfData::DxfData(double fn, double fs, double fa, // the ratio stored in 'radius; due to the parser code not checking entity type double r_minor = r_major * radius; double sweep_angle = ellipse_stop_angle-ellipse_start_angle; - int n = get_fragments_from_r(r_major, fn, fs, fa); + int n = Calc::get_fragments_from_r(r_major, fn, fs, fa); n = (int)ceil(n * sweep_angle / (2 * M_PI)); // Vector2d p1; Vector2d p1; p1 << 0,0; diff --git a/src/linearextrude.cc b/src/linearextrude.cc index c5d4529f..1812504a 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -32,7 +32,7 @@ #include "fileutils.h" #include "builtin.h" #include "PolySetEvaluator.h" -#include "openscad.h" // get_fragments_from_r() +#include "calc.h" #include "mathc99.h" #include @@ -113,7 +113,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI if (slices.type() == Value::NUMBER) { node->slices = (int)slices.toDouble(); } else { - node->slices = (int)fmax(2, fabs(get_fragments_from_r(node->height, + node->slices = (int)fmax(2, fabs(Calc::get_fragments_from_r(node->height, node->fn, node->fs, node->fa) * node->twist / 360)); } node->has_twist = true; diff --git a/src/primitives.cc b/src/primitives.cc index f1a4ba76..53b2e196 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -34,6 +34,7 @@ #include "printutils.h" #include "visitor.h" #include "context.h" +#include "calc.h" #include #include #include @@ -275,17 +276,6 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta return node; } -/*! - Returns the number of subdivision of a whole circle, given radius and - the three special variables $fn, $fs and $fa -*/ -int get_fragments_from_r(double r, double fn, double fs, double fa) -{ - if (r < GRID_FINE) return 3; - if (fn > 0.0) return (int)(fn >= 3 ? fn : 3); - return (int)ceil(fmax(fmin(360.0 / fa, r*2*M_PI / fs), 5)); -} - struct point2d { double x, y; }; @@ -364,7 +354,7 @@ PolySet *PrimitiveNode::evaluate_polyset(class PolySetEvaluator *) const double z; }; - int fragments = get_fragments_from_r(r1, fn, fs, fa); + int fragments = Calc::get_fragments_from_r(r1, fn, fs, fa); int rings = (fragments+1)/2; // 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 @@ -427,7 +417,7 @@ sphere_next_r2: if (this->type == CYLINDER && this->h > 0 && this->r1 >=0 && this->r2 >= 0 && (this->r1 > 0 || this->r2 > 0)) { - int fragments = get_fragments_from_r(fmax(this->r1, this->r2), this->fn, this->fs, this->fa); + int fragments = Calc::get_fragments_from_r(fmax(this->r1, this->r2), this->fn, this->fs, this->fa); double z1, z2; if (this->center) { @@ -525,7 +515,7 @@ sphere_next_r2: if (this->type == CIRCLE) { - int fragments = get_fragments_from_r(this->r1, this->fn, this->fs, this->fa); + int fragments = Calc::get_fragments_from_r(this->r1, this->fn, this->fs, this->fa); p->is2d = true; p->append_poly(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 70e56c61..0be819bb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -507,6 +507,7 @@ set(CORE_SOURCES ../src/linalg.cc ../src/handle_dep.cc ../src/value.cc + ../src/calc.cc ../src/expr.cc ../src/func.cc ../src/localscope.cc