diff --git a/.gitignore b/.gitignore index 767c89c4..5bfa3546 100644 --- a/.gitignore +++ b/.gitignore @@ -1,29 +1,49 @@ -/*.scad *.dmg *~ *.tar* +*.new Makefile objects .gdbinit -/*.stl -/*.dxf -/lexer_lex.cpp -/parser_yacc.cpp +.qmake.stash parser_yacc.h -/tmp -/OpenSCAD.app -*/#*# -/locale/*/*/*.mo -/locale/POTFILES -/nbproject -/openscad.pro.user -/openscad -/tests/openscad_nogui +**/#*# testdata/scad/features/import_dxf-tests.scad testdata/scad/features/import_stl-tests.scad testdata/scad/misc/include-tests.scad testdata/scad/misc/use-tests.scad -/mingw32 -/mingw64 **/project.xcworkspace **/xcuserdata +/*.scad +/*.stl +/*.dxf +/*.off +/*.amf +/*.png +/*.csg +/*.nef3 +/*.blend +/*.obj +/*.rcad +/*.xml +/*.dat +/*.gcode +/*.py +/*.svg +/*.h +/*.dump +/*.pl +/lexer_lex.cpp +/parser_yacc.cpp +/OpenSCAD.app +/openscad.pro.user +/openscad +/locale/*/*/*.mo +/locale/POTFILES +/tmp +/nbproject +/mingw32 +/mingw64 +src/*.org +src/*.old +src/*.debug \ No newline at end of file diff --git a/Arrowhead-Right-32.png b/Arrowhead-Right-32.png deleted file mode 100644 index 42dd282b..00000000 Binary files a/Arrowhead-Right-32.png and /dev/null differ diff --git a/Document-New-128.png b/Document-New-128.png deleted file mode 100644 index 7225b928..00000000 Binary files a/Document-New-128.png and /dev/null differ diff --git a/Open-128.png b/Open-128.png deleted file mode 100644 index c552c697..00000000 Binary files a/Open-128.png and /dev/null differ diff --git a/README.md b/README.md index 97d6c9e7..11ec3b3e 100644 --- a/README.md +++ b/README.md @@ -88,24 +88,23 @@ libraries from aptitude. If you're using Mac, or an older Linux/BSD, there are build scripts that download and compile the libraries from source. Follow the instructions for the platform you're compiling on below. -* [Qt4 (4.4 - 5.3)](http://www.qt.nokia.com/) -* [QScintilla2 (2.7)](http://www.riverbankcomputing.co.uk/software/qscintilla/) -* [CGAL (3.6 - 4.4)](http://www.cgal.org/) +* [Qt4 (4.4 - 5.4)](http://www.qt.nokia.com/) +* [QScintilla2 (2.7 - 2.8)](http://www.riverbankcomputing.co.uk/software/qscintilla/) +* [CGAL (3.6 - 4.5)](http://www.cgal.org/) * [GMP (5.x)](http://www.gmplib.org/) * [MPFR (3.x)](http://www.mpfr.org/) -* [cmake (2.8, required by CGAL and the test framework)](http://www.cmake.org/) -* [boost (1.35 - 1.55)](http://www.boost.org/) +* [cmake (2.8 - 3.0, required by CGAL and the test framework)](http://www.cmake.org/) +* [boost (1.35 - 1.57)](http://www.boost.org/) * [OpenCSG (1.3.2 ->)](http://www.opencsg.org/) * [GLEW (1.5.4 ->)](http://glew.sourceforge.net/) * [Eigen (3.x)](http://eigen.tuxfamily.org/) * [glib2 (2.x)](https://developer.gnome.org/glib/) -* [fontconfig (2.10)](http://fontconfig.org/) -* [freetype2 (2.4)](http://freetype.org/) -* [harfbuzz (0.9.19)](http://harfbuzz.org/) -* [GCC C++ Compiler (4.2 ->)](http://gcc.gnu.org/) -* [Bison (2.4)](http://www.gnu.org/software/bison/) -* [Flex (2.5.35)](http://flex.sourceforge.net/) -* [pkg-config (0.26)](http://www.freedesktop.org/wiki/Software/pkg-config/) +* [fontconfig (2.10 -> )](http://fontconfig.org/) +* [freetype2 (2.4 -> )](http://freetype.org/) +* [harfbuzz (0.9.19 -> )](http://harfbuzz.org/) +* [Bison (2.4 -> )](http://www.gnu.org/software/bison/) +* [Flex (2.5.35 -> )](http://flex.sourceforge.net/) +* [pkg-config (0.26 -> )](http://www.freedesktop.org/wiki/Software/pkg-config/) ### Getting the source code @@ -123,29 +122,41 @@ To pull the MCAD library (http://reprap.org/wiki/MCAD), do the following: ### Building for Mac OS X Prerequisites: -* XCode, including XCode command-line tools (install from XCode Preferences). -Prerequisites that can be installed through MacPorts/homebrew: -* [CMake](http://cmake.org/) -* [automake](http://www.gnu.org/software/automake/) -* [pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/) -* [libtool](https://www.gnu.org/software/libtool/) +* XCode, including XCode command-line tools. -Then after you've cloned this git repository, run the script that sets up the -environment variables. +Install Dependencies: - source setenv_mac-qt5.sh +Run the script that sets up the environment variables: + ```source setenv_mac-qt5.sh``` -Then run the script to compile all the prerequisite libraries above: +Then run the script to compile all the dependencies: + ```./scripts/macosx-build-dependencies.sh``` - ./scripts/macosx-build-dependencies.sh -You can also install the prerequisites using -[MacPorts](http://www.macports.org). Unfortunately, -[brew](http://mxcl.github.com/homebrew/) doesn't yet support CGAL and -OpenCSG. +After building dependencies, follow the instructions in the *Compilation* section. + +For the adventurous, it might be possible to build OpenSCAD using _MacPorts_ or _Homebrew_. The main challenge is that both these systems have partially broken libraries, but that tends to change from time to time. + +1. **MacPorts** (assumes [MacPorts](http://macports.org) is already installed) + + NB! MacPorts currently doesn't support Qt5 very well, so using Qt4 + is the only working option at the moment. However, MacPorts' Qt4 + has a broken ```moc``` command, causing OpenSCAD compilation to + break. This may be fixed in MacPorts by the time you read this. + + ```sudo port install opencsg qscintilla boost cgal pkgconfig eigen3 harfbuzz fontconfig``` + +1. **Homebrew** (assumes [Homebrew](http://brew.sh)) is already installed) + + NB! Homebrew's ```qscintilla2``` component doesn't support Qt5, so using Qt4 is currently necessary. + However, Homebrew's Qt4 has a broken ```moc``` command, causing OpenSCAD compilation to + break. This may be fixed in Homebrew by the time you read this. + NB! Homebrew's ```harfbuzz``` package requires X11, so you may have to install an X11 server. + NB! Homebrew doesnt have an OpenCSG package + + ```brew install cgal qscintilla2 eigen harfbuzz``` -After that, follow the Compilation instructions below. ### Building for Linux/BSD @@ -220,9 +231,9 @@ For a 64-bit Windows cross-build, replace 32 with 64 in the above instructions. ### Compilation -First, run 'qmake openscad.pro' from Qt4 to generate a Makefile. On some systems -you need to run 'qmake4', 'qmake-qt4' or something alike to run the qt4 version -of the tool. +First, run 'qmake openscad.pro' from Qt4 to generate a Makefile. + +On some systems, depending on which version(s) of Qt you have installed, you may need to specify which version you want to use, e.g. by running 'qmake4', 'qmake-qt4' or something alike. Then run make. Finally you might run 'make install' as root or simply copy the 'openscad' binary (OpenSCAD.app on Mac OS X) to the bin directory of your choice. diff --git a/Save-128.png b/Save-128.png deleted file mode 100644 index f56c70b1..00000000 Binary files a/Save-128.png and /dev/null differ diff --git a/appcast-snapshots.xml.in b/appcast-snapshots.xml.in index bf167139..fa076e20 100644 --- a/appcast-snapshots.xml.in +++ b/appcast-snapshots.xml.in @@ -7,9 +7,9 @@ OpenSCAD @VERSION@ @VERSIONDATE@ - https://raw.github.com/openscad/openscad/master/RELEASE_NOTES + https://raw.github.com/openscad/openscad/master/releases/2014.QX.md 10.7.0 - +#include +#include +#include +#include +#include + +#include "cgalutils.h" +#include "export.h" +#include "polyset.h" +#include "CGAL_Nef_polyhedron.h" +#include "boosty.h" + +#include + +using namespace CGALUtils; + +#define STL_FACET_NUMBYTES 4*3*4+2 +// as there is no 'float32_t' standard, we assume the systems 'float' +// is a 'binary32' aka 'single' standard IEEE 32-bit floating point type +union stl_facet { + uint8_t data8[ STL_FACET_NUMBYTES ]; + uint32_t data32[4*3]; + struct facet_data { + float i, j, k; + float x1, y1, z1; + float x2, y2, z2; + float x3, y3, z3; + uint16_t attribute_byte_count; + } data; +}; + +void uint32_byte_swap( uint32_t &x ) +{ +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 + x = __builtin_bswap32( x ); +#elif defined(__clang__) + x = __builtin_bswap32( x ); +#elif defined(_MSC_VER) + x = _byteswap_ulong( x ); +#else + uint32_t b1 = ( 0x000000FF & x ) << 24; + uint32_t b2 = ( 0x0000FF00 & x ) << 8; + uint32_t b3 = ( 0x00FF0000 & x ) >> 8; + uint32_t b4 = ( 0xFF000000 & x ) >> 24; + x = b1 | b2 | b3 | b4; +#endif +} + +void read_stl_facet( std::ifstream &f, stl_facet &facet ) +{ + f.read( (char*)facet.data8, STL_FACET_NUMBYTES ); +#ifdef BOOST_BIG_ENDIAN + for ( int i = 0; i < 12; i++ ) { + uint32_byte_swap( facet.data32[ i ] ); + } + // we ignore attribute byte count +#endif +} + +PolySet *import_stl(const std::string &filename) +{ + PolySet *p = new PolySet(3); + + // Open file and position at the end + std::ifstream f(filename.c_str(), std::ios::in | std::ios::binary | std::ios::ate); + if (!f.good()) { + PRINTB("WARNING: Can't open import file '%s'.", filename); + return NULL; + } + + boost::regex ex_sfe("solid|facet|endloop"); + boost::regex ex_outer("outer loop"); + boost::regex ex_vertex("vertex"); + boost::regex ex_vertices("\\s*vertex\\s+([^\\s]+)\\s+([^\\s]+)\\s+([^\\s]+)"); + + bool binary = false; + std::streampos file_size = f.tellg(); + f.seekg(80); + if (f.good() && !f.eof()) { + uint32_t facenum = 0; + f.read((char *)&facenum, sizeof(uint32_t)); +#ifdef BOOST_BIG_ENDIAN + uint32_byte_swap( facenum ); +#endif + if (file_size == static_cast(80 + 4 + 50*facenum)) { + binary = true; + } + } + f.seekg(0); + + char data[5]; + f.read(data, 5); + if (!binary && !f.eof() && f.good() && !memcmp(data, "solid", 5)) { + int i = 0; + double vdata[3][3]; + std::string line; + std::getline(f, line); + while (!f.eof()) { + std::getline(f, line); + boost::trim(line); + if (boost::regex_search(line, ex_sfe)) { + continue; + } + if (boost::regex_search(line, ex_outer)) { + i = 0; + continue; + } + boost::smatch results; + if (boost::regex_search(line, results, ex_vertices)) { + try { + for (int v=0;v<3;v++) { + vdata[i][v] = boost::lexical_cast(results[v+1]); + } + } + catch (const boost::bad_lexical_cast &blc) { + PRINTB("WARNING: Can't parse vertex line '%s'.", line); + i = 10; + continue; + } + if (++i == 3) { + p->append_poly(); + p->append_vertex(vdata[0][0], vdata[0][1], vdata[0][2]); + p->append_vertex(vdata[1][0], vdata[1][1], vdata[1][2]); + p->append_vertex(vdata[2][0], vdata[2][1], vdata[2][2]); + } + } + } + } + else if (binary && !f.eof() && f.good()) + { + f.ignore(80-5+4); + while (1) { + stl_facet facet; + read_stl_facet( f, facet ); + if (f.eof()) break; + p->append_poly(); + p->append_vertex(facet.data.x1, facet.data.y1, facet.data.z1); + p->append_vertex(facet.data.x2, facet.data.y2, facet.data.z2); + p->append_vertex(facet.data.x3, facet.data.y3, facet.data.z3); + } + } + return p; +} + +int main(int argc, char *argv[]) +{ + + OpenSCAD::debug = "export_nef"; + CGAL_Nef_polyhedron *N = NULL; + + PolySet *ps = NULL; + if (argc == 2) { + std::string filename(argv[1]); + std::string suffix = boosty::extension_str(filename); + boost::algorithm::to_lower(suffix); + if (suffix == ".stl") { + if (!(ps = import_stl(filename))) { + std::cerr << "Error importing STL " << argv[1] << std::endl; + exit(1); + } + std::cerr << "Imported " << ps->numPolygons() << " polygons" << std::endl; + } + else if (suffix == ".nef3") { + N = new CGAL_Nef_polyhedron(new CGAL_Nef_polyhedron3); + std::ifstream stream(filename.c_str()); + stream >> *N->p3; + std::cerr << "Imported Nef polyhedron" << std::endl; + } + } + else { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + exit(1); + } + + if (ps && !N) N = createNefPolyhedronFromGeometry(*ps); + + export_stl(N, std::cout); + std::cerr << "Done." << std::endl; +} diff --git a/cgal/export_nef.pro b/cgal/export_nef.pro new file mode 100644 index 00000000..6f6becbb --- /dev/null +++ b/cgal/export_nef.pro @@ -0,0 +1,109 @@ +CONFIG += debug +CONFIG -= qt +debug: DEFINES += DEBUG + +TEMPLATE = app + +INCLUDEPATH += ../src +DEPENDPATH += ../src + +# Handle custom library location. +# Used when manually installing 3rd party libraries +isEmpty(OPENSCAD_LIBDIR) OPENSCAD_LIBDIR = $$(OPENSCAD_LIBRARIES) +macx:isEmpty(OPENSCAD_LIBDIR) { + exists(/opt/local):exists(/usr/local/Cellar) { + error("It seems you might have libraries in both /opt/local and /usr/local. Please specify which one to use with qmake OPENSCAD_LIBDIR=") + } else { + exists(/opt/local) { + #Default to MacPorts on Mac OS X + message("Automatically searching for libraries in /opt/local. To override, use qmake OPENSCAD_LIBDIR=") + OPENSCAD_LIBDIR = /opt/local + } else:exists(/usr/local/Cellar) { + message("Automatically searching for libraries in /usr/local. To override, use qmake OPENSCAD_LIBDIR=") + OPENSCAD_LIBDIR = /usr/local + } + } +} +!isEmpty(OPENSCAD_LIBDIR) { + QMAKE_INCDIR = $$OPENSCAD_LIBDIR/include + QMAKE_LIBDIR = $$OPENSCAD_LIBDIR/lib +} + +TARGET = export_nef +mac { + CONFIG -= app_bundle +} + +macx { + # Mac needs special care to link against the correct C++ library + # We attempt to auto-detect it by inspecting Boost + dirs = $${BOOSTDIR} $${QMAKE_LIBDIR} + for(dir, dirs) { + system(grep -q __112basic_string $${dir}/libboost_thread* >& /dev/null) { + message("Detected libc++-linked boost in $${dir}") + CONFIG += libc++ + } + } + + libc++ { + QMAKE_CXXFLAGS += -stdlib=libc++ + QMAKE_LFLAGS += -stdlib=libc++ + QMAKE_OBJECTIVE_CFLAGS += -stdlib=libc++ + # libc++ on requires Mac OS X 10.7+ + QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 + } +} + +# See Dec 2011 OpenSCAD mailing list, re: CGAL/GCC bugs. +*g++* { + QMAKE_CXXFLAGS *= -fno-strict-aliasing + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-local-typedefs # ignored before 4.8 +} + +*clang* { + # http://llvm.org/bugs/show_bug.cgi?id=9182 + QMAKE_CXXFLAGS_WARN_ON += -Wno-overloaded-virtual + # disable enormous amount of warnings about CGAL / boost / etc + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-parameter + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-variable + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-function + QMAKE_CXXFLAGS_WARN_ON += -Wno-c++11-extensions + # might want to actually turn this on once in a while + QMAKE_CXXFLAGS_WARN_ON += -Wno-sign-compare +} + +# Application configuration +CONFIG += cgal +CONFIG += boost +CONFIG += eigen +CONFIG += gettext + +mac: { + LIBS += -framework OpenGL +} + +include(../common.pri) + +HEADERS += ../src/cgal.h \ + ../src/cgalutils.h \ + ../src/linalg.h \ + ../src/polyset.h \ + ../src/polyset-utils.h \ + ../src/printutils.h + +SOURCES += export_nef.cpp \ + ../src/polygon2d.cc \ + ../src/polygon2d-CGAL.cc \ + ../src/CGAL_Nef_polyhedron.cc \ + ../src/CGAL_Nef_polyhedron_DxfData.cc \ + ../src/cgalutils.cc \ + ../src/cgalutils-tess.cc \ + ../src/cgalutils-polyhedron.cc \ + ../src/polyset.cc \ + ../src/svg.cc \ + ../src/node.cc \ + ../src/export.cc \ + ../src/polyset-utils.cc \ + ../src/progress.cc \ + ../src/printutils.cc \ + ../src/grid.cc diff --git a/cgal/polyhole-tessellator-libtess2.cpp b/cgal/polyhole-tessellator-libtess2.cpp new file mode 100644 index 00000000..f0ef286b --- /dev/null +++ b/cgal/polyhole-tessellator-libtess2.cpp @@ -0,0 +1,159 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "GeometryUtils.h" +#include "Reindexer.h" +#include "linalg.h" +#include "grid.h" +#include "printutils.h" + +static void export_stl(const IndexedTriangleMesh &trimesh, std::ostream &output) +{ + setlocale(LC_NUMERIC, "C"); // Ensure radix is . (not ,) in output + output << "solid OpenSCAD_Model\n"; + const Vector3f *verts = &trimesh.vertices.front(); + BOOST_FOREACH(const IndexedTriangle &t, trimesh.triangles) { + assert(t[0] < trimesh.vertices.size()); + assert(t[1] < trimesh.vertices.size()); + assert(t[2] < trimesh.vertices.size()); + + Vector3f p[3]; + p[0] = verts[t[0]]; + p[1] = verts[t[1]]; + p[2] = verts[t[2]]; + std::stringstream stream; + stream << p[0][0] << " " << p[0][1] << " " << p[0][2]; + std::string vs1 = stream.str(); + stream.str(""); + stream << p[1][0] << " " << p[1][1] << " " << p[1][2]; + std::string vs2 = stream.str(); + stream.str(""); + stream << p[2][0] << " " << p[2][1] << " " << p[2][2]; + std::string vs3 = stream.str(); + // if (vs1 != vs2 && vs1 != vs3 && vs2 != vs3) { + // The above condition ensures that there are 3 distinct vertices, but + // they may be collinear. If they are, the unit normal is meaningless + // so the default value of "1 0 0" can be used. If the vertices are not + // collinear then the unit normal must be calculated from the + // components. + Vector3f normal = (p[1] - p[0]).cross(p[2] - p[0]); + normal.normalize(); + output << " facet normal " << normal[0] << " " << normal[1] << " " << normal[2] << "\n"; + output << " outer loop\n"; + + for (int i=0;i<3;i++) { + output << " vertex " << p[i][0] << " " << p[i][1] << " " << p[i][2] << "\n"; + } + output << " endloop\n"; + output << " endfacet\n"; + // } + } + output << "endsolid OpenSCAD_Model\n"; + setlocale(LC_NUMERIC, ""); // Set default locale +} + + +/*! + file format: + 1. polygon coordinates (x,y,z) are comma separated (+/- spaces) and + each coordinate is on a separate line + 2. each polygon is separated by one or more blank lines +*/ +bool import_polygon(IndexedPolygons &polyhole, const std::string &filename) +{ + Reindexer uniqueVertices; + std::ifstream ifs(filename.c_str()); + if (!ifs) return false; + + std::string line; + IndexedFace polygon; + while (std::getline(ifs, line)) { + std::stringstream ss(line); + double X = 0.0, Y = 0.0, Z = 0.0; + if (!(ss >> X)) { + //ie blank lines => flag start of next polygon + if (polygon.size() > 0) polyhole.faces.push_back(polygon); + polygon.clear(); + continue; + } + char c = ss.peek(); + while (c == ' ') {ss.read(&c, 1); c = ss.peek();} //gobble spaces before comma + if (c == ',') {ss.read(&c, 1); c = ss.peek();} //gobble comma + while (c == ' ') {ss.read(&c, 1); c = ss.peek();} //gobble spaces after comma + if (!(ss >> Y)) { + std::cerr << "Y error\n"; + return false; + } + c = ss.peek(); + while (c == ' ') {ss.read(&c, 1); c = ss.peek();} //gobble spaces before comma + if (c == ',') {ss.read(&c, 1); c = ss.peek();} //gobble comma + while (c == ' ') {ss.read(&c, 1); c = ss.peek();} //gobble spaces after comma + if (!(ss >> Z)) { + std::cerr << "Z error\n"; + return false; + } + polygon.push_back(uniqueVertices.lookup(Vector3f(X, Y, Z))); + } + if (polygon.size() > 0) polyhole.faces.push_back(polygon); + ifs.close(); + uniqueVertices.copy(std::back_inserter(polyhole.vertices)); + return true; +} + +int main(int argc, char *argv[]) +{ + OpenSCAD::debug = "GeometryUtils"; + + IndexedPolygons polyhole; + Vector3f *normal = NULL; + if (argc >= 2) { + if (!import_polygon(polyhole, argv[1])) { + std::cerr << "Error importing polygon" << std::endl; + exit(1); + } + std::cerr << "Imported " << polyhole.faces.size() << " polygons" << std::endl; + + if (argc == 3) { + std::vector strs; + std::vector normalvec; + std::string arg(argv[2]); + boost::split(strs, arg, boost::is_any_of(",")); + assert(strs.size() == 3); + BOOST_FOREACH(const std::string &s, strs) normalvec.push_back(boost::lexical_cast(s)); + normal = new Vector3f(normalvec[0], normalvec[1], normalvec[2]); + + } + } + else { + //construct two non-intersecting nested polygons + Reindexer uniqueVertices; + IndexedFace polygon1; + polygon1.push_back(uniqueVertices.lookup(Vector3f(0,0,0))); + polygon1.push_back(uniqueVertices.lookup(Vector3f(2,0,0))); + polygon1.push_back(uniqueVertices.lookup(Vector3f(2,2,0))); + polygon1.push_back(uniqueVertices.lookup(Vector3f(0,2,0))); + IndexedFace polygon2; + polygon2.push_back(uniqueVertices.lookup(Vector3f(0.5,0.5,0))); + polygon2.push_back(uniqueVertices.lookup(Vector3f(1.5,0.5,0))); + polygon2.push_back(uniqueVertices.lookup(Vector3f(1.5,1.5,0))); + polygon2.push_back(uniqueVertices.lookup(Vector3f(0.5,1.5,0))); + polyhole.faces.push_back(polygon1); + polyhole.faces.push_back(polygon2); + uniqueVertices.copy(std::back_inserter(polyhole.vertices)); + } + + std::vector triangles; + bool ok = GeometryUtils::tessellatePolygonWithHoles(polyhole, triangles, normal); + std::cerr << "Tessellated into " << triangles.size() << " triangles" << std::endl; + + IndexedTriangleMesh trimesh; + trimesh.vertices = polyhole.vertices; + trimesh.triangles = triangles; + + export_stl(trimesh, std::cout); +} diff --git a/cgal/polyhole-tessellator-libtess2.pro b/cgal/polyhole-tessellator-libtess2.pro new file mode 100644 index 00000000..98c9964f --- /dev/null +++ b/cgal/polyhole-tessellator-libtess2.pro @@ -0,0 +1,106 @@ +debug: DEFINES += DEBUG + +TEMPLATE = app + +INCLUDEPATH += ../src ../src/libtess2/Include +DEPENDPATH += ../src + +# Handle custom library location. +# Used when manually installing 3rd party libraries +isEmpty(OPENSCAD_LIBDIR) OPENSCAD_LIBDIR = $$(OPENSCAD_LIBRARIES) +macx:isEmpty(OPENSCAD_LIBDIR) { + exists(/opt/local):exists(/usr/local/Cellar) { + error("It seems you might have libraries in both /opt/local and /usr/local. Please specify which one to use with qmake OPENSCAD_LIBDIR=") + } else { + exists(/opt/local) { + #Default to MacPorts on Mac OS X + message("Automatically searching for libraries in /opt/local. To override, use qmake OPENSCAD_LIBDIR=") + OPENSCAD_LIBDIR = /opt/local + } else:exists(/usr/local/Cellar) { + message("Automatically searching for libraries in /usr/local. To override, use qmake OPENSCAD_LIBDIR=") + OPENSCAD_LIBDIR = /usr/local + } + } +} +!isEmpty(OPENSCAD_LIBDIR) { + QMAKE_INCDIR = $$OPENSCAD_LIBDIR/include + QMAKE_LIBDIR = $$OPENSCAD_LIBDIR/lib +} + +TARGET = polyhole-tessellator-libtess2 +mac { + CONFIG -= app_bundle +} + +macx { + # Mac needs special care to link against the correct C++ library + # We attempt to auto-detect it by inspecting Boost + dirs = $${BOOSTDIR} $${QMAKE_LIBDIR} + for(dir, dirs) { + system(grep -q __112basic_string $${dir}/libboost_thread* >& /dev/null) { + message("Detected libc++-linked boost in $${dir}") + CONFIG += libc++ + } + } + + libc++ { + QMAKE_CXXFLAGS += -stdlib=libc++ + QMAKE_LFLAGS += -stdlib=libc++ + QMAKE_OBJECTIVE_CFLAGS += -stdlib=libc++ + # libc++ on requires Mac OS X 10.7+ + QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 + } +} + +# See Dec 2011 OpenSCAD mailing list, re: CGAL/GCC bugs. +*g++* { + QMAKE_CXXFLAGS *= -fno-strict-aliasing + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-local-typedefs # ignored before 4.8 +} + +*clang* { + # http://llvm.org/bugs/show_bug.cgi?id=9182 + QMAKE_CXXFLAGS_WARN_ON += -Wno-overloaded-virtual + # disable enormous amount of warnings about CGAL / boost / etc + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-parameter + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-variable + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-function + QMAKE_CXXFLAGS_WARN_ON += -Wno-c++11-extensions + # might want to actually turn this on once in a while + QMAKE_CXXFLAGS_WARN_ON += -Wno-format-security +} + + + +# Application configuration +CONFIG += cgal +CONFIG += boost +CONFIG += eigen +CONFIG += gettext + +include(../common.pri) + +HEADERS += ../src/GeometryUtils.cc \ + ../src/linalg.h \ + ../src/printutils.h \ + ../src/grid.h \ + ../src/libtess2/Include/tesselator.h \ + ../src/libtess2/Source/bucketalloc.h \ + ../src/libtess2/Source/dict.h \ + ../src/libtess2/Source/geom.h \ + ../src/libtess2/Source/mesh.h \ + ../src/libtess2/Source/priorityq.h \ + ../src/libtess2/Source/sweep.h \ + ../src/libtess2/Source/tess.h + +SOURCES += polyhole-tessellator-libtess2.cpp \ + ../src/GeometryUtils.cc \ + ../src/printutils.cc \ + ../src/grid.cc \ + ../src/libtess2/Source/bucketalloc.c \ + ../src/libtess2/Source/dict.c \ + ../src/libtess2/Source/geom.c \ + ../src/libtess2/Source/mesh.c \ + ../src/libtess2/Source/priorityq.c \ + ../src/libtess2/Source/sweep.c \ + ../src/libtess2/Source/tess.c diff --git a/doc/openscad.1 b/doc/openscad.1 index d8853eac..26c38be0 100644 --- a/doc/openscad.1 +++ b/doc/openscad.1 @@ -1,4 +1,4 @@ -.TH OPENSCAD 1 "2014.03" +.TH OPENSCAD 1 "2015.02" .\" Please adjust this date whenever revising the manpage. .SH NAME openscad \- script file based graphical CAD environment @@ -19,7 +19,7 @@ the OpenSCAD user manual at http://en.wikibooks.org/wiki/OpenSCAD_User_Manual. .TP \fB-o\fP \fIoutputfile\fP -Export the given file to \fIoutputfile\fP in STL, OFF, DXF, or PNG +Export the given file to \fIoutputfile\fP in STL, OFF, AMF, DXF, SVG, or PNG format, depending on file extension of \fIoutputfile\fP. If this option is given, the GUI will not be started. @@ -49,10 +49,10 @@ strings, care has to be taken that the shell does not consume quotation marks. More than one \fB-D\fP option can be given. .TP .B \-\-render -If exporting an image, use a full CGAL render. (Default is an OpenCSG compile) +If exporting an image, render the model fully. (Default is preview) .TP .B \-\-preview[=throwntogether] -If exporting an image, use an OpenCSG previce (optionally in throwntogether mode for quicker rendering). +If exporting an image, use an OpenCSG preview (optionally in throwntogether mode for quicker rendering). .TP .B \-\-csglimit=limit If exporting an image as an OpenCSG preview, stop rendering after encountering \fIlimit\fP elements to avoid runaway resource usage. @@ -69,6 +69,12 @@ The first three are for the Eye position, while the next three are for the Center (or target) that the camera will look at. The 'up' vector is not currently supported. .TP +.B \-\-viewall +If exporting an image, adjust camera distance to fit the whole design in the frame +.TP +.B \-\-autocenter +If exporting an image, center the design in the frame +.TP .B \-\-imgsize=width,height If exporting an image, specify the pixel width and height .TP @@ -76,6 +82,9 @@ If exporting an image, specify the pixel width and height If exporting an image, specify whether to use orthographic or perspective projection .TP +.B \-\-colorscheme=[Cornfield|Sunset|Metallic|Starnight|BeforeDawn|Nature|DeepOcean] +If exporting an image, use the specified color scheme for the rendering. +.TP .B \-v, \-\-version Show version of program. .TP diff --git a/doc/release-checklist.txt b/doc/release-checklist.txt index 118c9f03..95a977e0 100644 --- a/doc/release-checklist.txt +++ b/doc/release-checklist.txt @@ -70,6 +70,8 @@ o Notify package managers - OpenSUSE: Pavol Rusnak - MacPorts: Frank Schima - Arch Linux: Kyle Keen +o Update dev version to release version in documentation + - https://en.wikibooks.org/wiki/OpenSCAD_User_Manual Build and Upload Release Binaries --------------------------------- diff --git a/down.png b/down.png deleted file mode 100644 index 149ccb5e..00000000 Binary files a/down.png and /dev/null differ diff --git a/examples/Advanced/advance_intersection.scad b/examples/Advanced/advance_intersection.scad index 5b415211..11ea6337 100644 --- a/examples/Advanced/advance_intersection.scad +++ b/examples/Advanced/advance_intersection.scad @@ -11,3 +11,15 @@ intersection() linear_extrude(height = 100, center = true, convexity= 3) import(file = "advance_intersection.dxf"); } + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/demo_cut.scad b/examples/Advanced/demo_cut.scad index 0b42c612..a63a76ed 100644 --- a/examples/Advanced/demo_cut.scad +++ b/examples/Advanced/demo_cut.scad @@ -31,3 +31,15 @@ module demo_cut() translate([ -30, 0, 0 ]) demo_proj(); translate([ +30, 0, 0 ]) demo_cut(); + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/difference.scad b/examples/Advanced/difference.scad index 790f25db..5cf6da7f 100644 --- a/examples/Advanced/difference.scad +++ b/examples/Advanced/difference.scad @@ -75,3 +75,15 @@ translate([ 30, 0, 0 ]) nut(); spring(); + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/fractal.scad b/examples/Advanced/fractal.scad index 871222a4..bab5eb15 100644 --- a/examples/Advanced/fractal.scad +++ b/examples/Advanced/fractal.scad @@ -1,6 +1,4 @@ // Menger Sponge -// By Nathan Hellweg, Emmett Lalish and Marius Kintel May 13, 2013 -// CC-BY-SA license // Size of edge of sponge D=100; @@ -32,3 +30,14 @@ difference() { rotate([45, atan(1/sqrt(2)), 0]) menger(); translate([0,0,-D]) cube(2*D, center=true); } + +// Written by Nathan Hellweg, Emmett Lalish and Marius Kintel May 13, 2013 +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/intersecting.scad b/examples/Advanced/intersecting.scad index 9cf62689..36537723 100644 --- a/examples/Advanced/intersecting.scad +++ b/examples/Advanced/intersecting.scad @@ -8,3 +8,14 @@ intersection_for(i = [ ]) rotate(i) cube([100, 20, 20], center = true); +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/iteration.scad b/examples/Advanced/iteration.scad index 25c51735..3895ffe7 100644 --- a/examples/Advanced/iteration.scad +++ b/examples/Advanced/iteration.scad @@ -43,3 +43,14 @@ module example006() example006(); +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/offset.scad b/examples/Advanced/offset.scad index 18cc2e4b..5f1ebdfa 100644 --- a/examples/Advanced/offset.scad +++ b/examples/Advanced/offset.scad @@ -1,6 +1,4 @@ -// Example for offset() usage -// (c) 2014 Torsten Paul -// CC-BY-SA 4.0 +// offset.scad - Example for offset() usage in OpenSCAD $fn = 40; @@ -31,3 +29,16 @@ translate([0, 0, foot_height]) { %cylinder(r = 14, h = 100); %translate([0, 0, 100]) sphere(r = 30); + + + +// Written in 2014 by Torsten Paul +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/search.scad b/examples/Advanced/search.scad index b4f44f03..dff02254 100644 --- a/examples/Advanced/search.scad +++ b/examples/Advanced/search.scad @@ -20,3 +20,15 @@ module clock_hour_words(word_offset=20.0,word_height=2.0) { } clock_hour_words(word_offset=16.0,word_height=5.0); + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/translation.scad b/examples/Advanced/translation.scad index 417557a1..aaecd2ff 100644 --- a/examples/Advanced/translation.scad +++ b/examples/Advanced/translation.scad @@ -22,3 +22,15 @@ for (i = [1:4]) } } } + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/LetterBlock.scad b/examples/Basics/LetterBlock.scad new file mode 100644 index 00000000..7eee768d --- /dev/null +++ b/examples/Basics/LetterBlock.scad @@ -0,0 +1,28 @@ +echo(version=version()); + +module LetterBlock(letter, size=30) { + difference() { + translate([0,0,size/4]) + cube([size,size,size/2], center=true); + translate([0,0,size/6]) + linear_extrude(height=size, convexity=3) + text(letter, + size=size*22/30, + font="Tahoma", + halign="center", + valign="center"); + } +} + +LetterBlock("M"); + +// Written by Marius Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/difference_cube.scad b/examples/Basics/difference_cube.scad index c8127844..c4b210ec 100644 --- a/examples/Basics/difference_cube.scad +++ b/examples/Basics/difference_cube.scad @@ -1,3 +1,5 @@ +// difference_cube.scad - Example for difference() usage in OpenSCAD + echo(version=version()); module difference_cube() @@ -10,3 +12,16 @@ module difference_cube() difference_cube(); + + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/difference_sphere.scad b/examples/Basics/difference_sphere.scad index 3d80d626..67d6dee9 100644 --- a/examples/Basics/difference_sphere.scad +++ b/examples/Basics/difference_sphere.scad @@ -1,3 +1,5 @@ +// difference_sphere.scad - Example for difference() usage in OpenSCAD + echo(version=version()); module difference_sphere() @@ -25,3 +27,16 @@ module difference_sphere() difference_sphere(); + + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/intersection.scad b/examples/Basics/intersection.scad index 082b72e7..ac2046bb 100644 --- a/examples/Basics/intersection.scad +++ b/examples/Basics/intersection.scad @@ -1,3 +1,5 @@ +// intersection.scad - Example for intersection() usage in OpenSCAD + echo(version=version()); module example_intersection() @@ -22,3 +24,16 @@ module example_intersection() example_intersection(); + + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/logo_and_text.scad b/examples/Basics/logo_and_text.scad index 140ff248..bddaa336 100644 --- a/examples/Basics/logo_and_text.scad +++ b/examples/Basics/logo_and_text.scad @@ -1,6 +1,4 @@ -// Example for text() usage -// (c) 2014 Torsten Paul -// CC-BY-SA 4.0 +// logo_and_text.scad - Example for text() usage in OpenSCAD echo(version=version()); @@ -46,3 +44,15 @@ translate([110, 0, 80]) { translate([160, 0, -40]) black() t("Solid 3D CAD Modeller"); } + + +// Written in 2014 by Torsten Paul +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/surface.scad b/examples/Basics/surface.scad index dbf93485..e49605e2 100644 --- a/examples/Basics/surface.scad +++ b/examples/Basics/surface.scad @@ -1,3 +1,5 @@ +// surface.scad - Example for surface() usage in OpenSCAD +// // surface.dat generated using octave: // d = (sin(1:0.2:10)' * cos(1:0.2:10)) * 10; // save("surface.dat", "d"); @@ -13,3 +15,17 @@ intersection() surface(file = "surface.dat", center = true, convexity = 5); } + + + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/text_on_cube.scad b/examples/Basics/text_on_cube.scad index 046be735..35647cf1 100644 --- a/examples/Basics/text_on_cube.scad +++ b/examples/Basics/text_on_cube.scad @@ -1,6 +1,4 @@ -// Example for text() usage -// (c) 2014 Torsten Paul -// CC-BY-SA 4.0 +// text_on_cube.scad - Example for text() usage in OpenSCAD echo(version=version()); @@ -38,3 +36,16 @@ difference() { translate([0, 0, o]) letter("\u263A"); translate([0, 0, -o - letter_height]) letter("\u263C"); } + + + +// Written in 2014 by Torsten Paul +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/translate.scad b/examples/Basics/translate.scad index 1aaa674c..a7c8fe9e 100644 --- a/examples/Basics/translate.scad +++ b/examples/Basics/translate.scad @@ -1,3 +1,5 @@ +// translate.scad - Example for translate() usage in OpenSCAD + echo(version=version()); module example_translate() @@ -19,3 +21,17 @@ module example_translate() } example_translate(); + + + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/union.scad b/examples/Basics/union.scad index 1b410e2c..681c5823 100644 --- a/examples/Basics/union.scad +++ b/examples/Basics/union.scad @@ -1,3 +1,5 @@ +// union.scad - Example for union() usage in OpenSCAD + echo(version=version()); module example_union() @@ -19,3 +21,16 @@ module example_union() example_union(); + + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/COPYING-CC0.txt b/examples/COPYING-CC0.txt new file mode 100644 index 00000000..0e259d42 --- /dev/null +++ b/examples/COPYING-CC0.txt @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/examples/Extrusion/cut_view.scad b/examples/Extrusion/cut_view.scad index 7d11b917..07a558b0 100644 --- a/examples/Extrusion/cut_view.scad +++ b/examples/Extrusion/cut_view.scad @@ -64,3 +64,14 @@ translate([0, 0, -10]) // cutview(); +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Extrusion/fan_view.scad b/examples/Extrusion/fan_view.scad index 5ea81811..37bcb1d5 100644 --- a/examples/Extrusion/fan_view.scad +++ b/examples/Extrusion/fan_view.scad @@ -29,3 +29,14 @@ intersection() import(file = "fan_view.dxf", layer = "fan_side", origin = fan_side_center); } +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Extrusion/text.scad b/examples/Extrusion/text.scad index 891cc0f0..838f70d7 100644 --- a/examples/Extrusion/text.scad +++ b/examples/Extrusion/text.scad @@ -31,3 +31,15 @@ difference() import(file = "text.dxf", layer = "X"); } } + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/M.stl b/examples/Shapes/M.stl new file mode 100644 index 00000000..699a7e0c --- /dev/null +++ b/examples/Shapes/M.stl @@ -0,0 +1,450 @@ +solid OpenSCAD_Model + facet normal -1 0 0 + outer loop + vertex -15 15 0 + vertex -15 -15 0 + vertex -15 -15 15 + endloop + endfacet + facet normal -1 -0 -0 + outer loop + vertex -15 15 15 + vertex -15 15 0 + vertex -15 -15 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 6.88264 -10.8438 15 + vertex -6.49335 -10.8438 15 + vertex 15 -15 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -9.24535 11.3642 15 + vertex -15 15 15 + vertex -9.24535 -10.8438 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 5.72964 11.3642 15 + vertex -5.22034 11.3642 15 + vertex 0.351639 -0.977737 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -15 15 15 + vertex -15 -15 15 + vertex -9.24535 -10.8438 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -5.22034 11.3642 15 + vertex -15 15 15 + vertex -9.24535 11.3642 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 15 15 15 + vertex -15 15 15 + vertex -5.22034 11.3642 15 + endloop + endfacet + facet normal 0 -0 1 + outer loop + vertex 9.82664 11.3642 15 + vertex 15 15 15 + vertex 5.72964 11.3642 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 15 15 15 + vertex -5.22034 11.3642 15 + vertex 5.72964 11.3642 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 9.82664 -10.8438 15 + vertex 15 15 15 + vertex 9.82664 11.3642 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 15 -15 15 + vertex 9.82664 -10.8438 15 + vertex 6.88264 -10.8438 15 + endloop + endfacet + facet normal 0 -0 1 + outer loop + vertex 15 -15 15 + vertex 15 15 15 + vertex 9.82664 -10.8438 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -15 -15 15 + vertex 15 -15 15 + vertex -6.49335 -10.8438 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -6.49335 -10.8438 15 + vertex 1.07065 -4.69974 15 + vertex -0.726349 -4.69974 15 + endloop + endfacet + facet normal 0 -0 1 + outer loop + vertex 6.88264 -10.8438 15 + vertex 6.88264 8.29724 15 + vertex 1.07065 -4.69974 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -15 -15 15 + vertex -6.49335 -10.8438 15 + vertex -9.24535 -10.8438 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 6.88264 -10.8438 15 + vertex 1.07065 -4.69974 15 + vertex -6.49335 -10.8438 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -6.49335 8.29724 15 + vertex -6.49335 -10.8438 15 + vertex -0.726349 -4.69974 15 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 15 -15 15 + vertex 15 -15 0 + vertex 15 15 0 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 15 15 15 + vertex 15 -15 15 + vertex 15 15 0 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 15 15 0 + vertex -15 15 0 + vertex -15 15 15 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 15 15 15 + vertex 15 15 0 + vertex -15 15 15 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 15 -15 0 + vertex -15 -15 0 + vertex -15 15 0 + endloop + endfacet + facet normal -0 -0 -1 + outer loop + vertex 15 15 0 + vertex 15 -15 0 + vertex -15 15 0 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex -15 -15 15 + vertex -15 -15 0 + vertex 15 -15 0 + endloop + endfacet + facet normal -0 -1 -0 + outer loop + vertex 15 -15 15 + vertex -15 -15 15 + vertex 15 -15 0 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -6.49335 8.29724 5 + vertex -9.24535 -10.8438 5 + vertex -6.49335 -10.8438 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -6.49335 8.29724 5 + vertex -9.24535 11.3642 5 + vertex -9.24535 -10.8438 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 1.07065 -4.69974 5 + vertex 0.351639 -0.977737 5 + vertex -0.726349 -4.69974 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 0.351639 -0.977737 5 + vertex -6.49335 8.29724 5 + vertex -0.726349 -4.69974 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -5.22034 11.3642 5 + vertex -9.24535 11.3642 5 + vertex -6.49335 8.29724 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 9.82664 -10.8438 5 + vertex 6.88264 8.29724 5 + vertex 6.88264 -10.8438 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 9.82664 11.3642 5 + vertex 6.88264 8.29724 5 + vertex 9.82664 -10.8438 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 9.82664 11.3642 5 + vertex 5.72964 11.3642 5 + vertex 6.88264 8.29724 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 6.88264 8.29724 5 + vertex 0.351639 -0.977737 5 + vertex 1.07065 -4.69974 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 5.72964 11.3642 5 + vertex 0.351639 -0.977737 5 + vertex 6.88264 8.29724 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 0.351639 -0.977737 5 + vertex -5.22034 11.3642 5 + vertex -6.49335 8.29724 5 + endloop + endfacet + facet normal 0.914058 0.405584 0 + outer loop + vertex -0.726349 -4.69974 5 + vertex -6.49335 8.29724 5 + vertex -6.49335 8.29724 15 + endloop + endfacet + facet normal 0.914058 0.405584 0 + outer loop + vertex -0.726349 -4.69974 15 + vertex -0.726349 -4.69974 5 + vertex -6.49335 8.29724 15 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 1.07065 -4.69974 5 + vertex -0.726349 -4.69974 5 + vertex -0.726349 -4.69974 15 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 1.07065 -4.69974 15 + vertex 1.07065 -4.69974 5 + vertex -0.726349 -4.69974 15 + endloop + endfacet + facet normal -0.912882 0.408223 0 + outer loop + vertex 6.88264 8.29724 5 + vertex 1.07065 -4.69974 5 + vertex 1.07065 -4.69974 15 + endloop + endfacet + facet normal -0.912882 0.408223 0 + outer loop + vertex 6.88264 8.29724 15 + vertex 6.88264 8.29724 5 + vertex 1.07065 -4.69974 15 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 6.88264 -10.8438 15 + vertex 6.88264 -10.8438 5 + vertex 6.88264 8.29724 5 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 6.88264 8.29724 15 + vertex 6.88264 -10.8438 15 + vertex 6.88264 8.29724 5 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 9.82664 -10.8438 5 + vertex 6.88264 -10.8438 5 + vertex 6.88264 -10.8438 15 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 9.82664 -10.8438 15 + vertex 9.82664 -10.8438 5 + vertex 6.88264 -10.8438 15 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 9.82664 11.3642 5 + vertex 9.82664 -10.8438 5 + vertex 9.82664 -10.8438 15 + endloop + endfacet + facet normal -1 -0 -0 + outer loop + vertex 9.82664 11.3642 15 + vertex 9.82664 11.3642 5 + vertex 9.82664 -10.8438 15 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 5.72964 11.3642 15 + vertex 5.72964 11.3642 5 + vertex 9.82664 11.3642 5 + endloop + endfacet + facet normal -0 -1 -0 + outer loop + vertex 9.82664 11.3642 15 + vertex 5.72964 11.3642 15 + vertex 9.82664 11.3642 5 + endloop + endfacet + facet normal 0.916746 -0.399471 0 + outer loop + vertex 0.351639 -0.977737 15 + vertex 0.351639 -0.977737 5 + vertex 5.72964 11.3642 5 + endloop + endfacet + facet normal 0.916746 -0.399471 0 + outer loop + vertex 5.72964 11.3642 15 + vertex 0.351639 -0.977737 15 + vertex 5.72964 11.3642 5 + endloop + endfacet + facet normal -0.911421 -0.411475 -0 + outer loop + vertex -5.22034 11.3642 15 + vertex -5.22034 11.3642 5 + vertex 0.351639 -0.977737 5 + endloop + endfacet + facet normal -0.911421 -0.411475 -0 + outer loop + vertex 0.351639 -0.977737 15 + vertex -5.22034 11.3642 15 + vertex 0.351639 -0.977737 5 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex -9.24535 11.3642 15 + vertex -9.24535 11.3642 5 + vertex -5.22034 11.3642 5 + endloop + endfacet + facet normal -0 -1 -0 + outer loop + vertex -5.22034 11.3642 15 + vertex -9.24535 11.3642 15 + vertex -5.22034 11.3642 5 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex -9.24535 -10.8438 15 + vertex -9.24535 -10.8438 5 + vertex -9.24535 11.3642 5 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex -9.24535 11.3642 15 + vertex -9.24535 -10.8438 15 + vertex -9.24535 11.3642 5 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -6.49335 -10.8438 5 + vertex -9.24535 -10.8438 5 + vertex -9.24535 -10.8438 15 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -6.49335 -10.8438 15 + vertex -6.49335 -10.8438 5 + vertex -9.24535 -10.8438 15 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -6.49335 8.29724 5 + vertex -6.49335 -10.8438 5 + vertex -6.49335 -10.8438 15 + endloop + endfacet + facet normal -1 -0 -0 + outer loop + vertex -6.49335 8.29724 15 + vertex -6.49335 8.29724 5 + vertex -6.49335 -10.8438 15 + endloop + endfacet +endsolid OpenSCAD_Model diff --git a/examples/Shapes/chopped_blocks.scad b/examples/Shapes/chopped_blocks.scad index ea5e27ac..30e24bc4 100644 --- a/examples/Shapes/chopped_blocks.scad +++ b/examples/Shapes/chopped_blocks.scad @@ -1,10 +1,5 @@ -// chopped_blocks.stl is derived from Mblock.stl -// (c) 2009 Will Langford licensed under -// the Creative Commons - GNU GPL license. -// http://www.thingiverse.com/thing:753 -// -// Jonas Pfeil converted the file to binary -// STL and duplicated its content. +// chopped_blocks.stl is derived from Basics/LetterBlock.scad +// The exported STL was converted to binary using MeshLab echo(version=version()); @@ -21,7 +16,7 @@ module blk2() { } module chop() { - translate([ -14, 0, 0 ]) + translate([ -18, 0, 0 ]) import(file = "chopped_blocks.stl", convexity = 12); } @@ -36,3 +31,14 @@ difference() { } } +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/chopped_blocks.stl b/examples/Shapes/chopped_blocks.stl index c24cdf77..0291b9fe 100644 Binary files a/examples/Shapes/chopped_blocks.stl and b/examples/Shapes/chopped_blocks.stl differ diff --git a/examples/Shapes/fence.scad b/examples/Shapes/fence.scad index 514cc697..015f3933 100644 --- a/examples/Shapes/fence.scad +++ b/examples/Shapes/fence.scad @@ -13,3 +13,14 @@ for (i = [-100:5:+100]) { translate([ i, 0, -30 ]) cylinder(r1 = 6, r2 = 2, h = get_cylinder_h(i)*3); } +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/flat_body.scad b/examples/Shapes/flat_body.scad index a18a94a7..135d8fbc 100644 --- a/examples/Shapes/flat_body.scad +++ b/examples/Shapes/flat_body.scad @@ -27,3 +27,14 @@ module shape() // linear_extrude(convexity = 10, center = true) shape(); +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/polyhedron.scad b/examples/Shapes/polyhedron.scad index 6aa44357..c0947f98 100644 --- a/examples/Shapes/polyhedron.scad +++ b/examples/Shapes/polyhedron.scad @@ -16,3 +16,15 @@ polyhedron( [4, 0, 3] ] ); + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/rounded_box.scad b/examples/Shapes/rounded_box.scad index aac5fd2f..48b1e5f6 100644 --- a/examples/Shapes/rounded_box.scad +++ b/examples/Shapes/rounded_box.scad @@ -36,3 +36,14 @@ module roundedBox(size, radius, sidesonly) translate([-15,0,0])roundedBox([20,30,40], 5, true); translate([15,0,0]) roundedBox([20,30,40], 5, false); +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/sphere.scad b/examples/Shapes/sphere.scad index 6e808acd..37cf3d4a 100644 --- a/examples/Shapes/sphere.scad +++ b/examples/Shapes/sphere.scad @@ -1,6 +1,4 @@ -// example012.stl is Mblock.stl, (c) 2009 Will Langford -// licensed under the Creative Commons - GNU GPL license. -// http://www.thingiverse.com/thing:753 +// M.stl is generated from Basics/LetterBlock.scad echo(version=version()); @@ -8,6 +6,18 @@ difference() { sphere(20); - translate([ -2.92, 0.5, +20 ]) rotate([180, 0, 180]) - import("sphere.stl", convexity = 5); + translate([ 0, 0.5, +20 ]) rotate([180, 0, 180]) + import("M.stl", convexity = 5); } + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/tripod.scad b/examples/Shapes/tripod.scad index c46d2cc4..bedc0f57 100644 --- a/examples/Shapes/tripod.scad +++ b/examples/Shapes/tripod.scad @@ -156,3 +156,14 @@ if (mode == "exploded") if (mode == "assembled") assembled(); +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/front.png b/front.png deleted file mode 100644 index 5e791c04..00000000 Binary files a/front.png and /dev/null differ diff --git a/gettext.pri b/gettext.pri index 84fffa55..26a562a4 100644 --- a/gettext.pri +++ b/gettext.pri @@ -19,8 +19,9 @@ macx: { GETTEXT_LIBPATH = $$OPENSCAD_LIBRARIES_DIR/lib } } - GETTEXT_CXXFLAGS=-I$$GETTEXT_INCLUDEPATH - GETTEXT_LIBS=-L$$GETTEXT_LIBPATH -lintl -liconv + !isEmpty(GETTEXT_INCLUDEPATH): GETTEXT_CXXFLAGS = -I$$GETTEXT_INCLUDEPATH + !isEmpty(GETTEXT_LIBPATH): GETTEXT_LIBS = -L$$GETTEXT_LIBPATH + GETTEXT_LIBS += -lintl -liconv } QMAKE_CXXFLAGS += $$GETTEXT_CXXFLAGS diff --git a/grid.png b/grid.png deleted file mode 100644 index 1b300627..00000000 Binary files a/grid.png and /dev/null differ diff --git a/icons/background.png b/icons/background.png index c0c304c1..db3b1134 100644 Binary files a/icons/background.png and b/icons/background.png differ diff --git a/icons/close.png b/icons/close.png new file mode 100644 index 00000000..9782e419 Binary files /dev/null and b/icons/close.png differ diff --git a/icons/information-icons-error.png b/icons/information-icons-error.png new file mode 100644 index 00000000..1d963f91 Binary files /dev/null and b/icons/information-icons-error.png differ diff --git a/icons/information-icons-info.png b/icons/information-icons-info.png new file mode 100644 index 00000000..73e5f3f1 Binary files /dev/null and b/icons/information-icons-info.png differ diff --git a/icons/information-icons-question.png b/icons/information-icons-question.png new file mode 100644 index 00000000..75bb0fe2 Binary files /dev/null and b/icons/information-icons-question.png differ diff --git a/icons/information-icons-warning.png b/icons/information-icons-warning.png new file mode 100644 index 00000000..6d439cba Binary files /dev/null and b/icons/information-icons-warning.png differ diff --git a/icons/license.txt b/icons/license.txt index 97e6931b..f73b0891 100644 --- a/icons/license.txt +++ b/icons/license.txt @@ -1,3 +1,14 @@ Taken from http://tango.freedesktop.org/Tango_Icon_Library, version 0.8.90 / public domain: - prefsFeatures.png (converted from preferences-system.svg) + +https://openclipart.org/detail/2281/information-icons-set-by-kuba / public domain: + +- information-icons-error.png +- information-icons-question.png +- information-icons-info.png +- information-icons-warning.png + +https://openclipart.org/detail/171382/cross-icon-by-zawertun-171382 / public domain: + +- close.png diff --git a/icons/openscad_doc.ico b/icons/openscad_doc.ico new file mode 100644 index 00000000..8a57e8d8 Binary files /dev/null and b/icons/openscad_doc.ico differ diff --git a/images/AMF-white.png b/images/AMF-white.png new file mode 100644 index 00000000..e2b19922 Binary files /dev/null and b/images/AMF-white.png differ diff --git a/images/AMF.png b/images/AMF.png new file mode 100644 index 00000000..a140bad0 Binary files /dev/null and b/images/AMF.png differ diff --git a/images/Arrowhead-Right-32.png b/images/Arrowhead-Right-32.png deleted file mode 100644 index 42dd282b..00000000 Binary files a/images/Arrowhead-Right-32.png and /dev/null differ diff --git a/images/CSG-white.png b/images/CSG-white.png new file mode 100644 index 00000000..23077154 Binary files /dev/null and b/images/CSG-white.png differ diff --git a/images/CSG.png b/images/CSG.png new file mode 100644 index 00000000..1cad4440 Binary files /dev/null and b/images/CSG.png differ diff --git a/images/Command-Redo-32-white.png b/images/Command-Redo-32-white.png new file mode 100644 index 00000000..51a198ce Binary files /dev/null and b/images/Command-Redo-32-white.png differ diff --git a/images/blackRender.png b/images/Command-Redo-32.png similarity index 53% rename from images/blackRender.png rename to images/Command-Redo-32.png index da50aee5..f9c77c5e 100644 Binary files a/images/blackRender.png and b/images/Command-Redo-32.png differ diff --git a/images/Command-Reset-32-white.png b/images/Command-Reset-32-white.png new file mode 100644 index 00000000..71f79b0c Binary files /dev/null and b/images/Command-Reset-32-white.png differ diff --git a/images/Command-Reset-32.png b/images/Command-Reset-32.png new file mode 100644 index 00000000..b24e419f Binary files /dev/null and b/images/Command-Reset-32.png differ diff --git a/images/Command-Undo-32-white.png b/images/Command-Undo-32-white.png new file mode 100644 index 00000000..a4c39fa3 Binary files /dev/null and b/images/Command-Undo-32-white.png differ diff --git a/images/Command-Undo-32.png b/images/Command-Undo-32.png new file mode 100644 index 00000000..2deea680 Binary files /dev/null and b/images/Command-Undo-32.png differ diff --git a/images/DXF-white.png b/images/DXF-white.png new file mode 100644 index 00000000..0afe5f2f Binary files /dev/null and b/images/DXF-white.png differ diff --git a/images/DXF.png b/images/DXF.png new file mode 100644 index 00000000..45ae376a Binary files /dev/null and b/images/DXF.png differ diff --git a/images/Decrease-Indent-32-white.png b/images/Decrease-Indent-32-white.png new file mode 100644 index 00000000..b2756c2d Binary files /dev/null and b/images/Decrease-Indent-32-white.png differ diff --git a/images/Decrease-Indent-32.png b/images/Decrease-Indent-32.png new file mode 100644 index 00000000..8697e9d0 Binary files /dev/null and b/images/Decrease-Indent-32.png differ diff --git a/images/Increase-Indent-32-white.png b/images/Increase-Indent-32-white.png new file mode 100644 index 00000000..8fc5049a Binary files /dev/null and b/images/Increase-Indent-32-white.png differ diff --git a/images/Increase-Indent-32.png b/images/Increase-Indent-32.png new file mode 100644 index 00000000..3be843cd Binary files /dev/null and b/images/Increase-Indent-32.png differ diff --git a/images/OFF-white.png b/images/OFF-white.png new file mode 100644 index 00000000..4f724b7f Binary files /dev/null and b/images/OFF-white.png differ diff --git a/images/OFF.png b/images/OFF.png new file mode 100644 index 00000000..c26dbf74 Binary files /dev/null and b/images/OFF.png differ diff --git a/images/PNG-white.png b/images/PNG-white.png new file mode 100644 index 00000000..6f94e3f8 Binary files /dev/null and b/images/PNG-white.png differ diff --git a/images/PNG.png b/images/PNG.png new file mode 100644 index 00000000..75a64adb Binary files /dev/null and b/images/PNG.png differ diff --git a/images/Preview-32 (1).png b/images/Preview-32 (1).png deleted file mode 100644 index 26f718c2..00000000 Binary files a/images/Preview-32 (1).png and /dev/null differ diff --git a/images/Preview-32.png b/images/Preview-32.png deleted file mode 100644 index 7da55318..00000000 Binary files a/images/Preview-32.png and /dev/null differ diff --git a/images/STL-white.png b/images/STL-white.png new file mode 100644 index 00000000..4392987d Binary files /dev/null and b/images/STL-white.png differ diff --git a/images/STL.png b/images/STL.png new file mode 100644 index 00000000..50949001 Binary files /dev/null and b/images/STL.png differ diff --git a/images/SVG-white.png b/images/SVG-white.png new file mode 100644 index 00000000..8b361cd3 Binary files /dev/null and b/images/SVG-white.png differ diff --git a/images/SVG.png b/images/SVG.png new file mode 100644 index 00000000..d7c18281 Binary files /dev/null and b/images/SVG.png differ diff --git a/images/export-white.png b/images/export-white.png index 9aeeade8..f89a27b3 100644 Binary files a/images/export-white.png and b/images/export-white.png differ diff --git a/images/export.png b/images/export.png index b0b59a76..2cefcef7 100644 Binary files a/images/export.png and b/images/export.png differ diff --git a/images/preview-32-white.png b/images/preview-32-white.png new file mode 100644 index 00000000..7001b9cf Binary files /dev/null and b/images/preview-32-white.png differ diff --git a/images/preview-32.png b/images/preview-32.png new file mode 100644 index 00000000..87be4bb3 Binary files /dev/null and b/images/preview-32.png differ diff --git a/images/render-32-white.png b/images/render-32-white.png new file mode 100644 index 00000000..6c17bb9f Binary files /dev/null and b/images/render-32-white.png differ diff --git a/images/render-32.png b/images/render-32.png new file mode 100644 index 00000000..f40cfdbd Binary files /dev/null and b/images/render-32.png differ diff --git a/images/scalemarkers-white.png b/images/scalemarkers-white.png new file mode 100644 index 00000000..1d6583c3 Binary files /dev/null and b/images/scalemarkers-white.png differ diff --git a/images/scalemarkers.png b/images/scalemarkers.png new file mode 100644 index 00000000..a6301354 Binary files /dev/null and b/images/scalemarkers.png differ diff --git a/images/zoom-text-in-white.png b/images/zoom-text-in-white.png new file mode 100644 index 00000000..2be2fafe Binary files /dev/null and b/images/zoom-text-in-white.png differ diff --git a/images/zoom-text-in.png b/images/zoom-text-in.png new file mode 100644 index 00000000..54bbbb36 Binary files /dev/null and b/images/zoom-text-in.png differ diff --git a/images/zoom-text-out-white.png b/images/zoom-text-out-white.png new file mode 100644 index 00000000..40214346 Binary files /dev/null and b/images/zoom-text-out-white.png differ diff --git a/images/zoom-text-out.png b/images/zoom-text-out.png new file mode 100644 index 00000000..db745e9b Binary files /dev/null and b/images/zoom-text-out.png differ diff --git a/locale/LINGUAS b/locale/LINGUAS index 9f82de46..ed46eb16 100644 --- a/locale/LINGUAS +++ b/locale/LINGUAS @@ -1,2 +1,2 @@ # available languages -fr ru de cs +fr ru de cs es diff --git a/locale/cs.po b/locale/cs.po index d9a8ed71..f7fc056c 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -7,39 +7,57 @@ msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2013.02.24\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-22 23:28+0100\n" -"PO-Revision-Date: 2014-12-23 12:24+0100\n" +"POT-Creation-Date: 2015-02-01 18:03+0100\n" +"PO-Revision-Date: 2015-02-01 20:54+0100\n" "Last-Translator: Miro Hrončok \n" "Language-Team: Czech \n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 1.5.4\n" -"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n>=2 && n<=4 ? 1 : 2;\n" +"X-Generator: Poedit 1.7.3\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" "X-Poedit-SourceCharset: UTF-8\n" -#: objects/ui_AboutDialog.h:51 src/AboutDialog.h:15 +#: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" msgstr "O OpenSCADu" -#: objects/ui_FontListDialog.h:102 +#: objects/ui_AboutDialog.h:105 objects/ui_launchingscreen.h:305 +msgid "" +"\n" +"

OpenSCAD

\n" +"

The Programmers Solid 3D CAD Modeller

\n" +"\n" +"\n" +"\n" +msgstr "" + +#: objects/ui_AboutDialog.h:112 +msgid "OK" +msgstr "OK" + +#: objects/ui_FontListDialog.h:105 msgid "OpenSCAD Font List" msgstr "Seznam OpenSCAD písem" -#: objects/ui_FontListDialog.h:103 objects/ui_LibraryInfoDialog.h:77 +#: objects/ui_FontListDialog.h:106 objects/ui_LibraryInfoDialog.h:77 msgid "&OK" msgstr "&OK" -#: objects/ui_FontListDialog.h:104 +#: objects/ui_FontListDialog.h:107 msgid "Copy to Clipboard" msgstr "Kopírovat do schránky" -#: objects/ui_FontListDialog.h:105 +#: objects/ui_FontListDialog.h:108 msgid "Filter:" msgstr "Filtr:" -#: objects/ui_FontListDialog.h:106 +#: objects/ui_FontListDialog.h:109 msgid "" "

This list shows the fonts currently registered with " "OpenSCAD.

Example:

  text(t = "OpenSCAD", font = "
 ""Liberation Sans:style=Italic");
" -#: objects/ui_launchingscreen.h:276 +#: objects/ui_launchingscreen.h:294 msgid "Welcome to OpenSCAD" msgstr "Vítá vás OpenSCAD" -#: objects/ui_launchingscreen.h:277 +#: objects/ui_launchingscreen.h:295 msgid "New" msgstr "Nový" -#: objects/ui_launchingscreen.h:278 +#: objects/ui_launchingscreen.h:296 msgid "Open" msgstr "Otevřít" -#: objects/ui_launchingscreen.h:279 +#: objects/ui_launchingscreen.h:297 msgid "Help" msgstr "Nápověda" -#: objects/ui_launchingscreen.h:280 +#: objects/ui_launchingscreen.h:298 msgid "Recents" msgstr "Nedávné" -#: objects/ui_launchingscreen.h:281 +#: objects/ui_launchingscreen.h:299 msgid "Open Recent" msgstr "Otevřít nedávný soubor" -#: objects/ui_launchingscreen.h:282 objects/ui_launchingscreen.h:284 -#: objects/ui_MainWindow.h:855 +#: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 msgid "Examples" msgstr "Příklady" -#: objects/ui_launchingscreen.h:285 +#: objects/ui_launchingscreen.h:303 msgid "Open Example" msgstr "Otevřít příklad" -#: objects/ui_launchingscreen.h:287 -msgid "" -"\n" -"

OpenSCAD

\n" -"

The Programmers Solid 3D CAD Modeller

\n" -"\n" -"\n" -"\n" -msgstr "" - -#: objects/ui_launchingscreen.h:294 +#: objects/ui_launchingscreen.h:312 msgid "Don't show again" msgstr "Příště nezobrazovat" +#: objects/ui_launchingscreen.h:313 +msgid "Version" +msgstr "Verze" + #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" msgstr "Info o knihovnách a sestavení" @@ -120,543 +127,567 @@ msgstr "Info o knihovnách a sestavení" msgid "OpenSCAD Detailed Library and Build Information" msgstr "Podrobné informace o tomto sestavení OpenSCADu a použitých knihovnách" -#: objects/ui_MainWindow.h:731 +#: objects/ui_MainWindow.h:837 msgid "&New" msgstr "&Nový" -#: objects/ui_MainWindow.h:732 +#: objects/ui_MainWindow.h:838 msgid "Ctrl+N" msgstr "Ctrl+N" -#: objects/ui_MainWindow.h:733 +#: objects/ui_MainWindow.h:839 msgid "&Open..." msgstr "&Otevřít..." -#: objects/ui_MainWindow.h:734 +#: objects/ui_MainWindow.h:840 msgid "Ctrl+O" msgstr "Ctrl+O" -#: objects/ui_MainWindow.h:735 +#: objects/ui_MainWindow.h:841 msgid "&Save" msgstr "&Uložit" -#: objects/ui_MainWindow.h:736 +#: objects/ui_MainWindow.h:842 msgid "Ctrl+S" msgstr "Ctrl+S" -#: objects/ui_MainWindow.h:737 +#: objects/ui_MainWindow.h:843 msgid "Save &As..." msgstr "Uložit &jako..." -#: objects/ui_MainWindow.h:738 +#: objects/ui_MainWindow.h:844 msgid "Ctrl+Shift+S" msgstr "Ctrl+Shift+S" -#: objects/ui_MainWindow.h:739 +#: objects/ui_MainWindow.h:845 msgid "&Reload" -msgstr "&Znovu načíst" +msgstr "Zno&vu načíst" -#: objects/ui_MainWindow.h:740 +#: objects/ui_MainWindow.h:846 msgid "Ctrl+R" msgstr "Ctrl+R" -#: objects/ui_MainWindow.h:741 +#: objects/ui_MainWindow.h:847 msgid "&Quit" msgstr "U&končit" -#: objects/ui_MainWindow.h:742 +#: objects/ui_MainWindow.h:848 msgid "Ctrl+Q" msgstr "Ctrl+Q" -#: objects/ui_MainWindow.h:743 +#: objects/ui_MainWindow.h:849 msgid "&Undo" msgstr "&Zpět" -#: objects/ui_MainWindow.h:744 +#: objects/ui_MainWindow.h:850 msgid "Ctrl+Z" msgstr "Ctrl+Z" -#: objects/ui_MainWindow.h:745 +#: objects/ui_MainWindow.h:851 msgid "&Redo" -msgstr "Zn&ovu" +msgstr "Znov&u" -#: objects/ui_MainWindow.h:746 +#: objects/ui_MainWindow.h:852 msgid "Ctrl+Shift+Z" msgstr "Ctrl+Shift+Z" -#: objects/ui_MainWindow.h:747 +#: objects/ui_MainWindow.h:853 msgid "Cu&t" -msgstr "&Vyjmout" +msgstr "Vy&jmout" -#: objects/ui_MainWindow.h:748 +#: objects/ui_MainWindow.h:854 msgid "Ctrl+X" msgstr "Ctrl+X" -#: objects/ui_MainWindow.h:749 +#: objects/ui_MainWindow.h:855 msgid "&Copy" msgstr "&Kopírovat" -#: objects/ui_MainWindow.h:750 +#: objects/ui_MainWindow.h:856 msgid "Ctrl+C" msgstr "Ctrl+C" -#: objects/ui_MainWindow.h:751 +#: objects/ui_MainWindow.h:857 msgid "&Paste" msgstr "V&ložit" -#: objects/ui_MainWindow.h:752 +#: objects/ui_MainWindow.h:858 msgid "Ctrl+V" msgstr "Ctrl+V" -#: objects/ui_MainWindow.h:753 +#: objects/ui_MainWindow.h:859 msgid "&Indent" msgstr "Odsad&it" -#: objects/ui_MainWindow.h:754 +#: objects/ui_MainWindow.h:860 msgid "Ctrl+I" msgstr "Ctrl+I" -#: objects/ui_MainWindow.h:755 -msgid "U&nindent" -msgstr "Z&rušit odsazení" - -#: objects/ui_MainWindow.h:756 -msgid "Ctrl+Shift+I" -msgstr "Ctrl+Shift+I" - -#: objects/ui_MainWindow.h:757 +#: objects/ui_MainWindow.h:861 msgid "C&omment" -msgstr "&Zakomentovat" +msgstr "Zakomen&tovat" -#: objects/ui_MainWindow.h:758 +#: objects/ui_MainWindow.h:862 msgid "Ctrl+D" msgstr "Ctrl+D" -#: objects/ui_MainWindow.h:759 +#: objects/ui_MainWindow.h:863 msgid "Unco&mment" msgstr "&Odkomentovat" -#: objects/ui_MainWindow.h:760 +#: objects/ui_MainWindow.h:864 msgid "Ctrl+Shift+D" msgstr "Ctrl+Shift+D" -#: objects/ui_MainWindow.h:761 -msgid "Paste viewport translation" -msgstr "Vložit posun pohledu" +#: objects/ui_MainWindow.h:865 +msgid "P&aste viewport translation" +msgstr "Vložit posun pohl&edu" -#: objects/ui_MainWindow.h:762 +#: objects/ui_MainWindow.h:866 msgid "Ctrl+T" msgstr "Ctrl+T" -#: objects/ui_MainWindow.h:763 -msgid "Paste viewport rotation" -msgstr "Vložit rotaci pohledu" +#: objects/ui_MainWindow.h:867 +msgid "Past&e viewport rotation" +msgstr "Vlo&žit rotaci pohledu" -#: objects/ui_MainWindow.h:764 objects/ui_MainWindow.h:842 -msgid "Zoom In" -msgstr "Přiblížit" +#: objects/ui_MainWindow.h:868 +msgid "Increase Font &Size" +msgstr "Zv&ětšit písmo" -#: objects/ui_MainWindow.h:765 +#: objects/ui_MainWindow.h:869 msgid "Ctrl++" msgstr "Ctrl++" -#: objects/ui_MainWindow.h:766 objects/ui_MainWindow.h:844 -msgid "Zoom Out" -msgstr "Oddálit" +#: objects/ui_MainWindow.h:870 +msgid "Decrease Font Si&ze" +msgstr "Z&menšit písmo" -#: objects/ui_MainWindow.h:767 +#: objects/ui_MainWindow.h:871 msgid "Ctrl+-" msgstr "Ctrl+-" -#: objects/ui_MainWindow.h:768 -msgid "Hide editor" -msgstr "Skrýt editor" +#: objects/ui_MainWindow.h:872 +msgid "H&ide editor" +msgstr "Skrýt &editor" -#: objects/ui_MainWindow.h:769 +#: objects/ui_MainWindow.h:873 msgid "&Reload and Preview" msgstr "Znovu &načíst a zobrazit" -#: objects/ui_MainWindow.h:770 +#: objects/ui_MainWindow.h:874 msgid "F4" msgstr "F4" -#: objects/ui_MainWindow.h:771 +#: objects/ui_MainWindow.h:875 msgid "&Preview" msgstr "&Zobrazit" -#: objects/ui_MainWindow.h:772 +#: objects/ui_MainWindow.h:876 msgid "F5" msgstr "F5" -#: objects/ui_MainWindow.h:773 -msgid "&Render" +#: objects/ui_MainWindow.h:877 +msgid "R&ender" msgstr "Vy&renderovat" -#: objects/ui_MainWindow.h:774 +#: objects/ui_MainWindow.h:878 msgid "F6" msgstr "F6" -#: objects/ui_MainWindow.h:775 -msgid "Check Validity" -msgstr "Zkontrolovat správnost" +#: objects/ui_MainWindow.h:879 +msgid "&Check Validity" +msgstr "Zkontrolovat &správnost" -#: objects/ui_MainWindow.h:776 -msgid "Display &AST..." -msgstr "Ukázat &ATS..." +#: objects/ui_MainWindow.h:880 +msgid "Display A&ST..." +msgstr "&Ukázat ATS..." -#: objects/ui_MainWindow.h:777 +#: objects/ui_MainWindow.h:881 msgid "Display CSG &Tree..." msgstr "Ukázat CSG s&trom..." -#: objects/ui_MainWindow.h:778 -msgid "Display CSG &Products..." +#: objects/ui_MainWindow.h:882 +msgid "Display CSG Pr&oducts..." msgstr "Ukázat CSG &produkty..." -#: objects/ui_MainWindow.h:779 +#: objects/ui_MainWindow.h:883 msgid "Export as &STL..." msgstr "Exportovat jako &STL..." -#: objects/ui_MainWindow.h:780 +#: objects/ui_MainWindow.h:884 msgid "Export as &OFF..." msgstr "Exportovat jako &OFF..." -#: objects/ui_MainWindow.h:781 +#: objects/ui_MainWindow.h:885 msgid "Preview" msgstr "Náhled" -#: objects/ui_MainWindow.h:782 +#: objects/ui_MainWindow.h:886 msgid "F9" msgstr "F9" -#: objects/ui_MainWindow.h:783 +#: objects/ui_MainWindow.h:887 msgid "Surfaces" msgstr "Povrchy" -#: objects/ui_MainWindow.h:784 +#: objects/ui_MainWindow.h:888 msgid "F10" msgstr "F10" -#: objects/ui_MainWindow.h:785 +#: objects/ui_MainWindow.h:889 msgid "Wireframe" msgstr "Drátové zobrazení" -#: objects/ui_MainWindow.h:786 +#: objects/ui_MainWindow.h:890 msgid "F11" msgstr "F11" -#: objects/ui_MainWindow.h:787 +#: objects/ui_MainWindow.h:891 msgid "Thrown Together" msgstr "Vše společně" -#: objects/ui_MainWindow.h:788 +#: objects/ui_MainWindow.h:892 msgid "F12" msgstr "F12" -#: objects/ui_MainWindow.h:789 +#: objects/ui_MainWindow.h:893 msgid "Show Edges" msgstr "Zobrazit hrany" -#: objects/ui_MainWindow.h:790 +#: objects/ui_MainWindow.h:894 msgid "Ctrl+1" msgstr "Ctrl+1" -#: objects/ui_MainWindow.h:791 +#: objects/ui_MainWindow.h:895 msgid "Show Axes" msgstr "Zobrazit osy" -#: objects/ui_MainWindow.h:792 +#: objects/ui_MainWindow.h:896 msgid "Ctrl+2" msgstr "Ctrl+2" -#: objects/ui_MainWindow.h:793 +#: objects/ui_MainWindow.h:897 msgid "Show Crosshairs" msgstr "Zobrazit zaměřovač" -#: objects/ui_MainWindow.h:794 +#: objects/ui_MainWindow.h:898 msgid "Ctrl+3" msgstr "Ctrl+3" -#: objects/ui_MainWindow.h:795 +#: objects/ui_MainWindow.h:899 +msgid "Show Scale Markers" +msgstr "Zobrazit pravítko" + +#: objects/ui_MainWindow.h:900 msgid "Animate" msgstr "Animovat" -#: objects/ui_MainWindow.h:796 -msgid "Top" -msgstr "Shora" +#: objects/ui_MainWindow.h:901 +msgid "&Top" +msgstr "Ses&hora" -#: objects/ui_MainWindow.h:797 +#: objects/ui_MainWindow.h:902 msgid "Ctrl+4" msgstr "Ctrl+4" -#: objects/ui_MainWindow.h:798 -msgid "Bottom" -msgstr "Zespoda" +#: objects/ui_MainWindow.h:903 +msgid "&Bottom" +msgstr "Ze&spoda" -#: objects/ui_MainWindow.h:799 +#: objects/ui_MainWindow.h:904 msgid "Ctrl+5" msgstr "Ctrl+5" -#: objects/ui_MainWindow.h:800 -msgid "Left" -msgstr "Zleva" +#: objects/ui_MainWindow.h:905 +msgid "&Left" +msgstr "Z&leva" -#: objects/ui_MainWindow.h:801 +#: objects/ui_MainWindow.h:906 msgid "Ctrl+6" msgstr "Ctrl+6" -#: objects/ui_MainWindow.h:802 -msgid "Right" -msgstr "Zprava" +#: objects/ui_MainWindow.h:907 +msgid "&Right" +msgstr "Z&prava" -#: objects/ui_MainWindow.h:803 +#: objects/ui_MainWindow.h:908 msgid "Ctrl+7" msgstr "Ctrl+7" -#: objects/ui_MainWindow.h:804 -msgid "Front" -msgstr "Zepředu" +#: objects/ui_MainWindow.h:909 +msgid "&Front" +msgstr "Zepře&du" -#: objects/ui_MainWindow.h:805 +#: objects/ui_MainWindow.h:910 msgid "Ctrl+8" msgstr "Ctrl+8" -#: objects/ui_MainWindow.h:806 -msgid "Back" -msgstr "Zezadu" +#: objects/ui_MainWindow.h:911 +msgid "Bac&k" +msgstr "Ze&zadu" -#: objects/ui_MainWindow.h:807 +#: objects/ui_MainWindow.h:912 msgid "Ctrl+9" msgstr "Ctrl+9" -#: objects/ui_MainWindow.h:808 -msgid "Diagonal" -msgstr "Diagonálně" +#: objects/ui_MainWindow.h:913 +msgid "&Diagonal" +msgstr "Dia&gonálně" -#: objects/ui_MainWindow.h:809 +#: objects/ui_MainWindow.h:914 msgid "Ctrl+0" msgstr "Ctrl+0" -#: objects/ui_MainWindow.h:810 -msgid "Center" -msgstr "Vycentrovat" +#: objects/ui_MainWindow.h:915 +msgid "Ce&nter" +msgstr "Vy¢rovat" -#: objects/ui_MainWindow.h:811 -msgid "Perspective" -msgstr "Perspektivně" +#: objects/ui_MainWindow.h:916 +msgid "&Perspective" +msgstr "Pe&rspektivně" -#: objects/ui_MainWindow.h:812 -msgid "Orthogonal" -msgstr "Ortogonálně" +#: objects/ui_MainWindow.h:917 +msgid "&Orthogonal" +msgstr "&Ortogonálně" -#: objects/ui_MainWindow.h:813 -msgid "Hide console" -msgstr "Skrýt terminál" +#: objects/ui_MainWindow.h:918 +msgid "H&ide console" +msgstr "Skrýt &terminál" -#: objects/ui_MainWindow.h:814 -msgid "About" -msgstr "O aplikaci" +#: objects/ui_MainWindow.h:919 +msgid "&About" +msgstr "&O aplikaci" -#: objects/ui_MainWindow.h:815 -msgid "Documentation" -msgstr "Dokumentace" +#: objects/ui_MainWindow.h:920 +msgid "&Documentation" +msgstr "&Dokumentace" -#: objects/ui_MainWindow.h:816 +#: objects/ui_MainWindow.h:921 msgid "Clear Recent" msgstr "Zapomenout nedávné" -#: objects/ui_MainWindow.h:817 -msgid "Export as DXF..." -msgstr "Exportovat jako &DXF" +#: objects/ui_MainWindow.h:922 +msgid "Export as &DXF..." +msgstr "Exportovat jako &DXF..." -#: objects/ui_MainWindow.h:818 objects/ui_OpenCSGWarningDialog.h:94 -msgid "Close" -msgstr "Zavřít" +#: objects/ui_MainWindow.h:923 +msgid "&Close" +msgstr "&Zavřít" -#: objects/ui_MainWindow.h:819 +#: objects/ui_MainWindow.h:924 msgid "Ctrl+W" msgstr "Ctrl+W" -#: objects/ui_MainWindow.h:820 objects/ui_Preferences.h:608 -msgid "Preferences" -msgstr "Předvolby" +#: objects/ui_MainWindow.h:925 +msgid "&Preferences" +msgstr "Předvolb&y" -#: objects/ui_MainWindow.h:821 -msgid "Find..." -msgstr "Najít..." +#: objects/ui_MainWindow.h:926 +msgid "&Find..." +msgstr "&Najít..." -#: objects/ui_MainWindow.h:822 +#: objects/ui_MainWindow.h:927 msgid "Ctrl+F" msgstr "Ctrl+F" -#: objects/ui_MainWindow.h:823 -msgid "Find and Replace..." -msgstr "Najít a nahradit..." +#: objects/ui_MainWindow.h:928 +msgid "Fin&d and Replace..." +msgstr "Najít a na&hradit..." -#: objects/ui_MainWindow.h:824 +#: objects/ui_MainWindow.h:929 msgid "Ctrl+Alt+F" msgstr "Ctrl+Alt+F" -#: objects/ui_MainWindow.h:825 -msgid "Find Next" -msgstr "Najít další" +#: objects/ui_MainWindow.h:930 +msgid "Find Ne&xt" +msgstr "Najít &další" -#: objects/ui_MainWindow.h:826 +#: objects/ui_MainWindow.h:931 msgid "Ctrl+G" msgstr "Ctrl+G" -#: objects/ui_MainWindow.h:827 -msgid "Find Previous" -msgstr "Najít předchozí" +#: objects/ui_MainWindow.h:932 +msgid "Find Pre&vious" +msgstr "Najít &předchozí" -#: objects/ui_MainWindow.h:828 +#: objects/ui_MainWindow.h:933 msgid "Ctrl+Shift+G" msgstr "Ctrl+Shift+G" -#: objects/ui_MainWindow.h:829 -msgid "Use Selection for Find" -msgstr "Hledat vybraný řetězec" +#: objects/ui_MainWindow.h:934 +msgid "Use Se&lection for Find" +msgstr "Hledat vybraný řetěze&c" -#: objects/ui_MainWindow.h:830 +#: objects/ui_MainWindow.h:935 msgid "Ctrl+E" msgstr "Ctrl+E" -#: objects/ui_MainWindow.h:831 -msgid "Flush Caches" -msgstr "Vyprázdnit mezipaměť" +#: objects/ui_MainWindow.h:936 +msgid "&Flush Caches" +msgstr "&Vyprázdnit mezipaměť" -#: objects/ui_MainWindow.h:832 -msgid "OpenSCAD Homepage" -msgstr "Domovská stránka OpenSCADu" +#: objects/ui_MainWindow.h:937 +msgid "&OpenSCAD Homepage" +msgstr "Domovská &stránka OpenSCADu" -#: objects/ui_MainWindow.h:833 -msgid "Automatic Reload and Preview" -msgstr "Automaticky načítat a zobrazovat" +#: objects/ui_MainWindow.h:938 +msgid "&Automatic Reload and Preview" +msgstr "&Automaticky načítat a zobrazovat" -#: objects/ui_MainWindow.h:834 -msgid "Export as Image..." -msgstr "Exportovat jako obrázek..." +#: objects/ui_MainWindow.h:939 +msgid "Export as &Image..." +msgstr "Exportovat jako &obrázek..." -#: objects/ui_MainWindow.h:835 -msgid "Export as CSG..." -msgstr "Exportovat jako CSG..." +#: objects/ui_MainWindow.h:940 +msgid "Export as &CSG..." +msgstr "Exportovat jako &CSG..." -#: objects/ui_MainWindow.h:836 -msgid "Library info" -msgstr "Informace o knihovnách" +#: objects/ui_MainWindow.h:941 +msgid "&Library info" +msgstr "&Informace o knihovnách" -#: objects/ui_MainWindow.h:837 -msgid "Show Library Folder..." -msgstr "Adresář s knihovnami..." +#: objects/ui_MainWindow.h:942 +msgid "Show &Library Folder..." +msgstr "&Adresář s knihovnami..." -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:943 msgid "Reset View" msgstr "Výchozí pohled" -#: objects/ui_MainWindow.h:839 -msgid "Font List" -msgstr "Seznam písem" +#: objects/ui_MainWindow.h:944 +msgid "&Font List" +msgstr "Seznam &písem" -#: objects/ui_MainWindow.h:840 -msgid "Export as SVG..." -msgstr "Exportovat jako SVG..." +#: objects/ui_MainWindow.h:945 +msgid "Export as S&VG..." +msgstr "Exportovat jako S&VG..." -#: objects/ui_MainWindow.h:841 -msgid "Export as AMF..." -msgstr "Exportovat jako AMF..." +#: objects/ui_MainWindow.h:946 +msgid "Export as &AMF..." +msgstr "Exportovat jako &AMF..." -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:947 +msgid "Zoom In" +msgstr "Přiblížit" + +#: objects/ui_MainWindow.h:948 msgid "Ctrl+]" msgstr "Ctrl+]" -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:949 +msgid "Zoom Out" +msgstr "Oddálit" + +#: objects/ui_MainWindow.h:950 msgid "Ctrl+[" msgstr "Ctrl+[" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:951 msgid "View All" msgstr "Zobrazit vše" -#: objects/ui_MainWindow.h:847 -msgid "Convert Tabs to Spaces" -msgstr "Převést tabulátory na mezery" +#: objects/ui_MainWindow.h:952 +msgid "Conv&ert Tabs to Spaces" +msgstr "Pře&vést tabulátory na mezery" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:953 msgid "Hide toolbars" msgstr "Skrýt nástrojové lišty" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:954 +msgid "U&nindent" +msgstr "Z&rušit odsazení" + +#: objects/ui_MainWindow.h:955 +msgid "Ctrl+Shift+I" +msgstr "Ctrl+Shift+I" + +#: objects/ui_MainWindow.h:956 +msgid "&Cheat Sheet" +msgstr "&Tahák" + +#: objects/ui_MainWindow.h:957 +msgid "Message" +msgstr "Zpráva" + +#: objects/ui_MainWindow.h:960 msgid "Time:" msgstr "Čas:" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:961 msgid "FPS:" msgstr "FPS:" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:962 msgid "Steps:" msgstr "Kroky:" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:963 msgid "Dump Pictures" msgstr "Ukládat obrázky" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:964 msgid "&File" msgstr "&Soubor" -#: objects/ui_MainWindow.h:854 -msgid "Recent Files" -msgstr "Nedávné soubory" +#: objects/ui_MainWindow.h:965 +msgid "Recen&t Files" +msgstr "Nedávné &soubory" -#: objects/ui_MainWindow.h:856 -msgid "Export" -msgstr "Exportovat" +#: objects/ui_MainWindow.h:966 +msgid "&Examples" +msgstr "&Příklady" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:967 +msgid "E&xport" +msgstr "&Exportovat" + +#: objects/ui_MainWindow.h:968 msgid "&Edit" msgstr "&Upravit" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:969 msgid "&Design" msgstr "&Design" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:970 msgid "&View" msgstr "&Zobrazit" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:971 msgid "&Help" msgstr "&Nápověda" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:974 msgid "Find" msgstr "Najít" -#: objects/ui_MainWindow.h:864 objects/ui_MainWindow.h:871 +#: objects/ui_MainWindow.h:975 objects/ui_MainWindow.h:982 msgid "Replace" msgstr "Nahradit" -#: objects/ui_MainWindow.h:866 +#: objects/ui_MainWindow.h:977 msgid "Search string" msgstr "Hledaný řetězec" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:978 msgid "<" msgstr "<" -#: objects/ui_MainWindow.h:868 +#: objects/ui_MainWindow.h:979 msgid ">" msgstr ">" -#: objects/ui_MainWindow.h:869 +#: objects/ui_MainWindow.h:980 msgid "Done" msgstr "Hotovo" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:981 msgid "Replacement string" msgstr "Nahradit za" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:983 msgid "All" msgstr "Vše" @@ -686,163 +717,329 @@ msgstr "Povolit OpenCSG" msgid "Show this message again" msgstr "Zobrazit tuto zprávu znovu" -#: objects/ui_Preferences.h:609 +#: objects/ui_OpenCSGWarningDialog.h:94 +msgid "Close" +msgstr "Zavřít" + +#: objects/ui_Preferences.h:1061 +msgid "Preferences" +msgstr "Předvolby" + +#: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "3D zobrazení" -#: objects/ui_Preferences.h:610 src/UIUtils.cc:85 +#: objects/ui_Preferences.h:1063 src/UIUtils.cc:86 msgid "Advanced" msgstr "Pokročilé" -#: objects/ui_Preferences.h:611 src/mainwin.cc:2315 +#: objects/ui_Preferences.h:1064 src/mainwin.cc:2418 msgid "Editor" msgstr "Editor" -#: objects/ui_Preferences.h:612 +#: objects/ui_Preferences.h:1065 msgid "Update" msgstr "Aktualizace" -#: objects/ui_Preferences.h:613 objects/ui_Preferences.h:633 +#: objects/ui_Preferences.h:1066 objects/ui_Preferences.h:1147 msgid "Features" msgstr "Funkce" -#: objects/ui_Preferences.h:615 +#: objects/ui_Preferences.h:1068 msgid "Enable/Disable experimental features" msgstr "Povolit/Zakázat experimentální funkce" -#: objects/ui_Preferences.h:617 +#: objects/ui_Preferences.h:1070 msgid "Color scheme:" msgstr "Barevné téma:" -#: objects/ui_Preferences.h:618 +#: objects/ui_Preferences.h:1071 +msgid "Show Warnings and Errors in 3D View" +msgstr "Zobrazovat varování a chyby v 3D okně" + +#: objects/ui_Preferences.h:1072 msgid "Editor Type" msgstr "Varianta editoru" -#: objects/ui_Preferences.h:621 +#: objects/ui_Preferences.h:1075 msgid "Simple Editor" msgstr "Jednoduchý editor" -#: objects/ui_Preferences.h:622 +#: objects/ui_Preferences.h:1076 msgid "QScintilla Editor" msgstr "Editor QScintilla" -#: objects/ui_Preferences.h:624 +#: objects/ui_Preferences.h:1078 msgid "(requires restart)" msgstr "(vyžaduje restart aplikace)" -#: objects/ui_Preferences.h:625 +#: objects/ui_Preferences.h:1079 msgid "Font" msgstr "Písmo" -#: objects/ui_Preferences.h:626 +#: objects/ui_Preferences.h:1080 msgid "Color syntax highlighting" msgstr "Barva zvýrazňování syntaxe" -#: objects/ui_Preferences.h:627 -msgid "Use Ctrl/Cmd-Mouse-wheel to zoom text" -msgstr "Použít Ctrl/Cmd a kolečko myši k změně velikosti písma" +#: objects/ui_Preferences.h:1081 +msgid "Ctrl/Cmd-Mouse-wheel zooms text" +msgstr "Ctrl/Cmd a kolečko myši mění velikost písma" -#: objects/ui_Preferences.h:629 +#: objects/ui_Preferences.h:1082 +msgid "Indentation" +msgstr "Odsazování" + +#: objects/ui_Preferences.h:1083 +msgid "Auto Indent" +msgstr "Automatické odsazování" + +#: objects/ui_Preferences.h:1084 +msgid "Indent using" +msgstr "Odsazovat pomocí" + +#: objects/ui_Preferences.h:1087 src/settings.cc:135 +msgid "Spaces" +msgstr "mezer" + +#: objects/ui_Preferences.h:1088 src/settings.cc:135 +msgid "Tabs" +msgstr "tabulátorů" + +#: objects/ui_Preferences.h:1090 +msgid "Indentation width" +msgstr "Velikost odsazení" + +#: objects/ui_Preferences.h:1091 +msgid "Tab width" +msgstr "Šířka tabulátoru" + +#: objects/ui_Preferences.h:1092 +msgid "Tab key function" +msgstr "Funkce klávesy tabulátor" + +#: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 +#: src/settings.cc:136 +msgid "Indent" +msgstr "odsadí" + +#: objects/ui_Preferences.h:1096 src/settings.cc:136 +msgid "Insert Tab" +msgstr "vloží znak tabulátoru" + +#: objects/ui_Preferences.h:1098 +msgid "Show whitespace" +msgstr "Zobrazovat mazery" + +#: objects/ui_Preferences.h:1101 src/settings.cc:132 +msgid "Never" +msgstr "nikdy" + +#: objects/ui_Preferences.h:1102 src/settings.cc:132 +msgid "Always" +msgstr "vždy" + +#: objects/ui_Preferences.h:1103 +msgid "Only after indentation" +msgstr "pouze za odsazením" + +#: objects/ui_Preferences.h:1105 +msgid "Size" +msgstr "Velikost" + +#: objects/ui_Preferences.h:1106 +msgid "Display" +msgstr "Vzhled" + +#: objects/ui_Preferences.h:1107 +msgid "Enable brace matching" +msgstr "Zvýrazňovat párové závorky" + +#: objects/ui_Preferences.h:1108 +msgid "Highlight current line" +msgstr "Zvýrazňovat aktuální řádek" + +#: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 +msgid "Line wrap" +msgstr "Zalamování řádek" + +#: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 +#: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 +#: src/settings.cc:131 +msgid "None" +msgstr "vypnout" + +#: objects/ui_Preferences.h:1113 src/settings.cc:127 +msgid "Wrap at character boundaries" +msgstr "zalamovat na úrovni znaků" + +#: objects/ui_Preferences.h:1114 src/settings.cc:127 +msgid "Wrap at word boundaries" +msgstr "zalamovat na úrovni slov" + +#: objects/ui_Preferences.h:1116 +msgid "Line wrap indentation" +msgstr "Odsazení zalomených řádek" + +#: objects/ui_Preferences.h:1117 +msgid "Line wrap visualization" +msgstr "Pozice symbolu zalomení" + +#: objects/ui_Preferences.h:1118 +msgid "Style" +msgstr "Styl" + +#: objects/ui_Preferences.h:1121 src/settings.cc:128 +msgid "Fixed" +msgstr "vždy stejný" + +#: objects/ui_Preferences.h:1122 src/settings.cc:128 +msgid "Same" +msgstr "jako počátek" + +#: objects/ui_Preferences.h:1123 src/settings.cc:128 +msgid "Indented" +msgstr "odsazený" + +#: objects/ui_Preferences.h:1126 +msgid "Start" +msgstr "Začátek" + +#: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Text" +msgstr "za textem" + +#: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Border" +msgstr "konec řádky" + +#: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Margin" +msgstr "levý okraj" + +#: objects/ui_Preferences.h:1134 +msgid "End" +msgstr "Konec" + +#: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" msgstr "Automaticky vyhledávat aktualizace" -#: objects/ui_Preferences.h:630 +#: objects/ui_Preferences.h:1144 msgid "Include development snapshots" msgstr "Včetně nestabilních verzí" -#: objects/ui_Preferences.h:631 +#: objects/ui_Preferences.h:1145 msgid "Check Now" msgstr "Zkontrolovat nyní" -#: objects/ui_Preferences.h:632 +#: objects/ui_Preferences.h:1146 msgid "Last checked: " msgstr "Poslední kontrola:" -#: objects/ui_Preferences.h:634 +#: objects/ui_Preferences.h:1148 msgid "OpenCSG" msgstr "OpenCSG" -#: objects/ui_Preferences.h:635 +#: objects/ui_Preferences.h:1149 msgid "Show capability warning" msgstr "Zobrazovat varování o vlastnostech" -#: objects/ui_Preferences.h:636 +#: objects/ui_Preferences.h:1150 msgid "Enable for OpenGL 1.x" msgstr "Povolit pro OpenGL 1.x" -#: objects/ui_Preferences.h:637 +#: objects/ui_Preferences.h:1151 msgid "Turn off rendering at " msgstr "Vypnout renderování při" -#: objects/ui_Preferences.h:638 +#: objects/ui_Preferences.h:1152 msgid "elements" msgstr "prvcích" -#: objects/ui_Preferences.h:639 +#: objects/ui_Preferences.h:1153 msgid "Force Goldfeather" msgstr "Vynutit zobrazení Goldfeather" -#: objects/ui_Preferences.h:640 +#: objects/ui_Preferences.h:1154 msgid "CGAL Cache size" msgstr "Velikost CGAL cache" -#: objects/ui_Preferences.h:641 objects/ui_Preferences.h:643 +#: objects/ui_Preferences.h:1155 objects/ui_Preferences.h:1157 msgid "bytes" msgstr "bytů" -#: objects/ui_Preferences.h:642 +#: objects/ui_Preferences.h:1156 msgid "PolySet Cache size" msgstr "Velikost PolySet cache" -#: objects/ui_Preferences.h:644 +#: objects/ui_Preferences.h:1158 msgid "Allow to open multiple documents" msgstr "Povolit současné otevření více dokumentů" -#: objects/ui_Preferences.h:645 +#: objects/ui_Preferences.h:1159 msgid "Enable docking of Editor and Console in different places" msgstr "Povolit zaparkování editoru a konzole na různá místa" -#: objects/ui_Preferences.h:646 +#: objects/ui_Preferences.h:1160 msgid "Enable undocking of Editor and Console to separate windows" msgstr "Povolit plovoucí editor a konzoli" -#: objects/ui_Preferences.h:647 +#: objects/ui_Preferences.h:1161 msgid "Show Welcome Screen" msgstr "Zobrazovat uvítací obrazovku" -#: objects/ui_Preferences.h:648 +#: objects/ui_Preferences.h:1162 msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "Povolit lokalizaci rozhraní OpenSCADu (vyžaduje restart aplikace)" -#: objects/ui_Preferences.h:649 -msgid "toolBar" -msgstr "" - #: objects/ui_ProgressWidget.h:72 -msgid "Form" -msgstr "" - -#: objects/ui_ProgressWidget.h:73 msgid "%v / %m" msgstr "%v / %m" -#: src/AboutDialog.h:15 -msgid "About OpenSCAD " -msgstr "O OpenSCADu " +#: src/Camera.cc:126 +#, c-format +msgid "" +"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " +"distance = %.2f" +msgstr "" +"Pohled: posun = [ %.2f %.2f %.2f ], rotace = [ %.2f %.2f %.2f ], vzdálenost " +"= %.2f" -#: src/mainwin.cc:773 src/mainwin.cc:1315 +#: src/mainwin.cc:778 src/mainwin.cc:1354 msgid "Untitled.scad" msgstr "Bezejmenný.scad" -#: src/mainwin.cc:1299 +#: src/mainwin.cc:971 +msgid "Compile error." +msgstr "Chyba kompilace." + +#: src/mainwin.cc:974 +msgid "Error while compiling '%1'." +msgstr "Chyba při kompilaci '%1'." + +#: src/mainwin.cc:978 +msgid "Compilation generated %1 warning." +msgid_plural "Compilation generated %1 warnings." +msgstr[0] "Kompilace vyvolala %1 varování." +msgstr[1] "Kompilace vyvolala %1 varování." +msgstr[2] "Kompilace vyvolala %1 varování." + +#: src/mainwin.cc:988 +msgid " For details see console window." +msgstr "Pro podrobnosti nahlédněte do konzole." + +#: src/mainwin.cc:1353 msgid "Save File" msgstr "Uložit soubor" -#: src/mainwin.cc:1301 +#: src/mainwin.cc:1355 msgid "OpenSCAD Designs (*.scad)" msgstr "OpenSCAD designy(*.scad)" -#: src/mainwin.cc:1311 +#: src/mainwin.cc:1365 msgid "" "%1 already exists.\n" "Do you want to replace it?" @@ -850,11 +1047,11 @@ msgstr "" "%1 již existuje.\n" "Chcete jej nahradit?" -#: src/mainwin.cc:1630 +#: src/mainwin.cc:1684 msgid "Application" msgstr "Aplikace" -#: src/mainwin.cc:1631 +#: src/mainwin.cc:1685 msgid "" "The document has been modified.\n" "Do you really want to reload the file?" @@ -862,65 +1059,63 @@ msgstr "" "Dokument byl pozměněn.\n" "Opravdu jej chcete znovu načíst?" -#: src/mainwin.cc:1942 src/mainwin.cc:1999 +#: src/mainwin.cc:2038 src/mainwin.cc:2094 msgid "Export %1 File" msgstr "Exportovat %s soubor(ů)" -#: src/mainwin.cc:1943 src/mainwin.cc:2003 +#: src/mainwin.cc:2039 src/mainwin.cc:2098 msgid "%1 Files (*%2)" msgstr "%1 Soubor(ů) (*%2)" -#: src/mainwin.cc:1944 +#: src/mainwin.cc:2040 msgid "Untitled" msgstr "Bezejmenný" -#: src/mainwin.cc:2001 +#: src/mainwin.cc:2096 msgid "Untitled%1" msgstr "Bezejmenný%1" -#: src/mainwin.cc:2052 +#: src/mainwin.cc:2147 msgid "Export CSG File" msgstr "Exportovat CSG soubor" -#: src/mainwin.cc:2053 +#: src/mainwin.cc:2148 msgid "Untitled.csg" msgstr "Bezejmenný.csg" -#: src/mainwin.cc:2054 +#: src/mainwin.cc:2149 msgid "CSG Files (*.csg)" msgstr "CSG soubory (*.csg)" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "Export Image" msgstr "Exportovat obrázek" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "PNG Files (*.png)" msgstr "PNG Soubory (*.png)" -#: src/mainwin.cc:2320 +#: src/mainwin.cc:2423 msgid "Console" msgstr "Konzole" -#: src/mainwin.cc:2447 +#: src/mainwin.cc:2560 msgid "The document has been modified." msgstr "Dokument byl pozměněn." -#: src/mainwin.cc:2448 +#: src/mainwin.cc:2561 msgid "Do you want to save your changes?" msgstr "Chcete uložit změny?" -#: src/QGLView.cc:114 +#: src/openscad.cc:604 msgid "" -"\n" -"Using QGLWidget\n" -"\n" +"Fontconfig needs to update its font cache.\n" +"This can take up to a couple of minutes." msgstr "" -"\n" -"Používám QGLWidget\n" -"\n" +"Fontconfig potřebuje aktualizovat cache.\n" +"To může trvat až několik minut." -#: src/QGLView.cc:131 +#: src/QGLView.cc:129 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" @@ -928,7 +1123,7 @@ msgstr "" "Varování: Můžete zaznamenat chyby zobrazení pomocí OpenCSG.\n" "\n" -#: src/QGLView.cc:134 +#: src/QGLView.cc:132 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" @@ -937,7 +1132,7 @@ msgstr "" "Varování: Chybí OpenGL funkce pro OpenCSG - OpenCSG bylo vypnuto.\n" "\n" -#: src/QGLView.cc:137 +#: src/QGLView.cc:135 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" @@ -946,7 +1141,7 @@ msgstr "" "Vysoce doporučujeme používat OpenSCAD na systému s OpenGL 2.0 nebo novější.\n" "Zde je informace o vašem vykreslovacím systému:\n" -#: src/QGLView.cc:141 +#: src/QGLView.cc:139 #, c-format msgid "" "GLEW version %s\n" @@ -957,27 +1152,40 @@ msgstr "" "%s (%s)\n" "OpenGL verze %s\n" -#: src/QGLView.cc:171 -#, c-format -msgid "" -"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " -"distance = %.2f" -msgstr "" -"Pohled: posun = [ %.2f %.2f %.2f ], rotace = [ %.2f %.2f %.2f ], vzdálenost " -"= %.2f" +#: src/settings.cc:132 +msgid "After indentation" +msgstr "za odsazením" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Basics" msgstr "Základy" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Shapes" msgstr "Tvary" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Extrusion" msgstr "Vytažení" +#~ msgid "Top" +#~ msgstr "Shora" + +#~ msgid "Back" +#~ msgstr "Zezadu" + +#~ msgid "" +#~ "\n" +#~ "Using QGLWidget\n" +#~ "\n" +#~ msgstr "" +#~ "\n" +#~ "Používám QGLWidget\n" +#~ "\n" + +#~ msgid "About OpenSCAD " +#~ msgstr "O OpenSCADu " + #~ msgid "Paste font selector to Editor Window" #~ msgstr "Vložit výběr písma do zdrojového kódu" @@ -993,9 +1201,6 @@ msgstr "Vytažení" #~ msgid "Sunset" #~ msgstr "Západ slunce" -#~ msgid "&Compile" -#~ msgstr "Z&kompilovat" - #~ msgid "Compile and &Render (CGAL)" #~ msgstr "Zkompilovat a vy&renderovat" diff --git a/locale/de.po b/locale/de.po index df48ce1c..1f017695 100644 --- a/locale/de.po +++ b/locale/de.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2014.01.05\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-22 23:28+0100\n" -"PO-Revision-Date: 2014-12-22 23:12+0100\n" +"POT-Creation-Date: 2015-02-01 18:03+0100\n" +"PO-Revision-Date: 2015-02-01 19:39+0100\n" "Last-Translator: Torsten Paul \n" "Language-Team: German\n" "Language: de\n" @@ -17,28 +17,57 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.6.10\n" "X-Poedit-SourceCharset: UTF-8\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: objects/ui_AboutDialog.h:51 src/AboutDialog.h:15 +#: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" msgstr "Über OpenSCAD" -#: objects/ui_FontListDialog.h:102 +#: objects/ui_AboutDialog.h:105 objects/ui_launchingscreen.h:305 +msgid "" +"\n" +"

OpenSCAD

\n" +"

The Programmers Solid 3D CAD Modeller

\n" +"\n" +"\n" +"\n" +msgstr "" +"\n" +"

OpenSCAD

\n" +"

The Programmers Solid 3D CAD Modeller

\n" +"\n" +"\n" +"\n" + +#: objects/ui_AboutDialog.h:112 +msgid "OK" +msgstr "OK" + +#: objects/ui_FontListDialog.h:105 msgid "OpenSCAD Font List" msgstr "OpenSCAD Fontliste" -#: objects/ui_FontListDialog.h:103 objects/ui_LibraryInfoDialog.h:77 +#: objects/ui_FontListDialog.h:106 objects/ui_LibraryInfoDialog.h:77 msgid "&OK" msgstr "OK" -#: objects/ui_FontListDialog.h:104 +#: objects/ui_FontListDialog.h:107 msgid "Copy to Clipboard" msgstr "Kopieren" -#: objects/ui_FontListDialog.h:105 +#: objects/ui_FontListDialog.h:108 msgid "Filter:" msgstr "Filter:" -#: objects/ui_FontListDialog.h:106 +#: objects/ui_FontListDialog.h:109 msgid "" "

This list shows the fonts currently registered with " "OpenSCAD.

Example:

  text(t = "OpenSCAD", font = "
 ""Liberation Sans:style=Italic");
" -#: objects/ui_launchingscreen.h:276 +#: objects/ui_launchingscreen.h:294 msgid "Welcome to OpenSCAD" msgstr "Willkommen zu OpenSCAD" -#: objects/ui_launchingscreen.h:277 +#: objects/ui_launchingscreen.h:295 msgid "New" msgstr "Neu" -#: objects/ui_launchingscreen.h:278 +#: objects/ui_launchingscreen.h:296 msgid "Open" msgstr "Öffnen" -#: objects/ui_launchingscreen.h:279 +#: objects/ui_launchingscreen.h:297 msgid "Help" msgstr "Hilfe" -#: objects/ui_launchingscreen.h:280 +#: objects/ui_launchingscreen.h:298 msgid "Recents" msgstr "Zuletzt benutze Dateien" -#: objects/ui_launchingscreen.h:281 +#: objects/ui_launchingscreen.h:299 msgid "Open Recent" msgstr "Datei öffnen" -#: objects/ui_launchingscreen.h:282 objects/ui_launchingscreen.h:284 -#: objects/ui_MainWindow.h:855 +#: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 msgid "Examples" msgstr "Beispiele" -#: objects/ui_launchingscreen.h:285 +#: objects/ui_launchingscreen.h:303 msgid "Open Example" msgstr "Beispiel öffnen" -#: objects/ui_launchingscreen.h:287 -msgid "" -"\n" -"

OpenSCAD

\n" -"

The Programmers Solid 3D CAD Modeller

\n" -"\n" -"\n" -"\n" -msgstr "" -"\n" -"

OpenSCAD

\n" -"

The Programmers Solid 3D CAD Modeller

\n" -"\n" -"\n" -"\n" - -#: objects/ui_launchingscreen.h:294 +#: objects/ui_launchingscreen.h:312 msgid "Don't show again" msgstr "Dialog nicht wieder anzeigen" +#: objects/ui_launchingscreen.h:313 +msgid "Version" +msgstr "Version" + #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" msgstr "Versionsinformationen" @@ -129,543 +137,567 @@ msgstr "Versionsinformationen" msgid "OpenSCAD Detailed Library and Build Information" msgstr "Detailierte Informationen über diese OpenSCAD Version" -#: objects/ui_MainWindow.h:731 +#: objects/ui_MainWindow.h:837 msgid "&New" msgstr "&Neu" -#: objects/ui_MainWindow.h:732 +#: objects/ui_MainWindow.h:838 msgid "Ctrl+N" msgstr "Ctrl+N" -#: objects/ui_MainWindow.h:733 +#: objects/ui_MainWindow.h:839 msgid "&Open..." -msgstr "Ö&ffnen" +msgstr "Ö&ffnen..." -#: objects/ui_MainWindow.h:734 +#: objects/ui_MainWindow.h:840 msgid "Ctrl+O" msgstr "Ctrl+O" -#: objects/ui_MainWindow.h:735 +#: objects/ui_MainWindow.h:841 msgid "&Save" msgstr "&Speichern" -#: objects/ui_MainWindow.h:736 +#: objects/ui_MainWindow.h:842 msgid "Ctrl+S" msgstr "Ctrl+S" -#: objects/ui_MainWindow.h:737 +#: objects/ui_MainWindow.h:843 msgid "Save &As..." msgstr "Speichern &Unter..." -#: objects/ui_MainWindow.h:738 +#: objects/ui_MainWindow.h:844 msgid "Ctrl+Shift+S" msgstr "Ctrl+Shift+S" -#: objects/ui_MainWindow.h:739 +#: objects/ui_MainWindow.h:845 msgid "&Reload" msgstr "Neu &laden" -#: objects/ui_MainWindow.h:740 +#: objects/ui_MainWindow.h:846 msgid "Ctrl+R" msgstr "Ctrl+R" -#: objects/ui_MainWindow.h:741 +#: objects/ui_MainWindow.h:847 msgid "&Quit" -msgstr "&Beenden" +msgstr "Beenden" -#: objects/ui_MainWindow.h:742 +#: objects/ui_MainWindow.h:848 msgid "Ctrl+Q" msgstr "Ctrl+Q" -#: objects/ui_MainWindow.h:743 +#: objects/ui_MainWindow.h:849 msgid "&Undo" msgstr "&Rückgängig" -#: objects/ui_MainWindow.h:744 +#: objects/ui_MainWindow.h:850 msgid "Ctrl+Z" msgstr "Ctrl+Z" -#: objects/ui_MainWindow.h:745 +#: objects/ui_MainWindow.h:851 msgid "&Redo" msgstr "&Wiederholen" -#: objects/ui_MainWindow.h:746 +#: objects/ui_MainWindow.h:852 msgid "Ctrl+Shift+Z" msgstr "Ctrl+Shift+Z" -#: objects/ui_MainWindow.h:747 +#: objects/ui_MainWindow.h:853 msgid "Cu&t" msgstr "Ausschneiden" -#: objects/ui_MainWindow.h:748 +#: objects/ui_MainWindow.h:854 msgid "Ctrl+X" msgstr "Ctrl+X" -#: objects/ui_MainWindow.h:749 +#: objects/ui_MainWindow.h:855 msgid "&Copy" msgstr "Kopieren" -#: objects/ui_MainWindow.h:750 +#: objects/ui_MainWindow.h:856 msgid "Ctrl+C" msgstr "Ctrl+C" -#: objects/ui_MainWindow.h:751 +#: objects/ui_MainWindow.h:857 msgid "&Paste" msgstr "Einfügen" -#: objects/ui_MainWindow.h:752 +#: objects/ui_MainWindow.h:858 msgid "Ctrl+V" msgstr "Ctrl+V" -#: objects/ui_MainWindow.h:753 +#: objects/ui_MainWindow.h:859 msgid "&Indent" -msgstr "Einzug erhöhen" +msgstr "Einzug er&höhen" -#: objects/ui_MainWindow.h:754 +#: objects/ui_MainWindow.h:860 msgid "Ctrl+I" msgstr "Ctrl+I" -#: objects/ui_MainWindow.h:755 -msgid "U&nindent" -msgstr "Einzug vermindern" - -#: objects/ui_MainWindow.h:756 -msgid "Ctrl+Shift+I" -msgstr "Ctrl+Shift+I" - -#: objects/ui_MainWindow.h:757 +#: objects/ui_MainWindow.h:861 msgid "C&omment" msgstr "K&ommentieren" -#: objects/ui_MainWindow.h:758 +#: objects/ui_MainWindow.h:862 msgid "Ctrl+D" msgstr "Ctrl+D" -#: objects/ui_MainWindow.h:759 +#: objects/ui_MainWindow.h:863 msgid "Unco&mment" -msgstr "Kommentar entfernen" +msgstr "Kommentar ent&fernen" -#: objects/ui_MainWindow.h:760 +#: objects/ui_MainWindow.h:864 msgid "Ctrl+Shift+D" msgstr "Ctrl+Shift+D" -#: objects/ui_MainWindow.h:761 -msgid "Paste viewport translation" -msgstr "Aktuelle Verschiebung einfügen" +#: objects/ui_MainWindow.h:865 +msgid "P&aste viewport translation" +msgstr "Aktuelle Versch&iebung einfügen" -#: objects/ui_MainWindow.h:762 +#: objects/ui_MainWindow.h:866 msgid "Ctrl+T" msgstr "Ctrl+T" -#: objects/ui_MainWindow.h:763 -msgid "Paste viewport rotation" -msgstr "Aktuelle Rotation einfügen" +#: objects/ui_MainWindow.h:867 +msgid "Past&e viewport rotation" +msgstr "Aktuelle Ro&tation einfügen" -#: objects/ui_MainWindow.h:764 objects/ui_MainWindow.h:842 -msgid "Zoom In" -msgstr "Vergrößern" +#: objects/ui_MainWindow.h:868 +msgid "Increase Font &Size" +msgstr "Font&größe erhöhen" -#: objects/ui_MainWindow.h:765 +#: objects/ui_MainWindow.h:869 msgid "Ctrl++" msgstr "Ctrl++" -#: objects/ui_MainWindow.h:766 objects/ui_MainWindow.h:844 -msgid "Zoom Out" -msgstr "Verkleinern" +#: objects/ui_MainWindow.h:870 +msgid "Decrease Font Si&ze" +msgstr "Fontgröße &verringern" -#: objects/ui_MainWindow.h:767 +#: objects/ui_MainWindow.h:871 msgid "Ctrl+-" msgstr "Ctrl+-" -#: objects/ui_MainWindow.h:768 -msgid "Hide editor" +#: objects/ui_MainWindow.h:872 +msgid "H&ide editor" msgstr "Editor verstecken" -#: objects/ui_MainWindow.h:769 +#: objects/ui_MainWindow.h:873 msgid "&Reload and Preview" -msgstr "Neu laden und Vorschau" +msgstr "Neu &laden und Vorschau" -#: objects/ui_MainWindow.h:770 +#: objects/ui_MainWindow.h:874 msgid "F4" msgstr "F4" -#: objects/ui_MainWindow.h:771 +#: objects/ui_MainWindow.h:875 msgid "&Preview" -msgstr "Vorschau" +msgstr "&Vorschau" -#: objects/ui_MainWindow.h:772 +#: objects/ui_MainWindow.h:876 msgid "F5" msgstr "F5" -#: objects/ui_MainWindow.h:773 -msgid "&Render" -msgstr "Rendern" +#: objects/ui_MainWindow.h:877 +msgid "R&ender" +msgstr "&Rendern" -#: objects/ui_MainWindow.h:774 +#: objects/ui_MainWindow.h:878 msgid "F6" msgstr "F6" -#: objects/ui_MainWindow.h:775 -msgid "Check Validity" -msgstr "Design überprüfen" +#: objects/ui_MainWindow.h:879 +msgid "&Check Validity" +msgstr "&Design überprüfen" -#: objects/ui_MainWindow.h:776 -msgid "Display &AST..." -msgstr "&AST Baum anzeigen..." +#: objects/ui_MainWindow.h:880 +msgid "Display A&ST..." +msgstr "A&ST Baum anzeigen..." -#: objects/ui_MainWindow.h:777 +#: objects/ui_MainWindow.h:881 msgid "Display CSG &Tree..." -msgstr "CSG Baum anzeigen..." +msgstr "CSG &Baum anzeigen..." -#: objects/ui_MainWindow.h:778 -msgid "Display CSG &Products..." -msgstr "CSG Gleichungen anzeigen..." +#: objects/ui_MainWindow.h:882 +msgid "Display CSG Pr&oducts..." +msgstr "CSG &Gleichungen anzeigen..." -#: objects/ui_MainWindow.h:779 +#: objects/ui_MainWindow.h:883 msgid "Export as &STL..." msgstr "&STL exportieren..." -#: objects/ui_MainWindow.h:780 +#: objects/ui_MainWindow.h:884 msgid "Export as &OFF..." msgstr "&OFF exportieren..." -#: objects/ui_MainWindow.h:781 +#: objects/ui_MainWindow.h:885 msgid "Preview" -msgstr "Vorschau" +msgstr "&Vorschau" -#: objects/ui_MainWindow.h:782 +#: objects/ui_MainWindow.h:886 msgid "F9" msgstr "F9" -#: objects/ui_MainWindow.h:783 +#: objects/ui_MainWindow.h:887 msgid "Surfaces" -msgstr "Flächen anzeigen" +msgstr "&Flächen anzeigen" -#: objects/ui_MainWindow.h:784 +#: objects/ui_MainWindow.h:888 msgid "F10" msgstr "F10" -#: objects/ui_MainWindow.h:785 +#: objects/ui_MainWindow.h:889 msgid "Wireframe" -msgstr "Gittermodell" +msgstr "&Gittermodell" -#: objects/ui_MainWindow.h:786 +#: objects/ui_MainWindow.h:890 msgid "F11" msgstr "F11" -#: objects/ui_MainWindow.h:787 +#: objects/ui_MainWindow.h:891 msgid "Thrown Together" -msgstr "Kombinierte Anzeige" +msgstr "Kom&binierte Anzeige" -#: objects/ui_MainWindow.h:788 +#: objects/ui_MainWindow.h:892 msgid "F12" msgstr "F12" -#: objects/ui_MainWindow.h:789 +#: objects/ui_MainWindow.h:893 msgid "Show Edges" -msgstr "Kanten anzeigen" +msgstr "&Kanten anzeigen" -#: objects/ui_MainWindow.h:790 +#: objects/ui_MainWindow.h:894 msgid "Ctrl+1" msgstr "Ctrl+1" -#: objects/ui_MainWindow.h:791 +#: objects/ui_MainWindow.h:895 msgid "Show Axes" -msgstr "Koordinatenachsen anzeigen" +msgstr "Koordinaten&achsen anzeigen" -#: objects/ui_MainWindow.h:792 +#: objects/ui_MainWindow.h:896 msgid "Ctrl+2" msgstr "Ctrl+2" -#: objects/ui_MainWindow.h:793 +#: objects/ui_MainWindow.h:897 msgid "Show Crosshairs" -msgstr "Rotationsmittelpunkt anzeigen" +msgstr "Rotations&mittelpunkt anzeigen" -#: objects/ui_MainWindow.h:794 +#: objects/ui_MainWindow.h:898 msgid "Ctrl+3" msgstr "Ctrl+3" -#: objects/ui_MainWindow.h:795 +#: objects/ui_MainWindow.h:899 +msgid "Show Scale Markers" +msgstr "Axen&einteilung anzeigen" + +#: objects/ui_MainWindow.h:900 msgid "Animate" msgstr "Animation" -#: objects/ui_MainWindow.h:796 -msgid "Top" -msgstr "Oben" +#: objects/ui_MainWindow.h:901 +msgid "&Top" +msgstr "&Oben" -#: objects/ui_MainWindow.h:797 +#: objects/ui_MainWindow.h:902 msgid "Ctrl+4" msgstr "Ctrl+4" -#: objects/ui_MainWindow.h:798 -msgid "Bottom" -msgstr "Unten" +#: objects/ui_MainWindow.h:903 +msgid "&Bottom" +msgstr "&Unten" -#: objects/ui_MainWindow.h:799 +#: objects/ui_MainWindow.h:904 msgid "Ctrl+5" msgstr "Ctrl+5" -#: objects/ui_MainWindow.h:800 -msgid "Left" -msgstr "Links" +#: objects/ui_MainWindow.h:905 +msgid "&Left" +msgstr "&Links" -#: objects/ui_MainWindow.h:801 +#: objects/ui_MainWindow.h:906 msgid "Ctrl+6" msgstr "Ctrl+6" -#: objects/ui_MainWindow.h:802 -msgid "Right" -msgstr "Rechts" +#: objects/ui_MainWindow.h:907 +msgid "&Right" +msgstr "&Rechts" -#: objects/ui_MainWindow.h:803 +#: objects/ui_MainWindow.h:908 msgid "Ctrl+7" msgstr "Ctrl+7" -#: objects/ui_MainWindow.h:804 -msgid "Front" -msgstr "Vorn" +#: objects/ui_MainWindow.h:909 +msgid "&Front" +msgstr "Vor&n" -#: objects/ui_MainWindow.h:805 +#: objects/ui_MainWindow.h:910 msgid "Ctrl+8" msgstr "Ctrl+8" -#: objects/ui_MainWindow.h:806 -msgid "Back" -msgstr "Hinten" +#: objects/ui_MainWindow.h:911 +msgid "Bac&k" +msgstr "&Hinten" -#: objects/ui_MainWindow.h:807 +#: objects/ui_MainWindow.h:912 msgid "Ctrl+9" msgstr "Ctrl+9" -#: objects/ui_MainWindow.h:808 -msgid "Diagonal" -msgstr "Diagonal" +#: objects/ui_MainWindow.h:913 +msgid "&Diagonal" +msgstr "&Diagonal" -#: objects/ui_MainWindow.h:809 +#: objects/ui_MainWindow.h:914 msgid "Ctrl+0" msgstr "Ctrl+0" -#: objects/ui_MainWindow.h:810 -msgid "Center" -msgstr "Zentriert" +#: objects/ui_MainWindow.h:915 +msgid "Ce&nter" +msgstr "&Zentriert" -#: objects/ui_MainWindow.h:811 -msgid "Perspective" -msgstr "Perspektivisch" +#: objects/ui_MainWindow.h:916 +msgid "&Perspective" +msgstr "&Perspektivisch" -#: objects/ui_MainWindow.h:812 -msgid "Orthogonal" -msgstr "Orthogonal" +#: objects/ui_MainWindow.h:917 +msgid "&Orthogonal" +msgstr "Or&thogonal" -#: objects/ui_MainWindow.h:813 -msgid "Hide console" +#: objects/ui_MainWindow.h:918 +msgid "H&ide console" msgstr "Konsole verstecken" -#: objects/ui_MainWindow.h:814 -msgid "About" -msgstr "Über OpenSCAD" +#: objects/ui_MainWindow.h:919 +msgid "&About" +msgstr "Über &OpenSCAD" -#: objects/ui_MainWindow.h:815 -msgid "Documentation" -msgstr "Dokumentation" +#: objects/ui_MainWindow.h:920 +msgid "&Documentation" +msgstr "&Dokumentation" -#: objects/ui_MainWindow.h:816 +#: objects/ui_MainWindow.h:921 msgid "Clear Recent" msgstr "Zuletzt benutze Dateien löschen" -#: objects/ui_MainWindow.h:817 -msgid "Export as DXF..." +#: objects/ui_MainWindow.h:922 +msgid "Export as &DXF..." msgstr "DXF exportieren..." -#: objects/ui_MainWindow.h:818 objects/ui_OpenCSGWarningDialog.h:94 -msgid "Close" +#: objects/ui_MainWindow.h:923 +msgid "&Close" msgstr "Schließen" -#: objects/ui_MainWindow.h:819 +#: objects/ui_MainWindow.h:924 msgid "Ctrl+W" msgstr "Ctrl+W" -#: objects/ui_MainWindow.h:820 objects/ui_Preferences.h:608 -msgid "Preferences" -msgstr "Einstellungen" +#: objects/ui_MainWindow.h:925 +msgid "&Preferences" +msgstr "Ei&nstellungen" -#: objects/ui_MainWindow.h:821 -msgid "Find..." -msgstr "Suchen..." +#: objects/ui_MainWindow.h:926 +msgid "&Find..." +msgstr "&Suchen..." -#: objects/ui_MainWindow.h:822 +#: objects/ui_MainWindow.h:927 msgid "Ctrl+F" msgstr "Ctrl+F" -#: objects/ui_MainWindow.h:823 -msgid "Find and Replace..." -msgstr "Suchen und Ersetzen..." +#: objects/ui_MainWindow.h:928 +msgid "Fin&d and Replace..." +msgstr "Suchen und &Ersetzen..." -#: objects/ui_MainWindow.h:824 +#: objects/ui_MainWindow.h:929 msgid "Ctrl+Alt+F" msgstr "Ctrl+Alt+F" -#: objects/ui_MainWindow.h:825 -msgid "Find Next" -msgstr "Weiter suchen" +#: objects/ui_MainWindow.h:930 +msgid "Find Ne&xt" +msgstr "&Weiter suchen" -#: objects/ui_MainWindow.h:826 +#: objects/ui_MainWindow.h:931 msgid "Ctrl+G" msgstr "Ctrl+G" -#: objects/ui_MainWindow.h:827 -msgid "Find Previous" -msgstr "Rückwärts suchen" +#: objects/ui_MainWindow.h:932 +msgid "Find Pre&vious" +msgstr "Rüc&kwärts suchen" -#: objects/ui_MainWindow.h:828 +#: objects/ui_MainWindow.h:933 msgid "Ctrl+Shift+G" msgstr "Ctrl+Shift+G" -#: objects/ui_MainWindow.h:829 -msgid "Use Selection for Find" -msgstr "Auswahl suchen" +#: objects/ui_MainWindow.h:934 +msgid "Use Se&lection for Find" +msgstr "&Auswahl suchen" -#: objects/ui_MainWindow.h:830 +#: objects/ui_MainWindow.h:935 msgid "Ctrl+E" msgstr "Ctrl+E" -#: objects/ui_MainWindow.h:831 -msgid "Flush Caches" -msgstr "Cache leeren" +#: objects/ui_MainWindow.h:936 +msgid "&Flush Caches" +msgstr "&Cache leeren" -#: objects/ui_MainWindow.h:832 -msgid "OpenSCAD Homepage" -msgstr "OpenSCAD Homepage" +#: objects/ui_MainWindow.h:937 +msgid "&OpenSCAD Homepage" +msgstr "OpenSCAD &Homepage" -#: objects/ui_MainWindow.h:833 -msgid "Automatic Reload and Preview" -msgstr "Automatisch neu Laden und Vorschau" +#: objects/ui_MainWindow.h:938 +msgid "&Automatic Reload and Preview" +msgstr "&Automatisch neu Laden und Vorschau" -#: objects/ui_MainWindow.h:834 -msgid "Export as Image..." +#: objects/ui_MainWindow.h:939 +msgid "Export as &Image..." msgstr "Image exportieren..." -#: objects/ui_MainWindow.h:835 -msgid "Export as CSG..." +#: objects/ui_MainWindow.h:940 +msgid "Export as &CSG..." msgstr "CSG exportieren..." -#: objects/ui_MainWindow.h:836 -msgid "Library info" -msgstr "Versionsinformationen" +#: objects/ui_MainWindow.h:941 +msgid "&Library info" +msgstr "&Versionsinformationen" -#: objects/ui_MainWindow.h:837 -msgid "Show Library Folder..." -msgstr "Bibliotheken anzeigen..." +#: objects/ui_MainWindow.h:942 +msgid "Show &Library Folder..." +msgstr "Bibli&otheken anzeigen..." -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:943 msgid "Reset View" -msgstr "Ansicht zurücksetzen" +msgstr "Ans&icht zurücksetzen" -#: objects/ui_MainWindow.h:839 -msgid "Font List" -msgstr "Fontliste" +#: objects/ui_MainWindow.h:944 +msgid "&Font List" +msgstr "&Fontliste" -#: objects/ui_MainWindow.h:840 -msgid "Export as SVG..." +#: objects/ui_MainWindow.h:945 +msgid "Export as S&VG..." msgstr "SVG exportieren..." -#: objects/ui_MainWindow.h:841 -msgid "Export as AMF..." +#: objects/ui_MainWindow.h:946 +msgid "Export as &AMF..." msgstr "AMF exportieren..." -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:947 +msgid "Zoom In" +msgstr "Vergrößern" + +#: objects/ui_MainWindow.h:948 msgid "Ctrl+]" msgstr "Ctrl+]" -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:949 +msgid "Zoom Out" +msgstr "Verkleinern" + +#: objects/ui_MainWindow.h:950 msgid "Ctrl+[" msgstr "Ctrl+[" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:951 msgid "View All" -msgstr "Alles anzeigen" +msgstr "Alle&s anzeigen" -#: objects/ui_MainWindow.h:847 -msgid "Convert Tabs to Spaces" -msgstr "Tabs in Leerzeichen umwandeln" +#: objects/ui_MainWindow.h:952 +msgid "Conv&ert Tabs to Spaces" +msgstr "Tabs in Leerzeichen &umwandeln" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:953 msgid "Hide toolbars" msgstr "Symbolleisten verstecken" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:954 +msgid "U&nindent" +msgstr "Einzug ver&mindern" + +#: objects/ui_MainWindow.h:955 +msgid "Ctrl+Shift+I" +msgstr "Ctrl+Shift+I" + +#: objects/ui_MainWindow.h:956 +msgid "&Cheat Sheet" +msgstr "&Befehlsübersicht" + +#: objects/ui_MainWindow.h:957 +msgid "Message" +msgstr "Message" + +#: objects/ui_MainWindow.h:960 msgid "Time:" msgstr "Zeit:" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:961 msgid "FPS:" msgstr "FPS:" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:962 msgid "Steps:" msgstr "Schritte:" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:963 msgid "Dump Pictures" msgstr "Bilder ausgeben" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:964 msgid "&File" msgstr "&Datei" -#: objects/ui_MainWindow.h:854 -msgid "Recent Files" -msgstr "Zuletzt benutze Dateien" +#: objects/ui_MainWindow.h:965 +msgid "Recen&t Files" +msgstr "Zuletzt benutze &Dateien" -#: objects/ui_MainWindow.h:856 -msgid "Export" -msgstr "Exportieren" +#: objects/ui_MainWindow.h:966 +msgid "&Examples" +msgstr "&Beispiele" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:967 +msgid "E&xport" +msgstr "&Exportieren" + +#: objects/ui_MainWindow.h:968 msgid "&Edit" msgstr "&Bearbeiten" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:969 msgid "&Design" msgstr "D&esign" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:970 msgid "&View" msgstr "&Ansicht" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:971 msgid "&Help" msgstr "&Hilfe" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:974 msgid "Find" msgstr "Suchen" -#: objects/ui_MainWindow.h:864 objects/ui_MainWindow.h:871 +#: objects/ui_MainWindow.h:975 objects/ui_MainWindow.h:982 msgid "Replace" msgstr "Ersetzen" -#: objects/ui_MainWindow.h:866 +#: objects/ui_MainWindow.h:977 msgid "Search string" msgstr "Suchtext" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:978 msgid "<" msgstr "<" -#: objects/ui_MainWindow.h:868 +#: objects/ui_MainWindow.h:979 msgid ">" msgstr ">" -#: objects/ui_MainWindow.h:869 +#: objects/ui_MainWindow.h:980 msgid "Done" msgstr "Fertig" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:981 msgid "Replacement string" msgstr "Ersetzen mit" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:983 msgid "All" msgstr "Alles" @@ -705,160 +737,328 @@ msgstr "OpenCSG benutzen" msgid "Show this message again" msgstr "Diesen Dialog wieder anzeigen" -#: objects/ui_Preferences.h:609 +#: objects/ui_OpenCSGWarningDialog.h:94 +msgid "Close" +msgstr "Schließen" + +#: objects/ui_Preferences.h:1061 +msgid "Preferences" +msgstr "Einstellungen" + +#: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "3D Ansicht" -#: objects/ui_Preferences.h:610 src/UIUtils.cc:85 +#: objects/ui_Preferences.h:1063 src/UIUtils.cc:86 msgid "Advanced" msgstr "Erweitert" -#: objects/ui_Preferences.h:611 src/mainwin.cc:2315 +#: objects/ui_Preferences.h:1064 src/mainwin.cc:2418 msgid "Editor" msgstr "Editor" -#: objects/ui_Preferences.h:612 +#: objects/ui_Preferences.h:1065 msgid "Update" msgstr "Aktualisieren" -#: objects/ui_Preferences.h:613 objects/ui_Preferences.h:633 +#: objects/ui_Preferences.h:1066 objects/ui_Preferences.h:1147 msgid "Features" msgstr "Funktionen" -#: objects/ui_Preferences.h:615 +#: objects/ui_Preferences.h:1068 msgid "Enable/Disable experimental features" msgstr "Experimentelle Erweiterungen ein-/ausschalten" -#: objects/ui_Preferences.h:617 +#: objects/ui_Preferences.h:1070 msgid "Color scheme:" msgstr "Farbschema:" -#: objects/ui_Preferences.h:618 +#: objects/ui_Preferences.h:1071 +msgid "Show Warnings and Errors in 3D View" +msgstr "Fehler und Warnungen in der 3D Ansicht anzeigen" + +#: objects/ui_Preferences.h:1072 msgid "Editor Type" msgstr "Editor" -#: objects/ui_Preferences.h:621 +#: objects/ui_Preferences.h:1075 msgid "Simple Editor" msgstr "Einfacher Editor" -#: objects/ui_Preferences.h:622 +#: objects/ui_Preferences.h:1076 msgid "QScintilla Editor" msgstr "QScintilla Editor" -#: objects/ui_Preferences.h:624 +#: objects/ui_Preferences.h:1078 msgid "(requires restart)" msgstr "(Neustart erforderlich)" -#: objects/ui_Preferences.h:625 +#: objects/ui_Preferences.h:1079 msgid "Font" msgstr "Font" -#: objects/ui_Preferences.h:626 +#: objects/ui_Preferences.h:1080 msgid "Color syntax highlighting" msgstr "Syntaxhervorhebung" -#: objects/ui_Preferences.h:627 -msgid "Use Ctrl/Cmd-Mouse-wheel to zoom text" +#: objects/ui_Preferences.h:1081 +msgid "Ctrl/Cmd-Mouse-wheel zooms text" msgstr "Ctrl/Cmd+Mausrad zum Vergrößern des Textes benutzen" -#: objects/ui_Preferences.h:629 +#: objects/ui_Preferences.h:1082 +msgid "Indentation" +msgstr "Einrückung" + +#: objects/ui_Preferences.h:1083 +msgid "Auto Indent" +msgstr "Automatisch einrücken" + +#: objects/ui_Preferences.h:1084 +msgid "Indent using" +msgstr "Einrücken mit" + +#: objects/ui_Preferences.h:1087 src/settings.cc:135 +msgid "Spaces" +msgstr "Leerzeichen" + +#: objects/ui_Preferences.h:1088 src/settings.cc:135 +msgid "Tabs" +msgstr "Tabs" + +#: objects/ui_Preferences.h:1090 +msgid "Indentation width" +msgstr "Einrückungstiefe" + +#: objects/ui_Preferences.h:1091 +msgid "Tab width" +msgstr "Tabulatorschrittweite" + +#: objects/ui_Preferences.h:1092 +msgid "Tab key function" +msgstr "Funktion der Tab-Taste" + +#: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 +#: src/settings.cc:136 +msgid "Indent" +msgstr "Einrücken" + +#: objects/ui_Preferences.h:1096 src/settings.cc:136 +msgid "Insert Tab" +msgstr "Tab einfügen" + +#: objects/ui_Preferences.h:1098 +msgid "Show whitespace" +msgstr "Formatierungsymbole anzeigen" + +#: objects/ui_Preferences.h:1101 src/settings.cc:132 +msgid "Never" +msgstr "nie" + +#: objects/ui_Preferences.h:1102 src/settings.cc:132 +msgid "Always" +msgstr "immer" + +#: objects/ui_Preferences.h:1103 +msgid "Only after indentation" +msgstr "nur nach Einrückung" + +#: objects/ui_Preferences.h:1105 +msgid "Size" +msgstr "Größe" + +#: objects/ui_Preferences.h:1106 +msgid "Display" +msgstr "Anzeige" + +#: objects/ui_Preferences.h:1107 +msgid "Enable brace matching" +msgstr "zusammengehörige Klammern hervorheben" + +#: objects/ui_Preferences.h:1108 +msgid "Highlight current line" +msgstr "Aktuelle Zeile hervorheben" + +#: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 +msgid "Line wrap" +msgstr "Zeilenumbruch" + +#: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 +#: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 +#: src/settings.cc:131 +msgid "None" +msgstr "nie" + +#: objects/ui_Preferences.h:1113 src/settings.cc:127 +msgid "Wrap at character boundaries" +msgstr "an jedem Zeichen" + +#: objects/ui_Preferences.h:1114 src/settings.cc:127 +msgid "Wrap at word boundaries" +msgstr "an Wörtern" + +#: objects/ui_Preferences.h:1116 +msgid "Line wrap indentation" +msgstr "Einrückung nach Zeilenumbruch" + +#: objects/ui_Preferences.h:1117 +msgid "Line wrap visualization" +msgstr "Zeilenumbruch anzeigen" + +#: objects/ui_Preferences.h:1118 +msgid "Style" +msgstr "Stil" + +#: objects/ui_Preferences.h:1121 src/settings.cc:128 +msgid "Fixed" +msgstr "Fest" + +#: objects/ui_Preferences.h:1122 src/settings.cc:128 +msgid "Same" +msgstr "Wie vorherige Zeile" + +#: objects/ui_Preferences.h:1123 src/settings.cc:128 +msgid "Indented" +msgstr "Eingerückt" + +#: objects/ui_Preferences.h:1126 +msgid "Start" +msgstr "Anfang" + +#: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Text" +msgstr "Text" + +#: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Border" +msgstr "Rand" + +#: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Margin" +msgstr "Seitenrand" + +#: objects/ui_Preferences.h:1134 +msgid "End" +msgstr "Ende" + +#: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" msgstr "Automatisch nach Aktualisierungen suchen" -#: objects/ui_Preferences.h:630 +#: objects/ui_Preferences.h:1144 msgid "Include development snapshots" msgstr "Entwickler-Versionen einschließen" -#: objects/ui_Preferences.h:631 +#: objects/ui_Preferences.h:1145 msgid "Check Now" msgstr "Jetzt suchen" -#: objects/ui_Preferences.h:632 +#: objects/ui_Preferences.h:1146 msgid "Last checked: " msgstr "Zuletzt gesucht: " -#: objects/ui_Preferences.h:634 +#: objects/ui_Preferences.h:1148 msgid "OpenCSG" msgstr "OpenCSG" -#: objects/ui_Preferences.h:635 +#: objects/ui_Preferences.h:1149 msgid "Show capability warning" msgstr "Kompatibilitätswarnung anzeigen" -#: objects/ui_Preferences.h:636 +#: objects/ui_Preferences.h:1150 msgid "Enable for OpenGL 1.x" msgstr "Aktivieren bei OpenGL 1.x" -#: objects/ui_Preferences.h:637 +#: objects/ui_Preferences.h:1151 msgid "Turn off rendering at " msgstr "Rendern abbrechen ab " -#: objects/ui_Preferences.h:638 +#: objects/ui_Preferences.h:1152 msgid "elements" msgstr "Elementen" -#: objects/ui_Preferences.h:639 +#: objects/ui_Preferences.h:1153 msgid "Force Goldfeather" msgstr "Goldfeather Algorithmus erzwingen" -#: objects/ui_Preferences.h:640 +#: objects/ui_Preferences.h:1154 msgid "CGAL Cache size" msgstr "CGAL Cache Größe" -#: objects/ui_Preferences.h:641 objects/ui_Preferences.h:643 +#: objects/ui_Preferences.h:1155 objects/ui_Preferences.h:1157 msgid "bytes" msgstr "Byte" -#: objects/ui_Preferences.h:642 +#: objects/ui_Preferences.h:1156 msgid "PolySet Cache size" msgstr "PolySet Cache Größe" -#: objects/ui_Preferences.h:644 +#: objects/ui_Preferences.h:1158 msgid "Allow to open multiple documents" msgstr "Öffnen von mehreren Dokumenten erlauben" -#: objects/ui_Preferences.h:645 +#: objects/ui_Preferences.h:1159 msgid "Enable docking of Editor and Console in different places" msgstr "Verschieben des Editor und Konsole Fensters erlauben" -#: objects/ui_Preferences.h:646 +#: objects/ui_Preferences.h:1160 msgid "Enable undocking of Editor and Console to separate windows" msgstr "Separate Editor und Konsole Fenster erlauben" -#: objects/ui_Preferences.h:647 +#: objects/ui_Preferences.h:1161 msgid "Show Welcome Screen" msgstr "Startbildschirm anzeigen" -#: objects/ui_Preferences.h:648 +#: objects/ui_Preferences.h:1162 msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "Lokalisierung der GUI einschalten (benötigt Neustart von OpenSCAD)" -# This should not be visible (window title of the ToolBar). -#: objects/ui_Preferences.h:649 -msgid "toolBar" -msgstr "toolBar" - #: objects/ui_ProgressWidget.h:72 -msgid "Form" -msgstr "Form" - -#: objects/ui_ProgressWidget.h:73 msgid "%v / %m" msgstr "%v / %m" -#: src/mainwin.cc:768 src/mainwin.cc:1300 +#: src/Camera.cc:126 +#, c-format +msgid "" +"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " +"distance = %.2f" +msgstr "" +"Ansicht: Verschiebung = [ %.2f %.2f %.2f ], Rotation = [ %.2f %.2f %.2f ], " +"Abstand = %.2f" + +#: src/mainwin.cc:778 src/mainwin.cc:1354 msgid "Untitled.scad" msgstr "Unbenannt.scad" -#: src/mainwin.cc:1299 +#: src/mainwin.cc:971 +msgid "Compile error." +msgstr "Fehler" + +#: src/mainwin.cc:974 +msgid "Error while compiling '%1'." +msgstr "Fehler beim Kompilieren von '%1'." + +#: src/mainwin.cc:978 +msgid "Compilation generated %1 warning." +msgid_plural "Compilation generated %1 warnings." +msgstr[0] "%1 Warnung beim kompilieren." +msgstr[1] "%1 Warnungen beim kompilieren." + +#: src/mainwin.cc:988 +msgid " For details see console window." +msgstr " Für Details das Konsole Fenster öffnen." + +#: src/mainwin.cc:1353 msgid "Save File" msgstr "Datei speichern" -#: src/mainwin.cc:1301 +#: src/mainwin.cc:1355 msgid "OpenSCAD Designs (*.scad)" msgstr "OpenSCAD Designs (*.scad)" -#: src/mainwin.cc:1311 +#: src/mainwin.cc:1365 msgid "" "%1 already exists.\n" "Do you want to replace it?" @@ -866,11 +1066,11 @@ msgstr "" "%1 existiert bereits.\n" "Mochten Sie die Datei ersetzen?" -#: src/mainwin.cc:1630 +#: src/mainwin.cc:1684 msgid "Application" msgstr "Application" -#: src/mainwin.cc:1631 +#: src/mainwin.cc:1685 msgid "" "The document has been modified.\n" "Do you really want to reload the file?" @@ -878,65 +1078,63 @@ msgstr "" "Das Dokument ist verändert.\n" "Möchten Sie die Datei wirklich neu laden?" -#: src/mainwin.cc:1942 src/mainwin.cc:1999 +#: src/mainwin.cc:2038 src/mainwin.cc:2094 msgid "Export %1 File" msgstr "%1 Datei exportieren" -#: src/mainwin.cc:1943 src/mainwin.cc:2003 +#: src/mainwin.cc:2039 src/mainwin.cc:2098 msgid "%1 Files (*%2)" msgstr "%1 Dateien (*%2)" -#: src/mainwin.cc:1944 +#: src/mainwin.cc:2040 msgid "Untitled" msgstr "Unbenannt" -#: src/mainwin.cc:2001 +#: src/mainwin.cc:2096 msgid "Untitled%1" msgstr "Unbenannt%1" -#: src/mainwin.cc:2052 +#: src/mainwin.cc:2147 msgid "Export CSG File" msgstr "Export CSG File" -#: src/mainwin.cc:2053 +#: src/mainwin.cc:2148 msgid "Untitled.csg" msgstr "Unbenannt.csg" -#: src/mainwin.cc:2054 +#: src/mainwin.cc:2149 msgid "CSG Files (*.csg)" msgstr "CSG Dateien (*.csg)" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "Export Image" msgstr "Image exportieren" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "PNG Files (*.png)" msgstr "PNG Dateien (*.png)" -#: src/mainwin.cc:2320 +#: src/mainwin.cc:2423 msgid "Console" msgstr "Konsole" -#: src/mainwin.cc:2447 +#: src/mainwin.cc:2560 msgid "The document has been modified." msgstr "Das Dokument ist verändert." -#: src/mainwin.cc:2448 +#: src/mainwin.cc:2561 msgid "Do you want to save your changes?" msgstr "Möchten Sie die Änderungen speichern?" -#: src/QGLView.cc:114 +#: src/openscad.cc:604 msgid "" -"\n" -"Using QGLWidget\n" -"\n" +"Fontconfig needs to update its font cache.\n" +"This can take up to a couple of minutes." msgstr "" -"\n" -"Benutze QGLWidget\n" -"\n" +"Fontconfig muss den Font-Cache aktualisieren.\n" +"Dies kann einige Minuten dauern." -#: src/QGLView.cc:131 +#: src/QGLView.cc:129 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" @@ -944,7 +1142,7 @@ msgstr "" "Achtung: Es können Darstellungsfehler beim Anzeigen der Vorschau auftreten.\n" "\n" -#: src/QGLView.cc:134 +#: src/QGLView.cc:132 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" @@ -954,7 +1152,7 @@ msgstr "" "nicht aus - OpenCSG wurde deaktiviert.\n" "\n" -#: src/QGLView.cc:137 +#: src/QGLView.cc:135 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" @@ -964,7 +1162,7 @@ msgstr "" "2.0.\n" "Informationen zum OpenGL Treiber:\n" -#: src/QGLView.cc:141 +#: src/QGLView.cc:139 #, c-format msgid "" "GLEW version %s\n" @@ -975,27 +1173,44 @@ msgstr "" "%s (%s)\n" "OpenGL version %s\n" -#: src/QGLView.cc:171 -#, c-format -msgid "" -"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " -"distance = %.2f" -msgstr "" -"Ansicht: Verschiebung = [ %.2f %.2f %.2f ], Rotation = [ %.2f %.2f %.2f ], " -"Abstand = %.2f" +#: src/settings.cc:132 +msgid "After indentation" +msgstr "nach Einrückung" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Basics" msgstr "Grundlagen" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Shapes" msgstr "Formen" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Extrusion" msgstr "Extrusion" +#~ msgid "Top" +#~ msgstr "Oben" + +#~ msgid "Back" +#~ msgstr "Hinten" + +# This should not be visible (window title of the ToolBar). +#~ msgid "toolBar" +#~ msgstr "toolBar" + +#~ msgid "Form" +#~ msgstr "Form" + +#~ msgid "" +#~ "\n" +#~ "Using QGLWidget\n" +#~ "\n" +#~ msgstr "" +#~ "\n" +#~ "Benutze QGLWidget\n" +#~ "\n" + #~ msgid "Paste font selector to Editor Window" #~ msgstr "Font Selektor in Editor kopieren" @@ -1014,9 +1229,6 @@ msgstr "Extrusion" #~ msgid "Sunset" #~ msgstr "Sunset" -#~ msgid "Starnight" -#~ msgstr "Starnight" - #~ msgid "BeforeDawn" #~ msgstr "BeforeDawn" @@ -1813,9 +2025,6 @@ msgstr "Extrusion" #~ msgid "Allowed options" #~ msgstr "Allowed options" -#~ msgid "help message" -#~ msgstr "help message" - #~ msgid "print the version" #~ msgstr "print the version" @@ -1988,9 +2197,6 @@ msgstr "Extrusion" #~ "DEPRECATED: Using ranges of the form [begin:end] with begin value greater " #~ "than the end value is deprecated." -#~ msgid "&Compile" -#~ msgstr "Übersetzen" - #~ msgid "Compile and &Render (CGAL)" #~ msgstr "Übersetzen und Rendern (CGAL)" diff --git a/locale/es.po b/locale/es.po new file mode 100644 index 00000000..cdf29b7b --- /dev/null +++ b/locale/es.po @@ -0,0 +1,1278 @@ +# Spanish translations for OpenSCAD package. +# Copyright (C) 2015 THE OpenSCAD'S COPYRIGHT HOLDER +# This file is distributed under the same license as the OpenSCAD package. +# bazza , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: OpenSCAD 2015.01.21\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-02-01 18:03+0100\n" +"PO-Revision-Date: 2015-01-21 22:36-0300\n" +"Last-Translator: Ernesto Bazzano \n" +"Language-Team: Español\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Generator: Poedit 1.5.4\n" + +#: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 +msgid "About OpenSCAD" +msgstr "acerca de OpenSCAD" + +#: objects/ui_AboutDialog.h:105 objects/ui_launchingscreen.h:305 +msgid "" +"\n" +"

OpenSCAD

\n" +"

The Programmers Solid 3D CAD Modeller

\n" +"\n" +"\n" +"\n" +msgstr "" +"\n" +"

OpenSCAD

\n" +"

Le modeleur CAD 3D des programmeurs

\n" +"\n" +"\n" +"\n" + +#: objects/ui_AboutDialog.h:112 +#, fuzzy +msgid "OK" +msgstr "&Aceptar" + +#: objects/ui_FontListDialog.h:105 +msgid "OpenSCAD Font List" +msgstr "Lista de fuentes OpenSCAD" + +#: objects/ui_FontListDialog.h:106 objects/ui_LibraryInfoDialog.h:77 +msgid "&OK" +msgstr "&Aceptar" + +#: objects/ui_FontListDialog.h:107 +msgid "Copy to Clipboard" +msgstr "Copiar al portapapeles" + +#: objects/ui_FontListDialog.h:108 +msgid "Filter:" +msgstr "Filtro:" + +#: objects/ui_FontListDialog.h:109 +msgid "" +"

This list shows the fonts currently registered with " +"OpenSCAD.

Example:

  text(t = "
+""OpenSCAD", font = "DejaVu Sans");
  text(t = "OpenSCAD", font = "
+""Liberation Sans:style=Italic");
" +msgstr "" +"

Esta lista muestra los tipos de letra registrados " +"actualmente en OpenSCAD

Ejemplo:

  "
+"text(t = "OpenSCAD", font = "DejaVu Sans");
  text(t = "OpenSCAD", font = "
+""Liberation Sans:style=Italic");
" + +#: objects/ui_launchingscreen.h:294 +msgid "Welcome to OpenSCAD" +msgstr "Bienvenido a OpenSCAD" + +#: objects/ui_launchingscreen.h:295 +msgid "New" +msgstr "Nuevo" + +#: objects/ui_launchingscreen.h:296 +msgid "Open" +msgstr "Abrir" + +#: objects/ui_launchingscreen.h:297 +msgid "Help" +msgstr "Ayuda" + +#: objects/ui_launchingscreen.h:298 +msgid "Recents" +msgstr "Recientes" + +#: objects/ui_launchingscreen.h:299 +msgid "Open Recent" +msgstr "Abrir recientes" + +#: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 +msgid "Examples" +msgstr "Ejemplos" + +#: objects/ui_launchingscreen.h:303 +msgid "Open Example" +msgstr "Abrir ejemplos" + +#: objects/ui_launchingscreen.h:312 +msgid "Don't show again" +msgstr "No mostrar de nuevo" + +#: objects/ui_launchingscreen.h:313 +#, fuzzy +msgid "Version" +msgstr "Extrusión" + +#: objects/ui_LibraryInfoDialog.h:75 +msgid "Lib & Build Info" +msgstr "Informacion de las librerias y compilación" + +#: objects/ui_LibraryInfoDialog.h:76 +msgid "OpenSCAD Detailed Library and Build Information" +msgstr "Informations detalles de las librerias y compilación" + +#: objects/ui_MainWindow.h:837 +msgid "&New" +msgstr "&Nuevos" + +#: objects/ui_MainWindow.h:838 +msgid "Ctrl+N" +msgstr "Ctrl+N" + +#: objects/ui_MainWindow.h:839 +msgid "&Open..." +msgstr "&Abrir..." + +#: objects/ui_MainWindow.h:840 +msgid "Ctrl+O" +msgstr "Ctrl+O" + +#: objects/ui_MainWindow.h:841 +msgid "&Save" +msgstr "&Salvar" + +#: objects/ui_MainWindow.h:842 +msgid "Ctrl+S" +msgstr "Ctrl+S" + +#: objects/ui_MainWindow.h:843 +msgid "Save &As..." +msgstr "S&alvar como..." + +#: objects/ui_MainWindow.h:844 +msgid "Ctrl+Shift+S" +msgstr "Ctrl+Shift+S" + +#: objects/ui_MainWindow.h:845 +msgid "&Reload" +msgstr "&Recargar" + +#: objects/ui_MainWindow.h:846 +msgid "Ctrl+R" +msgstr "Ctrl+R" + +#: objects/ui_MainWindow.h:847 +msgid "&Quit" +msgstr "Salir" + +#: objects/ui_MainWindow.h:848 +msgid "Ctrl+Q" +msgstr "Ctrl+Q" + +#: objects/ui_MainWindow.h:849 +msgid "&Undo" +msgstr "An&ular" + +#: objects/ui_MainWindow.h:850 +msgid "Ctrl+Z" +msgstr "Ctrl+Z" + +#: objects/ui_MainWindow.h:851 +msgid "&Redo" +msgstr "&Repetir" + +#: objects/ui_MainWindow.h:852 +msgid "Ctrl+Shift+Z" +msgstr "Ctrl+Shift+Z" + +#: objects/ui_MainWindow.h:853 +msgid "Cu&t" +msgstr "Co&rtar" + +#: objects/ui_MainWindow.h:854 +msgid "Ctrl+X" +msgstr "Ctrl+X" + +#: objects/ui_MainWindow.h:855 +msgid "&Copy" +msgstr "&Copiar" + +#: objects/ui_MainWindow.h:856 +msgid "Ctrl+C" +msgstr "Ctrl+C" + +#: objects/ui_MainWindow.h:857 +msgid "&Paste" +msgstr "&Pegar" + +#: objects/ui_MainWindow.h:858 +msgid "Ctrl+V" +msgstr "Ctrl+V" + +# no se que es +#: objects/ui_MainWindow.h:859 +msgid "&Indent" +msgstr "&Indenter" + +#: objects/ui_MainWindow.h:860 +msgid "Ctrl+I" +msgstr "Ctrl+I" + +#: objects/ui_MainWindow.h:861 +msgid "C&omment" +msgstr "C&omentar" + +#: objects/ui_MainWindow.h:862 +msgid "Ctrl+D" +msgstr "Ctrl+D" + +#: objects/ui_MainWindow.h:863 +msgid "Unco&mment" +msgstr "Desco&mentar" + +#: objects/ui_MainWindow.h:864 +msgid "Ctrl+Shift+D" +msgstr "Ctrl+Shift+D" + +#: objects/ui_MainWindow.h:865 +#, fuzzy +msgid "P&aste viewport translation" +msgstr "Pegar posición de la marco" + +#: objects/ui_MainWindow.h:866 +msgid "Ctrl+T" +msgstr "Ctrl+T" + +#: objects/ui_MainWindow.h:867 +#, fuzzy +msgid "Past&e viewport rotation" +msgstr "Pegar rotación de la ventana" + +#: objects/ui_MainWindow.h:868 +msgid "Increase Font &Size" +msgstr "" + +#: objects/ui_MainWindow.h:869 +msgid "Ctrl++" +msgstr "Ctrl++" + +#: objects/ui_MainWindow.h:870 +msgid "Decrease Font Si&ze" +msgstr "" + +#: objects/ui_MainWindow.h:871 +msgid "Ctrl+-" +msgstr "Ctrl+-" + +#: objects/ui_MainWindow.h:872 +#, fuzzy +msgid "H&ide editor" +msgstr "Ocultar editor" + +#: objects/ui_MainWindow.h:873 +msgid "&Reload and Preview" +msgstr "&Recargar y previsualizar" + +#: objects/ui_MainWindow.h:874 +msgid "F4" +msgstr "F4" + +#: objects/ui_MainWindow.h:875 +msgid "&Preview" +msgstr "&Previsualizar" + +#: objects/ui_MainWindow.h:876 +msgid "F5" +msgstr "F5" + +#: objects/ui_MainWindow.h:877 +#, fuzzy +msgid "R&ender" +msgstr "&Renderizar" + +#: objects/ui_MainWindow.h:878 +msgid "F6" +msgstr "F6" + +#: objects/ui_MainWindow.h:879 +#, fuzzy +msgid "&Check Validity" +msgstr "Chequear validez" + +#: objects/ui_MainWindow.h:880 +#, fuzzy +msgid "Display A&ST..." +msgstr "Mostrar &AST..." + +#: objects/ui_MainWindow.h:881 +msgid "Display CSG &Tree..." +msgstr "Mostrar CSG &Arbre" + +#: objects/ui_MainWindow.h:882 +#, fuzzy +msgid "Display CSG Pr&oducts..." +msgstr "Mostar CSG &Produits" + +#: objects/ui_MainWindow.h:883 +msgid "Export as &STL..." +msgstr "Exportar como &STL..." + +#: objects/ui_MainWindow.h:884 +msgid "Export as &OFF..." +msgstr "Exportar como &OFF..." + +#: objects/ui_MainWindow.h:885 +msgid "Preview" +msgstr "Previsualizar" + +#: objects/ui_MainWindow.h:886 +msgid "F9" +msgstr "F9" + +#: objects/ui_MainWindow.h:887 +msgid "Surfaces" +msgstr "Superficie" + +#: objects/ui_MainWindow.h:888 +msgid "F10" +msgstr "F10" + +#: objects/ui_MainWindow.h:889 +msgid "Wireframe" +msgstr "Estructura" + +#: objects/ui_MainWindow.h:890 +msgid "F11" +msgstr "F11" + +#: objects/ui_MainWindow.h:891 +msgid "Thrown Together" +msgstr "Lanzar Juntos" + +#: objects/ui_MainWindow.h:892 +msgid "F12" +msgstr "F12" + +#: objects/ui_MainWindow.h:893 +msgid "Show Edges" +msgstr "Mostrar puntos" + +#: objects/ui_MainWindow.h:894 +msgid "Ctrl+1" +msgstr "Ctrl+1" + +#: objects/ui_MainWindow.h:895 +msgid "Show Axes" +msgstr "Mostrar ejes" + +#: objects/ui_MainWindow.h:896 +msgid "Ctrl+2" +msgstr "Ctrl+2" + +#: objects/ui_MainWindow.h:897 +msgid "Show Crosshairs" +msgstr "Mostrar punto de mira" + +#: objects/ui_MainWindow.h:898 +msgid "Ctrl+3" +msgstr "Ctrl+3" + +#: objects/ui_MainWindow.h:899 +msgid "Show Scale Markers" +msgstr "" + +#: objects/ui_MainWindow.h:900 +msgid "Animate" +msgstr "Animar" + +#: objects/ui_MainWindow.h:901 +msgid "&Top" +msgstr "" + +#: objects/ui_MainWindow.h:902 +msgid "Ctrl+4" +msgstr "Ctrl+4" + +#: objects/ui_MainWindow.h:903 +#, fuzzy +msgid "&Bottom" +msgstr "Abajo" + +#: objects/ui_MainWindow.h:904 +msgid "Ctrl+5" +msgstr "Ctrl+5" + +#: objects/ui_MainWindow.h:905 +#, fuzzy +msgid "&Left" +msgstr "Izquierda" + +#: objects/ui_MainWindow.h:906 +msgid "Ctrl+6" +msgstr "Ctrl+6" + +#: objects/ui_MainWindow.h:907 +#, fuzzy +msgid "&Right" +msgstr "Derecha" + +#: objects/ui_MainWindow.h:908 +msgid "Ctrl+7" +msgstr "Ctrl+7" + +#: objects/ui_MainWindow.h:909 +#, fuzzy +msgid "&Front" +msgstr "Frente" + +#: objects/ui_MainWindow.h:910 +msgid "Ctrl+8" +msgstr "Ctrl+8" + +#: objects/ui_MainWindow.h:911 +msgid "Bac&k" +msgstr "" + +#: objects/ui_MainWindow.h:912 +msgid "Ctrl+9" +msgstr "Ctrl+9" + +#: objects/ui_MainWindow.h:913 +#, fuzzy +msgid "&Diagonal" +msgstr "Diagonal" + +#: objects/ui_MainWindow.h:914 +msgid "Ctrl+0" +msgstr "Ctrl+0" + +#: objects/ui_MainWindow.h:915 +#, fuzzy +msgid "Ce&nter" +msgstr "Centro" + +#: objects/ui_MainWindow.h:916 +#, fuzzy +msgid "&Perspective" +msgstr "Perspectiva" + +#: objects/ui_MainWindow.h:917 +#, fuzzy +msgid "&Orthogonal" +msgstr "Orthogonal" + +#: objects/ui_MainWindow.h:918 +#, fuzzy +msgid "H&ide console" +msgstr "Ocultar consola" + +#: objects/ui_MainWindow.h:919 +#, fuzzy +msgid "&About" +msgstr "Acerca de" + +#: objects/ui_MainWindow.h:920 +#, fuzzy +msgid "&Documentation" +msgstr "Documentación" + +#: objects/ui_MainWindow.h:921 +msgid "Clear Recent" +msgstr "Borrar recientes" + +#: objects/ui_MainWindow.h:922 +#, fuzzy +msgid "Export as &DXF..." +msgstr "Exportar a DXF..." + +#: objects/ui_MainWindow.h:923 +#, fuzzy +msgid "&Close" +msgstr "Cerrar" + +#: objects/ui_MainWindow.h:924 +msgid "Ctrl+W" +msgstr "Ctrl+W" + +#: objects/ui_MainWindow.h:925 +#, fuzzy +msgid "&Preferences" +msgstr "Preferencias" + +#: objects/ui_MainWindow.h:926 +#, fuzzy +msgid "&Find..." +msgstr "Buscar..." + +#: objects/ui_MainWindow.h:927 +msgid "Ctrl+F" +msgstr "Ctrl+F" + +#: objects/ui_MainWindow.h:928 +#, fuzzy +msgid "Fin&d and Replace..." +msgstr "Buscar y reemplazar..." + +#: objects/ui_MainWindow.h:929 +msgid "Ctrl+Alt+F" +msgstr "Ctrl+Alt+F" + +#: objects/ui_MainWindow.h:930 +#, fuzzy +msgid "Find Ne&xt" +msgstr "Buscar próximo" + +#: objects/ui_MainWindow.h:931 +msgid "Ctrl+G" +msgstr "Ctrl+G" + +#: objects/ui_MainWindow.h:932 +#, fuzzy +msgid "Find Pre&vious" +msgstr "Buscar previo" + +#: objects/ui_MainWindow.h:933 +msgid "Ctrl+Shift+G" +msgstr "Ctrl+Shift+G" + +#: objects/ui_MainWindow.h:934 +#, fuzzy +msgid "Use Se&lection for Find" +msgstr "Buscar selección" + +#: objects/ui_MainWindow.h:935 +msgid "Ctrl+E" +msgstr "Ctrl+E" + +#: objects/ui_MainWindow.h:936 +#, fuzzy +msgid "&Flush Caches" +msgstr "Borrar cache" + +#: objects/ui_MainWindow.h:937 +#, fuzzy +msgid "&OpenSCAD Homepage" +msgstr "Pagina de OpenSCAD" + +#: objects/ui_MainWindow.h:938 +#, fuzzy +msgid "&Automatic Reload and Preview" +msgstr "Recargar y previsualizar automáticamente" + +#: objects/ui_MainWindow.h:939 +#, fuzzy +msgid "Export as &Image..." +msgstr "Exportar imagen..." + +#: objects/ui_MainWindow.h:940 +#, fuzzy +msgid "Export as &CSG..." +msgstr "Exportar en CSG..." + +#: objects/ui_MainWindow.h:941 +#, fuzzy +msgid "&Library info" +msgstr "Información de librerías" + +#: objects/ui_MainWindow.h:942 +#, fuzzy +msgid "Show &Library Folder..." +msgstr "Mostrar carpeta de librerías" + +#: objects/ui_MainWindow.h:943 +msgid "Reset View" +msgstr "Reiniciar vista" + +#: objects/ui_MainWindow.h:944 +#, fuzzy +msgid "&Font List" +msgstr "Lista de fuentes" + +#: objects/ui_MainWindow.h:945 +#, fuzzy +msgid "Export as S&VG..." +msgstr "Exportar en SVG..." + +#: objects/ui_MainWindow.h:946 +#, fuzzy +msgid "Export as &AMF..." +msgstr "Exportar en AMF..." + +#: objects/ui_MainWindow.h:947 +msgid "Zoom In" +msgstr "Acercar" + +#: objects/ui_MainWindow.h:948 +msgid "Ctrl+]" +msgstr "Ctrl+]" + +#: objects/ui_MainWindow.h:949 +msgid "Zoom Out" +msgstr "Alejar" + +#: objects/ui_MainWindow.h:950 +msgid "Ctrl+[" +msgstr "Ctrl+[" + +#: objects/ui_MainWindow.h:951 +msgid "View All" +msgstr "Ver todo" + +#: objects/ui_MainWindow.h:952 +#, fuzzy +msgid "Conv&ert Tabs to Spaces" +msgstr "Convertir tabulado en espacios" + +#: objects/ui_MainWindow.h:953 +msgid "Hide toolbars" +msgstr "Ocultar barra de herramientas" + +#: objects/ui_MainWindow.h:954 +msgid "U&nindent" +msgstr "Dési&ndenter" + +#: objects/ui_MainWindow.h:955 +msgid "Ctrl+Shift+I" +msgstr "Ctrl+Shift+I" + +#: objects/ui_MainWindow.h:956 +msgid "&Cheat Sheet" +msgstr "" + +#: objects/ui_MainWindow.h:957 +msgid "Message" +msgstr "" + +#: objects/ui_MainWindow.h:960 +msgid "Time:" +msgstr "Tiempo:" + +#: objects/ui_MainWindow.h:961 +msgid "FPS:" +msgstr "FPS:" + +#: objects/ui_MainWindow.h:962 +msgid "Steps:" +msgstr "Pasos:" + +#: objects/ui_MainWindow.h:963 +msgid "Dump Pictures" +msgstr "Grabar imágenes" + +#: objects/ui_MainWindow.h:964 +msgid "&File" +msgstr "&Archivo" + +#: objects/ui_MainWindow.h:965 +#, fuzzy +msgid "Recen&t Files" +msgstr "Archivos recientes" + +#: objects/ui_MainWindow.h:966 +#, fuzzy +msgid "&Examples" +msgstr "Ejemplos" + +#: objects/ui_MainWindow.h:967 +#, fuzzy +msgid "E&xport" +msgstr "Exportar" + +#: objects/ui_MainWindow.h:968 +msgid "&Edit" +msgstr "&Editar" + +#: objects/ui_MainWindow.h:969 +msgid "&Design" +msgstr "&Diseñar" + +#: objects/ui_MainWindow.h:970 +msgid "&View" +msgstr "&Ver" + +#: objects/ui_MainWindow.h:971 +msgid "&Help" +msgstr "&Ayuda" + +#: objects/ui_MainWindow.h:974 +msgid "Find" +msgstr "Buscar" + +#: objects/ui_MainWindow.h:975 objects/ui_MainWindow.h:982 +msgid "Replace" +msgstr "Reemplazar" + +#: objects/ui_MainWindow.h:977 +msgid "Search string" +msgstr "Buscar palabra" + +#: objects/ui_MainWindow.h:978 +msgid "<" +msgstr "<" + +#: objects/ui_MainWindow.h:979 +msgid ">" +msgstr ">" + +#: objects/ui_MainWindow.h:980 +msgid "Done" +msgstr "Terminar" + +#: objects/ui_MainWindow.h:981 +msgid "Replacement string" +msgstr "Remplazar palabra" + +#: objects/ui_MainWindow.h:983 +msgid "All" +msgstr "Todo" + +#: objects/ui_OpenCSGWarningDialog.h:86 +msgid "OpenGL Warning" +msgstr "Advertencia OpenGL" + +#: objects/ui_OpenCSGWarningDialog.h:87 +msgid "" +"\n" +"\n" +"

" +msgstr "" +"\n" +"\n" +"

" + +#: objects/ui_OpenCSGWarningDialog.h:92 +msgid "Enable OpenCSG" +msgstr "Activar OpenCSG" + +#: objects/ui_OpenCSGWarningDialog.h:93 +msgid "Show this message again" +msgstr "Mostrar el mensaje de nuevo" + +#: objects/ui_OpenCSGWarningDialog.h:94 +msgid "Close" +msgstr "Cerrar" + +#: objects/ui_Preferences.h:1061 +msgid "Preferences" +msgstr "Preferencias" + +#: objects/ui_Preferences.h:1062 +msgid "3D View" +msgstr "Vista 3D" + +#: objects/ui_Preferences.h:1063 src/UIUtils.cc:86 +msgid "Advanced" +msgstr "Advertencia" + +#: objects/ui_Preferences.h:1064 src/mainwin.cc:2418 +msgid "Editor" +msgstr "Editar" + +#: objects/ui_Preferences.h:1065 +msgid "Update" +msgstr "Actualizar" + +#: objects/ui_Preferences.h:1066 objects/ui_Preferences.h:1147 +msgid "Features" +msgstr "Mejoras" + +#: objects/ui_Preferences.h:1068 +msgid "Enable/Disable experimental features" +msgstr "Activar/Desactivar mejoras experimentales" + +#: objects/ui_Preferences.h:1070 +msgid "Color scheme:" +msgstr "Paleta de colores:" + +#: objects/ui_Preferences.h:1071 +msgid "Show Warnings and Errors in 3D View" +msgstr "" + +#: objects/ui_Preferences.h:1072 +msgid "Editor Type" +msgstr "Editor de texto" + +#: objects/ui_Preferences.h:1075 +msgid "Simple Editor" +msgstr "Editor simple" + +#: objects/ui_Preferences.h:1076 +msgid "QScintilla Editor" +msgstr "Editor QScintilla" + +#: objects/ui_Preferences.h:1078 +msgid "(requires restart)" +msgstr "(necesita reiniciar)" + +#: objects/ui_Preferences.h:1079 +msgid "Font" +msgstr "Fuente" + +#: objects/ui_Preferences.h:1080 +msgid "Color syntax highlighting" +msgstr "Colorear sintaxis" + +#: objects/ui_Preferences.h:1081 +#, fuzzy +msgid "Ctrl/Cmd-Mouse-wheel zooms text" +msgstr "Use ctrl/cmd + rueda del mouse para hacer zoom al texto" + +#: objects/ui_Preferences.h:1082 +#, fuzzy +msgid "Indentation" +msgstr "Documentación" + +# no se que es +#: objects/ui_Preferences.h:1083 +#, fuzzy +msgid "Auto Indent" +msgstr "&Indenter" + +# no se que es +#: objects/ui_Preferences.h:1084 +#, fuzzy +msgid "Indent using" +msgstr "&Indenter" + +#: objects/ui_Preferences.h:1087 src/settings.cc:135 +#, fuzzy +msgid "Spaces" +msgstr "Superficie" + +#: objects/ui_Preferences.h:1088 src/settings.cc:135 +msgid "Tabs" +msgstr "" + +#: objects/ui_Preferences.h:1090 +msgid "Indentation width" +msgstr "" + +#: objects/ui_Preferences.h:1091 +msgid "Tab width" +msgstr "" + +#: objects/ui_Preferences.h:1092 +msgid "Tab key function" +msgstr "" + +# no se que es +#: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 +#: src/settings.cc:136 +#, fuzzy +msgid "Indent" +msgstr "&Indenter" + +#: objects/ui_Preferences.h:1096 src/settings.cc:136 +msgid "Insert Tab" +msgstr "" + +#: objects/ui_Preferences.h:1098 +msgid "Show whitespace" +msgstr "" + +#: objects/ui_Preferences.h:1101 src/settings.cc:132 +msgid "Never" +msgstr "" + +#: objects/ui_Preferences.h:1102 src/settings.cc:132 +msgid "Always" +msgstr "" + +#: objects/ui_Preferences.h:1103 +msgid "Only after indentation" +msgstr "" + +#: objects/ui_Preferences.h:1105 +msgid "Size" +msgstr "" + +#: objects/ui_Preferences.h:1106 +#, fuzzy +msgid "Display" +msgstr "Mostrar &AST..." + +#: objects/ui_Preferences.h:1107 +msgid "Enable brace matching" +msgstr "" + +#: objects/ui_Preferences.h:1108 +msgid "Highlight current line" +msgstr "" + +#: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 +msgid "Line wrap" +msgstr "" + +#: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 +#: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 +#: src/settings.cc:131 +msgid "None" +msgstr "" + +#: objects/ui_Preferences.h:1113 src/settings.cc:127 +msgid "Wrap at character boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1114 src/settings.cc:127 +msgid "Wrap at word boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1116 +msgid "Line wrap indentation" +msgstr "" + +#: objects/ui_Preferences.h:1117 +msgid "Line wrap visualization" +msgstr "" + +#: objects/ui_Preferences.h:1118 +msgid "Style" +msgstr "" + +#: objects/ui_Preferences.h:1121 src/settings.cc:128 +msgid "Fixed" +msgstr "" + +#: objects/ui_Preferences.h:1122 src/settings.cc:128 +msgid "Same" +msgstr "" + +# no se que es +#: objects/ui_Preferences.h:1123 src/settings.cc:128 +#, fuzzy +msgid "Indented" +msgstr "&Indenter" + +#: objects/ui_Preferences.h:1126 +msgid "Start" +msgstr "" + +#: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Text" +msgstr "" + +#: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Border" +msgstr "" + +#: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Margin" +msgstr "" + +#: objects/ui_Preferences.h:1134 +msgid "End" +msgstr "" + +#: objects/ui_Preferences.h:1143 +msgid "Automatically check for updates" +msgstr "Comprobar actualización automáticamente" + +#: objects/ui_Preferences.h:1144 +msgid "Include development snapshots" +msgstr "Incluir las versiones en desarrollo" + +#: objects/ui_Preferences.h:1145 +msgid "Check Now" +msgstr "Chequear ahora" + +#: objects/ui_Preferences.h:1146 +msgid "Last checked: " +msgstr "Último chequeo:" + +#: objects/ui_Preferences.h:1148 +msgid "OpenCSG" +msgstr "OpenCSG" + +#: objects/ui_Preferences.h:1149 +msgid "Show capability warning" +msgstr "Advertir incapacidad" + +#: objects/ui_Preferences.h:1150 +msgid "Enable for OpenGL 1.x" +msgstr "Activar OpenGL 1.x" + +#: objects/ui_Preferences.h:1151 +msgid "Turn off rendering at " +msgstr "Desactivar el render de" + +#: objects/ui_Preferences.h:1152 +msgid "elements" +msgstr "elementos" + +#: objects/ui_Preferences.h:1153 +msgid "Force Goldfeather" +msgstr "Forzar Goldfeather" + +#: objects/ui_Preferences.h:1154 +msgid "CGAL Cache size" +msgstr "Tamaño de cache de CGAL" + +#: objects/ui_Preferences.h:1155 objects/ui_Preferences.h:1157 +msgid "bytes" +msgstr "bytes" + +#: objects/ui_Preferences.h:1156 +msgid "PolySet Cache size" +msgstr "Tamaño de cache de PolySet" + +#: objects/ui_Preferences.h:1158 +msgid "Allow to open multiple documents" +msgstr "Permitir a abrir varios documentos" + +#: objects/ui_Preferences.h:1159 +msgid "Enable docking of Editor and Console in different places" +msgstr "Habilitar soporte de editor y consola en diferentes lugares" + +#: objects/ui_Preferences.h:1160 +msgid "Enable undocking of Editor and Console to separate windows" +msgstr "" +"Habilitar el desacoplamiento de editor y consola para separar las ventanas" + +#: objects/ui_Preferences.h:1161 +msgid "Show Welcome Screen" +msgstr "Pantalla de bienvenida" + +#: objects/ui_Preferences.h:1162 +msgid "Enable user interface localization (requires restart of OpenSCAD)" +msgstr "" +"Habilitar interfaz de usuario localización (requiere reiniciar OpenSCAD)" + +#: objects/ui_ProgressWidget.h:72 +msgid "%v / %m" +msgstr "%v / %m" + +#: src/Camera.cc:126 +#, c-format +msgid "" +"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " +"distance = %.2f" +msgstr "" +"Marco: posición = [ %.2f %.2f %.2f ], rotación = [ %.2f %.2f %.2f ], " +"distancia = %.2f" + +#: src/mainwin.cc:778 src/mainwin.cc:1354 +msgid "Untitled.scad" +msgstr "Sintitulo.scad" + +#: src/mainwin.cc:971 +msgid "Compile error." +msgstr "" + +#: src/mainwin.cc:974 +msgid "Error while compiling '%1'." +msgstr "" + +#: src/mainwin.cc:978 +msgid "Compilation generated %1 warning." +msgid_plural "Compilation generated %1 warnings." +msgstr[0] "" +msgstr[1] "" + +#: src/mainwin.cc:988 +msgid " For details see console window." +msgstr "" + +#: src/mainwin.cc:1353 +msgid "Save File" +msgstr "Salver archivo" + +#: src/mainwin.cc:1355 +msgid "OpenSCAD Designs (*.scad)" +msgstr "Diseño OpenSCAD (*.scad)" + +#: src/mainwin.cc:1365 +msgid "" +"%1 already exists.\n" +"Do you want to replace it?" +msgstr "" +"%1 existe.\n" +"Deseas reemplazarlo?" + +#: src/mainwin.cc:1684 +msgid "Application" +msgstr "Aplicación" + +#: src/mainwin.cc:1685 +msgid "" +"The document has been modified.\n" +"Do you really want to reload the file?" +msgstr "" +"El documento ha sido modificado.\n" +"¿Realmente desea volver a cargar el archivo ?" + +#: src/mainwin.cc:2038 src/mainwin.cc:2094 +msgid "Export %1 File" +msgstr "Exportar %1 Archivo" + +#: src/mainwin.cc:2039 src/mainwin.cc:2098 +msgid "%1 Files (*%2)" +msgstr "%1 Archivo (*%2)" + +#: src/mainwin.cc:2040 +msgid "Untitled" +msgstr "Sin titulo" + +#: src/mainwin.cc:2096 +msgid "Untitled%1" +msgstr "Sintitulo%1" + +#: src/mainwin.cc:2147 +msgid "Export CSG File" +msgstr "Exportar archivo CSG" + +#: src/mainwin.cc:2148 +msgid "Untitled.csg" +msgstr "Sintitulo.csg" + +#: src/mainwin.cc:2149 +msgid "CSG Files (*.csg)" +msgstr "Archivo CSG (*.csg)" + +#: src/mainwin.cc:2175 +msgid "Export Image" +msgstr "Exportar una imagen" + +#: src/mainwin.cc:2175 +msgid "PNG Files (*.png)" +msgstr "Archivo PNG (*.png)" + +#: src/mainwin.cc:2423 +msgid "Console" +msgstr "Consola" + +#: src/mainwin.cc:2560 +msgid "The document has been modified." +msgstr "El documento ha sido modificado." + +#: src/mainwin.cc:2561 +msgid "Do you want to save your changes?" +msgstr "¿Quieres guardar los cambios ?" + +#: src/openscad.cc:604 +msgid "" +"Fontconfig needs to update its font cache.\n" +"This can take up to a couple of minutes." +msgstr "" + +#: src/QGLView.cc:129 +msgid "" +"Warning: You may experience OpenCSG rendering errors.\n" +"\n" +msgstr "" +"Advertencia: Usted puede experimentar OpenCSG errores de renderizado.\n" +"\n" + +#: src/QGLView.cc:132 +msgid "" +"Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " +"disabled.\n" +"\n" +msgstr "" +"Advertencia: Manquantes capacités OpenGL vierten OpenCSG - OpenCSG ha sido " +"desactivada. .\n" +"\n" + +#: src/QGLView.cc:135 +msgid "" +"It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " +"later.\n" +"Your renderer information is as follows:\n" +msgstr "" +"Es muy recomendable utilizar OpenSCAD en un sistema con OpenGL 2.0 o " +"posterior.\n" +"Su información renderer es como sigue:\n" + +#: src/QGLView.cc:139 +#, c-format +msgid "" +"GLEW version %s\n" +"%s (%s)\n" +"OpenGL version %s\n" +msgstr "" +"Versión GLEW %s\n" +"%s (%s)\n" +"Versión OpenGL %s\n" + +#: src/settings.cc:132 +msgid "After indentation" +msgstr "" + +#: src/UIUtils.cc:86 +msgid "Basics" +msgstr "Básico" + +#: src/UIUtils.cc:86 +msgid "Shapes" +msgstr "Formas" + +#: src/UIUtils.cc:86 +msgid "Extrusion" +msgstr "Extrusión" + +#~ msgid "Top" +#~ msgstr "Arriba" + +#~ msgid "Back" +#~ msgstr "Atrás" + +#~ msgid "toolBar" +#~ msgstr "barra de herramientas" + +#~ msgid "Form" +#~ msgstr "Formulario" + +#~ msgid "" +#~ "\n" +#~ "Using QGLWidget\n" +#~ "\n" +#~ msgstr "" +#~ "\n" +#~ "Utilizar QGLWidget\n" +#~ "\n" + +#~ msgid "Paste font selector to Editor Window" +#~ msgstr "Coller le sélecteur de polices dans l'éditeur de fenêtres" + +#~ msgid "About OpenSCAD " +#~ msgstr "À propos de OpenSCAD" + +#~ msgid "Check for Update.." +#~ msgstr "Vérifier les mises à jours" + +#~ msgid "OpenGL Info" +#~ msgstr "Information OpenGL" diff --git a/locale/fr.po b/locale/fr.po index b3b892a5..eaa37802 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -1,14 +1,14 @@ -# French translations for OpenSCAD package. -# Copyright (C) 2013 THE OpenSCAD'S COPYRIGHT HOLDER -# This file is distributed under the same license as the OpenSCAD package. -# don , 2013. -# +# French translations for OpenSCAD package. +# Copyright (C) 2013 THE OpenSCAD'S COPYRIGHT HOLDER +# This file is distributed under the same license as the OpenSCAD package. +# don , 2013. +# msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2013.02.07\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-22 23:28+0100\n" -"PO-Revision-Date: 2014-12-14 10:20-0500\n" +"POT-Creation-Date: 2015-02-01 18:03+0100\n" +"PO-Revision-Date: 2015-01-27 18:47-0500\n" "Last-Translator: Keven Villeneuve \n" "Language-Team: French\n" "Language: fr\n" @@ -17,84 +17,13 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Poedit-SourceCharset: utf-8\n" -"X-Generator: Poedit 1.7.1\n" +"X-Generator: Poedit 1.7.4\n" -#: objects/ui_AboutDialog.h:51 src/AboutDialog.h:15 +#: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" msgstr "À propos de OpenSCAD" -#: objects/ui_FontListDialog.h:102 -msgid "OpenSCAD Font List" -msgstr "Liste des polices OpenSCAD" - -#: objects/ui_FontListDialog.h:103 objects/ui_LibraryInfoDialog.h:77 -msgid "&OK" -msgstr "&OK" - -#: objects/ui_FontListDialog.h:104 -msgid "Copy to Clipboard" -msgstr "Coller dans le presse-papier" - -#: objects/ui_FontListDialog.h:105 -msgid "Filter:" -msgstr "Filtre:" - -#: objects/ui_FontListDialog.h:106 -msgid "" -"

This list shows the fonts currently registered with " -"OpenSCAD.

Example:

  text(t = "
-""OpenSCAD", font = "DejaVu Sans");
  text(t = "OpenSCAD", font = "
-""Liberation Sans:style=Italic");
" -msgstr "" -"

Cette liste affiche les polices présentement chargées " -"avec OpenSCAD

Example:

  text(t = "
-""OpenSCAD", font = "DejaVu Sans");
  text(t = "OpenSCAD", font = "
-""Liberation Sans:style=Italic");
" - -#: objects/ui_launchingscreen.h:276 -msgid "Welcome to OpenSCAD" -msgstr "Bienvenue dans OpenSCAD" - -#: objects/ui_launchingscreen.h:277 -msgid "New" -msgstr "Nouveau" - -#: objects/ui_launchingscreen.h:278 -msgid "Open" -msgstr "Ouvrir..." - -#: objects/ui_launchingscreen.h:279 -msgid "Help" -msgstr "Aide" - -#: objects/ui_launchingscreen.h:280 -msgid "Recents" -msgstr "Récents" - -#: objects/ui_launchingscreen.h:281 -msgid "Open Recent" -msgstr "Ouvrir un fichier récent" - -#: objects/ui_launchingscreen.h:282 objects/ui_launchingscreen.h:284 -#: objects/ui_MainWindow.h:855 -msgid "Examples" -msgstr "Exemples" - -#: objects/ui_launchingscreen.h:285 -msgid "Open Example" -msgstr "&Ouvrir un example" - -#: objects/ui_launchingscreen.h:287 +#: objects/ui_AboutDialog.h:105 objects/ui_launchingscreen.h:305 msgid "" "\n" "

This list shows the fonts currently registered with " +"OpenSCAD.

Example:

  text(t = "
+""OpenSCAD", font = "DejaVu Sans");
  text(t = "OpenSCAD", font = "
+""Liberation Sans:style=Italic");
" +msgstr "" +"

Cette liste affiche les polices présentement chargées " +"avec OpenSCAD

Example:

  text(t = "
+""OpenSCAD", font = "DejaVu Sans");
  text(t = "OpenSCAD", font = "
+""Liberation Sans:style=Italic");
" + #: objects/ui_launchingscreen.h:294 +msgid "Welcome to OpenSCAD" +msgstr "Bienvenue dans OpenSCAD" + +#: objects/ui_launchingscreen.h:295 +msgid "New" +msgstr "Nouveau" + +#: objects/ui_launchingscreen.h:296 +msgid "Open" +msgstr "Ouvrir..." + +#: objects/ui_launchingscreen.h:297 +msgid "Help" +msgstr "Aide" + +#: objects/ui_launchingscreen.h:298 +msgid "Recents" +msgstr "Récents" + +#: objects/ui_launchingscreen.h:299 +msgid "Open Recent" +msgstr "Ouvrir un fichier récent" + +#: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 +msgid "Examples" +msgstr "Exemples" + +#: objects/ui_launchingscreen.h:303 +msgid "Open Example" +msgstr "&Ouvrir un example" + +#: objects/ui_launchingscreen.h:312 msgid "Don't show again" msgstr "Ne plus afficher" +#: objects/ui_launchingscreen.h:313 +msgid "Version" +msgstr "Version" + #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" msgstr "Bibliothèques et Infos de la version" @@ -130,543 +137,610 @@ msgstr "Bibliothèques et Infos de la version" msgid "OpenSCAD Detailed Library and Build Information" msgstr "Informations détaillées des bibliothèques et de la version d'OpenSCAD" -#: objects/ui_MainWindow.h:731 +#: objects/ui_MainWindow.h:837 msgid "&New" msgstr "&Nouveau" -#: objects/ui_MainWindow.h:732 +#: objects/ui_MainWindow.h:838 msgid "Ctrl+N" msgstr "Ctrl+N" -#: objects/ui_MainWindow.h:733 +#: objects/ui_MainWindow.h:839 msgid "&Open..." msgstr "&Ouvrir..." -#: objects/ui_MainWindow.h:734 +#: objects/ui_MainWindow.h:840 msgid "Ctrl+O" msgstr "Ctrl+O" -#: objects/ui_MainWindow.h:735 +#: objects/ui_MainWindow.h:841 msgid "&Save" msgstr "Enregi&strer" -#: objects/ui_MainWindow.h:736 +#: objects/ui_MainWindow.h:842 msgid "Ctrl+S" msgstr "Ctrl+S" -#: objects/ui_MainWindow.h:737 +#: objects/ui_MainWindow.h:843 msgid "Save &As..." msgstr "Enregistrer &sous..." -#: objects/ui_MainWindow.h:738 +#: objects/ui_MainWindow.h:844 msgid "Ctrl+Shift+S" msgstr "Ctrl+Shift+S" -#: objects/ui_MainWindow.h:739 +#: objects/ui_MainWindow.h:845 msgid "&Reload" msgstr "&Recharger" -#: objects/ui_MainWindow.h:740 +#: objects/ui_MainWindow.h:846 msgid "Ctrl+R" msgstr "Ctrl+R" -#: objects/ui_MainWindow.h:741 +#: objects/ui_MainWindow.h:847 msgid "&Quit" msgstr "&Quitter" -#: objects/ui_MainWindow.h:742 +#: objects/ui_MainWindow.h:848 msgid "Ctrl+Q" msgstr "Ctrl+Q" -#: objects/ui_MainWindow.h:743 +#: objects/ui_MainWindow.h:849 msgid "&Undo" msgstr "Ann&uler" -#: objects/ui_MainWindow.h:744 +#: objects/ui_MainWindow.h:850 msgid "Ctrl+Z" msgstr "Ctrl+Z" -#: objects/ui_MainWindow.h:745 +#: objects/ui_MainWindow.h:851 msgid "&Redo" msgstr "&Répéter" -#: objects/ui_MainWindow.h:746 +#: objects/ui_MainWindow.h:852 msgid "Ctrl+Shift+Z" msgstr "Ctrl+Shift+Z" -#: objects/ui_MainWindow.h:747 +#: objects/ui_MainWindow.h:853 msgid "Cu&t" msgstr "Co&uper" -#: objects/ui_MainWindow.h:748 +#: objects/ui_MainWindow.h:854 msgid "Ctrl+X" msgstr "Ctrl+X" -#: objects/ui_MainWindow.h:749 +#: objects/ui_MainWindow.h:855 msgid "&Copy" msgstr "&Copier" -#: objects/ui_MainWindow.h:750 +#: objects/ui_MainWindow.h:856 msgid "Ctrl+C" msgstr "Ctrl+C" -#: objects/ui_MainWindow.h:751 +#: objects/ui_MainWindow.h:857 msgid "&Paste" msgstr "&Coller" -#: objects/ui_MainWindow.h:752 +#: objects/ui_MainWindow.h:858 msgid "Ctrl+V" msgstr "Ctrl+V" -#: objects/ui_MainWindow.h:753 +#: objects/ui_MainWindow.h:859 msgid "&Indent" msgstr "&Indenter" -#: objects/ui_MainWindow.h:754 +#: objects/ui_MainWindow.h:860 msgid "Ctrl+I" msgstr "Ctrl+I" -#: objects/ui_MainWindow.h:755 -msgid "U&nindent" -msgstr "Dési&ndenter" - -#: objects/ui_MainWindow.h:756 -msgid "Ctrl+Shift+I" -msgstr "Ctrl+Shift+I" - -#: objects/ui_MainWindow.h:757 +#: objects/ui_MainWindow.h:861 msgid "C&omment" msgstr "C&ommenter" -#: objects/ui_MainWindow.h:758 +#: objects/ui_MainWindow.h:862 msgid "Ctrl+D" msgstr "Ctrl+D" -#: objects/ui_MainWindow.h:759 +#: objects/ui_MainWindow.h:863 msgid "Unco&mment" msgstr "Déco&mmenter" -#: objects/ui_MainWindow.h:760 +#: objects/ui_MainWindow.h:864 msgid "Ctrl+Shift+D" msgstr "Ctrl+Shift+D" -#: objects/ui_MainWindow.h:761 -msgid "Paste viewport translation" +#: objects/ui_MainWindow.h:865 +#, fuzzy +msgid "P&aste viewport translation" msgstr "Coller la translation de la fenêtre de rendu" -#: objects/ui_MainWindow.h:762 +#: objects/ui_MainWindow.h:866 msgid "Ctrl+T" msgstr "Ctrl+T" -#: objects/ui_MainWindow.h:763 -msgid "Paste viewport rotation" +#: objects/ui_MainWindow.h:867 +#, fuzzy +msgid "Past&e viewport rotation" msgstr "Coller la rotation de la fenêtre de rendu" -#: objects/ui_MainWindow.h:764 objects/ui_MainWindow.h:842 -msgid "Zoom In" -msgstr "Zoom Avant" +#: objects/ui_MainWindow.h:868 +#, fuzzy +msgid "Increase Font &Size" +msgstr "Agrandir la police" -#: objects/ui_MainWindow.h:765 +#: objects/ui_MainWindow.h:869 msgid "Ctrl++" msgstr "Ctrl++" -#: objects/ui_MainWindow.h:766 objects/ui_MainWindow.h:844 -msgid "Zoom Out" -msgstr "Zoom Arrière" +#: objects/ui_MainWindow.h:870 +#, fuzzy +msgid "Decrease Font Si&ze" +msgstr "Réduire la police" -#: objects/ui_MainWindow.h:767 +#: objects/ui_MainWindow.h:871 msgid "Ctrl+-" msgstr "Ctrl+-" -#: objects/ui_MainWindow.h:768 -msgid "Hide editor" +#: objects/ui_MainWindow.h:872 +#, fuzzy +msgid "H&ide editor" msgstr "Cacher l'éditeur" -#: objects/ui_MainWindow.h:769 +#: objects/ui_MainWindow.h:873 msgid "&Reload and Preview" msgstr "&Recharger et Aperçu" -#: objects/ui_MainWindow.h:770 +#: objects/ui_MainWindow.h:874 msgid "F4" msgstr "F4" -#: objects/ui_MainWindow.h:771 +#: objects/ui_MainWindow.h:875 msgid "&Preview" msgstr "&Aperçu" -#: objects/ui_MainWindow.h:772 +#: objects/ui_MainWindow.h:876 msgid "F5" msgstr "F5" -#: objects/ui_MainWindow.h:773 -msgid "&Render" +#: objects/ui_MainWindow.h:877 +#, fuzzy +msgid "R&ender" msgstr "&Rendu" -#: objects/ui_MainWindow.h:774 +#: objects/ui_MainWindow.h:878 msgid "F6" msgstr "F6" -#: objects/ui_MainWindow.h:775 -msgid "Check Validity" +#: objects/ui_MainWindow.h:879 +#, fuzzy +msgid "&Check Validity" msgstr "Vérifier la Validité" -#: objects/ui_MainWindow.h:776 -msgid "Display &AST..." +#: objects/ui_MainWindow.h:880 +#, fuzzy +msgid "Display A&ST..." msgstr "Afficher &AST..." -#: objects/ui_MainWindow.h:777 +#: objects/ui_MainWindow.h:881 msgid "Display CSG &Tree..." msgstr "Afficher CSG &Arbre" -#: objects/ui_MainWindow.h:778 -msgid "Display CSG &Products..." +#: objects/ui_MainWindow.h:882 +#, fuzzy +msgid "Display CSG Pr&oducts..." msgstr "Afficher CSG &Produits" -#: objects/ui_MainWindow.h:779 +#: objects/ui_MainWindow.h:883 msgid "Export as &STL..." msgstr "Exporter comme &STL..." -#: objects/ui_MainWindow.h:780 +#: objects/ui_MainWindow.h:884 msgid "Export as &OFF..." msgstr "Exporter comme &OFF..." -#: objects/ui_MainWindow.h:781 +#: objects/ui_MainWindow.h:885 msgid "Preview" msgstr "Aperçu" -#: objects/ui_MainWindow.h:782 +#: objects/ui_MainWindow.h:886 msgid "F9" msgstr "F9" -#: objects/ui_MainWindow.h:783 +#: objects/ui_MainWindow.h:887 msgid "Surfaces" msgstr "Surfaces" -#: objects/ui_MainWindow.h:784 +#: objects/ui_MainWindow.h:888 msgid "F10" msgstr "F10" -#: objects/ui_MainWindow.h:785 +#: objects/ui_MainWindow.h:889 msgid "Wireframe" msgstr "Wireframe" -#: objects/ui_MainWindow.h:786 +#: objects/ui_MainWindow.h:890 msgid "F11" msgstr "F11" -#: objects/ui_MainWindow.h:787 +#: objects/ui_MainWindow.h:891 msgid "Thrown Together" msgstr "Jeté ensemble" -#: objects/ui_MainWindow.h:788 +#: objects/ui_MainWindow.h:892 msgid "F12" msgstr "F12" -#: objects/ui_MainWindow.h:789 +#: objects/ui_MainWindow.h:893 msgid "Show Edges" msgstr "Afficher les Arêtes" -#: objects/ui_MainWindow.h:790 +#: objects/ui_MainWindow.h:894 msgid "Ctrl+1" msgstr "Ctrl+1" -#: objects/ui_MainWindow.h:791 +#: objects/ui_MainWindow.h:895 msgid "Show Axes" msgstr "Afficher les Axes" -#: objects/ui_MainWindow.h:792 +#: objects/ui_MainWindow.h:896 msgid "Ctrl+2" msgstr "Ctrl+2" -#: objects/ui_MainWindow.h:793 +#: objects/ui_MainWindow.h:897 msgid "Show Crosshairs" msgstr "Afficher la Mire" -#: objects/ui_MainWindow.h:794 +#: objects/ui_MainWindow.h:898 msgid "Ctrl+3" msgstr "Ctrl+3" -#: objects/ui_MainWindow.h:795 +#: objects/ui_MainWindow.h:899 +msgid "Show Scale Markers" +msgstr "Afficher les Marqueurs d'Échelle" + +#: objects/ui_MainWindow.h:900 msgid "Animate" msgstr "Animer" -#: objects/ui_MainWindow.h:796 -msgid "Top" -msgstr "Dessus" +#: objects/ui_MainWindow.h:901 +msgid "&Top" +msgstr "" -#: objects/ui_MainWindow.h:797 +#: objects/ui_MainWindow.h:902 msgid "Ctrl+4" msgstr "Ctrl+4" -#: objects/ui_MainWindow.h:798 -msgid "Bottom" +#: objects/ui_MainWindow.h:903 +#, fuzzy +msgid "&Bottom" msgstr "Dessous" -#: objects/ui_MainWindow.h:799 +#: objects/ui_MainWindow.h:904 msgid "Ctrl+5" msgstr "Ctrl+5" -#: objects/ui_MainWindow.h:800 -msgid "Left" +#: objects/ui_MainWindow.h:905 +#, fuzzy +msgid "&Left" msgstr "Gauche" -#: objects/ui_MainWindow.h:801 +#: objects/ui_MainWindow.h:906 msgid "Ctrl+6" msgstr "Ctrl+6" -#: objects/ui_MainWindow.h:802 -msgid "Right" +#: objects/ui_MainWindow.h:907 +#, fuzzy +msgid "&Right" msgstr "Droite" -#: objects/ui_MainWindow.h:803 +#: objects/ui_MainWindow.h:908 msgid "Ctrl+7" msgstr "Ctrl+7" -#: objects/ui_MainWindow.h:804 -msgid "Front" +#: objects/ui_MainWindow.h:909 +#, fuzzy +msgid "&Front" msgstr "Face" -#: objects/ui_MainWindow.h:805 +#: objects/ui_MainWindow.h:910 msgid "Ctrl+8" msgstr "Ctrl+8" -#: objects/ui_MainWindow.h:806 -msgid "Back" -msgstr "Arrière" +#: objects/ui_MainWindow.h:911 +msgid "Bac&k" +msgstr "" -#: objects/ui_MainWindow.h:807 +#: objects/ui_MainWindow.h:912 msgid "Ctrl+9" msgstr "Ctrl+9" -#: objects/ui_MainWindow.h:808 -msgid "Diagonal" +#: objects/ui_MainWindow.h:913 +#, fuzzy +msgid "&Diagonal" msgstr "Diagonale" -#: objects/ui_MainWindow.h:809 +#: objects/ui_MainWindow.h:914 msgid "Ctrl+0" msgstr "Ctrl+0" -#: objects/ui_MainWindow.h:810 -msgid "Center" +#: objects/ui_MainWindow.h:915 +#, fuzzy +msgid "Ce&nter" msgstr "Centre" -#: objects/ui_MainWindow.h:811 -msgid "Perspective" +#: objects/ui_MainWindow.h:916 +#, fuzzy +msgid "&Perspective" msgstr "Perspective" -#: objects/ui_MainWindow.h:812 -msgid "Orthogonal" +#: objects/ui_MainWindow.h:917 +#, fuzzy +msgid "&Orthogonal" msgstr "Orthogonale" -#: objects/ui_MainWindow.h:813 -msgid "Hide console" +#: objects/ui_MainWindow.h:918 +#, fuzzy +msgid "H&ide console" msgstr "Cache la console" -#: objects/ui_MainWindow.h:814 -msgid "About" +#: objects/ui_MainWindow.h:919 +#, fuzzy +msgid "&About" msgstr "À propos" -#: objects/ui_MainWindow.h:815 -msgid "Documentation" +#: objects/ui_MainWindow.h:920 +#, fuzzy +msgid "&Documentation" msgstr "Documentation" -#: objects/ui_MainWindow.h:816 +#: objects/ui_MainWindow.h:921 msgid "Clear Recent" msgstr "Effacer Récents" -#: objects/ui_MainWindow.h:817 -msgid "Export as DXF..." +#: objects/ui_MainWindow.h:922 +#, fuzzy +msgid "Export as &DXF..." msgstr "Exporter comme DXF..." -#: objects/ui_MainWindow.h:818 objects/ui_OpenCSGWarningDialog.h:94 -msgid "Close" +#: objects/ui_MainWindow.h:923 +#, fuzzy +msgid "&Close" msgstr "Fermer" -#: objects/ui_MainWindow.h:819 +#: objects/ui_MainWindow.h:924 msgid "Ctrl+W" msgstr "Ctrl+W" -#: objects/ui_MainWindow.h:820 objects/ui_Preferences.h:608 -msgid "Preferences" +#: objects/ui_MainWindow.h:925 +#, fuzzy +msgid "&Preferences" msgstr "Préférences" -#: objects/ui_MainWindow.h:821 -msgid "Find..." +#: objects/ui_MainWindow.h:926 +#, fuzzy +msgid "&Find..." msgstr "Rechercher..." -#: objects/ui_MainWindow.h:822 +#: objects/ui_MainWindow.h:927 msgid "Ctrl+F" msgstr "Ctrl+F" -#: objects/ui_MainWindow.h:823 -msgid "Find and Replace..." +#: objects/ui_MainWindow.h:928 +#, fuzzy +msgid "Fin&d and Replace..." msgstr "Rechercher et remplacer..." -#: objects/ui_MainWindow.h:824 +#: objects/ui_MainWindow.h:929 msgid "Ctrl+Alt+F" msgstr "Ctrl+Alt+F" -#: objects/ui_MainWindow.h:825 -msgid "Find Next" +#: objects/ui_MainWindow.h:930 +#, fuzzy +msgid "Find Ne&xt" msgstr "Rechercher Suivant" -#: objects/ui_MainWindow.h:826 +#: objects/ui_MainWindow.h:931 msgid "Ctrl+G" msgstr "Ctrl+G" -#: objects/ui_MainWindow.h:827 -msgid "Find Previous" +#: objects/ui_MainWindow.h:932 +#, fuzzy +msgid "Find Pre&vious" msgstr "Rechercher Précédent" -#: objects/ui_MainWindow.h:828 +#: objects/ui_MainWindow.h:933 msgid "Ctrl+Shift+G" msgstr "Ctrl+Shift+G" -#: objects/ui_MainWindow.h:829 -msgid "Use Selection for Find" +#: objects/ui_MainWindow.h:934 +#, fuzzy +msgid "Use Se&lection for Find" msgstr "Utiliser la sélection pour Rechercher" -#: objects/ui_MainWindow.h:830 +#: objects/ui_MainWindow.h:935 msgid "Ctrl+E" msgstr "Ctrl+E" -#: objects/ui_MainWindow.h:831 -msgid "Flush Caches" +#: objects/ui_MainWindow.h:936 +#, fuzzy +msgid "&Flush Caches" msgstr "Vider les caches" -#: objects/ui_MainWindow.h:832 -msgid "OpenSCAD Homepage" +#: objects/ui_MainWindow.h:937 +#, fuzzy +msgid "&OpenSCAD Homepage" msgstr "Page d'accueil OpenSCAD" -#: objects/ui_MainWindow.h:833 -msgid "Automatic Reload and Preview" +#: objects/ui_MainWindow.h:938 +#, fuzzy +msgid "&Automatic Reload and Preview" msgstr "Recharger et Aperçu Automatique" -#: objects/ui_MainWindow.h:834 -msgid "Export as Image..." +#: objects/ui_MainWindow.h:939 +#, fuzzy +msgid "Export as &Image..." msgstr "Exporter comme Image..." -#: objects/ui_MainWindow.h:835 -msgid "Export as CSG..." +#: objects/ui_MainWindow.h:940 +#, fuzzy +msgid "Export as &CSG..." msgstr "Exporter comme CSG..." -#: objects/ui_MainWindow.h:836 -msgid "Library info" +#: objects/ui_MainWindow.h:941 +#, fuzzy +msgid "&Library info" msgstr "Informations Bibliothèques" -#: objects/ui_MainWindow.h:837 -msgid "Show Library Folder..." +#: objects/ui_MainWindow.h:942 +#, fuzzy +msgid "Show &Library Folder..." msgstr "Afficher le dossier des bibliothèques" -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:943 msgid "Reset View" msgstr "Réinitialiser la vue" -#: objects/ui_MainWindow.h:839 -msgid "Font List" +#: objects/ui_MainWindow.h:944 +#, fuzzy +msgid "&Font List" msgstr "Liste des polices" -#: objects/ui_MainWindow.h:840 -msgid "Export as SVG..." +#: objects/ui_MainWindow.h:945 +#, fuzzy +msgid "Export as S&VG..." msgstr "Exporter comme SVG..." -#: objects/ui_MainWindow.h:841 -msgid "Export as AMF..." +#: objects/ui_MainWindow.h:946 +#, fuzzy +msgid "Export as &AMF..." msgstr "Exporter comme AMF..." -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:947 +msgid "Zoom In" +msgstr "Zoom Avant" + +#: objects/ui_MainWindow.h:948 msgid "Ctrl+]" msgstr "Ctrl+]" -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:949 +msgid "Zoom Out" +msgstr "Zoom Arrière" + +#: objects/ui_MainWindow.h:950 msgid "Ctrl+[" msgstr "Ctrl+[" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:951 msgid "View All" msgstr "&Voir Tout" -#: objects/ui_MainWindow.h:847 -msgid "Convert Tabs to Spaces" +#: objects/ui_MainWindow.h:952 +#, fuzzy +msgid "Conv&ert Tabs to Spaces" msgstr "Convertir les tabulations par des espaces" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:953 msgid "Hide toolbars" msgstr "Cacher les boîtes à outils" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:954 +msgid "U&nindent" +msgstr "Dési&ndenter" + +#: objects/ui_MainWindow.h:955 +msgid "Ctrl+Shift+I" +msgstr "Ctrl+Shift+I" + +#: objects/ui_MainWindow.h:956 +#, fuzzy +msgid "&Cheat Sheet" +msgstr "Aide-Mémoire" + +#: objects/ui_MainWindow.h:957 +msgid "Message" +msgstr "Message" + +#: objects/ui_MainWindow.h:960 msgid "Time:" msgstr "Temps:" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:961 msgid "FPS:" msgstr "FPS:" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:962 msgid "Steps:" msgstr "Étapes:" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:963 msgid "Dump Pictures" msgstr "Vider les photos" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:964 msgid "&File" msgstr "&Fichier" -#: objects/ui_MainWindow.h:854 -msgid "Recent Files" +#: objects/ui_MainWindow.h:965 +#, fuzzy +msgid "Recen&t Files" msgstr "Fichiers Récents" -#: objects/ui_MainWindow.h:856 -msgid "Export" +#: objects/ui_MainWindow.h:966 +#, fuzzy +msgid "&Examples" +msgstr "Exemples" + +#: objects/ui_MainWindow.h:967 +#, fuzzy +msgid "E&xport" msgstr "Exporter" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:968 msgid "&Edit" msgstr "&Édition" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:969 msgid "&Design" msgstr "Conception" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:970 msgid "&View" msgstr "&Vue" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:971 msgid "&Help" msgstr "&Aide" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:974 msgid "Find" msgstr "Rechercher" -#: objects/ui_MainWindow.h:864 objects/ui_MainWindow.h:871 +#: objects/ui_MainWindow.h:975 objects/ui_MainWindow.h:982 msgid "Replace" msgstr "Remplacer" -#: objects/ui_MainWindow.h:866 +#: objects/ui_MainWindow.h:977 msgid "Search string" msgstr "Rechercher une chaîne de caractères" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:978 msgid "<" msgstr "<" -#: objects/ui_MainWindow.h:868 +#: objects/ui_MainWindow.h:979 msgid ">" msgstr ">" -#: objects/ui_MainWindow.h:869 +#: objects/ui_MainWindow.h:980 msgid "Done" msgstr "Terminer" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:981 msgid "Replacement string" msgstr "Remplacer une chaîne de caractères" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:983 msgid "All" msgstr "Tout" @@ -706,162 +780,331 @@ msgstr "Activer OpenCSG" msgid "Show this message again" msgstr "Affiche ce message à nouveau" -#: objects/ui_Preferences.h:609 +#: objects/ui_OpenCSGWarningDialog.h:94 +msgid "Close" +msgstr "Fermer" + +#: objects/ui_Preferences.h:1061 +msgid "Preferences" +msgstr "Préférences" + +#: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "&Vue 3D" -#: objects/ui_Preferences.h:610 src/UIUtils.cc:85 +#: objects/ui_Preferences.h:1063 src/UIUtils.cc:86 msgid "Advanced" msgstr "Avancé" -#: objects/ui_Preferences.h:611 src/mainwin.cc:2315 +#: objects/ui_Preferences.h:1064 src/mainwin.cc:2418 msgid "Editor" msgstr "Éditeur" -#: objects/ui_Preferences.h:612 +#: objects/ui_Preferences.h:1065 msgid "Update" msgstr "Mettre à jour" -#: objects/ui_Preferences.h:613 objects/ui_Preferences.h:633 +#: objects/ui_Preferences.h:1066 objects/ui_Preferences.h:1147 msgid "Features" msgstr "Fonctionnalités" -#: objects/ui_Preferences.h:615 +#: objects/ui_Preferences.h:1068 msgid "Enable/Disable experimental features" msgstr "Activer/Désactiver les fonctionnalités expérimentales" -#: objects/ui_Preferences.h:617 +#: objects/ui_Preferences.h:1070 msgid "Color scheme:" msgstr "Palette de couleurs:" -#: objects/ui_Preferences.h:618 +#: objects/ui_Preferences.h:1071 +msgid "Show Warnings and Errors in 3D View" +msgstr "Afficher les Avertissements et les Erreurs dans la fenêtre de rendu" + +#: objects/ui_Preferences.h:1072 msgid "Editor Type" msgstr "Type d'éditeur" -#: objects/ui_Preferences.h:621 +#: objects/ui_Preferences.h:1075 msgid "Simple Editor" msgstr "Éditeur Simple" -#: objects/ui_Preferences.h:622 +#: objects/ui_Preferences.h:1076 msgid "QScintilla Editor" msgstr "Éditeur QScintilla" -#: objects/ui_Preferences.h:624 +#: objects/ui_Preferences.h:1078 msgid "(requires restart)" msgstr "(nécessite un redémarrage)" -#: objects/ui_Preferences.h:625 +#: objects/ui_Preferences.h:1079 msgid "Font" msgstr "Police" -#: objects/ui_Preferences.h:626 +#: objects/ui_Preferences.h:1080 msgid "Color syntax highlighting" msgstr "Colorer la coloration syntaxique" -#: objects/ui_Preferences.h:627 -msgid "Use Ctrl/Cmd-Mouse-wheel to zoom text" -msgstr "Utiliser Ctrl/Cmd-Roulette-Souris pour agrandir le texte" +#: objects/ui_Preferences.h:1081 +msgid "Ctrl/Cmd-Mouse-wheel zooms text" +msgstr "Ctrl/Cmd-Roulette-Souris agrandit le texte" -#: objects/ui_Preferences.h:629 +#: objects/ui_Preferences.h:1082 +msgid "Indentation" +msgstr "Indentation" + +#: objects/ui_Preferences.h:1083 +msgid "Auto Indent" +msgstr "Indentation Auto" + +#: objects/ui_Preferences.h:1084 +msgid "Indent using" +msgstr "Indenter en utilisant" + +#: objects/ui_Preferences.h:1087 src/settings.cc:135 +msgid "Spaces" +msgstr "Espaces" + +#: objects/ui_Preferences.h:1088 src/settings.cc:135 +msgid "Tabs" +msgstr "Tabulations" + +#: objects/ui_Preferences.h:1090 +msgid "Indentation width" +msgstr "Largeur d'Indentation" + +#: objects/ui_Preferences.h:1091 +msgid "Tab width" +msgstr "Largeur des tabulations" + +#: objects/ui_Preferences.h:1092 +msgid "Tab key function" +msgstr "Fonction de la touche Tab" + +#: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 +#: src/settings.cc:136 +msgid "Indent" +msgstr "Indenter" + +#: objects/ui_Preferences.h:1096 src/settings.cc:136 +msgid "Insert Tab" +msgstr "Insérer une Tabulation" + +#: objects/ui_Preferences.h:1098 +msgid "Show whitespace" +msgstr "Afficher les espaces blancs" + +#: objects/ui_Preferences.h:1101 src/settings.cc:132 +msgid "Never" +msgstr "Jamais" + +#: objects/ui_Preferences.h:1102 src/settings.cc:132 +msgid "Always" +msgstr "Toujours" + +#: objects/ui_Preferences.h:1103 +msgid "Only after indentation" +msgstr "Seulement après indentation" + +#: objects/ui_Preferences.h:1105 +msgid "Size" +msgstr "Taille" + +#: objects/ui_Preferences.h:1106 +msgid "Display" +msgstr "Afficher" + +#: objects/ui_Preferences.h:1107 +msgid "Enable brace matching" +msgstr "Activer la correspondance d'accolades" + +#: objects/ui_Preferences.h:1108 +msgid "Highlight current line" +msgstr "Surligner la ligne courante" + +#: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 +msgid "Line wrap" +msgstr "Retour à la ligne" + +#: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 +#: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 +#: src/settings.cc:131 +msgid "None" +msgstr "Aucun" + +#: objects/ui_Preferences.h:1113 src/settings.cc:127 +msgid "Wrap at character boundaries" +msgstr "Enveloppez aux limites des caractères" + +#: objects/ui_Preferences.h:1114 src/settings.cc:127 +msgid "Wrap at word boundaries" +msgstr "Enveloppez aux limites des mots" + +#: objects/ui_Preferences.h:1116 +msgid "Line wrap indentation" +msgstr "Indentation des retours à la ligne" + +#: objects/ui_Preferences.h:1117 +msgid "Line wrap visualization" +msgstr "Visualisation des retours à la ligne" + +#: objects/ui_Preferences.h:1118 +msgid "Style" +msgstr "Style" + +#: objects/ui_Preferences.h:1121 src/settings.cc:128 +msgid "Fixed" +msgstr "Fixé" + +#: objects/ui_Preferences.h:1122 src/settings.cc:128 +msgid "Same" +msgstr "Identique" + +#: objects/ui_Preferences.h:1123 src/settings.cc:128 +msgid "Indented" +msgstr "Indenté" + +#: objects/ui_Preferences.h:1126 +msgid "Start" +msgstr "Début" + +#: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Text" +msgstr "Texte" + +#: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Border" +msgstr "Bordure" + +#: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Margin" +msgstr "Marge" + +#: objects/ui_Preferences.h:1134 +msgid "End" +msgstr "Fin" + +#: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" msgstr "Vérifier les mises à jour automatiquement" -#: objects/ui_Preferences.h:630 +#: objects/ui_Preferences.h:1144 msgid "Include development snapshots" msgstr "Inclure les versions de développement" -#: objects/ui_Preferences.h:631 +#: objects/ui_Preferences.h:1145 msgid "Check Now" msgstr "Vérifier Maintenant" -#: objects/ui_Preferences.h:632 +#: objects/ui_Preferences.h:1146 msgid "Last checked: " msgstr "Dernière vérification:" -#: objects/ui_Preferences.h:634 +#: objects/ui_Preferences.h:1148 msgid "OpenCSG" msgstr "OpenCSG" -#: objects/ui_Preferences.h:635 +#: objects/ui_Preferences.h:1149 msgid "Show capability warning" msgstr "Afficher les avertissements de capacité" -#: objects/ui_Preferences.h:636 +#: objects/ui_Preferences.h:1150 msgid "Enable for OpenGL 1.x" msgstr "Activer pour OpenGL 1.x" -#: objects/ui_Preferences.h:637 +#: objects/ui_Preferences.h:1151 msgid "Turn off rendering at " msgstr "Désactiver le rendu à" -#: objects/ui_Preferences.h:638 +#: objects/ui_Preferences.h:1152 msgid "elements" msgstr "éléments" -#: objects/ui_Preferences.h:639 +#: objects/ui_Preferences.h:1153 msgid "Force Goldfeather" msgstr "Forcer Goldfeather" -#: objects/ui_Preferences.h:640 +#: objects/ui_Preferences.h:1154 msgid "CGAL Cache size" msgstr "Taille du Cache de CGAL" -#: objects/ui_Preferences.h:641 objects/ui_Preferences.h:643 +#: objects/ui_Preferences.h:1155 objects/ui_Preferences.h:1157 msgid "bytes" msgstr "octets" -#: objects/ui_Preferences.h:642 +#: objects/ui_Preferences.h:1156 msgid "PolySet Cache size" msgstr "Taille du Cache PolySet" -#: objects/ui_Preferences.h:644 +#: objects/ui_Preferences.h:1158 msgid "Allow to open multiple documents" msgstr "Autoriser l'ouverture de plusieurs documents" -#: objects/ui_Preferences.h:645 +#: objects/ui_Preferences.h:1159 msgid "Enable docking of Editor and Console in different places" msgstr "Activer l'ancrage de l'Éditeur et de la Console à différents endroits" -#: objects/ui_Preferences.h:646 +#: objects/ui_Preferences.h:1160 msgid "Enable undocking of Editor and Console to separate windows" msgstr "" "Activer désancrage de l'Éditeur et de la Console dans des fenêtres séparés" -#: objects/ui_Preferences.h:647 +#: objects/ui_Preferences.h:1161 msgid "Show Welcome Screen" msgstr "Affiche l'écran d'accueil" -#: objects/ui_Preferences.h:648 +#: objects/ui_Preferences.h:1162 msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "" "Activer la localisation de l'interface utilisateur (Nécessite un redémarrage " "d'OpenSCAD)" -#: objects/ui_Preferences.h:649 -msgid "toolBar" -msgstr "boîte à outils" - #: objects/ui_ProgressWidget.h:72 -msgid "Form" -msgstr "Formulaire" - -#: objects/ui_ProgressWidget.h:73 msgid "%v / %m" msgstr "%v / %m" -#: src/mainwin.cc:768 src/mainwin.cc:1300 +#: src/Camera.cc:126 +#, c-format +msgid "" +"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " +"distance = %.2f" +msgstr "" +"Fenêtre de rendu: translation = [ %.2f %.2f %.2f ], rotation = [ %.2f %.2f " +"%.2f ], distance = %.2f" + +#: src/mainwin.cc:778 src/mainwin.cc:1354 msgid "Untitled.scad" msgstr "Untitled.scad" -#: src/mainwin.cc:1299 +#: src/mainwin.cc:971 +msgid "Compile error." +msgstr "Erreur de Compilation." + +#: src/mainwin.cc:974 +msgid "Error while compiling '%1'." +msgstr "Erreur lors de la compilation de '%1'." + +#: src/mainwin.cc:978 +msgid "Compilation generated %1 warning." +msgid_plural "Compilation generated %1 warnings." +msgstr[0] "La compilation a généré %1 avertissement" +msgstr[1] "La compilation a généré %1 avertissements" + +#: src/mainwin.cc:988 +msgid " For details see console window." +msgstr " Pour détails voir Fenêtre de la Console." + +#: src/mainwin.cc:1353 msgid "Save File" msgstr "Enregistrer le Fichier" -#: src/mainwin.cc:1301 +#: src/mainwin.cc:1355 msgid "OpenSCAD Designs (*.scad)" msgstr "OpenSCAD Designs (*.scad)" -#: src/mainwin.cc:1311 +#: src/mainwin.cc:1365 msgid "" "%1 already exists.\n" "Do you want to replace it?" @@ -869,11 +1112,11 @@ msgstr "" "%1 existe déjà.\n" "Voulez-vous le remplacer?" -#: src/mainwin.cc:1630 +#: src/mainwin.cc:1684 msgid "Application" msgstr "Application" -#: src/mainwin.cc:1631 +#: src/mainwin.cc:1685 msgid "" "The document has been modified.\n" "Do you really want to reload the file?" @@ -881,65 +1124,63 @@ msgstr "" "Ce document a été modifié.\n" "Voulez-vous vraiment recharger le fichier?" -#: src/mainwin.cc:1942 src/mainwin.cc:1999 +#: src/mainwin.cc:2038 src/mainwin.cc:2094 msgid "Export %1 File" msgstr "Exporter %1 Fichier" -#: src/mainwin.cc:1943 src/mainwin.cc:2003 +#: src/mainwin.cc:2039 src/mainwin.cc:2098 msgid "%1 Files (*%2)" msgstr "%1 Fichiers (*%2)" -#: src/mainwin.cc:1944 +#: src/mainwin.cc:2040 msgid "Untitled" msgstr "Sans Titre" -#: src/mainwin.cc:2001 +#: src/mainwin.cc:2096 msgid "Untitled%1" msgstr "Sans Titre%1" -#: src/mainwin.cc:2052 +#: src/mainwin.cc:2147 msgid "Export CSG File" msgstr "Exporter un fichier CSG" -#: src/mainwin.cc:2053 +#: src/mainwin.cc:2148 msgid "Untitled.csg" msgstr "SansTitre.csg" -#: src/mainwin.cc:2054 +#: src/mainwin.cc:2149 msgid "CSG Files (*.csg)" msgstr "Fichiers CSG (*.csg)" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "Export Image" msgstr "Exporter une Image" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "PNG Files (*.png)" msgstr "Fichiers PNG (*.png)" -#: src/mainwin.cc:2320 +#: src/mainwin.cc:2423 msgid "Console" msgstr "Console" -#: src/mainwin.cc:2447 +#: src/mainwin.cc:2560 msgid "The document has been modified." msgstr "Ce document a été modifié" -#: src/mainwin.cc:2448 +#: src/mainwin.cc:2561 msgid "Do you want to save your changes?" msgstr "Voulez-vous enregistrer vos changements?" -#: src/QGLView.cc:114 +#: src/openscad.cc:604 msgid "" -"\n" -"Using QGLWidget\n" -"\n" +"Fontconfig needs to update its font cache.\n" +"This can take up to a couple of minutes." msgstr "" -"\n" -"Utilise QGLWidget\n" -"\n" +"Fontconfig a besoin de mettre à jour son cache de polices.\n" +"Celà peut prendre quelques minutes." -#: src/QGLView.cc:131 +#: src/QGLView.cc:129 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" @@ -947,7 +1188,7 @@ msgstr "" "Avertissement: Vous pourriez avoir des erreurs de rendu OpenCSG\n" "\n" -#: src/QGLView.cc:134 +#: src/QGLView.cc:132 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" @@ -957,7 +1198,7 @@ msgstr "" "désactivé.\n" "\n" -#: src/QGLView.cc:137 +#: src/QGLView.cc:135 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" @@ -967,7 +1208,7 @@ msgstr "" "OpenGL 2.0 ou ultérieur.\n" "Voici les informations de votre moteur de rendu:\n" -#: src/QGLView.cc:141 +#: src/QGLView.cc:139 #, c-format msgid "" "GLEW version %s\n" @@ -978,27 +1219,43 @@ msgstr "" "%s (%s)\n" "Version OpenGL %s\n" -#: src/QGLView.cc:171 -#, c-format -msgid "" -"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " -"distance = %.2f" -msgstr "" -"Fenêtre de rendu: translation = [ %.2f %.2f %.2f ], rotation = [ %.2f %.2f " -"%.2f ], distance = %.2f" +#: src/settings.cc:132 +msgid "After indentation" +msgstr "Après indentation" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Basics" msgstr "Bases" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Shapes" msgstr "Formes" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Extrusion" msgstr "Extrusion" +#~ msgid "Top" +#~ msgstr "Dessus" + +#~ msgid "Back" +#~ msgstr "Arrière" + +#~ msgid "toolBar" +#~ msgstr "boîte à outils" + +#~ msgid "Form" +#~ msgstr "Formulaire" + +#~ msgid "" +#~ "\n" +#~ "Using QGLWidget\n" +#~ "\n" +#~ msgstr "" +#~ "\n" +#~ "Utilise QGLWidget\n" +#~ "\n" + #~ msgid "Paste font selector to Editor Window" #~ msgstr "Coller le sélecteur de polices dans l'éditeur de fenêtres" diff --git a/locale/openscad.pot b/locale/openscad.pot index b3587cc0..fc958879 100644 --- a/locale/openscad.pot +++ b/locale/openscad.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: OpenSCAD 2014.12.22\n" +"Project-Id-Version: OpenSCAD 2015.02.01\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-22 23:37+0100\n" +"POT-Creation-Date: 2015-02-01 19:40+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,74 +16,13 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#: objects/ui_AboutDialog.h:51 src/AboutDialog.h:15 +#: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" msgstr "" -#: objects/ui_FontListDialog.h:102 -msgid "OpenSCAD Font List" -msgstr "" - -#: objects/ui_FontListDialog.h:103 objects/ui_LibraryInfoDialog.h:77 -msgid "&OK" -msgstr "" - -#: objects/ui_FontListDialog.h:104 -msgid "Copy to Clipboard" -msgstr "" - -#: objects/ui_FontListDialog.h:105 -msgid "Filter:" -msgstr "" - -#: objects/ui_FontListDialog.h:106 -msgid "" -"

This list shows the fonts currently registered with " -"OpenSCAD.

Example:

  text(t = "
-""OpenSCAD", font = "DejaVu Sans");
  text(t = "OpenSCAD", font = "
-""Liberation Sans:style=Italic");
" -msgstr "" - -#: objects/ui_launchingscreen.h:276 -msgid "Welcome to OpenSCAD" -msgstr "" - -#: objects/ui_launchingscreen.h:277 -msgid "New" -msgstr "" - -#: objects/ui_launchingscreen.h:278 -msgid "Open" -msgstr "" - -#: objects/ui_launchingscreen.h:279 -msgid "Help" -msgstr "" - -#: objects/ui_launchingscreen.h:280 -msgid "Recents" -msgstr "" - -#: objects/ui_launchingscreen.h:281 -msgid "Open Recent" -msgstr "" - -#: objects/ui_launchingscreen.h:282 objects/ui_launchingscreen.h:284 -#: objects/ui_MainWindow.h:855 -msgid "Examples" -msgstr "" - -#: objects/ui_launchingscreen.h:285 -msgid "Open Example" -msgstr "" - -#: objects/ui_launchingscreen.h:287 +#: objects/ui_AboutDialog.h:105 objects/ui_launchingscreen.h:305 msgid "" "\n" "

This list shows the fonts currently registered with " +"OpenSCAD.

Example:

  text(t = "
+""OpenSCAD", font = "DejaVu Sans");
  text(t = "OpenSCAD", font = "
+""Liberation Sans:style=Italic");
" +msgstr "" + #: objects/ui_launchingscreen.h:294 +msgid "Welcome to OpenSCAD" +msgstr "" + +#: objects/ui_launchingscreen.h:295 +msgid "New" +msgstr "" + +#: objects/ui_launchingscreen.h:296 +msgid "Open" +msgstr "" + +#: objects/ui_launchingscreen.h:297 +msgid "Help" +msgstr "" + +#: objects/ui_launchingscreen.h:298 +msgid "Recents" +msgstr "" + +#: objects/ui_launchingscreen.h:299 +msgid "Open Recent" +msgstr "" + +#: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 +msgid "Examples" +msgstr "" + +#: objects/ui_launchingscreen.h:303 +msgid "Open Example" +msgstr "" + +#: objects/ui_launchingscreen.h:312 msgid "Don't show again" msgstr "" +#: objects/ui_launchingscreen.h:313 +msgid "Version" +msgstr "" + #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" msgstr "" @@ -109,543 +117,567 @@ msgstr "" msgid "OpenSCAD Detailed Library and Build Information" msgstr "" -#: objects/ui_MainWindow.h:731 +#: objects/ui_MainWindow.h:837 msgid "&New" msgstr "" -#: objects/ui_MainWindow.h:732 +#: objects/ui_MainWindow.h:838 msgid "Ctrl+N" msgstr "" -#: objects/ui_MainWindow.h:733 +#: objects/ui_MainWindow.h:839 msgid "&Open..." msgstr "" -#: objects/ui_MainWindow.h:734 +#: objects/ui_MainWindow.h:840 msgid "Ctrl+O" msgstr "" -#: objects/ui_MainWindow.h:735 +#: objects/ui_MainWindow.h:841 msgid "&Save" msgstr "" -#: objects/ui_MainWindow.h:736 +#: objects/ui_MainWindow.h:842 msgid "Ctrl+S" msgstr "" -#: objects/ui_MainWindow.h:737 +#: objects/ui_MainWindow.h:843 msgid "Save &As..." msgstr "" -#: objects/ui_MainWindow.h:738 +#: objects/ui_MainWindow.h:844 msgid "Ctrl+Shift+S" msgstr "" -#: objects/ui_MainWindow.h:739 +#: objects/ui_MainWindow.h:845 msgid "&Reload" msgstr "" -#: objects/ui_MainWindow.h:740 +#: objects/ui_MainWindow.h:846 msgid "Ctrl+R" msgstr "" -#: objects/ui_MainWindow.h:741 +#: objects/ui_MainWindow.h:847 msgid "&Quit" msgstr "" -#: objects/ui_MainWindow.h:742 +#: objects/ui_MainWindow.h:848 msgid "Ctrl+Q" msgstr "" -#: objects/ui_MainWindow.h:743 +#: objects/ui_MainWindow.h:849 msgid "&Undo" msgstr "" -#: objects/ui_MainWindow.h:744 +#: objects/ui_MainWindow.h:850 msgid "Ctrl+Z" msgstr "" -#: objects/ui_MainWindow.h:745 +#: objects/ui_MainWindow.h:851 msgid "&Redo" msgstr "" -#: objects/ui_MainWindow.h:746 +#: objects/ui_MainWindow.h:852 msgid "Ctrl+Shift+Z" msgstr "" -#: objects/ui_MainWindow.h:747 +#: objects/ui_MainWindow.h:853 msgid "Cu&t" msgstr "" -#: objects/ui_MainWindow.h:748 +#: objects/ui_MainWindow.h:854 msgid "Ctrl+X" msgstr "" -#: objects/ui_MainWindow.h:749 +#: objects/ui_MainWindow.h:855 msgid "&Copy" msgstr "" -#: objects/ui_MainWindow.h:750 +#: objects/ui_MainWindow.h:856 msgid "Ctrl+C" msgstr "" -#: objects/ui_MainWindow.h:751 +#: objects/ui_MainWindow.h:857 msgid "&Paste" msgstr "" -#: objects/ui_MainWindow.h:752 +#: objects/ui_MainWindow.h:858 msgid "Ctrl+V" msgstr "" -#: objects/ui_MainWindow.h:753 +#: objects/ui_MainWindow.h:859 msgid "&Indent" msgstr "" -#: objects/ui_MainWindow.h:754 +#: objects/ui_MainWindow.h:860 msgid "Ctrl+I" msgstr "" -#: objects/ui_MainWindow.h:755 -msgid "U&nindent" -msgstr "" - -#: objects/ui_MainWindow.h:756 -msgid "Ctrl+Shift+I" -msgstr "" - -#: objects/ui_MainWindow.h:757 +#: objects/ui_MainWindow.h:861 msgid "C&omment" msgstr "" -#: objects/ui_MainWindow.h:758 +#: objects/ui_MainWindow.h:862 msgid "Ctrl+D" msgstr "" -#: objects/ui_MainWindow.h:759 +#: objects/ui_MainWindow.h:863 msgid "Unco&mment" msgstr "" -#: objects/ui_MainWindow.h:760 +#: objects/ui_MainWindow.h:864 msgid "Ctrl+Shift+D" msgstr "" -#: objects/ui_MainWindow.h:761 -msgid "Paste viewport translation" -msgstr "" - -#: objects/ui_MainWindow.h:762 -msgid "Ctrl+T" -msgstr "" - -#: objects/ui_MainWindow.h:763 -msgid "Paste viewport rotation" -msgstr "" - -#: objects/ui_MainWindow.h:764 objects/ui_MainWindow.h:842 -msgid "Zoom In" -msgstr "" - -#: objects/ui_MainWindow.h:765 -msgid "Ctrl++" -msgstr "" - -#: objects/ui_MainWindow.h:766 objects/ui_MainWindow.h:844 -msgid "Zoom Out" -msgstr "" - -#: objects/ui_MainWindow.h:767 -msgid "Ctrl+-" -msgstr "" - -#: objects/ui_MainWindow.h:768 -msgid "Hide editor" -msgstr "" - -#: objects/ui_MainWindow.h:769 -msgid "&Reload and Preview" -msgstr "" - -#: objects/ui_MainWindow.h:770 -msgid "F4" -msgstr "" - -#: objects/ui_MainWindow.h:771 -msgid "&Preview" -msgstr "" - -#: objects/ui_MainWindow.h:772 -msgid "F5" -msgstr "" - -#: objects/ui_MainWindow.h:773 -msgid "&Render" -msgstr "" - -#: objects/ui_MainWindow.h:774 -msgid "F6" -msgstr "" - -#: objects/ui_MainWindow.h:775 -msgid "Check Validity" -msgstr "" - -#: objects/ui_MainWindow.h:776 -msgid "Display &AST..." -msgstr "" - -#: objects/ui_MainWindow.h:777 -msgid "Display CSG &Tree..." -msgstr "" - -#: objects/ui_MainWindow.h:778 -msgid "Display CSG &Products..." -msgstr "" - -#: objects/ui_MainWindow.h:779 -msgid "Export as &STL..." -msgstr "" - -#: objects/ui_MainWindow.h:780 -msgid "Export as &OFF..." -msgstr "" - -#: objects/ui_MainWindow.h:781 -msgid "Preview" -msgstr "" - -#: objects/ui_MainWindow.h:782 -msgid "F9" -msgstr "" - -#: objects/ui_MainWindow.h:783 -msgid "Surfaces" -msgstr "" - -#: objects/ui_MainWindow.h:784 -msgid "F10" -msgstr "" - -#: objects/ui_MainWindow.h:785 -msgid "Wireframe" -msgstr "" - -#: objects/ui_MainWindow.h:786 -msgid "F11" -msgstr "" - -#: objects/ui_MainWindow.h:787 -msgid "Thrown Together" -msgstr "" - -#: objects/ui_MainWindow.h:788 -msgid "F12" -msgstr "" - -#: objects/ui_MainWindow.h:789 -msgid "Show Edges" -msgstr "" - -#: objects/ui_MainWindow.h:790 -msgid "Ctrl+1" -msgstr "" - -#: objects/ui_MainWindow.h:791 -msgid "Show Axes" -msgstr "" - -#: objects/ui_MainWindow.h:792 -msgid "Ctrl+2" -msgstr "" - -#: objects/ui_MainWindow.h:793 -msgid "Show Crosshairs" -msgstr "" - -#: objects/ui_MainWindow.h:794 -msgid "Ctrl+3" -msgstr "" - -#: objects/ui_MainWindow.h:795 -msgid "Animate" -msgstr "" - -#: objects/ui_MainWindow.h:796 -msgid "Top" -msgstr "" - -#: objects/ui_MainWindow.h:797 -msgid "Ctrl+4" -msgstr "" - -#: objects/ui_MainWindow.h:798 -msgid "Bottom" -msgstr "" - -#: objects/ui_MainWindow.h:799 -msgid "Ctrl+5" -msgstr "" - -#: objects/ui_MainWindow.h:800 -msgid "Left" -msgstr "" - -#: objects/ui_MainWindow.h:801 -msgid "Ctrl+6" -msgstr "" - -#: objects/ui_MainWindow.h:802 -msgid "Right" -msgstr "" - -#: objects/ui_MainWindow.h:803 -msgid "Ctrl+7" -msgstr "" - -#: objects/ui_MainWindow.h:804 -msgid "Front" -msgstr "" - -#: objects/ui_MainWindow.h:805 -msgid "Ctrl+8" -msgstr "" - -#: objects/ui_MainWindow.h:806 -msgid "Back" -msgstr "" - -#: objects/ui_MainWindow.h:807 -msgid "Ctrl+9" -msgstr "" - -#: objects/ui_MainWindow.h:808 -msgid "Diagonal" -msgstr "" - -#: objects/ui_MainWindow.h:809 -msgid "Ctrl+0" -msgstr "" - -#: objects/ui_MainWindow.h:810 -msgid "Center" -msgstr "" - -#: objects/ui_MainWindow.h:811 -msgid "Perspective" -msgstr "" - -#: objects/ui_MainWindow.h:812 -msgid "Orthogonal" -msgstr "" - -#: objects/ui_MainWindow.h:813 -msgid "Hide console" -msgstr "" - -#: objects/ui_MainWindow.h:814 -msgid "About" -msgstr "" - -#: objects/ui_MainWindow.h:815 -msgid "Documentation" -msgstr "" - -#: objects/ui_MainWindow.h:816 -msgid "Clear Recent" -msgstr "" - -#: objects/ui_MainWindow.h:817 -msgid "Export as DXF..." -msgstr "" - -#: objects/ui_MainWindow.h:818 objects/ui_OpenCSGWarningDialog.h:94 -msgid "Close" -msgstr "" - -#: objects/ui_MainWindow.h:819 -msgid "Ctrl+W" -msgstr "" - -#: objects/ui_MainWindow.h:820 objects/ui_Preferences.h:608 -msgid "Preferences" -msgstr "" - -#: objects/ui_MainWindow.h:821 -msgid "Find..." -msgstr "" - -#: objects/ui_MainWindow.h:822 -msgid "Ctrl+F" -msgstr "" - -#: objects/ui_MainWindow.h:823 -msgid "Find and Replace..." -msgstr "" - -#: objects/ui_MainWindow.h:824 -msgid "Ctrl+Alt+F" -msgstr "" - -#: objects/ui_MainWindow.h:825 -msgid "Find Next" -msgstr "" - -#: objects/ui_MainWindow.h:826 -msgid "Ctrl+G" -msgstr "" - -#: objects/ui_MainWindow.h:827 -msgid "Find Previous" -msgstr "" - -#: objects/ui_MainWindow.h:828 -msgid "Ctrl+Shift+G" -msgstr "" - -#: objects/ui_MainWindow.h:829 -msgid "Use Selection for Find" -msgstr "" - -#: objects/ui_MainWindow.h:830 -msgid "Ctrl+E" -msgstr "" - -#: objects/ui_MainWindow.h:831 -msgid "Flush Caches" -msgstr "" - -#: objects/ui_MainWindow.h:832 -msgid "OpenSCAD Homepage" -msgstr "" - -#: objects/ui_MainWindow.h:833 -msgid "Automatic Reload and Preview" -msgstr "" - -#: objects/ui_MainWindow.h:834 -msgid "Export as Image..." -msgstr "" - -#: objects/ui_MainWindow.h:835 -msgid "Export as CSG..." -msgstr "" - -#: objects/ui_MainWindow.h:836 -msgid "Library info" -msgstr "" - -#: objects/ui_MainWindow.h:837 -msgid "Show Library Folder..." -msgstr "" - -#: objects/ui_MainWindow.h:838 -msgid "Reset View" -msgstr "" - -#: objects/ui_MainWindow.h:839 -msgid "Font List" -msgstr "" - -#: objects/ui_MainWindow.h:840 -msgid "Export as SVG..." -msgstr "" - -#: objects/ui_MainWindow.h:841 -msgid "Export as AMF..." -msgstr "" - -#: objects/ui_MainWindow.h:843 -msgid "Ctrl+]" -msgstr "" - -#: objects/ui_MainWindow.h:845 -msgid "Ctrl+[" -msgstr "" - -#: objects/ui_MainWindow.h:846 -msgid "View All" -msgstr "" - -#: objects/ui_MainWindow.h:847 -msgid "Convert Tabs to Spaces" -msgstr "" - -#: objects/ui_MainWindow.h:848 -msgid "Hide toolbars" -msgstr "" - -#: objects/ui_MainWindow.h:849 -msgid "Time:" -msgstr "" - -#: objects/ui_MainWindow.h:850 -msgid "FPS:" -msgstr "" - -#: objects/ui_MainWindow.h:851 -msgid "Steps:" -msgstr "" - -#: objects/ui_MainWindow.h:852 -msgid "Dump Pictures" -msgstr "" - -#: objects/ui_MainWindow.h:853 -msgid "&File" -msgstr "" - -#: objects/ui_MainWindow.h:854 -msgid "Recent Files" -msgstr "" - -#: objects/ui_MainWindow.h:856 -msgid "Export" -msgstr "" - -#: objects/ui_MainWindow.h:857 -msgid "&Edit" -msgstr "" - -#: objects/ui_MainWindow.h:858 -msgid "&Design" -msgstr "" - -#: objects/ui_MainWindow.h:859 -msgid "&View" -msgstr "" - -#: objects/ui_MainWindow.h:860 -msgid "&Help" -msgstr "" - -#: objects/ui_MainWindow.h:863 -msgid "Find" -msgstr "" - -#: objects/ui_MainWindow.h:864 objects/ui_MainWindow.h:871 -msgid "Replace" +#: objects/ui_MainWindow.h:865 +msgid "P&aste viewport translation" msgstr "" #: objects/ui_MainWindow.h:866 -msgid "Search string" +msgid "Ctrl+T" msgstr "" #: objects/ui_MainWindow.h:867 -msgid "<" +msgid "Past&e viewport rotation" msgstr "" #: objects/ui_MainWindow.h:868 -msgid ">" +msgid "Increase Font &Size" msgstr "" #: objects/ui_MainWindow.h:869 -msgid "Done" +msgid "Ctrl++" msgstr "" #: objects/ui_MainWindow.h:870 -msgid "Replacement string" +msgid "Decrease Font Si&ze" +msgstr "" + +#: objects/ui_MainWindow.h:871 +msgid "Ctrl+-" msgstr "" #: objects/ui_MainWindow.h:872 +msgid "H&ide editor" +msgstr "" + +#: objects/ui_MainWindow.h:873 +msgid "&Reload and Preview" +msgstr "" + +#: objects/ui_MainWindow.h:874 +msgid "F4" +msgstr "" + +#: objects/ui_MainWindow.h:875 +msgid "&Preview" +msgstr "" + +#: objects/ui_MainWindow.h:876 +msgid "F5" +msgstr "" + +#: objects/ui_MainWindow.h:877 +msgid "R&ender" +msgstr "" + +#: objects/ui_MainWindow.h:878 +msgid "F6" +msgstr "" + +#: objects/ui_MainWindow.h:879 +msgid "&Check Validity" +msgstr "" + +#: objects/ui_MainWindow.h:880 +msgid "Display A&ST..." +msgstr "" + +#: objects/ui_MainWindow.h:881 +msgid "Display CSG &Tree..." +msgstr "" + +#: objects/ui_MainWindow.h:882 +msgid "Display CSG Pr&oducts..." +msgstr "" + +#: objects/ui_MainWindow.h:883 +msgid "Export as &STL..." +msgstr "" + +#: objects/ui_MainWindow.h:884 +msgid "Export as &OFF..." +msgstr "" + +#: objects/ui_MainWindow.h:885 +msgid "Preview" +msgstr "" + +#: objects/ui_MainWindow.h:886 +msgid "F9" +msgstr "" + +#: objects/ui_MainWindow.h:887 +msgid "Surfaces" +msgstr "" + +#: objects/ui_MainWindow.h:888 +msgid "F10" +msgstr "" + +#: objects/ui_MainWindow.h:889 +msgid "Wireframe" +msgstr "" + +#: objects/ui_MainWindow.h:890 +msgid "F11" +msgstr "" + +#: objects/ui_MainWindow.h:891 +msgid "Thrown Together" +msgstr "" + +#: objects/ui_MainWindow.h:892 +msgid "F12" +msgstr "" + +#: objects/ui_MainWindow.h:893 +msgid "Show Edges" +msgstr "" + +#: objects/ui_MainWindow.h:894 +msgid "Ctrl+1" +msgstr "" + +#: objects/ui_MainWindow.h:895 +msgid "Show Axes" +msgstr "" + +#: objects/ui_MainWindow.h:896 +msgid "Ctrl+2" +msgstr "" + +#: objects/ui_MainWindow.h:897 +msgid "Show Crosshairs" +msgstr "" + +#: objects/ui_MainWindow.h:898 +msgid "Ctrl+3" +msgstr "" + +#: objects/ui_MainWindow.h:899 +msgid "Show Scale Markers" +msgstr "" + +#: objects/ui_MainWindow.h:900 +msgid "Animate" +msgstr "" + +#: objects/ui_MainWindow.h:901 +msgid "&Top" +msgstr "" + +#: objects/ui_MainWindow.h:902 +msgid "Ctrl+4" +msgstr "" + +#: objects/ui_MainWindow.h:903 +msgid "&Bottom" +msgstr "" + +#: objects/ui_MainWindow.h:904 +msgid "Ctrl+5" +msgstr "" + +#: objects/ui_MainWindow.h:905 +msgid "&Left" +msgstr "" + +#: objects/ui_MainWindow.h:906 +msgid "Ctrl+6" +msgstr "" + +#: objects/ui_MainWindow.h:907 +msgid "&Right" +msgstr "" + +#: objects/ui_MainWindow.h:908 +msgid "Ctrl+7" +msgstr "" + +#: objects/ui_MainWindow.h:909 +msgid "&Front" +msgstr "" + +#: objects/ui_MainWindow.h:910 +msgid "Ctrl+8" +msgstr "" + +#: objects/ui_MainWindow.h:911 +msgid "Bac&k" +msgstr "" + +#: objects/ui_MainWindow.h:912 +msgid "Ctrl+9" +msgstr "" + +#: objects/ui_MainWindow.h:913 +msgid "&Diagonal" +msgstr "" + +#: objects/ui_MainWindow.h:914 +msgid "Ctrl+0" +msgstr "" + +#: objects/ui_MainWindow.h:915 +msgid "Ce&nter" +msgstr "" + +#: objects/ui_MainWindow.h:916 +msgid "&Perspective" +msgstr "" + +#: objects/ui_MainWindow.h:917 +msgid "&Orthogonal" +msgstr "" + +#: objects/ui_MainWindow.h:918 +msgid "H&ide console" +msgstr "" + +#: objects/ui_MainWindow.h:919 +msgid "&About" +msgstr "" + +#: objects/ui_MainWindow.h:920 +msgid "&Documentation" +msgstr "" + +#: objects/ui_MainWindow.h:921 +msgid "Clear Recent" +msgstr "" + +#: objects/ui_MainWindow.h:922 +msgid "Export as &DXF..." +msgstr "" + +#: objects/ui_MainWindow.h:923 +msgid "&Close" +msgstr "" + +#: objects/ui_MainWindow.h:924 +msgid "Ctrl+W" +msgstr "" + +#: objects/ui_MainWindow.h:925 +msgid "&Preferences" +msgstr "" + +#: objects/ui_MainWindow.h:926 +msgid "&Find..." +msgstr "" + +#: objects/ui_MainWindow.h:927 +msgid "Ctrl+F" +msgstr "" + +#: objects/ui_MainWindow.h:928 +msgid "Fin&d and Replace..." +msgstr "" + +#: objects/ui_MainWindow.h:929 +msgid "Ctrl+Alt+F" +msgstr "" + +#: objects/ui_MainWindow.h:930 +msgid "Find Ne&xt" +msgstr "" + +#: objects/ui_MainWindow.h:931 +msgid "Ctrl+G" +msgstr "" + +#: objects/ui_MainWindow.h:932 +msgid "Find Pre&vious" +msgstr "" + +#: objects/ui_MainWindow.h:933 +msgid "Ctrl+Shift+G" +msgstr "" + +#: objects/ui_MainWindow.h:934 +msgid "Use Se&lection for Find" +msgstr "" + +#: objects/ui_MainWindow.h:935 +msgid "Ctrl+E" +msgstr "" + +#: objects/ui_MainWindow.h:936 +msgid "&Flush Caches" +msgstr "" + +#: objects/ui_MainWindow.h:937 +msgid "&OpenSCAD Homepage" +msgstr "" + +#: objects/ui_MainWindow.h:938 +msgid "&Automatic Reload and Preview" +msgstr "" + +#: objects/ui_MainWindow.h:939 +msgid "Export as &Image..." +msgstr "" + +#: objects/ui_MainWindow.h:940 +msgid "Export as &CSG..." +msgstr "" + +#: objects/ui_MainWindow.h:941 +msgid "&Library info" +msgstr "" + +#: objects/ui_MainWindow.h:942 +msgid "Show &Library Folder..." +msgstr "" + +#: objects/ui_MainWindow.h:943 +msgid "Reset View" +msgstr "" + +#: objects/ui_MainWindow.h:944 +msgid "&Font List" +msgstr "" + +#: objects/ui_MainWindow.h:945 +msgid "Export as S&VG..." +msgstr "" + +#: objects/ui_MainWindow.h:946 +msgid "Export as &AMF..." +msgstr "" + +#: objects/ui_MainWindow.h:947 +msgid "Zoom In" +msgstr "" + +#: objects/ui_MainWindow.h:948 +msgid "Ctrl+]" +msgstr "" + +#: objects/ui_MainWindow.h:949 +msgid "Zoom Out" +msgstr "" + +#: objects/ui_MainWindow.h:950 +msgid "Ctrl+[" +msgstr "" + +#: objects/ui_MainWindow.h:951 +msgid "View All" +msgstr "" + +#: objects/ui_MainWindow.h:952 +msgid "Conv&ert Tabs to Spaces" +msgstr "" + +#: objects/ui_MainWindow.h:953 +msgid "Hide toolbars" +msgstr "" + +#: objects/ui_MainWindow.h:954 +msgid "U&nindent" +msgstr "" + +#: objects/ui_MainWindow.h:955 +msgid "Ctrl+Shift+I" +msgstr "" + +#: objects/ui_MainWindow.h:956 +msgid "&Cheat Sheet" +msgstr "" + +#: objects/ui_MainWindow.h:957 +msgid "Message" +msgstr "" + +#: objects/ui_MainWindow.h:960 +msgid "Time:" +msgstr "" + +#: objects/ui_MainWindow.h:961 +msgid "FPS:" +msgstr "" + +#: objects/ui_MainWindow.h:962 +msgid "Steps:" +msgstr "" + +#: objects/ui_MainWindow.h:963 +msgid "Dump Pictures" +msgstr "" + +#: objects/ui_MainWindow.h:964 +msgid "&File" +msgstr "" + +#: objects/ui_MainWindow.h:965 +msgid "Recen&t Files" +msgstr "" + +#: objects/ui_MainWindow.h:966 +msgid "&Examples" +msgstr "" + +#: objects/ui_MainWindow.h:967 +msgid "E&xport" +msgstr "" + +#: objects/ui_MainWindow.h:968 +msgid "&Edit" +msgstr "" + +#: objects/ui_MainWindow.h:969 +msgid "&Design" +msgstr "" + +#: objects/ui_MainWindow.h:970 +msgid "&View" +msgstr "" + +#: objects/ui_MainWindow.h:971 +msgid "&Help" +msgstr "" + +#: objects/ui_MainWindow.h:974 +msgid "Find" +msgstr "" + +#: objects/ui_MainWindow.h:975 objects/ui_MainWindow.h:982 +msgid "Replace" +msgstr "" + +#: objects/ui_MainWindow.h:977 +msgid "Search string" +msgstr "" + +#: objects/ui_MainWindow.h:978 +msgid "<" +msgstr "" + +#: objects/ui_MainWindow.h:979 +msgid ">" +msgstr "" + +#: objects/ui_MainWindow.h:980 +msgid "Done" +msgstr "" + +#: objects/ui_MainWindow.h:981 +msgid "Replacement string" +msgstr "" + +#: objects/ui_MainWindow.h:983 msgid "All" msgstr "" @@ -675,250 +707,416 @@ msgstr "" msgid "Show this message again" msgstr "" -#: objects/ui_Preferences.h:609 +#: objects/ui_OpenCSGWarningDialog.h:94 +msgid "Close" +msgstr "" + +#: objects/ui_Preferences.h:1061 +msgid "Preferences" +msgstr "" + +#: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "" -#: objects/ui_Preferences.h:610 src/UIUtils.cc:85 +#: objects/ui_Preferences.h:1063 src/UIUtils.cc:86 msgid "Advanced" msgstr "" -#: objects/ui_Preferences.h:611 src/mainwin.cc:2315 +#: objects/ui_Preferences.h:1064 src/mainwin.cc:2418 msgid "Editor" msgstr "" -#: objects/ui_Preferences.h:612 +#: objects/ui_Preferences.h:1065 msgid "Update" msgstr "" -#: objects/ui_Preferences.h:613 objects/ui_Preferences.h:633 +#: objects/ui_Preferences.h:1066 objects/ui_Preferences.h:1147 msgid "Features" msgstr "" -#: objects/ui_Preferences.h:615 +#: objects/ui_Preferences.h:1068 msgid "Enable/Disable experimental features" msgstr "" -#: objects/ui_Preferences.h:617 +#: objects/ui_Preferences.h:1070 msgid "Color scheme:" msgstr "" -#: objects/ui_Preferences.h:618 +#: objects/ui_Preferences.h:1071 +msgid "Show Warnings and Errors in 3D View" +msgstr "" + +#: objects/ui_Preferences.h:1072 msgid "Editor Type" msgstr "" -#: objects/ui_Preferences.h:621 +#: objects/ui_Preferences.h:1075 msgid "Simple Editor" msgstr "" -#: objects/ui_Preferences.h:622 +#: objects/ui_Preferences.h:1076 msgid "QScintilla Editor" msgstr "" -#: objects/ui_Preferences.h:624 +#: objects/ui_Preferences.h:1078 msgid "(requires restart)" msgstr "" -#: objects/ui_Preferences.h:625 +#: objects/ui_Preferences.h:1079 msgid "Font" msgstr "" -#: objects/ui_Preferences.h:626 +#: objects/ui_Preferences.h:1080 msgid "Color syntax highlighting" msgstr "" -#: objects/ui_Preferences.h:627 -msgid "Use Ctrl/Cmd-Mouse-wheel to zoom text" +#: objects/ui_Preferences.h:1081 +msgid "Ctrl/Cmd-Mouse-wheel zooms text" msgstr "" -#: objects/ui_Preferences.h:629 +#: objects/ui_Preferences.h:1082 +msgid "Indentation" +msgstr "" + +#: objects/ui_Preferences.h:1083 +msgid "Auto Indent" +msgstr "" + +#: objects/ui_Preferences.h:1084 +msgid "Indent using" +msgstr "" + +#: objects/ui_Preferences.h:1087 src/settings.cc:135 +msgid "Spaces" +msgstr "" + +#: objects/ui_Preferences.h:1088 src/settings.cc:135 +msgid "Tabs" +msgstr "" + +#: objects/ui_Preferences.h:1090 +msgid "Indentation width" +msgstr "" + +#: objects/ui_Preferences.h:1091 +msgid "Tab width" +msgstr "" + +#: objects/ui_Preferences.h:1092 +msgid "Tab key function" +msgstr "" + +#: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 +#: src/settings.cc:136 +msgid "Indent" +msgstr "" + +#: objects/ui_Preferences.h:1096 src/settings.cc:136 +msgid "Insert Tab" +msgstr "" + +#: objects/ui_Preferences.h:1098 +msgid "Show whitespace" +msgstr "" + +#: objects/ui_Preferences.h:1101 src/settings.cc:132 +msgid "Never" +msgstr "" + +#: objects/ui_Preferences.h:1102 src/settings.cc:132 +msgid "Always" +msgstr "" + +#: objects/ui_Preferences.h:1103 +msgid "Only after indentation" +msgstr "" + +#: objects/ui_Preferences.h:1105 +msgid "Size" +msgstr "" + +#: objects/ui_Preferences.h:1106 +msgid "Display" +msgstr "" + +#: objects/ui_Preferences.h:1107 +msgid "Enable brace matching" +msgstr "" + +#: objects/ui_Preferences.h:1108 +msgid "Highlight current line" +msgstr "" + +#: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 +msgid "Line wrap" +msgstr "" + +#: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 +#: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 +#: src/settings.cc:131 +msgid "None" +msgstr "" + +#: objects/ui_Preferences.h:1113 src/settings.cc:127 +msgid "Wrap at character boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1114 src/settings.cc:127 +msgid "Wrap at word boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1116 +msgid "Line wrap indentation" +msgstr "" + +#: objects/ui_Preferences.h:1117 +msgid "Line wrap visualization" +msgstr "" + +#: objects/ui_Preferences.h:1118 +msgid "Style" +msgstr "" + +#: objects/ui_Preferences.h:1121 src/settings.cc:128 +msgid "Fixed" +msgstr "" + +#: objects/ui_Preferences.h:1122 src/settings.cc:128 +msgid "Same" +msgstr "" + +#: objects/ui_Preferences.h:1123 src/settings.cc:128 +msgid "Indented" +msgstr "" + +#: objects/ui_Preferences.h:1126 +msgid "Start" +msgstr "" + +#: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Text" +msgstr "" + +#: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Border" +msgstr "" + +#: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Margin" +msgstr "" + +#: objects/ui_Preferences.h:1134 +msgid "End" +msgstr "" + +#: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" msgstr "" -#: objects/ui_Preferences.h:630 +#: objects/ui_Preferences.h:1144 msgid "Include development snapshots" msgstr "" -#: objects/ui_Preferences.h:631 +#: objects/ui_Preferences.h:1145 msgid "Check Now" msgstr "" -#: objects/ui_Preferences.h:632 +#: objects/ui_Preferences.h:1146 msgid "Last checked: " msgstr "" -#: objects/ui_Preferences.h:634 +#: objects/ui_Preferences.h:1148 msgid "OpenCSG" msgstr "" -#: objects/ui_Preferences.h:635 +#: objects/ui_Preferences.h:1149 msgid "Show capability warning" msgstr "" -#: objects/ui_Preferences.h:636 +#: objects/ui_Preferences.h:1150 msgid "Enable for OpenGL 1.x" msgstr "" -#: objects/ui_Preferences.h:637 +#: objects/ui_Preferences.h:1151 msgid "Turn off rendering at " msgstr "" -#: objects/ui_Preferences.h:638 +#: objects/ui_Preferences.h:1152 msgid "elements" msgstr "" -#: objects/ui_Preferences.h:639 +#: objects/ui_Preferences.h:1153 msgid "Force Goldfeather" msgstr "" -#: objects/ui_Preferences.h:640 +#: objects/ui_Preferences.h:1154 msgid "CGAL Cache size" msgstr "" -#: objects/ui_Preferences.h:641 objects/ui_Preferences.h:643 +#: objects/ui_Preferences.h:1155 objects/ui_Preferences.h:1157 msgid "bytes" msgstr "" -#: objects/ui_Preferences.h:642 +#: objects/ui_Preferences.h:1156 msgid "PolySet Cache size" msgstr "" -#: objects/ui_Preferences.h:644 +#: objects/ui_Preferences.h:1158 msgid "Allow to open multiple documents" msgstr "" -#: objects/ui_Preferences.h:645 +#: objects/ui_Preferences.h:1159 msgid "Enable docking of Editor and Console in different places" msgstr "" -#: objects/ui_Preferences.h:646 +#: objects/ui_Preferences.h:1160 msgid "Enable undocking of Editor and Console to separate windows" msgstr "" -#: objects/ui_Preferences.h:647 +#: objects/ui_Preferences.h:1161 msgid "Show Welcome Screen" msgstr "" -#: objects/ui_Preferences.h:648 +#: objects/ui_Preferences.h:1162 msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "" -#: objects/ui_Preferences.h:649 -msgid "toolBar" -msgstr "" - #: objects/ui_ProgressWidget.h:72 -msgid "Form" -msgstr "" - -#: objects/ui_ProgressWidget.h:73 msgid "%v / %m" msgstr "" -#: src/mainwin.cc:768 src/mainwin.cc:1300 +#: src/Camera.cc:126 +#, c-format +msgid "" +"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " +"distance = %.2f" +msgstr "" + +#: src/mainwin.cc:778 src/mainwin.cc:1354 msgid "Untitled.scad" msgstr "" -#: src/mainwin.cc:1299 +#: src/mainwin.cc:971 +msgid "Compile error." +msgstr "" + +#: src/mainwin.cc:974 +msgid "Error while compiling '%1'." +msgstr "" + +#: src/mainwin.cc:978 +msgid "Compilation generated %1 warning." +msgid_plural "Compilation generated %1 warnings." +msgstr[0] "" +msgstr[1] "" + +#: src/mainwin.cc:988 +msgid " For details see console window." +msgstr "" + +#: src/mainwin.cc:1353 msgid "Save File" msgstr "" -#: src/mainwin.cc:1301 +#: src/mainwin.cc:1355 msgid "OpenSCAD Designs (*.scad)" msgstr "" -#: src/mainwin.cc:1311 +#: src/mainwin.cc:1365 msgid "" "%1 already exists.\n" "Do you want to replace it?" msgstr "" -#: src/mainwin.cc:1630 +#: src/mainwin.cc:1684 msgid "Application" msgstr "" -#: src/mainwin.cc:1631 +#: src/mainwin.cc:1685 msgid "" "The document has been modified.\n" "Do you really want to reload the file?" msgstr "" -#: src/mainwin.cc:1942 src/mainwin.cc:1999 +#: src/mainwin.cc:2038 src/mainwin.cc:2094 msgid "Export %1 File" msgstr "" -#: src/mainwin.cc:1943 src/mainwin.cc:2003 +#: src/mainwin.cc:2039 src/mainwin.cc:2098 msgid "%1 Files (*%2)" msgstr "" -#: src/mainwin.cc:1944 +#: src/mainwin.cc:2040 msgid "Untitled" msgstr "" -#: src/mainwin.cc:2001 +#: src/mainwin.cc:2096 msgid "Untitled%1" msgstr "" -#: src/mainwin.cc:2052 +#: src/mainwin.cc:2147 msgid "Export CSG File" msgstr "" -#: src/mainwin.cc:2053 +#: src/mainwin.cc:2148 msgid "Untitled.csg" msgstr "" -#: src/mainwin.cc:2054 +#: src/mainwin.cc:2149 msgid "CSG Files (*.csg)" msgstr "" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "Export Image" msgstr "" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "PNG Files (*.png)" msgstr "" -#: src/mainwin.cc:2320 +#: src/mainwin.cc:2423 msgid "Console" msgstr "" -#: src/mainwin.cc:2447 +#: src/mainwin.cc:2560 msgid "The document has been modified." msgstr "" -#: src/mainwin.cc:2448 +#: src/mainwin.cc:2561 msgid "Do you want to save your changes?" msgstr "" -#: src/QGLView.cc:114 +#: src/openscad.cc:604 msgid "" -"\n" -"Using QGLWidget\n" -"\n" +"Fontconfig needs to update its font cache.\n" +"This can take up to a couple of minutes." msgstr "" -#: src/QGLView.cc:131 +#: src/QGLView.cc:129 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" msgstr "" -#: src/QGLView.cc:134 +#: src/QGLView.cc:132 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" "\n" msgstr "" -#: src/QGLView.cc:137 +#: src/QGLView.cc:135 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" "Your renderer information is as follows:\n" msgstr "" -#: src/QGLView.cc:141 +#: src/QGLView.cc:139 #, c-format msgid "" "GLEW version %s\n" @@ -926,21 +1124,18 @@ msgid "" "OpenGL version %s\n" msgstr "" -#: src/QGLView.cc:171 -#, c-format -msgid "" -"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " -"distance = %.2f" +#: src/settings.cc:132 +msgid "After indentation" msgstr "" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Basics" msgstr "" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Shapes" msgstr "" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Extrusion" msgstr "" diff --git a/locale/ru.po b/locale/ru.po index 8fc11980..8e6f6e0e 100644 --- a/locale/ru.po +++ b/locale/ru.po @@ -7,9 +7,9 @@ msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2014.01.05\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-22 23:28+0100\n" +"POT-Creation-Date: 2015-02-01 18:03+0100\n" "PO-Revision-Date: 2013-02-24 17:50+0100\n" -"Last-Translator: \n" +"Last-Translator: \n" "Language-Team: Russian\n" "Language: ru\n" "MIME-Version: 1.0\n" @@ -18,80 +18,11 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: objects/ui_AboutDialog.h:51 src/AboutDialog.h:15 +#: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" msgstr "О программе OpenSCAD" -#: objects/ui_FontListDialog.h:102 -#, fuzzy -msgid "OpenSCAD Font List" -msgstr "Шрифт" - -#: objects/ui_FontListDialog.h:103 objects/ui_LibraryInfoDialog.h:77 -msgid "&OK" -msgstr "" - -#: objects/ui_FontListDialog.h:104 -msgid "Copy to Clipboard" -msgstr "" - -#: objects/ui_FontListDialog.h:105 -msgid "Filter:" -msgstr "" - -#: objects/ui_FontListDialog.h:106 -msgid "" -"

This list shows the fonts currently registered with " -"OpenSCAD.

Example:

  text(t = "
-""OpenSCAD", font = "DejaVu Sans");
  text(t = "OpenSCAD", font = "
-""Liberation Sans:style=Italic");
" -msgstr "" - -#: objects/ui_launchingscreen.h:276 -#, fuzzy -msgid "Welcome to OpenSCAD" -msgstr "О программе OpenSCAD" - -#: objects/ui_launchingscreen.h:277 -#, fuzzy -msgid "New" -msgstr "&Создать" - -#: objects/ui_launchingscreen.h:278 -#, fuzzy -msgid "Open" -msgstr "&Открыть..." - -#: objects/ui_launchingscreen.h:279 -#, fuzzy -msgid "Help" -msgstr "&Справка" - -#: objects/ui_launchingscreen.h:280 -#, fuzzy -msgid "Recents" -msgstr "Открыть файл" - -#: objects/ui_launchingscreen.h:281 -msgid "Open Recent" -msgstr "Открыть недавние" - -#: objects/ui_launchingscreen.h:282 objects/ui_launchingscreen.h:284 -#: objects/ui_MainWindow.h:855 -msgid "Examples" -msgstr "Примеры" - -#: objects/ui_launchingscreen.h:285 -#, fuzzy -msgid "Open Example" -msgstr "Примеры" - -#: objects/ui_launchingscreen.h:287 +#: objects/ui_AboutDialog.h:105 objects/ui_launchingscreen.h:305 msgid "" "\n" "

This list shows the fonts currently registered with " +"OpenSCAD.

Example:

  text(t = "
+""OpenSCAD", font = "DejaVu Sans");
  text(t = "OpenSCAD", font = "
+""Liberation Sans:style=Italic");
" msgstr "" +#: objects/ui_launchingscreen.h:294 +#, fuzzy +msgid "Welcome to OpenSCAD" +msgstr "О программе OpenSCAD" + +#: objects/ui_launchingscreen.h:295 +#, fuzzy +msgid "New" +msgstr "&Создать" + +#: objects/ui_launchingscreen.h:296 +#, fuzzy +msgid "Open" +msgstr "&Открыть..." + +#: objects/ui_launchingscreen.h:297 +#, fuzzy +msgid "Help" +msgstr "&Справка" + +#: objects/ui_launchingscreen.h:298 +#, fuzzy +msgid "Recents" +msgstr "Открыть файл" + +#: objects/ui_launchingscreen.h:299 +msgid "Open Recent" +msgstr "Открыть недавние" + +#: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 +msgid "Examples" +msgstr "Примеры" + +#: objects/ui_launchingscreen.h:303 +#, fuzzy +msgid "Open Example" +msgstr "Примеры" + +#: objects/ui_launchingscreen.h:312 +msgid "Don't show again" +msgstr "Не показывать снова" + +#: objects/ui_launchingscreen.h:313 +msgid "Version" +msgstr "Версия" + #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" -msgstr "" +msgstr "Информация о сборке" #: objects/ui_LibraryInfoDialog.h:76 msgid "OpenSCAD Detailed Library and Build Information" msgstr "Подробная информация о библиотеках и сборке OpenSCAD" -#: objects/ui_MainWindow.h:731 +#: objects/ui_MainWindow.h:837 msgid "&New" msgstr "&Создать" -#: objects/ui_MainWindow.h:732 +#: objects/ui_MainWindow.h:838 msgid "Ctrl+N" -msgstr "" +msgstr "Ctrl+N" -#: objects/ui_MainWindow.h:733 +#: objects/ui_MainWindow.h:839 msgid "&Open..." msgstr "&Открыть..." -#: objects/ui_MainWindow.h:734 +#: objects/ui_MainWindow.h:840 msgid "Ctrl+O" -msgstr "" +msgstr "Ctrl+O" -#: objects/ui_MainWindow.h:735 +#: objects/ui_MainWindow.h:841 msgid "&Save" msgstr "&Сохранить" -#: objects/ui_MainWindow.h:736 +#: objects/ui_MainWindow.h:842 msgid "Ctrl+S" -msgstr "" +msgstr "Ctrl+S" -#: objects/ui_MainWindow.h:737 +#: objects/ui_MainWindow.h:843 msgid "Save &As..." msgstr "Сохранить &как..." -#: objects/ui_MainWindow.h:738 +#: objects/ui_MainWindow.h:844 msgid "Ctrl+Shift+S" -msgstr "" +msgstr "Ctrl+Shift+S" -#: objects/ui_MainWindow.h:739 +#: objects/ui_MainWindow.h:845 msgid "&Reload" msgstr "&Обновить" -#: objects/ui_MainWindow.h:740 +#: objects/ui_MainWindow.h:846 msgid "Ctrl+R" -msgstr "" +msgstr "Ctrl+R" -#: objects/ui_MainWindow.h:741 +#: objects/ui_MainWindow.h:847 msgid "&Quit" msgstr "&Выход" -#: objects/ui_MainWindow.h:742 +#: objects/ui_MainWindow.h:848 msgid "Ctrl+Q" -msgstr "" +msgstr "Ctrl+Q" -#: objects/ui_MainWindow.h:743 +#: objects/ui_MainWindow.h:849 msgid "&Undo" msgstr "&Отменить" -#: objects/ui_MainWindow.h:744 +#: objects/ui_MainWindow.h:850 msgid "Ctrl+Z" -msgstr "" +msgstr "Ctrl+Z" -#: objects/ui_MainWindow.h:745 +#: objects/ui_MainWindow.h:851 msgid "&Redo" msgstr "&Повторить" -#: objects/ui_MainWindow.h:746 +#: objects/ui_MainWindow.h:852 msgid "Ctrl+Shift+Z" -msgstr "" +msgstr "Ctrl+Shift+Z" -#: objects/ui_MainWindow.h:747 +#: objects/ui_MainWindow.h:853 msgid "Cu&t" msgstr "Вы&резать" -#: objects/ui_MainWindow.h:748 +#: objects/ui_MainWindow.h:854 msgid "Ctrl+X" -msgstr "" +msgstr "Ctrl+X" -#: objects/ui_MainWindow.h:749 +#: objects/ui_MainWindow.h:855 msgid "&Copy" msgstr "&Копировать" -#: objects/ui_MainWindow.h:750 +#: objects/ui_MainWindow.h:856 msgid "Ctrl+C" -msgstr "" +msgstr "Ctrl+C" -#: objects/ui_MainWindow.h:751 +#: objects/ui_MainWindow.h:857 msgid "&Paste" msgstr "&Вставить" -#: objects/ui_MainWindow.h:752 +#: objects/ui_MainWindow.h:858 msgid "Ctrl+V" -msgstr "" +msgstr "Ctrl+V" -#: objects/ui_MainWindow.h:753 +#: objects/ui_MainWindow.h:859 msgid "&Indent" msgstr "&Добавить отступ" -#: objects/ui_MainWindow.h:754 +#: objects/ui_MainWindow.h:860 msgid "Ctrl+I" -msgstr "" +msgstr "Ctrl+I" -#: objects/ui_MainWindow.h:755 -msgid "U&nindent" -msgstr "У&брать отступ" - -#: objects/ui_MainWindow.h:756 -msgid "Ctrl+Shift+I" -msgstr "" - -#: objects/ui_MainWindow.h:757 +#: objects/ui_MainWindow.h:861 msgid "C&omment" msgstr "Зако&мментировать" -#: objects/ui_MainWindow.h:758 +#: objects/ui_MainWindow.h:862 msgid "Ctrl+D" -msgstr "" +msgstr "Ctrl+D" -#: objects/ui_MainWindow.h:759 +#: objects/ui_MainWindow.h:863 msgid "Unco&mment" msgstr "Р&аскомментировать" -#: objects/ui_MainWindow.h:760 +#: objects/ui_MainWindow.h:864 msgid "Ctrl+Shift+D" -msgstr "" +msgstr "Ctrl+Shift+D" -#: objects/ui_MainWindow.h:761 -msgid "Paste viewport translation" +#: objects/ui_MainWindow.h:865 +#, fuzzy +msgid "P&aste viewport translation" msgstr "Вставить смещение точки обзора" -#: objects/ui_MainWindow.h:762 +#: objects/ui_MainWindow.h:866 msgid "Ctrl+T" -msgstr "" +msgstr "Ctrl+T" -#: objects/ui_MainWindow.h:763 -msgid "Paste viewport rotation" +#: objects/ui_MainWindow.h:867 +#, fuzzy +msgid "Past&e viewport rotation" msgstr "Вставить поворот точки обзора" -#: objects/ui_MainWindow.h:764 objects/ui_MainWindow.h:842 -msgid "Zoom In" -msgstr "Увеличить масштаб" +#: objects/ui_MainWindow.h:868 +#, fuzzy +msgid "Increase Font &Size" +msgstr "Увеличить размер шрифта" -#: objects/ui_MainWindow.h:765 +#: objects/ui_MainWindow.h:869 msgid "Ctrl++" -msgstr "" +msgstr "Ctrl++" -#: objects/ui_MainWindow.h:766 objects/ui_MainWindow.h:844 -msgid "Zoom Out" -msgstr "Уменьшить масштаб" +#: objects/ui_MainWindow.h:870 +#, fuzzy +msgid "Decrease Font Si&ze" +msgstr "Уменьшить размер шрифта" -#: objects/ui_MainWindow.h:767 +#: objects/ui_MainWindow.h:871 msgid "Ctrl+-" -msgstr "" +msgstr "Ctrl+-" -#: objects/ui_MainWindow.h:768 -msgid "Hide editor" +#: objects/ui_MainWindow.h:872 +#, fuzzy +msgid "H&ide editor" msgstr "Скрыть редактор" -#: objects/ui_MainWindow.h:769 +#: objects/ui_MainWindow.h:873 #, fuzzy msgid "&Reload and Preview" msgstr "&Обновить и компилировать" -#: objects/ui_MainWindow.h:770 +#: objects/ui_MainWindow.h:874 msgid "F4" -msgstr "" +msgstr "F4" -#: objects/ui_MainWindow.h:771 +#: objects/ui_MainWindow.h:875 +#, fuzzy msgid "&Preview" -msgstr "" +msgstr "&Превью" -#: objects/ui_MainWindow.h:772 +#: objects/ui_MainWindow.h:876 msgid "F5" -msgstr "" +msgstr "F5" -#: objects/ui_MainWindow.h:773 -msgid "&Render" -msgstr "" +#: objects/ui_MainWindow.h:877 +#, fuzzy +msgid "R&ender" +msgstr "&Рендер" -#: objects/ui_MainWindow.h:774 +#: objects/ui_MainWindow.h:878 msgid "F6" -msgstr "" +msgstr "F6" -#: objects/ui_MainWindow.h:775 -msgid "Check Validity" -msgstr "" +#: objects/ui_MainWindow.h:879 +#, fuzzy +msgid "&Check Validity" +msgstr "Проверить" -#: objects/ui_MainWindow.h:776 -msgid "Display &AST..." +#: objects/ui_MainWindow.h:880 +#, fuzzy +msgid "Display A&ST..." msgstr "Показать &AST..." -#: objects/ui_MainWindow.h:777 +#: objects/ui_MainWindow.h:881 msgid "Display CSG &Tree..." msgstr "Показать &дерево CSG..." -#: objects/ui_MainWindow.h:778 -msgid "Display CSG &Products..." +#: objects/ui_MainWindow.h:882 +#, fuzzy +msgid "Display CSG Pr&oducts..." msgstr "Показать &результаты CSG..." -#: objects/ui_MainWindow.h:779 +#: objects/ui_MainWindow.h:883 msgid "Export as &STL..." msgstr "Экспортировать в &STL..." -#: objects/ui_MainWindow.h:780 +#: objects/ui_MainWindow.h:884 msgid "Export as &OFF..." msgstr "Экспортировать в &OFF..." -#: objects/ui_MainWindow.h:781 +#: objects/ui_MainWindow.h:885 msgid "Preview" -msgstr "" +msgstr "Превью" -#: objects/ui_MainWindow.h:782 +#: objects/ui_MainWindow.h:886 msgid "F9" -msgstr "" +msgstr "F9" -#: objects/ui_MainWindow.h:783 +#: objects/ui_MainWindow.h:887 #, fuzzy msgid "Surfaces" msgstr "Поверхности CGAL" -#: objects/ui_MainWindow.h:784 +#: objects/ui_MainWindow.h:888 msgid "F10" -msgstr "" +msgstr "F10" -#: objects/ui_MainWindow.h:785 +#: objects/ui_MainWindow.h:889 msgid "Wireframe" msgstr "" -#: objects/ui_MainWindow.h:786 +#: objects/ui_MainWindow.h:890 msgid "F11" -msgstr "" +msgstr "F11" -#: objects/ui_MainWindow.h:787 +#: objects/ui_MainWindow.h:891 msgid "Thrown Together" msgstr "Всё вместе" -#: objects/ui_MainWindow.h:788 +#: objects/ui_MainWindow.h:892 msgid "F12" -msgstr "" +msgstr "F12" -#: objects/ui_MainWindow.h:789 +#: objects/ui_MainWindow.h:893 msgid "Show Edges" msgstr "Показывать рёбра" -#: objects/ui_MainWindow.h:790 +#: objects/ui_MainWindow.h:894 msgid "Ctrl+1" -msgstr "" +msgstr "Ctrl+1" -#: objects/ui_MainWindow.h:791 +#: objects/ui_MainWindow.h:895 msgid "Show Axes" msgstr "Показывать оси" -#: objects/ui_MainWindow.h:792 +#: objects/ui_MainWindow.h:896 msgid "Ctrl+2" -msgstr "" +msgstr "Ctrl+2" -#: objects/ui_MainWindow.h:793 +#: objects/ui_MainWindow.h:897 msgid "Show Crosshairs" msgstr "Показывать перекрестия" -#: objects/ui_MainWindow.h:794 +#: objects/ui_MainWindow.h:898 msgid "Ctrl+3" -msgstr "" +msgstr "Ctrl+3" -#: objects/ui_MainWindow.h:795 +#: objects/ui_MainWindow.h:899 +#, fuzzy +msgid "Show Scale Markers" +msgstr "Показать метки масштаба" + +#: objects/ui_MainWindow.h:900 msgid "Animate" msgstr "Анимация" -#: objects/ui_MainWindow.h:796 -msgid "Top" -msgstr "Сверху" - -#: objects/ui_MainWindow.h:797 -msgid "Ctrl+4" +#: objects/ui_MainWindow.h:901 +msgid "&Top" msgstr "" -#: objects/ui_MainWindow.h:798 -msgid "Bottom" +#: objects/ui_MainWindow.h:902 +msgid "Ctrl+4" +msgstr "Ctrl+4" + +#: objects/ui_MainWindow.h:903 +#, fuzzy +msgid "&Bottom" msgstr "Снизу" -#: objects/ui_MainWindow.h:799 +#: objects/ui_MainWindow.h:904 msgid "Ctrl+5" -msgstr "" +msgstr "Ctrl+5" -#: objects/ui_MainWindow.h:800 -msgid "Left" +#: objects/ui_MainWindow.h:905 +#, fuzzy +msgid "&Left" msgstr "Слева" -#: objects/ui_MainWindow.h:801 +#: objects/ui_MainWindow.h:906 msgid "Ctrl+6" -msgstr "" +msgstr "Ctrl+6" -#: objects/ui_MainWindow.h:802 -msgid "Right" +#: objects/ui_MainWindow.h:907 +#, fuzzy +msgid "&Right" msgstr "Справа" -#: objects/ui_MainWindow.h:803 +#: objects/ui_MainWindow.h:908 msgid "Ctrl+7" -msgstr "" +msgstr "Ctrl+7" -#: objects/ui_MainWindow.h:804 -msgid "Front" +#: objects/ui_MainWindow.h:909 +#, fuzzy +msgid "&Front" msgstr "Спереди" -#: objects/ui_MainWindow.h:805 +#: objects/ui_MainWindow.h:910 msgid "Ctrl+8" +msgstr "Ctrl+8" + +#: objects/ui_MainWindow.h:911 +msgid "Bac&k" msgstr "" -#: objects/ui_MainWindow.h:806 -msgid "Back" -msgstr "Сзади" - -#: objects/ui_MainWindow.h:807 +#: objects/ui_MainWindow.h:912 msgid "Ctrl+9" -msgstr "" +msgstr "Ctrl+9" -#: objects/ui_MainWindow.h:808 -msgid "Diagonal" +#: objects/ui_MainWindow.h:913 +#, fuzzy +msgid "&Diagonal" msgstr "Аксонометрический" -#: objects/ui_MainWindow.h:809 +#: objects/ui_MainWindow.h:914 msgid "Ctrl+0" -msgstr "" +msgstr "Ctrl+0" -#: objects/ui_MainWindow.h:810 -msgid "Center" +#: objects/ui_MainWindow.h:915 +#, fuzzy +msgid "Ce&nter" msgstr "По центру" -#: objects/ui_MainWindow.h:811 -msgid "Perspective" +#: objects/ui_MainWindow.h:916 +#, fuzzy +msgid "&Perspective" msgstr "Перспектива" -#: objects/ui_MainWindow.h:812 -msgid "Orthogonal" +#: objects/ui_MainWindow.h:917 +#, fuzzy +msgid "&Orthogonal" msgstr "Прямоугольная проекция" -#: objects/ui_MainWindow.h:813 -msgid "Hide console" +#: objects/ui_MainWindow.h:918 +#, fuzzy +msgid "H&ide console" msgstr "Скрыть консоль" -#: objects/ui_MainWindow.h:814 -msgid "About" +#: objects/ui_MainWindow.h:919 +#, fuzzy +msgid "&About" msgstr "О программе" -#: objects/ui_MainWindow.h:815 -msgid "Documentation" +#: objects/ui_MainWindow.h:920 +#, fuzzy +msgid "&Documentation" msgstr "Документация" -#: objects/ui_MainWindow.h:816 +#: objects/ui_MainWindow.h:921 msgid "Clear Recent" msgstr "Очистить список" -#: objects/ui_MainWindow.h:817 -msgid "Export as DXF..." +#: objects/ui_MainWindow.h:922 +#, fuzzy +msgid "Export as &DXF..." msgstr "Экспортировать в DXF..." -#: objects/ui_MainWindow.h:818 objects/ui_OpenCSGWarningDialog.h:94 -msgid "Close" +#: objects/ui_MainWindow.h:923 +#, fuzzy +msgid "&Close" msgstr "Закрыть" -#: objects/ui_MainWindow.h:819 +#: objects/ui_MainWindow.h:924 msgid "Ctrl+W" -msgstr "" +msgstr "Ctrl+W" -#: objects/ui_MainWindow.h:820 objects/ui_Preferences.h:608 -msgid "Preferences" +#: objects/ui_MainWindow.h:925 +#, fuzzy +msgid "&Preferences" msgstr "Настройки" -#: objects/ui_MainWindow.h:821 -msgid "Find..." -msgstr "" +#: objects/ui_MainWindow.h:926 +#, fuzzy +msgid "&Find..." +msgstr "Найти..." -#: objects/ui_MainWindow.h:822 +#: objects/ui_MainWindow.h:927 msgid "Ctrl+F" -msgstr "" +msgstr "Ctrl+F" -#: objects/ui_MainWindow.h:823 -msgid "Find and Replace..." -msgstr "" +#: objects/ui_MainWindow.h:928 +#, fuzzy +msgid "Fin&d and Replace..." +msgstr "Найти и замена..." -#: objects/ui_MainWindow.h:824 +#: objects/ui_MainWindow.h:929 msgid "Ctrl+Alt+F" -msgstr "" +msgstr "Ctrl+Alt+F" -#: objects/ui_MainWindow.h:825 -msgid "Find Next" -msgstr "" +#: objects/ui_MainWindow.h:930 +#, fuzzy +msgid "Find Ne&xt" +msgstr "Искать дальше" -#: objects/ui_MainWindow.h:826 +#: objects/ui_MainWindow.h:931 msgid "Ctrl+G" -msgstr "" +msgstr "Ctrl+G" -#: objects/ui_MainWindow.h:827 -msgid "Find Previous" -msgstr "" +#: objects/ui_MainWindow.h:932 +#, fuzzy +msgid "Find Pre&vious" +msgstr "Искать раньше" -#: objects/ui_MainWindow.h:828 +#: objects/ui_MainWindow.h:933 msgid "Ctrl+Shift+G" -msgstr "" +msgstr "Ctrl+Shift+G" -#: objects/ui_MainWindow.h:829 -msgid "Use Selection for Find" -msgstr "" +#: objects/ui_MainWindow.h:934 +#, fuzzy +msgid "Use Se&lection for Find" +msgstr "Найти выделенный текст" -#: objects/ui_MainWindow.h:830 +#: objects/ui_MainWindow.h:935 msgid "Ctrl+E" -msgstr "" +msgstr "Ctrl+E" -#: objects/ui_MainWindow.h:831 -msgid "Flush Caches" +#: objects/ui_MainWindow.h:936 +#, fuzzy +msgid "&Flush Caches" msgstr "Очистить кэш" -#: objects/ui_MainWindow.h:832 -msgid "OpenSCAD Homepage" +#: objects/ui_MainWindow.h:937 +#, fuzzy +msgid "&OpenSCAD Homepage" msgstr "Домашняя страница OpenSCAD" -#: objects/ui_MainWindow.h:833 +#: objects/ui_MainWindow.h:938 #, fuzzy -msgid "Automatic Reload and Preview" +msgid "&Automatic Reload and Preview" msgstr "Автоматически обновлять и комилировать" -#: objects/ui_MainWindow.h:834 -msgid "Export as Image..." +#: objects/ui_MainWindow.h:939 +#, fuzzy +msgid "Export as &Image..." msgstr "Экспортировать в растр..." -#: objects/ui_MainWindow.h:835 -msgid "Export as CSG..." +#: objects/ui_MainWindow.h:940 +#, fuzzy +msgid "Export as &CSG..." msgstr "Экспортировать в CSG..." -#: objects/ui_MainWindow.h:836 -msgid "Library info" +#: objects/ui_MainWindow.h:941 +#, fuzzy +msgid "&Library info" msgstr "Информация о библиотеках" -#: objects/ui_MainWindow.h:837 -msgid "Show Library Folder..." +#: objects/ui_MainWindow.h:942 +#, fuzzy +msgid "Show &Library Folder..." msgstr "Открыть каталог библиотек..." -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:943 msgid "Reset View" msgstr "Сбросить настройки вида" -#: objects/ui_MainWindow.h:839 +#: objects/ui_MainWindow.h:944 #, fuzzy -msgid "Font List" +msgid "&Font List" msgstr "Шрифт" -#: objects/ui_MainWindow.h:840 +#: objects/ui_MainWindow.h:945 #, fuzzy -msgid "Export as SVG..." +msgid "Export as S&VG..." msgstr "Экспортировать в CSG..." -#: objects/ui_MainWindow.h:841 +#: objects/ui_MainWindow.h:946 #, fuzzy -msgid "Export as AMF..." +msgid "Export as &AMF..." msgstr "Экспортировать в DXF..." -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:947 +msgid "Zoom In" +msgstr "Увеличить масштаб" + +#: objects/ui_MainWindow.h:948 msgid "Ctrl+]" -msgstr "" +msgstr "Ctrl+]" -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:949 +msgid "Zoom Out" +msgstr "Уменьшить масштаб" + +#: objects/ui_MainWindow.h:950 msgid "Ctrl+[" -msgstr "" +msgstr "Ctrl+[" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:951 #, fuzzy msgid "View All" msgstr "&Вид" -#: objects/ui_MainWindow.h:847 -msgid "Convert Tabs to Spaces" -msgstr "" +#: objects/ui_MainWindow.h:952 +#, fuzzy +msgid "Conv&ert Tabs to Spaces" +msgstr "Преобразовать табуляции в пробелы" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:953 #, fuzzy msgid "Hide toolbars" -msgstr "Скрыть редактор" +msgstr "Скрыть панель" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:954 +msgid "U&nindent" +msgstr "У&брать отступ" + +#: objects/ui_MainWindow.h:955 +msgid "Ctrl+Shift+I" +msgstr "Ctrl+Shift+I" + +#: objects/ui_MainWindow.h:956 +#, fuzzy +msgid "&Cheat Sheet" +msgstr "Указатель" + +#: objects/ui_MainWindow.h:957 +msgid "Message" +msgstr "Сообщение" + +#: objects/ui_MainWindow.h:960 msgid "Time:" msgstr "Время:" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:961 msgid "FPS:" msgstr "Кадров в секунду:" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:962 msgid "Steps:" msgstr "Шагов:" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:963 msgid "Dump Pictures" msgstr "Сохранять кадры" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:964 msgid "&File" msgstr "&Файл" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:965 #, fuzzy -msgid "Recent Files" +msgid "Recen&t Files" msgstr "Открыть файл" -#: objects/ui_MainWindow.h:856 -msgid "Export" -msgstr "" +#: objects/ui_MainWindow.h:966 +#, fuzzy +msgid "&Examples" +msgstr "Примеры" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:967 +#, fuzzy +msgid "E&xport" +msgstr "Экспорт" + +#: objects/ui_MainWindow.h:968 msgid "&Edit" msgstr "&Правка" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:969 msgid "&Design" msgstr "&Модель" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:970 msgid "&View" msgstr "&Вид" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:971 msgid "&Help" msgstr "&Справка" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:974 msgid "Find" -msgstr "" +msgstr "Найти" -#: objects/ui_MainWindow.h:864 objects/ui_MainWindow.h:871 +#: objects/ui_MainWindow.h:975 objects/ui_MainWindow.h:982 msgid "Replace" -msgstr "" +msgstr "Заменить" -#: objects/ui_MainWindow.h:866 +#: objects/ui_MainWindow.h:977 msgid "Search string" -msgstr "" +msgstr "Строка поиска" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:978 msgid "<" -msgstr "" +msgstr "<" -#: objects/ui_MainWindow.h:868 +#: objects/ui_MainWindow.h:979 msgid ">" -msgstr "" +msgstr ">" -#: objects/ui_MainWindow.h:869 +#: objects/ui_MainWindow.h:980 msgid "Done" -msgstr "" +msgstr "Готово" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:981 #, fuzzy msgid "Replacement string" msgstr "элементах" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:983 msgid "All" -msgstr "" +msgstr "Все" #: objects/ui_OpenCSGWarningDialog.h:86 msgid "OpenGL Warning" @@ -694,261 +765,454 @@ msgstr "Включить для OpenGL 1.x" msgid "Show this message again" msgstr "" -#: objects/ui_Preferences.h:609 +#: objects/ui_OpenCSGWarningDialog.h:94 +msgid "Close" +msgstr "Закрыть" + +#: objects/ui_Preferences.h:1061 +msgid "Preferences" +msgstr "Настройки" + +#: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "3D Вид" -#: objects/ui_Preferences.h:610 src/UIUtils.cc:85 +#: objects/ui_Preferences.h:1063 src/UIUtils.cc:86 msgid "Advanced" msgstr "Дополнительные" -#: objects/ui_Preferences.h:611 src/mainwin.cc:2315 +#: objects/ui_Preferences.h:1064 src/mainwin.cc:2418 msgid "Editor" msgstr "Редактор" -#: objects/ui_Preferences.h:612 +#: objects/ui_Preferences.h:1065 msgid "Update" msgstr "Обновления" -#: objects/ui_Preferences.h:613 objects/ui_Preferences.h:633 +#: objects/ui_Preferences.h:1066 objects/ui_Preferences.h:1147 msgid "Features" msgstr "Функции" -#: objects/ui_Preferences.h:615 +#: objects/ui_Preferences.h:1068 msgid "Enable/Disable experimental features" -msgstr "" +msgstr "Включить/Выключить экспериментальные возможности" -#: objects/ui_Preferences.h:617 +#: objects/ui_Preferences.h:1070 msgid "Color scheme:" msgstr "Цветовая схема:" -#: objects/ui_Preferences.h:618 +#: objects/ui_Preferences.h:1071 +msgid "Show Warnings and Errors in 3D View" +msgstr "Показывать ошибки и предупреждения в 3D виде" + +#: objects/ui_Preferences.h:1072 #, fuzzy msgid "Editor Type" msgstr "Редактор" -#: objects/ui_Preferences.h:621 +#: objects/ui_Preferences.h:1075 #, fuzzy msgid "Simple Editor" -msgstr "Скрыть редактор" +msgstr "Простой редактор" -#: objects/ui_Preferences.h:622 +#: objects/ui_Preferences.h:1076 msgid "QScintilla Editor" msgstr "" -#: objects/ui_Preferences.h:624 +#: objects/ui_Preferences.h:1078 msgid "(requires restart)" -msgstr "" +msgstr "(требуется перезапуск)" -#: objects/ui_Preferences.h:625 +#: objects/ui_Preferences.h:1079 msgid "Font" msgstr "Шрифт" -#: objects/ui_Preferences.h:626 +#: objects/ui_Preferences.h:1080 msgid "Color syntax highlighting" msgstr "Подсветка синтаксиса" -#: objects/ui_Preferences.h:627 -msgid "Use Ctrl/Cmd-Mouse-wheel to zoom text" +#: objects/ui_Preferences.h:1081 +msgid "Ctrl/Cmd-Mouse-wheel zooms text" +msgstr "Ctrl/Cmd-Колесико-мыши увеличивает текст" + +#: objects/ui_Preferences.h:1082 +#, fuzzy +msgid "Indentation" +msgstr "Документация" + +#: objects/ui_Preferences.h:1083 +#, fuzzy +msgid "Auto Indent" +msgstr "&Добавить отступ" + +#: objects/ui_Preferences.h:1084 +#, fuzzy +msgid "Indent using" +msgstr "&Добавить отступ" + +#: objects/ui_Preferences.h:1087 src/settings.cc:135 +#, fuzzy +msgid "Spaces" +msgstr "Поверхности CGAL" + +#: objects/ui_Preferences.h:1088 src/settings.cc:135 +msgid "Tabs" msgstr "" -#: objects/ui_Preferences.h:629 +#: objects/ui_Preferences.h:1090 +msgid "Indentation width" +msgstr "Ширина отступа" + +#: objects/ui_Preferences.h:1091 +msgid "Tab width" +msgstr "Ширина табуляции" + +#: objects/ui_Preferences.h:1092 +msgid "Tab key function" +msgstr "Функция клавиши Tab" + +#: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 +#: src/settings.cc:136 +#, fuzzy +msgid "Indent" +msgstr "&Добавить отступ" + +#: objects/ui_Preferences.h:1096 src/settings.cc:136 +msgid "Insert Tab" +msgstr "Вставить Tab" + +#: objects/ui_Preferences.h:1098 +msgid "Show whitespace" +msgstr "Показать пробел" + +#: objects/ui_Preferences.h:1101 src/settings.cc:132 +msgid "Never" +msgstr "Никогда" + +#: objects/ui_Preferences.h:1102 src/settings.cc:132 +msgid "Always" +msgstr "Всегда" + +#: objects/ui_Preferences.h:1103 +msgid "Only after indentation" +msgstr "Только после отступа" + +#: objects/ui_Preferences.h:1105 +msgid "Size" +msgstr "Размер" + +#: objects/ui_Preferences.h:1106 +#, fuzzy +msgid "Display" +msgstr "Показать &AST..." + +#: objects/ui_Preferences.h:1107 +#, fuzzy +msgid "Enable brace matching" +msgstr "Вклчить автозакрытие скобок" + +#: objects/ui_Preferences.h:1108 +msgid "Highlight current line" +msgstr "Выделить текущую строчку" + +#: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 +msgid "Line wrap" +msgstr "" + +#: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 +#: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 +#: src/settings.cc:131 +#, fuzzy +msgid "None" +msgstr "Нет" + +#: objects/ui_Preferences.h:1113 src/settings.cc:127 +msgid "Wrap at character boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1114 src/settings.cc:127 +msgid "Wrap at word boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1116 +msgid "Line wrap indentation" +msgstr "" + +#: objects/ui_Preferences.h:1117 +msgid "Line wrap visualization" +msgstr "" + +#: objects/ui_Preferences.h:1118 +msgid "Style" +msgstr "Стиль" + +#: objects/ui_Preferences.h:1121 src/settings.cc:128 +msgid "Fixed" +msgstr "Фиксированный" + +#: objects/ui_Preferences.h:1122 src/settings.cc:128 +#, fuzzy +msgid "Same" +msgstr "Так же" + +#: objects/ui_Preferences.h:1123 src/settings.cc:128 +#, fuzzy +msgid "Indented" +msgstr "&Добавить отступ" + +#: objects/ui_Preferences.h:1126 +#, fuzzy +msgid "Start" +msgstr "Начало" + +#: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Text" +msgstr "Текст" + +#: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Border" +msgstr "Граница" + +#: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Margin" +msgstr "" + +#: objects/ui_Preferences.h:1134 +msgid "End" +msgstr "Конец" + +#: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" msgstr "Автоматически проверять обновления" -#: objects/ui_Preferences.h:630 +#: objects/ui_Preferences.h:1144 msgid "Include development snapshots" msgstr "Включая рабочие сборки" -#: objects/ui_Preferences.h:631 +#: objects/ui_Preferences.h:1145 msgid "Check Now" msgstr "Проверить сейчас" -#: objects/ui_Preferences.h:632 +#: objects/ui_Preferences.h:1146 msgid "Last checked: " msgstr "Последняя проверка: " -#: objects/ui_Preferences.h:634 +#: objects/ui_Preferences.h:1148 msgid "OpenCSG" -msgstr "" +msgstr "OpenCSG" -#: objects/ui_Preferences.h:635 +#: objects/ui_Preferences.h:1149 msgid "Show capability warning" msgstr "Показывать предупреждение о возможностях" -#: objects/ui_Preferences.h:636 +#: objects/ui_Preferences.h:1150 msgid "Enable for OpenGL 1.x" msgstr "Включить для OpenGL 1.x" -#: objects/ui_Preferences.h:637 +#: objects/ui_Preferences.h:1151 msgid "Turn off rendering at " msgstr "Отключать отрисовку на " -#: objects/ui_Preferences.h:638 +#: objects/ui_Preferences.h:1152 msgid "elements" msgstr "элементах" -#: objects/ui_Preferences.h:639 +#: objects/ui_Preferences.h:1153 msgid "Force Goldfeather" msgstr "Принудительно использовать алгоритм Goldfeather («Золотое перо»)" -#: objects/ui_Preferences.h:640 +#: objects/ui_Preferences.h:1154 msgid "CGAL Cache size" msgstr "Размер кэша CGAL" -#: objects/ui_Preferences.h:641 objects/ui_Preferences.h:643 +#: objects/ui_Preferences.h:1155 objects/ui_Preferences.h:1157 msgid "bytes" msgstr "байт" -#: objects/ui_Preferences.h:642 +#: objects/ui_Preferences.h:1156 msgid "PolySet Cache size" msgstr "Размер кэша PolySet" -#: objects/ui_Preferences.h:644 +#: objects/ui_Preferences.h:1158 msgid "Allow to open multiple documents" -msgstr "" +msgstr "Разрешить открытие нескольких документов" -#: objects/ui_Preferences.h:645 +#: objects/ui_Preferences.h:1159 msgid "Enable docking of Editor and Console in different places" -msgstr "" +msgstr "Включить прилипание Редактора и Консоли в разных местах" -#: objects/ui_Preferences.h:646 +#: objects/ui_Preferences.h:1160 msgid "Enable undocking of Editor and Console to separate windows" -msgstr "" +msgstr "Включить перетаскивание Редактора и Консоли в разные окна" -#: objects/ui_Preferences.h:647 +#: objects/ui_Preferences.h:1161 msgid "Show Welcome Screen" -msgstr "" +msgstr "Показать экран преветствия" -#: objects/ui_Preferences.h:648 +#: objects/ui_Preferences.h:1162 msgid "Enable user interface localization (requires restart of OpenSCAD)" -msgstr "" - -#: objects/ui_Preferences.h:649 -msgid "toolBar" -msgstr "" +msgstr "Включить локализацию интерфейса (необходимо перезапустить OpenSCAD)" #: objects/ui_ProgressWidget.h:72 -msgid "Form" -msgstr "" - -#: objects/ui_ProgressWidget.h:73 msgid "%v / %m" msgstr "" -#: src/mainwin.cc:768 src/mainwin.cc:1300 +#: src/Camera.cc:126 +#, c-format +msgid "" +"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " +"distance = %.2f" +msgstr "" + +#: src/mainwin.cc:778 src/mainwin.cc:1354 msgid "Untitled.scad" msgstr "Безымянный.scad" -#: src/mainwin.cc:1299 +#: src/mainwin.cc:971 +#, fuzzy +msgid "Compile error." +msgstr "&Компилировать" + +#: src/mainwin.cc:974 +msgid "Error while compiling '%1'." +msgstr "Ошибка во время компиляции '%1'." + +#: src/mainwin.cc:978 +msgid "Compilation generated %1 warning." +msgid_plural "Compilation generated %1 warnings." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: src/mainwin.cc:988 +msgid " For details see console window." +msgstr "Для подробностей смотреть окно консоли." + +#: src/mainwin.cc:1353 msgid "Save File" msgstr "Сохранить файл" -#: src/mainwin.cc:1301 +#: src/mainwin.cc:1355 msgid "OpenSCAD Designs (*.scad)" msgstr "Модели OpenSCAD (*.scad)" -#: src/mainwin.cc:1311 +#: src/mainwin.cc:1365 msgid "" "%1 already exists.\n" "Do you want to replace it?" msgstr "" +"%1 уже существует.\n" +"Перезаписать?" -#: src/mainwin.cc:1630 +#: src/mainwin.cc:1684 msgid "Application" -msgstr "" +msgstr "Приложение" -#: src/mainwin.cc:1631 +#: src/mainwin.cc:1685 msgid "" "The document has been modified.\n" "Do you really want to reload the file?" msgstr "" +"Документ был изменен.\n" +"Хотите перезагрузить документ?" -#: src/mainwin.cc:1942 src/mainwin.cc:1999 +#: src/mainwin.cc:2038 src/mainwin.cc:2094 #, fuzzy msgid "Export %1 File" msgstr "Экспортировать в DXF..." -#: src/mainwin.cc:1943 src/mainwin.cc:2003 +#: src/mainwin.cc:2039 src/mainwin.cc:2098 msgid "%1 Files (*%2)" msgstr "" -#: src/mainwin.cc:1944 +#: src/mainwin.cc:2040 #, fuzzy msgid "Untitled" msgstr "Безымянный.scad" -#: src/mainwin.cc:2001 +#: src/mainwin.cc:2096 #, fuzzy msgid "Untitled%1" msgstr "Безымянный.scad" -#: src/mainwin.cc:2052 +#: src/mainwin.cc:2147 msgid "Export CSG File" -msgstr "" +msgstr "Экспортировать файл CSG" -#: src/mainwin.cc:2053 +#: src/mainwin.cc:2148 msgid "Untitled.csg" -msgstr "" +msgstr "Безимянный.csg" -#: src/mainwin.cc:2054 +#: src/mainwin.cc:2149 msgid "CSG Files (*.csg)" -msgstr "" +msgstr "Файлы CSG (*.csg)" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "Export Image" -msgstr "" +msgstr "Экспортировать изображение" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "PNG Files (*.png)" -msgstr "" +msgstr "Файлы PNG (*.png)" -#: src/mainwin.cc:2320 +#: src/mainwin.cc:2423 msgid "Console" -msgstr "" +msgstr "Консоль" -#: src/mainwin.cc:2447 +#: src/mainwin.cc:2560 #, fuzzy msgid "The document has been modified." msgstr "" "Документ был изменен.\n" "Сохранить изменения?" -#: src/mainwin.cc:2448 +#: src/mainwin.cc:2561 #, fuzzy msgid "Do you want to save your changes?" msgstr "" "Документ был изменен.\n" "Сохранить изменения?" -#: src/QGLView.cc:114 +#: src/openscad.cc:604 msgid "" -"\n" -"Using QGLWidget\n" -"\n" +"Fontconfig needs to update its font cache.\n" +"This can take up to a couple of minutes." msgstr "" +"Fontconfig требуется обновить кеш шрифтов.\n" +"Это может занять пару минут." -#: src/QGLView.cc:131 +#: src/QGLView.cc:129 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" msgstr "" +"Предупреждение: Возможны ошибки рендринга OpenCSG.\n" +"\n" -#: src/QGLView.cc:134 +#: src/QGLView.cc:132 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" "\n" msgstr "" +"Предупреждение: Не найдены OpenGL расширения для OpenCSG - OpenCSG был " +"отключен.\n" +"\n" -#: src/QGLView.cc:137 +#: src/QGLView.cc:135 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" "Your renderer information is as follows:\n" msgstr "" +"Крайне рекомендуется использовать OpenSCAD на системе с поддержкой OpenGL " +"2.0 или новее.\n" +"Информация о рендере:\n" -#: src/QGLView.cc:141 +#: src/QGLView.cc:139 #, c-format msgid "" "GLEW version %s\n" @@ -956,24 +1220,30 @@ msgid "" "OpenGL version %s\n" msgstr "" -#: src/QGLView.cc:171 -#, c-format -msgid "" -"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " -"distance = %.2f" -msgstr "" +#: src/settings.cc:132 +msgid "After indentation" +msgstr "После отступа" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Basics" -msgstr "" +msgstr "Примитивы" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Shapes" -msgstr "" +msgstr "Формы" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Extrusion" -msgstr "" +msgstr "Выдавливание" + +#~ msgid "Top" +#~ msgstr "Сверху" + +#~ msgid "Back" +#~ msgstr "Сзади" + +#~ msgid "toolBar" +#~ msgstr "Панель инструментов" #~ msgid "Check for Update.." #~ msgstr "Проверить обновления..." @@ -990,9 +1260,6 @@ msgstr "" #~ msgid "OpenSCAD Designs (*.scad *.csg)" #~ msgstr "Модели OpenSCAD (*.scad *.csg)" -#~ msgid "&Compile" -#~ msgstr "&Компилировать" - #~ msgid "Compile and &Render (CGAL)" #~ msgstr "Компилировать и &отрисовать (CGAL)" diff --git a/mjau.gdb b/mjau.gdb deleted file mode 100644 index 6d394114..00000000 --- a/mjau.gdb +++ /dev/null @@ -1,2 +0,0 @@ -set environment DYLD_LIBRARY_PATH=/Users/kintel/code/OpenSCAD/libraries/install/lib -set environment DYLD_FRAMEWORK_PATH=/Users/kintel/code/OpenSCAD/libraries/install/lib diff --git a/openscad.png b/openscad.png deleted file mode 100644 index 11f807eb..00000000 Binary files a/openscad.png and /dev/null differ diff --git a/openscad.pro b/openscad.pro index 247632bf..26b39937 100644 --- a/openscad.pro +++ b/openscad.pro @@ -279,6 +279,7 @@ HEADERS += src/typedefs.h \ src/Geometry.h \ src/Polygon2d.h \ src/clipper-utils.h \ + src/GeometryUtils.h \ src/polyset-utils.h \ src/polyset.h \ src/printutils.h \ @@ -347,6 +348,7 @@ SOURCES += src/version_check.cc \ src/Polygon2d.cc \ src/clipper-utils.cc \ src/polyset-utils.cc \ + src/GeometryUtils.cc \ src/polyset.cc \ src/csgops.cc \ src/transform.cc \ @@ -392,6 +394,7 @@ SOURCES += src/version_check.cc \ src/QGLView.cc \ src/AutoUpdater.cc \ \ + src/grid.cc \ src/builtin.cc \ src/calc.cc \ src/export.cc \ @@ -422,6 +425,24 @@ SOURCES += src/version_check.cc \ SOURCES += src/polyclipping/clipper.cpp HEADERS += src/polyclipping/clipper.hpp +# libtess2 +INCLUDEPATH += src/libtess2/Include +SOURCES += src/libtess2/Source/bucketalloc.c \ + src/libtess2/Source/dict.c \ + src/libtess2/Source/geom.c \ + src/libtess2/Source/mesh.c \ + src/libtess2/Source/priorityq.c \ + src/libtess2/Source/sweep.c \ + src/libtess2/Source/tess.c +HEADERS += src/libtess2/Include/tesselator.h \ + src/libtess2/Source/bucketalloc.h \ + src/libtess2/Source/dict.h \ + src/libtess2/Source/geom.h \ + src/libtess2/Source/mesh.h \ + src/libtess2/Source/priorityq.h \ + src/libtess2/Source/sweep.h \ + src/libtess2/Source/tess.h + unix:!macx { SOURCES += src/imageutils-lodepng.cc SOURCES += src/OffscreenContextGLX.cc @@ -449,13 +470,13 @@ HEADERS += src/cgal.h \ src/CGALRenderer.h \ src/CGAL_Nef_polyhedron.h \ src/CGAL_Nef3_workaround.h \ + src/convex_hull_3_bugfix.h \ src/cgalworker.h \ src/Polygon2d-CGAL.h SOURCES += src/cgalutils.cc \ src/cgalutils-tess.cc \ src/cgalutils-polyhedron.cc \ - src/cgalutils-tess-old.cc \ src/CGALCache.cc \ src/CGALRenderer.cc \ src/CGAL_Nef_polyhedron.cc \ @@ -476,6 +497,7 @@ unix:!macx { SOURCES += src/PlatformUtils-posix.cc } win* { + HEADERS += src/findversion.h SOURCES += src/PlatformUtils-win.cc } diff --git a/openscad.qrc b/openscad.qrc index f202c2d4..bc855681 100644 --- a/openscad.qrc +++ b/openscad.qrc @@ -1,5 +1,24 @@ + images/zoom-text-in-white.png + images/zoom-text-in.png + images/zoom-text-out-white.png + images/zoom-text-out.png + images/Command-Redo-32-white.png + images/Command-Reset-32-white.png + images/Command-Undo-32-white.png + images/Decrease-Indent-32-white.png + images/Increase-Indent-32-white.png + images/Command-Redo-32.png + images/Command-Reset-32.png + images/Command-Undo-32.png + images/Decrease-Indent-32.png + images/Increase-Indent-32.png + icons/close.png + icons/information-icons-error.png + icons/information-icons-info.png + icons/information-icons-question.png + icons/information-icons-warning.png icons/openscad.png icons/button.png icons/background-welcome-screen.svg @@ -11,7 +30,6 @@ icons/prefsUpdate.png icons/flattr.png src/AboutDialog.html - images/Arrowhead-Right-32.png images/export.png images/axes.png images/export-white.png @@ -28,7 +46,6 @@ images/left.png images/blackUp.png images/blackNew.png - images/blackRender.png images/Rotation-32.png images/Shape-Cube-32.png images/Open-32.png @@ -52,12 +69,30 @@ images/orthogonal.png images/cross.png images/perspective1.png - images/Preview-32.png + images/preview-32.png + images/preview-32-white.png + images/render-32.png + images/render-32-white.png images/animate.png - images/Preview-32 (1).png images/orthogonalwhite.png images/perspective1white.png images/crosswhite.png icons/background.png + images/scalemarkers.png + images/scalemarkers-white.png + images/AMF.png + images/AMF-white.png + images/CSG.png + images/CSG-white.png + images/DXF.png + images/DXF-white.png + images/OFF.png + images/OFF-white.png + images/PNG.png + images/PNG-white.png + images/STL.png + images/STL-white.png + images/SVG.png + images/SVG-white.png diff --git a/openscad_win32.rc b/openscad_win32.rc index ffdc7e24..95be2192 100644 --- a/openscad_win32.rc +++ b/openscad_win32.rc @@ -33,5 +33,6 @@ VS_VERSION_INFO VERSIONINFO /* End of Version info */ IDI_ICON1 ICON DISCARDABLE "icons/openscad.ico" +IDI_ICON2 ICON DISCARDABLE "icons/openscad_doc.ico" diff --git a/qxs/openscad.qnfa b/qxs/openscad.qnfa deleted file mode 100644 index bdd64f2e..00000000 --- a/qxs/openscad.qnfa +++ /dev/null @@ -1,71 +0,0 @@ - - - - - /\* - \*/ - - - - // - \n - - - \\\n - \n - \\ - - - - - " - " - \n - \\[nrtvf\\"'\n] - - - - use - \n - - < - > - - - - - include - \n - - < - > - - - - ( - ) - { - } - \[ - \] - - - module - function - - - - for - if - else - - - - false - true - undef - - - -?[0-9]*.[0-9]+f? - -?[0-9]+[ulUL]* - diff --git a/qxs/openscad.qxf b/qxs/openscad.qxf deleted file mode 100644 index f0df3d54..00000000 --- a/qxs/openscad.qxf +++ /dev/null @@ -1,142 +0,0 @@ - - - - false - false - false - false - false - false - - - false - false - false - false - false - false - #008000 - - - true - false - false - false - false - false - #ff00ff - - - false - true - false - false - false - false - #a0a0a4 - - - false - true - false - false - false - false - #000080 - - - true - false - false - false - false - false - #000000 - - - true - false - false - false - false - false - #0095ff - - - true - false - false - false - false - false - #ff0000 - #ffff00 - - - true - false - false - false - false - false - #ff0000 - #ffff00 - - - true - false - false - false - false - false - #ffff00 - #ff0000 - - - true - true - false - false - false - false - #ff0000 - #ffff00 - - - true - false - false - false - false - true - #d060d0 - #ff0000 - - - false - false - false - false - false - false - #800080 - - - false - false - false - false - false - false - #ff0000 - - - false - false - false - false - false - false - #ff1493 - - diff --git a/releases/2014.QX.md b/releases/2015.02.md similarity index 83% rename from releases/2014.QX.md rename to releases/2015.02.md index 15500944..2904cd18 100644 --- a/releases/2014.QX.md +++ b/releases/2015.02.md @@ -1,10 +1,10 @@ **Language Features:** -* surface() can now take PNG images as input -* List comprehensions, let() * text() module * offset() -* min() and max() can now take a wvector argument +* List comprehensions, let() * concat() +* surface() can now take PNG images as input +* min() and max() can now take a vector argument * 2D minkowski and holes * chr() @@ -13,25 +13,25 @@ * MDI * FIXME: Windows cmd-line fixes * Qt5, retina -* SVG import/export -* AMF import/export +* SVG export +* AMF export * Color schemes for viewer and editor can be user-edited * Improved editor * Splash screen * Docking of GUI components -* Toolbar +* Toolbars * More robust STL export **Bugfixes/improvements:** * Internal cavity fix * Performance: 2D (clipper), preview, hull, minkowski, surface, n-ary-union, transforms (polyset) * Performance: Reduce duplicate evaluation of identical expressions -* STL export/import fixes +* STL export/import stability fixes * F6 stability fixes * Better recursion behavior * Reorganized examples a bit * improved search() behavior -* Mac: Timestamps is output fixed +* Mac: Timestamps in output fixed **Deprecations:** * polyhedron triangles diff --git a/right.png b/right.png deleted file mode 100644 index 0635ca38..00000000 Binary files a/right.png and /dev/null differ diff --git a/scripts/check-dependencies.sh b/scripts/check-dependencies.sh index 242b969e..d2e7b08e 100755 --- a/scripts/check-dependencies.sh +++ b/scripts/check-dependencies.sh @@ -167,7 +167,7 @@ qt_sysver() export QT_SELECT=5 qtpath="`qtchooser -run-tool=qmake -qt=5 -query QT_INSTALL_HEADERS`"/QtCore/qglobal.h fi - if [ ! -e $qtpath ]; then + if [ ! -e "$qtpath" ]; then if qtchooser -run-tool=qmake -qt=4 -v >/dev/null 2>&1 ; then export QT_SELECT=4 qtpath="`qtchooser -run-tool=qmake -qt=4 -query QT_INSTALL_HEADERS`"/QtCore/qglobal.h @@ -193,10 +193,10 @@ qt_sysver() # netbsd qtpath=$1/qt4/include/QtCore/qglobal.h fi - if [ ! -e $qtpath ]; then - unset QT_SELECT - return - fi + fi + if [ ! -e "$qtpath" ]; then + unset QT_SELECT + return fi qtver=`grep 'define *QT_VERSION_STR *' $qtpath | awk '{print $3}'` qtver=`echo $qtver | sed s/'"'//g` diff --git a/scripts/common-build-dependencies.sh b/scripts/common-build-dependencies.sh index 87a2bed0..8ef303df 100644 --- a/scripts/common-build-dependencies.sh +++ b/scripts/common-build-dependencies.sh @@ -161,7 +161,7 @@ build_ragel() cd "$BASEDIR"/src rm -rf "ragel-$version" if [ ! -f "ragel-$version.tar.gz" ]; then - curl --insecure -LO "http://www.complang.org/ragel/ragel-$version.tar.gz" + curl --insecure -LO "http://www.colm.net/files/ragel/ragel-$version.tar.gz" fi tar xzf "ragel-$version.tar.gz" cd "ragel-$version" diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh index 109b95a5..244c2800 100755 --- a/scripts/macosx-build-dependencies.sh +++ b/scripts/macosx-build-dependencies.sh @@ -1,4 +1,4 @@ -#!/bin/sh -e +#!/bin/bash # # This script builds all library dependencies of OpenSCAD for Mac OS X. # The libraries will be build in 64-bit (and optionally 32-bit mode) mode @@ -6,18 +6,18 @@ # # This script must be run from the OpenSCAD source root directory # -# Usage: macosx-build-dependencies.sh [-6lcd] +# Usage: macosx-build-dependencies.sh [-6lcd] [] # -6 Build only 64-bit binaries # -l Force use of LLVM compiler # -c Force use of clang compiler # -d Build for deployment (if not specified, e.g. Sparkle won't be built) +# -f Force build even if package is installed # # Prerequisites: # - MacPorts: curl, cmake # # FIXME: # o Verbose option -# o Force rebuild vs. only rebuild changes # BASEDIR=$PWD/../libraries @@ -30,17 +30,116 @@ OPTION_LLVM=false OPTION_CLANG=false OPTION_GCC=false OPTION_DEPLOY=false +OPTION_FORCE=0 + +PACKAGES=( + "eigen 3.2.4" + "gmp 5.1.3" + "mpfr 3.1.2" + "boost 1.57.0" + "qt5 5.4.0" + "qscintilla 2.8.4" + # NB! For eigen, also update the path in the function + # NB! For CGAL, also update the actual download URL in the function + "cgal 4.5.1" + "glew 1.12.0" + "gettext 0.19.4" + "libffi 3.2.1" + "glib2 2.42.1" + "opencsg 1.4.0" + "freetype 2.5.5" + "ragel 6.9" + "harfbuzz 0.9.37" + "libxml2 2.9.2" + "fontconfig 2.11.1" +) +DEPLOY_PACKAGES=( + "sparkle Cocoanetics:1e7dcb1a48b96d1a8c62100b5864bd50211cbae1" +) printUsage() { - echo "Usage: $0 [-6lcd]" + echo "Usage: $0 [-6lcd] []" echo echo " -6 Build only 64-bit binaries" echo " -l Force use of LLVM compiler" echo " -c Force use of clang compiler" echo " -d Build for deployment" + echo " -f Force build even if package is installed" + echo + echo " If is not specified, builds all packages" } +# Outputs all package names +all_packages() +{ + for i in $(seq 0 $(( ${#PACKAGES[@]} - 1 )) ); do + local p=${PACKAGES[$i]} + echo -n "${p%%\ *} " # Cut at first space + done +} + +# Usage: package_version +# Outputs the package version for the given package +package_version() +{ + for i in $(seq 0 $(( ${#PACKAGES[@]} - 1 )) ); do + local p=${PACKAGES[$i]} + if [ "$1" = "${p%%\ *}" ]; then + echo "${p#*\ }" # cut until first space + return 0 + fi + done + return 1 +} + +# Usage: build +build() +{ + local package=$1 + local version=$2 + + local should_install=$(( $OPTION_FORCE == 1 )) + if [[ $should_install == 0 ]]; then + is_installed $package $version + should_install=$? + fi + if [[ $should_install == 1 ]]; then + set -e + build_$package $version + set +e + fi + +} + +# Usage: is_installed [] +# Returns success (0) if the/a version of the package is already installed +is_installed() +{ + if check_$1 $2; then + echo "$1 already installed - not building" + return 0 + fi + return 1 +} + +# Usage: check_dir +# Checks if $DEPLOYDIR/ exists and is a folder +# Returns success (0) if the folder exists +check_dir() +{ + test -d "$DEPLOYDIR/$1" +} + +# Usage: check_file +# Checks if $DEPLOYDIR/ exists and is a file +# Returns success (0) if the file exists +check_file() +{ + test -f "$DEPLOYDIR/$1" +} + + patch_qt_disable_core_wlan() { version="$1" @@ -104,15 +203,15 @@ build_qt() make -j"$NUMCPU" install } +check_qt5() +{ + check_dir lib/QtCore.framework +} + build_qt5() { version=$1 - if [ -d $DEPLOYDIR/lib/QtCore.framework ]; then - echo "Qt5 already installed. not building" - return - fi - echo "Building Qt" $version "..." cd $BASEDIR/src v=(${version//./ }) # Split into array @@ -133,6 +232,11 @@ build_qt5() make -j"$NUMCPU" install } +check_qscintilla() +{ + check_file include/Qsci/qsciscintilla.h +} + build_qscintilla() { version=$1 @@ -149,6 +253,11 @@ build_qscintilla() install_name_tool -id $DEPLOYDIR/lib/libqscintilla2.dylib $DEPLOYDIR/lib/libqscintilla2.dylib } +check_gmp() +{ + check_file lib/libgmp.dylib +} + # Hack warning: gmplib is built separately in 32-bit and 64-bit mode # and then merged afterwards. gmplib's header files are dependent on # the CPU architecture on which configure was run and will be patched accordingly. @@ -156,11 +265,6 @@ build_gmp() { version=$1 - if [ -f $DEPLOYDIR/lib/libgmp.dylib ]; then - echo "gmp already installed. not building" - return - fi - echo "Building gmp" $version "..." cd $BASEDIR/src rm -rf gmp-$version @@ -252,17 +356,17 @@ EOF cp x86_64/include/gmpxx.h include/ } +check_mpfr() +{ + check_file include/mpfr.h +} + # As with gmplib, mpfr is built separately in 32-bit and 64-bit mode and then merged # afterwards. build_mpfr() { version=$1 - if [ -f $DEPLOYDIR/include/mpfr.h ]; then - echo "mpfr already installed. not building" - return - fi - echo "Building mpfr" $version "..." cd $BASEDIR/src rm -rf mpfr-$version @@ -300,15 +404,15 @@ build_mpfr() cp x86_64/include/mpf2mpfr.h include/ } +check_boost() +{ + check_file lib/libboost_system.dylib +} + build_boost() { version=$1 - if [ -f $DEPLOYDIR/lib/libboost_system.dylib ]; then - echo "boost already installed. not building" - return - fi - bversion=`echo $version | tr "." "_"` echo "Building boost" $version "..." cd $BASEDIR/src @@ -343,15 +447,15 @@ build_boost() } +check_cgal() +{ + check_file lib/libCGAL.dylib +} + build_cgal() { version=$1 - if [ -f $DEPLOYDIR/lib/libCGAL.dylib ]; then - echo "cgal already installed. not building" - return - fi - echo "Building CGAL" $version "..." cd $BASEDIR/src rm -rf CGAL-$version @@ -383,15 +487,15 @@ build_cgal() install_name_tool -change $PWD/lib/libCGAL.9.dylib $DEPLOYDIR/lib/libCGAL.dylib $DEPLOYDIR/lib/libCGAL_Core.dylib } +check_glew() +{ + check_file lib/libGLEW.dylib +} + build_glew() { version=$1 - if [ -f $DEPLOYDIR/lib/libGLEW.dylib ]; then - echo "glew already installed. not building" - return - fi - echo "Building GLEW" $version "..." cd $BASEDIR/src rm -rf glew-$version @@ -407,15 +511,15 @@ build_glew() make GLEW_DEST=$DEPLOYDIR CC=$CC CFLAGS.EXTRA="-no-cpp-precomp -dynamic -fno-common -mmacosx-version-min=$MAC_OSX_VERSION_MIN $GLEW_EXTRA_FLAGS -arch x86_64" LDFLAGS.EXTRA="-mmacosx-version-min=$MAC_OSX_VERSION_MIN $GLEW_EXTRA_FLAGS -arch x86_64" STRIP= install } +check_opencsg() +{ + check_file lib/libopencsg.dylib +} + build_opencsg() { version=$1 - if [ -f $DEPLOYDIR/lib/libopencsg.dylib ]; then - echo "opencsg already installed. not building" - return - fi - echo "Building OpenCSG" $version "..." cd $BASEDIR/src rm -rf OpenCSG-$version @@ -432,15 +536,23 @@ build_opencsg() make install } +# Usage: func [] +check_eigen() +{ + # To check version: + # include/eigen3/Eigen/src/Core/util/Macros.h: + # #define EIGEN_WORLD_VERSION 3 + # #define EIGEN_MAJOR_VERSION 2 + # #define EIGEN_MINOR_VERSION 3 + + check_dir include/eigen3 +} + +# Usage: func build_eigen() { version=$1 - if [ -d $DEPLOYDIR/include/eigen3 ]; then - echo "eigen3 already installed. not building" - return - fi - echo "Building eigen" $version "..." cd $BASEDIR/src rm -rf eigen-$version @@ -453,6 +565,7 @@ build_eigen() elif [ $version = "3.2.1" ]; then EIGENDIR=eigen-eigen-6b38706d90a9; elif [ $version = "3.2.2" ]; then EIGENDIR=eigen-eigen-1306d75b4a21; elif [ $version = "3.2.3" ]; then EIGENDIR=eigen-eigen-36fd1ba04c12; + elif [ $version = "3.2.4" ]; then EIGENDIR=eigen-eigen-10219c95fe65; fi if [ $EIGENDIR = "none" ]; then @@ -473,19 +586,28 @@ build_eigen() if $OPTION_32BIT; then EIGEN_EXTRA_FLAGS=";i386" fi - cmake -DCMAKE_INSTALL_PREFIX=$DEPLOYDIR -DEIGEN_BUILD_LIB=ON -DBUILD_SHARED_LIBS=FALSE -DCMAKE_OSX_DEPLOYMENT_TARGET="$MAC_OSX_VERSION_MIN" -DCMAKE_OSX_ARCHITECTURES="x86_64$EIGEN_EXTRA_FLAGS" .. + cmake -DCMAKE_INSTALL_PREFIX=$DEPLOYDIR -DEIGEN_TEST_NOQT=TRUE -DCMAKE_OSX_DEPLOYMENT_TARGET="$MAC_OSX_VERSION_MIN" -DCMAKE_OSX_ARCHITECTURES="x86_64$EIGEN_EXTRA_FLAGS" .. make -j"$NUMCPU" install - make install } +check_sparkle() +{ + check_file lib/Sparkle.framework/Sparkle +} + +# Usage: build_sparkle : build_sparkle() { + v=$1 + github=${1%%:*} # Cut at first colon + version=${1#*:} # cut until first colon + + echo "Building Sparkle" $version "..." + # Let Sparkle use the default compiler unset CC unset CXX - github=$1 - version=$2 - echo "Building Sparkle" $version "..." + cd $BASEDIR/src rm -rf Sparkle-$version if [ ! -f Sparkle-$version.zip ]; then @@ -504,15 +626,15 @@ build_sparkle() install_name_tool -id $DEPLOYDIR/lib/Sparkle.framework/Versions/A/Sparkle $DEPLOYDIR/lib/Sparkle.framework/Sparkle } +check_freetype() +{ + check_file lib/libfreetype.dylib +} + build_freetype() { version="$1" - extra_config_flags="$2" - - if [ -f $DEPLOYDIR/lib/libfreetype.dylib ]; then - echo "freetype already installed. not building" - return - fi + extra_config_flags="--without-png" echo "Building freetype $version..." cd "$BASEDIR"/src @@ -522,20 +644,23 @@ build_freetype() fi tar xzf "freetype-$version.tar.gz" cd "freetype-$version" + + export FREETYPE_CFLAGS="-I$DEPLOYDIR/include -I$DEPLOYDIR/include/freetype2" + export FREETYPE_LIBS="-L$DEPLOYDIR/lib -lfreetype" PKG_CONFIG_LIBDIR="$DEPLOYDOR/lib/pkgconfig" ./configure --prefix="$DEPLOYDIR" CFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN LDFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN $extra_config_flags make -j"$NUMCPU" make install } +check_libxml2() +{ + check_file lib/libxml2.dylib +} + build_libxml2() { version="$1" - if [ -f $DEPLOYDIR/lib/libxml2.dylib ]; then - echo "libxml2 already installed. not building" - return - fi - echo "Building libxml2 $version..." cd "$BASEDIR"/src rm -rf "libxml2-$version" @@ -549,15 +674,15 @@ build_libxml2() make install } +check_fontconfig() +{ + check_file lib/libfontconfig.dylib +} + build_fontconfig() { version=$1 - if [ -f $DEPLOYDIR/lib/libfontconfig.dylib ]; then - echo "fontconfig already installed. not building" - return - fi - echo "Building fontconfig $version..." cd "$BASEDIR"/src rm -rf "fontconfig-$version" @@ -573,15 +698,15 @@ build_fontconfig() make install } +check_libffi() +{ + check_file lib/libffi.dylib +} + build_libffi() { version="$1" - if [ -f $DEPLOYDIR/lib/libffi.dylib ]; then - echo "libffi already installed. not building" - return - fi - echo "Building libffi $version..." cd "$BASEDIR"/src rm -rf "libffi-$version" @@ -595,15 +720,15 @@ build_libffi() make install } +check_gettext() +{ + check_file lib/libgettextlib.dylib +} + build_gettext() { version="$1" - if [ -f $DEPLOYDIR/lib/libgettextlib.dylib ]; then - echo "gettext already installed. not building" - return - fi - echo "Building gettext $version..." cd "$BASEDIR"/src rm -rf "gettext-$version" @@ -618,15 +743,15 @@ build_gettext() make install } +check_glib2() +{ + check_file lib/libglib-2.0.dylib +} + build_glib2() { version="$1" - if [ -f $DEPLOYDIR/lib/libglib-2.0.dylib ]; then - echo "glib2 already installed. not building" - return - fi - echo "Building glib2 $version..." cd "$BASEDIR"/src @@ -645,15 +770,15 @@ build_glib2() make install } +check_ragel() +{ + check_file bin/ragel +} + build_ragel() { version=$1 - if [ -f $DEPLOYDIR/bin/ragel ]; then - echo "ragel already installed. not building" - return - fi - echo "Building ragel $version..." cd "$BASEDIR"/src rm -rf "ragel-$version" @@ -668,15 +793,15 @@ build_ragel() make install } +check_harfbuzz() +{ + check_file lib/libharfbuzz.dylib +} + build_harfbuzz() { version=$1 - extra_config_flags="$2" - - if [ -f $DEPLOYDIR/lib/libharfbuzz.dylib ]; then - echo "harfbuzz already installed. not building" - return - fi + extra_config_flags="--with-coretext=auto --with-glib=no" echo "Building harfbuzz $version..." cd "$BASEDIR"/src @@ -700,19 +825,27 @@ if [ ! -f $OPENSCADDIR/openscad.pro ]; then fi OPENSCAD_SCRIPTDIR=$PWD/scripts -while getopts '6lcd' c +while getopts '6lcdf' c do case $c in 6) OPTION_32BIT=false;; l) OPTION_LLVM=true;; c) OPTION_CLANG=true;; d) OPTION_DEPLOY=true;; + f) OPTION_FORCE=1;; + *) printUsage;exit 1;; esac done +OPTION_PACKAGES="${@:$OPTIND}" + OSX_VERSION=`sw_vers -productVersion | cut -d. -f2` -if (( $OSX_VERSION >= 8 )); then - echo "Detected Mountain Lion (10.8) or later" +if (( $OSX_VERSION >= 10 )); then + echo "Detected Yosemite (10.10) or later" +elif (( $OSX_VERSION >= 9 )); then + echo "Detected Mavericks (10.9)" +elif (( $OSX_VERSION >= 8 )); then + echo "Detected Mountain Lion (10.8)" elif (( $OSX_VERSION >= 7 )); then echo "Detected Lion (10.7)" else @@ -771,30 +904,32 @@ else echo "Building 64-bit binaries" fi +if (( $OPTION_FORCE )); then + echo "Forcing rebuild" +fi + echo "Using basedir:" $BASEDIR mkdir -p $SRCDIR $DEPLOYDIR -build_qt5 5.4.0 -build_qscintilla 2.8.4 -# NB! For eigen, also update the path in the function -build_eigen 3.2.3 -build_gmp 5.1.3 -build_mpfr 3.1.2 -build_boost 1.57.0 -# NB! For CGAL, also update the actual download URL in the function -build_cgal 4.5.1 -build_glew 1.11.0 -build_gettext 0.19.4 -build_libffi 3.2.1 -build_glib2 2.42.1 -build_opencsg 1.4.0 -build_freetype 2.5.4 --without-png -build_ragel 6.9 -build_harfbuzz 0.9.37 "--with-coretext=auto --with-glib=no" -export FREETYPE_CFLAGS="-I$DEPLOYDIR/include -I$DEPLOYDIR/include/freetype2" -export FREETYPE_LIBS="-L$DEPLOYDIR/lib -lfreetype" -build_libxml2 2.9.2 -build_fontconfig 2.11.1 + +# Only build deploy packages in deploy mode if $OPTION_DEPLOY; then -# build_sparkle andymatuschak 0ed83cf9f2eeb425d4fdd141c01a29d843970c20 - build_sparkle Cocoanetics 1e7dcb1a48b96d1a8c62100b5864bd50211cbae1 + # Array concatenation + PACKAGES=("${PACKAGES[@]}" "${DEPLOY_PACKAGES[@]}") fi + +# Build specified (or all) packages +ALL_PACKAGES=$(all_packages) +if [ -z "$OPTION_PACKAGES" ]; then + OPTION_PACKAGES=$ALL_PACKAGES +fi + +echo "Building packages: $OPTION_PACKAGES" +echo + +for package in $OPTION_PACKAGES; do + if [[ $ALL_PACKAGES =~ $package ]]; then + build $package $(package_version $package) + else + echo "Skipping unknown package $package" + fi +done diff --git a/scripts/release-common.sh b/scripts/release-common.sh index 2da42495..2c98a625 100755 --- a/scripts/release-common.sh +++ b/scripts/release-common.sh @@ -255,7 +255,7 @@ case $OS in exit fi # make console pipe-able openscad.com - see winconsole.pro for info - qmake ../winconsole.pro + qmake ../winconsole/winconsole.pro make if [ ! -e $TARGET/openscad.com ]; then echo "cant find $TARGET/openscad.com. build failed. stopping." diff --git a/scripts/uni-build-dependencies.sh b/scripts/uni-build-dependencies.sh index 5ee34919..eb59665e 100755 --- a/scripts/uni-build-dependencies.sh +++ b/scripts/uni-build-dependencies.sh @@ -813,7 +813,7 @@ build_glib2 2.38.2 build_freetype 2.5.0.1 --without-png build_libxml2 2.9.1 build_fontconfig 2.11.0 --with-add-fonts=/usr/X11R6/lib/X11/fonts,/usr/local/share/fonts -build_ragel 6.8 +build_ragel 6.9 build_harfbuzz 0.9.23 --with-glib=yes echo "OpenSCAD dependencies built and installed to " $BASEDIR diff --git a/src/AboutDialog.html b/src/AboutDialog.html index 22ca9272..478c5e20 100644 --- a/src/AboutDialog.html +++ b/src/AboutDialog.html @@ -23,7 +23,7 @@

-Copyright (C) 2009-2014 Marius Kintel <marius@kintel.net> and Clifford Wolf <clifford@clifford.at> +Copyright (C) 2009-2015 Marius Kintel <marius@kintel.net> and Clifford Wolf <clifford@clifford.at>

@@ -47,12 +47,18 @@ Please visit this link for a copy of the license: GNU GMP

  • GNU MPFR
  • CGAL +
  • Clipper
  • Eigen
  • OpenCSG
  • OpenGL
  • GLEW -
  • Qt Toolkit +
  • Qt Toolkit +
  • QScintilla
  • Boost +
  • GLib +
  • Fontconfig +
  • Freetype +
  • Harfbuzz
  • Bison
  • Flex
  • CMake diff --git a/src/CGALRenderer.cc b/src/CGALRenderer.cc index c9b816c5..a3505856 100644 --- a/src/CGALRenderer.cc +++ b/src/CGALRenderer.cc @@ -32,6 +32,7 @@ // dxfdata.h must come first for Eigen SIMD alignment issues #include "dxfdata.h" #include "polyset.h" +#include "polyset-utils.h" #include "printutils.h" #include "CGALRenderer.h" @@ -44,7 +45,13 @@ CGALRenderer::CGALRenderer(shared_ptr geom) { if (shared_ptr ps = dynamic_pointer_cast(geom)) { - this->polyset = ps; + assert(ps->getDimension() == 3); + // We need to tessellate here, in case the generated PolySet contains concave polygons + // See testdata/scad/3D/features/polyhedron-concave-test.scad + PolySet *ps_tri = new PolySet(3, ps->convexValue()); + ps_tri->setConvexity(ps->getConvexity()); + PolysetUtils::tessellate_faces(*ps, *ps_tri); + this->polyset.reset(ps_tri); } else if (shared_ptr poly = dynamic_pointer_cast(geom)) { this->polyset.reset(poly->tessellate()); diff --git a/src/CSGTermEvaluator.cc b/src/CSGTermEvaluator.cc index 4adfa62d..e2207f76 100644 --- a/src/CSGTermEvaluator.cc +++ b/src/CSGTermEvaluator.cc @@ -11,6 +11,7 @@ #include "printutils.h" #include "GeometryEvaluator.h" #include "polyset.h" +#include "polyset-utils.h" #include #include @@ -98,8 +99,23 @@ static shared_ptr evaluate_csg_term_from_geometry(const State &state, // We cannot render Polygon2d directly, so we preprocess (tessellate) it here shared_ptr g = geom; - shared_ptr p2d = dynamic_pointer_cast(geom); - if (p2d) g.reset(p2d->tessellate()); + if (!g->isEmpty()) { + shared_ptr p2d = dynamic_pointer_cast(geom); + if (p2d) { + g.reset(p2d->tessellate()); + } + else { + // We cannot render concave polygons, so tessellate any 3D PolySets + shared_ptr ps = dynamic_pointer_cast(geom); + if (ps) { + assert(ps->getDimension() == 3); + PolySet *ps_tri = new PolySet(3, ps->convexValue()); + ps_tri->setConvexity(ps->getConvexity()); + PolysetUtils::tessellate_faces(*ps, *ps_tri); + g.reset(ps_tri); + } + } + } shared_ptr t(new CSGTerm(g, state.matrix(), state.color(), stream.str())); if (modinst->isHighlight()) { diff --git a/src/Camera.cc b/src/Camera.cc index 7e53d363..a386aef6 100644 --- a/src/Camera.cc +++ b/src/Camera.cc @@ -26,8 +26,7 @@ void Camera::setup(std::vector params) type = Camera::GIMBAL; object_trans << params[0], params[1], params[2]; object_rot << params[3], params[4], params[5]; - viewer_distance = params[6]; - height = params[6]; + height = viewer_distance = params[6]; } else if (params.size() == 6) { type = Camera::VECTOR; eye << params[0], params[1], params[2]; @@ -74,13 +73,13 @@ void Camera::viewAll(const BoundingBox &bbox, float scalefactor) switch (this->projection) { case Camera::ORTHOGONAL: - this->height = bbox.diagonal().norm(); + this->height = this->viewer_distance = bbox.diagonal().norm(); break; case Camera::PERSPECTIVE: { double radius = bbox.diagonal().norm()/2; switch (this->type) { case Camera::GIMBAL: - this->viewer_distance = radius / tan(this->fov*M_PI/360); + this->height = this->viewer_distance = radius / tan(this->fov*M_PI/360); break; case Camera::VECTOR: { Vector3d cameradir = (this->center - this->eye).normalized(); @@ -101,8 +100,7 @@ void Camera::viewAll(const BoundingBox &bbox, float scalefactor) void Camera::zoom(int delta) { - this->viewer_distance *= pow(0.9, delta / 120.0); - this->height = this->viewer_distance; + this->height = this->viewer_distance *= pow(0.9, delta / 120.0); } void Camera::setProjection(ProjectionType type) @@ -115,8 +113,7 @@ void Camera::resetView() type = Camera::GIMBAL; object_rot << 35, 0, -25; object_trans << 0, 0, 0; - height = 140; - viewer_distance = 140; + height = viewer_distance = 140; } double Camera::zoomValue() diff --git a/src/FontCache.cc b/src/FontCache.cc index c353fe6f..1786dca8 100644 --- a/src/FontCache.cc +++ b/src/FontCache.cc @@ -83,7 +83,7 @@ const std::string &FontInfo::get_file() const FontCache * FontCache::self = NULL; FontCache::InitHandlerFunc *FontCache::cb_handler = FontCache::defaultInitHandler; void *FontCache::cb_userdata = NULL; -const std::string FontCache::DEFAULT_FONT("XXX"); +const std::string FontCache::DEFAULT_FONT("Liberation Sans:style=Regular"); /** * Default implementation for the font cache initialization. In case no other diff --git a/src/FontListDialog.cc b/src/FontListDialog.cc index 474c2ef3..90b46cba 100644 --- a/src/FontListDialog.cc +++ b/src/FontListDialog.cc @@ -136,11 +136,11 @@ void FontListDialog::update_font_list() QString FontListDialog::quote(const QString& text) { QString result = text; - result.replace('\\', "\\\\") - .replace('-', "\\-") - .replace(':', "\\:") - .replace(',', "\\,") - .replace('=', "\\=") - .replace('_', "\\_"); + result.replace('\\', "\\\\\\\\") + .replace('-', "\\\\-") + .replace(':', "\\\\:") + .replace(',', "\\\\,") + .replace('=', "\\\\=") + .replace('_', "\\\\_"); return result; } diff --git a/src/GLView.cc b/src/GLView.cc index e76a10c3..687db19f 100644 --- a/src/GLView.cc +++ b/src/GLView.cc @@ -23,6 +23,7 @@ GLView::GLView() showfaces = true; showaxes = false; showcrosshairs = false; + showscale = false; renderer = NULL; colorscheme = &ColorMap::inst()->defaultColorScheme(); cam = Camera(); @@ -168,6 +169,8 @@ void GLView::paintGL() glTranslated(cam.object_trans.x(), cam.object_trans.y(), cam.object_trans.z()); // ...the axis lines need to follow the object translation. if (showaxes) GLView::showAxes(bgcontrast); + // mark the scale along the axis lines + if (showscale) GLView::showScalemarkers(bgcontrast); } glEnable(GL_LIGHTING); @@ -500,3 +503,321 @@ void GLView::showCrosshairs() glEnd(); } +void GLView::showScalemarkers(const Color4f &col) +{ + // Add scale tics on large axes + double l = cam.zoomValue(); + glLineWidth(this->getDPI()); + glColor3f(col[0], col[1], col[2]); + + // determine the log value to provide proportional tics + int log_l = (int)log10(l); + + // j represents the increment for each minor tic + double j = 10; + // deal with 0 log values + if (l < 1.5){ + j = pow(10,log_l-2); + } else { + j = pow(10,log_l-1); + } + + int size_div_sm = 60; // divisor for l to determine minor tic size + int size_div = size_div_sm; + int line_cnt = 0; + + for (double i=0;i( &(std::ostringstream() << i) )->str(); + + // setup how far above the axis (or tic TBD) to draw the number + double dig_buf = (l/size_div_sm)/4; + // setup the size of the character box + double dig_w = (l/size_div_sm)/2; + double dig_h = (l/size_div_sm) + dig_buf; + // setup the distance between characters + double kern = dig_buf; + double dig_wk = (dig_w) + kern; + + // set up ordering for different axes + int ax[6][3] = { + {0,1,2}, + {1,0,2}, + {1,2,0}, + {0,1,2}, + {1,0,2}, + {1,2,0}}; + + // set up character vertex seqeunces for different axes + int or_2[6][6]={ + {0,1,3,2,4,5}, + {1,0,2,3,5,4}, + {1,0,2,3,5,4}, + {1,0,2,3,5,4}, + {0,1,3,2,4,5}, + {0,1,3,2,4,5}}; + + int or_3[6][7]={ + {0,1,3,2,3,5,4}, + {1,0,2,3,2,4,5}, + {1,0,2,3,2,4,5}, + {1,0,2,3,2,4,5}, + {0,1,3,2,3,5,4}, + {0,1,3,2,3,5,4}}; + + int or_4[6][5]={ + {0,2,3,1,5}, + {1,3,2,0,4}, + {1,3,2,0,4}, + {1,3,2,0,4}, + {0,2,3,1,5}, + {0,2,3,1,5}}; + + int or_5[6][6]={ + {1,0,2,3,5,4}, + {0,1,3,2,4,5}, + {0,1,3,2,4,5}, + {0,1,3,2,4,5}, + {1,0,2,3,5,4}, + {1,0,2,3,5,4}}; + + int or_6[6][6]={ + {1,0,4,5,3,2}, + {0,1,5,4,2,3}, + {0,1,5,4,2,3}, + {0,1,5,4,2,3}, + {1,0,4,5,3,2}, + {1,0,4,5,3,2}}; + + int or_7[6][3]={ + {0,1,4}, + {1,0,5}, + {1,0,5}, + {1,0,5}, + {0,1,4}, + {0,1,4}}; + + int or_9[6][5]={ + {5,1,0,2,3}, + {4,0,1,3,2}, + {4,0,1,3,2}, + {4,0,1,3,2}, + {5,1,0,2,3}, + {5,1,0,2,3}}; + + std::string stash_digit = digit; + + // walk through axes + for (int di=0;di<6;di++){ + + // setup negative axes + double polarity = 1; + if (di>2){ + polarity = -1; + digit = "-" + stash_digit; + } + + // fix the axes that need to run the opposite direction + if (di>0 && di<4){ + std::reverse(digit.begin(),digit.end()); + } + + // walk through and render the characters of the string + for(std::string::size_type char_num = 0; char_num < digit.size(); ++char_num){ + // setup the vertices for the char rendering based on the axis and position + double dig_vrt[6][3] = { + {polarity*((i+((char_num)*dig_wk))-(dig_w/2)),dig_h,0}, + {polarity*((i+((char_num)*dig_wk))+(dig_w/2)),dig_h,0}, + {polarity*((i+((char_num)*dig_wk))-(dig_w/2)),dig_h/2+dig_buf,0}, + {polarity*((i+((char_num)*dig_wk))+(dig_w/2)),dig_h/2+dig_buf,0}, + {polarity*((i+((char_num)*dig_wk))-(dig_w/2)),dig_buf,0}, + {polarity*((i+((char_num)*dig_wk))+(dig_w/2)),dig_buf,0}}; + + // convert the char into lines appropriate for the axis being used + // psuedo 7 segment vertices are: + // A--B + // | | + // C--D + // | | + // E--F + switch(digit[char_num]){ + case '1': + glBegin(GL_LINES); + glVertex3d(dig_vrt[0][ax[di][0]],dig_vrt[0][ax[di][1]],dig_vrt[0][ax[di][2]]); //a + glVertex3d(dig_vrt[4][ax[di][0]],dig_vrt[4][ax[di][1]],dig_vrt[4][ax[di][2]]); //e + glEnd(); + break; + + case '2': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_2[di][0]][ax[di][0]],dig_vrt[or_2[di][0]][ax[di][1]],dig_vrt[or_2[di][0]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_2[di][1]][ax[di][0]],dig_vrt[or_2[di][1]][ax[di][1]],dig_vrt[or_2[di][1]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_2[di][2]][ax[di][0]],dig_vrt[or_2[di][2]][ax[di][1]],dig_vrt[or_2[di][2]][ax[di][2]]); //d + glVertex3d(dig_vrt[or_2[di][3]][ax[di][0]],dig_vrt[or_2[di][3]][ax[di][1]],dig_vrt[or_2[di][3]][ax[di][2]]); //c + glVertex3d(dig_vrt[or_2[di][4]][ax[di][0]],dig_vrt[or_2[di][4]][ax[di][1]],dig_vrt[or_2[di][4]][ax[di][2]]); //e + glVertex3d(dig_vrt[or_2[di][5]][ax[di][0]],dig_vrt[or_2[di][5]][ax[di][1]],dig_vrt[or_2[di][5]][ax[di][2]]); //f + glEnd(); + break; + + case '3': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_3[di][0]][ax[di][0]],dig_vrt[or_3[di][0]][ax[di][1]],dig_vrt[or_3[di][0]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_3[di][1]][ax[di][0]],dig_vrt[or_3[di][1]][ax[di][1]],dig_vrt[or_3[di][1]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_3[di][2]][ax[di][0]],dig_vrt[or_3[di][2]][ax[di][1]],dig_vrt[or_3[di][2]][ax[di][2]]); //d + glVertex3d(dig_vrt[or_3[di][3]][ax[di][0]],dig_vrt[or_3[di][3]][ax[di][1]],dig_vrt[or_3[di][3]][ax[di][2]]); //c + glVertex3d(dig_vrt[or_3[di][4]][ax[di][0]],dig_vrt[or_3[di][4]][ax[di][1]],dig_vrt[or_3[di][4]][ax[di][2]]); //d + glVertex3d(dig_vrt[or_3[di][5]][ax[di][0]],dig_vrt[or_3[di][5]][ax[di][1]],dig_vrt[or_3[di][5]][ax[di][2]]); //f + glVertex3d(dig_vrt[or_3[di][6]][ax[di][0]],dig_vrt[or_3[di][6]][ax[di][1]],dig_vrt[or_3[di][6]][ax[di][2]]); //e + glEnd(); + break; + + case '4': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_4[di][0]][ax[di][0]],dig_vrt[or_4[di][0]][ax[di][1]],dig_vrt[or_4[di][0]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_4[di][1]][ax[di][0]],dig_vrt[or_4[di][1]][ax[di][1]],dig_vrt[or_4[di][1]][ax[di][2]]); //c + glVertex3d(dig_vrt[or_4[di][2]][ax[di][0]],dig_vrt[or_4[di][2]][ax[di][1]],dig_vrt[or_4[di][2]][ax[di][2]]); //d + glVertex3d(dig_vrt[or_4[di][3]][ax[di][0]],dig_vrt[or_4[di][3]][ax[di][1]],dig_vrt[or_4[di][3]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_4[di][4]][ax[di][0]],dig_vrt[or_4[di][4]][ax[di][1]],dig_vrt[or_4[di][4]][ax[di][2]]); //f + glEnd(); + break; + + case '5': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_5[di][0]][ax[di][0]],dig_vrt[or_5[di][0]][ax[di][1]],dig_vrt[or_5[di][0]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_5[di][1]][ax[di][0]],dig_vrt[or_5[di][1]][ax[di][1]],dig_vrt[or_5[di][1]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_5[di][2]][ax[di][0]],dig_vrt[or_5[di][2]][ax[di][1]],dig_vrt[or_5[di][2]][ax[di][2]]); //c + glVertex3d(dig_vrt[or_5[di][3]][ax[di][0]],dig_vrt[or_5[di][3]][ax[di][1]],dig_vrt[or_5[di][3]][ax[di][2]]); //d + glVertex3d(dig_vrt[or_5[di][4]][ax[di][0]],dig_vrt[or_5[di][4]][ax[di][1]],dig_vrt[or_5[di][4]][ax[di][2]]); //f + glVertex3d(dig_vrt[or_5[di][5]][ax[di][0]],dig_vrt[or_5[di][5]][ax[di][1]],dig_vrt[or_5[di][5]][ax[di][2]]); //e + glEnd(); + break; + + case '6': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_6[di][0]][ax[di][0]],dig_vrt[or_6[di][0]][ax[di][1]],dig_vrt[or_6[di][0]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_6[di][1]][ax[di][0]],dig_vrt[or_6[di][1]][ax[di][1]],dig_vrt[or_6[di][1]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_6[di][2]][ax[di][0]],dig_vrt[or_6[di][2]][ax[di][1]],dig_vrt[or_6[di][2]][ax[di][2]]); //e + glVertex3d(dig_vrt[or_6[di][3]][ax[di][0]],dig_vrt[or_6[di][3]][ax[di][1]],dig_vrt[or_6[di][3]][ax[di][2]]); //f + glVertex3d(dig_vrt[or_6[di][4]][ax[di][0]],dig_vrt[or_6[di][4]][ax[di][1]],dig_vrt[or_6[di][4]][ax[di][2]]); //d + glVertex3d(dig_vrt[or_6[di][5]][ax[di][0]],dig_vrt[or_6[di][5]][ax[di][1]],dig_vrt[or_6[di][5]][ax[di][2]]); //c + glEnd(); + break; + + case '7': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_7[di][0]][ax[di][0]],dig_vrt[or_7[di][0]][ax[di][1]],dig_vrt[or_7[di][0]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_7[di][1]][ax[di][0]],dig_vrt[or_7[di][1]][ax[di][1]],dig_vrt[or_7[di][1]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_7[di][2]][ax[di][0]],dig_vrt[or_7[di][2]][ax[di][1]],dig_vrt[or_7[di][2]][ax[di][2]]); //e + glEnd(); + break; + + case '8': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[2][ax[di][0]],dig_vrt[2][ax[di][1]],dig_vrt[2][ax[di][2]]); //c + glVertex3d(dig_vrt[3][ax[di][0]],dig_vrt[3][ax[di][1]],dig_vrt[3][ax[di][2]]); //d + glVertex3d(dig_vrt[1][ax[di][0]],dig_vrt[1][ax[di][1]],dig_vrt[1][ax[di][2]]); //b + glVertex3d(dig_vrt[0][ax[di][0]],dig_vrt[0][ax[di][1]],dig_vrt[0][ax[di][2]]); //a + glVertex3d(dig_vrt[4][ax[di][0]],dig_vrt[4][ax[di][1]],dig_vrt[4][ax[di][2]]); //e + glVertex3d(dig_vrt[5][ax[di][0]],dig_vrt[5][ax[di][1]],dig_vrt[5][ax[di][2]]); //f + glVertex3d(dig_vrt[3][ax[di][0]],dig_vrt[3][ax[di][1]],dig_vrt[3][ax[di][2]]); //d + glEnd(); + break; + + case '9': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_9[di][0]][ax[di][0]],dig_vrt[or_9[di][0]][ax[di][1]],dig_vrt[or_9[di][0]][ax[di][2]]); //f + glVertex3d(dig_vrt[or_9[di][1]][ax[di][0]],dig_vrt[or_9[di][1]][ax[di][1]],dig_vrt[or_9[di][1]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_9[di][2]][ax[di][0]],dig_vrt[or_9[di][2]][ax[di][1]],dig_vrt[or_9[di][2]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_9[di][3]][ax[di][0]],dig_vrt[or_9[di][3]][ax[di][1]],dig_vrt[or_9[di][3]][ax[di][2]]); //c + glVertex3d(dig_vrt[or_9[di][4]][ax[di][0]],dig_vrt[or_9[di][4]][ax[di][1]],dig_vrt[or_9[di][4]][ax[di][2]]); //d + glEnd(); + break; + + case '0': + glBegin(GL_LINE_LOOP); + glVertex3d(dig_vrt[0][ax[di][0]],dig_vrt[0][ax[di][1]],dig_vrt[0][ax[di][2]]); //a + glVertex3d(dig_vrt[1][ax[di][0]],dig_vrt[1][ax[di][1]],dig_vrt[1][ax[di][2]]); //b + glVertex3d(dig_vrt[5][ax[di][0]],dig_vrt[5][ax[di][1]],dig_vrt[5][ax[di][2]]); //f + glVertex3d(dig_vrt[4][ax[di][0]],dig_vrt[4][ax[di][1]],dig_vrt[4][ax[di][2]]); //e + glEnd(); + break; + + case '-': + glBegin(GL_LINES); + glVertex3d(dig_vrt[2][ax[di][0]],dig_vrt[2][ax[di][1]],dig_vrt[2][ax[di][2]]); //c + glVertex3d(dig_vrt[3][ax[di][0]],dig_vrt[3][ax[di][1]],dig_vrt[3][ax[di][2]]); //d + glEnd(); + break; + + case '.': + glBegin(GL_LINES); + glVertex3d(dig_vrt[4][ax[di][0]],dig_vrt[4][ax[di][1]],dig_vrt[4][ax[di][2]]); //e + glVertex3d(dig_vrt[5][ax[di][0]],dig_vrt[5][ax[di][1]],dig_vrt[5][ax[di][2]]); //f + glEnd(); + break; + } + } + } +} + diff --git a/src/GLView.h b/src/GLView.h index 5e3e4c53..734139c6 100644 --- a/src/GLView.h +++ b/src/GLView.h @@ -62,6 +62,7 @@ public: bool showfaces; bool showedges; bool showcrosshairs; + bool showscale; #ifdef ENABLE_OPENCSG GLint shaderinfo[11]; @@ -76,4 +77,6 @@ private: void showCrosshairs(); void showAxes(const Color4f &col); void showSmallaxes(const Color4f &col); + void showScalemarkers(const Color4f &col); + void decodeMarkerValue(double i, double l, int size_div_sm); }; diff --git a/src/GeometryEvaluator.cc b/src/GeometryEvaluator.cc index 72490314..658c6d7f 100644 --- a/src/GeometryEvaluator.cc +++ b/src/GeometryEvaluator.cc @@ -123,7 +123,15 @@ GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren3D(const Abstr // Only one child -> this is a noop if (children.size() == 1) return ResultObject(children.front().second); - if (op == OPENSCAD_MINKOWSKI) return ResultObject(CGALUtils::applyMinkowski(children)); + if (op == OPENSCAD_MINKOWSKI) { + Geometry::ChildList actualchildren; + BOOST_FOREACH(const Geometry::ChildItem &item, children) { + if (!item.second->isEmpty()) actualchildren.push_back(item); + } + if (actualchildren.empty()) return ResultObject(); + if (actualchildren.size() == 1) return ResultObject(actualchildren.front().second); + return ResultObject(CGALUtils::applyMinkowski(actualchildren)); + } CGAL_Nef_polyhedron *N = CGALUtils::applyOperator(children, op); // FIXME: Clarify when we can return NULL and what that means @@ -366,14 +374,17 @@ void GeometryEvaluator::addToParent(const State &state, */ Response GeometryEvaluator::visit(State &state, const AbstractNode &node) { - if (state.isPrefix() && isSmartCached(node)) return PruneTraversal; + if (state.isPrefix()) { + if (isSmartCached(node)) return PruneTraversal; + state.setPreferNef(true); // Improve quality of CSG by avoiding conversion loss + } if (state.isPostfix()) { shared_ptr geom; if (!isSmartCached(node)) { geom = applyToChildren(node, OPENSCAD_UNION).constptr(); } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, state.preferNef()); } addToParent(state, node, geom); } @@ -400,7 +411,7 @@ Response GeometryEvaluator::visit(State &state, const OffsetNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, false); } addToParent(state, node, geom); } @@ -412,7 +423,10 @@ Response GeometryEvaluator::visit(State &state, const OffsetNode &node) */ Response GeometryEvaluator::visit(State &state, const RenderNode &node) { - if (state.isPrefix() && isSmartCached(node)) return PruneTraversal; + if (state.isPrefix()) { + if (isSmartCached(node)) return PruneTraversal; + state.setPreferNef(true); // Improve quality of CSG by avoiding conversion loss + } if (state.isPostfix()) { shared_ptr geom; if (!isSmartCached(node)) { @@ -437,7 +451,7 @@ Response GeometryEvaluator::visit(State &state, const RenderNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, state.preferNef()); } addToParent(state, node, geom); } @@ -466,7 +480,7 @@ Response GeometryEvaluator::visit(State &state, const LeafNode &node) } geom.reset(geometry); } - else geom = smartCacheGet(node); + else geom = smartCacheGet(node, state.preferNef()); addToParent(state, node, geom); } return PruneTraversal; @@ -501,14 +515,17 @@ Response GeometryEvaluator::visit(State &state, const TextNode &node) */ Response GeometryEvaluator::visit(State &state, const CsgNode &node) { - if (state.isPrefix() && isSmartCached(node)) return PruneTraversal; + if (state.isPrefix()) { + if (isSmartCached(node)) return PruneTraversal; + state.setPreferNef(true); // Improve quality of CSG by avoiding conversion loss + } if (state.isPostfix()) { shared_ptr geom; if (!isSmartCached(node)) { geom = applyToChildren(node, node.type).constptr(); } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, state.preferNef()); } addToParent(state, node, geom); } @@ -583,7 +600,7 @@ Response GeometryEvaluator::visit(State &state, const TransformNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, state.preferNef()); } addToParent(state, node, geom); } @@ -736,7 +753,7 @@ Response GeometryEvaluator::visit(State &state, const LinearExtrudeNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, false); } addToParent(state, node, geom); } @@ -844,7 +861,7 @@ Response GeometryEvaluator::visit(State &state, const RotateExtrudeNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, false); } addToParent(state, node, geom); } @@ -962,7 +979,7 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, false); } addToParent(state, node, geom); } @@ -1038,7 +1055,7 @@ Response GeometryEvaluator::visit(State &state, const CgaladvNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, state.preferNef()); } addToParent(state, node, geom); } @@ -1047,14 +1064,17 @@ Response GeometryEvaluator::visit(State &state, const CgaladvNode &node) Response GeometryEvaluator::visit(State &state, const AbstractIntersectionNode &node) { - if (state.isPrefix() && isSmartCached(node)) return PruneTraversal; + if (state.isPrefix()) { + if (isSmartCached(node)) return PruneTraversal; + state.setPreferNef(true); // Improve quality of CSG by avoiding conversion loss + } if (state.isPostfix()) { shared_ptr geom; if (!isSmartCached(node)) { geom = applyToChildren(node, OPENSCAD_INTERSECTION).constptr(); } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, state.preferNef()); } addToParent(state, node, geom); } diff --git a/src/GeometryEvaluator.h b/src/GeometryEvaluator.h index ca9b30dd..dd4f2131 100644 --- a/src/GeometryEvaluator.h +++ b/src/GeometryEvaluator.h @@ -54,7 +54,7 @@ private: }; void smartCacheInsert(const AbstractNode &node, const shared_ptr &geom); - shared_ptr smartCacheGet(const AbstractNode &node, bool preferNef = false); + shared_ptr smartCacheGet(const AbstractNode &node, bool preferNef); bool isSmartCached(const AbstractNode &node); std::vector collectChildren2D(const AbstractNode &node); Geometry::ChildList collectChildren3D(const AbstractNode &node); diff --git a/src/GeometryUtils.cc b/src/GeometryUtils.cc new file mode 100644 index 00000000..46f02e79 --- /dev/null +++ b/src/GeometryUtils.cc @@ -0,0 +1,234 @@ +#include "GeometryUtils.h" +#include "tesselator.h" +#include "printutils.h" +#include "Reindexer.h" +#include "grid.h" +#include + +static void *stdAlloc(void* userData, unsigned int size) { + TESS_NOTUSED(userData); + return malloc(size); +} + +static void stdFree(void* userData, void* ptr) { + TESS_NOTUSED(userData); + free(ptr); +} + +/*! + Tessellates input contours into a triangle mesh. + + The input contours may consist of positive (CCW) and negative (CW) + contours. These define holes, and possibly islands. + + The output will be written as indices into the input vertex vector. + + This function should be robust wrt. malformed input. + + It will only use existing vertices and is guaranteed to maintain + connectivity if the input polygon is part of a polygon mesh. + + One requirement: The input vertices must be distinct + (i.e. duplicated must resolve to the same index). + + Returns true on error, false on success. +*/ +bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, + std::vector &triangles, + const Vector3f *normal) +{ + // No polygon. FIXME: Will this ever happen or can we assert here? + if (polygons.faces.empty()) return false; + + // Remove consecutive equal vertices, as well as null ears + std::vector faces = polygons.faces; + BOOST_FOREACH(IndexedFace &face, faces) { + int i=0; + while (i < face.size()) { + if (face[i] == face[(i+1)%face.size()]) { // Two consecutively equal indices + face.erase(face.begin()+i); + } + else if (face[i] == face[(i+2)%face.size()]) { // Null ear + face.erase(face.begin() + (i+1)%face.size()); + } + else { + i++; + } + } + } + // First polygon has < 3 points - no output + if (faces[0].size() < 3) return false; + // Remove collapsed holes + for (int i=1;i contour; + // Since libtess2's indices is based on the running number of points added, we need to map back + // to our indices. allindices does the mapping. + std::vector allindices; + BOOST_FOREACH(const IndexedFace &face, faces) { + contour.clear(); + BOOST_FOREACH(int idx, face) { + const Vector3f &v = verts[idx]; + contour.push_back(v[0]); + contour.push_back(v[1]); + contour.push_back(v[2]); + allindices.push_back(idx); + } + assert(face.size() >= 3); + PRINTDB("Contour: %d\n", face.size()); + tessAddContour(tess, 3, &contour.front(), sizeof(TESSreal) * 3, face.size()); + numContours++; + } + + if (!tessTesselate(tess, TESS_WINDING_ODD, TESS_CONSTRAINED_DELAUNAY_TRIANGLES, 3, 3, normalvec)) return -1; + + const TESSindex *vindices = tessGetVertexIndices(tess); + const TESSindex *elements = tessGetElements(tess); + int numelems = tessGetElementCount(tess); + + /* + At this point, we have a delaunay triangle mesh. + + However, as libtess2 might merge vertices, as well as insert new + vertices for intersecting edges, we need to detect these and + insert dummy triangles to maintain external connectivity. + + FIXME: This currently only works for polygons without holes. + */ + if (faces.size() == 1) { // Only works for polygons without holes + + /* + Algorithm: + A) Collect all triangles using _only_ existing vertices -> triangles + B) Locate all unused vertices + C) For each unused vertex, create a triangle connecting it to the existing mesh + */ + int inputSize = allindices.size(); // inputSize is number of points added to libtess2 + std::vector vflags(inputSize); // Inits with 0's + + IndexedTriangle tri; + for (int t=0;t uniqueVertices; + IndexedPolygons indexedpolygons; + indexedpolygons.faces.push_back(IndexedFace()); + IndexedFace &currface = indexedpolygons.faces.back(); + BOOST_FOREACH (const Vector3d &v, polygon) { + int idx = uniqueVertices.lookup(v.cast()); + if (currface.empty() || idx != currface.back()) currface.push_back(idx); + } + if (currface.front() == currface.back()) currface.pop_back(); + if (currface.size() >= 3) { // Cull empty triangles + uniqueVertices.copy(std::back_inserter(indexedpolygons.vertices)); + std::vector indexedtriangles; + err = tessellatePolygonWithHoles(indexedpolygons, indexedtriangles, normal); + Vector3f *verts = &indexedpolygons.vertices.front(); + BOOST_FOREACH(const IndexedTriangle &t, indexedtriangles) { + triangles.push_back(Polygon()); + Polygon &p = triangles.back(); + p.push_back(verts[t[0]].cast()); + p.push_back(verts[t[1]].cast()); + p.push_back(verts[t[2]].cast()); + } + } + return err; +} diff --git a/src/GeometryUtils.h b/src/GeometryUtils.h new file mode 100644 index 00000000..4d3b3f19 --- /dev/null +++ b/src/GeometryUtils.h @@ -0,0 +1,27 @@ +#pragma once + +#include "linalg.h" +#include + +typedef std::vector Polygon; +typedef std::vector Polygons; + +typedef std::vector IndexedFace; +typedef Vector3i IndexedTriangle; + +struct IndexedPolygons { + std::vector vertices; + std::vector faces; +}; + +struct IndexedTriangleMesh { + std::vector vertices; + std::vector triangles; +}; + +namespace GeometryUtils { + bool tessellatePolygon(const Polygon &polygon, Polygons &triangles, + const Vector3f *normal = NULL); + bool tessellatePolygonWithHoles(const IndexedPolygons &polygons, std::vector &triangles, + const Vector3f *normal = NULL); +} diff --git a/src/MainWindow.h b/src/MainWindow.h index 50d4bb6d..41870d46 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -78,6 +78,9 @@ public: QString editortype; bool useScintilla; + int compileErrors; + int compileWarnings; + MainWindow(const QString &filename); ~MainWindow(); @@ -95,7 +98,10 @@ private slots: void setColorScheme(const QString &cs); void showProgress(); void openCSGSettingsChanged(); + void consoleOutput(const QString &msg); + private: + void initActionIcon(QAction *action, const char *darkResource, const char *lightResource); void openFile(const QString &filename); void handleFileDrop(const QString &filename); void refreshDocument(); @@ -103,6 +109,7 @@ private: void updateTemporalVariables(); bool fileChangedOnDisk(); void compileTopLevelDocument(); + void updateCompileResult(); void compile(bool reload, bool forcedone = false); void compileCSG(bool procevents); bool maybeSave(); @@ -149,6 +156,7 @@ private slots: void hideToolbars(); void hideEditor(); void hideConsole(); + void showConsole(); private slots: void selectFindType(int); @@ -200,6 +208,7 @@ public slots: void actionReloadRenderPreview(); void on_editorDock_visibilityChanged(bool); void on_consoleDock_visibilityChanged(bool); + void on_toolButtonCompileResultClose_clicked(); void editorTopLevelChanged(bool); void consoleTopLevelChanged(bool); #ifdef ENABLE_OPENCSG @@ -213,6 +222,7 @@ public slots: void viewModeShowEdges(); void viewModeShowAxes(); void viewModeShowCrosshairs(); + void viewModeShowScaleProportional(); void viewModeAnimate(); void viewAngleTop(); void viewAngleBottom(); @@ -233,6 +243,7 @@ public slots: void helpAbout(); void helpHomepage(); void helpManual(); + void helpCheatSheet(); void helpLibrary(); void helpFontInfo(); void quit(); @@ -240,6 +251,8 @@ public slots: void waitAfterReload(); void autoReloadSet(bool); void setContentsChanged(); + void showFontCacheDialog(); + void hideFontCacheDialog(); private: static void report_func(const class AbstractNode*, void *vp, int mark); @@ -247,6 +260,7 @@ private: static bool undockMode; static bool reorderMode; static QSet *windows; + static class QProgressDialog *fontCacheDialog; char const * afterCompileSlot; bool procevents; diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 74365644..422b3b2c 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -6,8 +6,8 @@ 0 0 - 1397 - 586 + 1118 + 636 @@ -15,16 +15,7 @@ 0 - - 0 - - - 0 - - - 0 - - + 0 @@ -39,18 +30,107 @@ 0 - - 0 - - - 0 - - - 0 - - + 0 + + + + QFrame::Box + + + QFrame::Raised + + + + 6 + + + 6 + + + 6 + + + 4 + + + 4 + + + + + + 1 + 0 + + + + + 75 + true + + + + Message + + + true + + + + + + + + + + + + + + :/icons/close.png:/icons/close.png + + + + 22 + 22 + + + + Qt::ToolButtonIconOnly + + + true + + + + + + + QToolButton { border: none; } + + + + + + + :/icons/information-icons-error.png:/icons/information-icons-error.png + + + + 22 + 22 + + + + false + + + + + + @@ -82,16 +162,7 @@ 0 - - 0 - - - 0 - - - 0 - - + 0 @@ -142,6 +213,7 @@ + @@ -152,7 +224,9 @@ + + @@ -160,6 +234,7 @@ animate_panel qglview viewerToolBar + frameCompileResult @@ -169,7 +244,7 @@ 0 0 - 1397 + 1118 22 @@ -179,26 +254,26 @@ - Recent Files + Recen&t Files - Examples + &Examples - Export + E&xport - - - - - - + + + + + + - + @@ -242,8 +317,8 @@ - - + + @@ -273,6 +348,7 @@ + @@ -285,12 +361,11 @@ + - - @@ -305,6 +380,7 @@ + @@ -324,16 +400,7 @@ 0 - - 0 - - - 0 - - - 0 - - + 0 @@ -342,10 +409,15 @@ + + + + + - + @@ -453,16 +525,7 @@ - - 0 - - - 0 - - - 0 - - + 0 @@ -548,6 +611,10 @@ + + + :/images/Command-Undo-32.png:/images/Command-Undo-32.png + &Undo @@ -559,6 +626,10 @@ + + + :/images/Command-Redo-32.png:/images/Command-Redo-32.png + &Redo @@ -603,6 +674,10 @@ + + + :/images/Increase-Indent-32.png:/images/Increase-Indent-32.png + &Indent @@ -610,14 +685,6 @@ Ctrl+I - - - U&nindent - - - Ctrl+Shift+I - - C&omment @@ -636,7 +703,7 @@ - Paste viewport translation + P&aste viewport translation Ctrl+T @@ -644,20 +711,20 @@ - Paste viewport rotation + Past&e viewport rotation - + - Zoom In + Increase Font &Size Ctrl++ - + - Zoom Out + Decrease Font Si&ze Ctrl+- @@ -668,7 +735,7 @@ true - Hide editor + H&ide editor @@ -682,7 +749,7 @@ - :/images/Preview-32.png:/images/Preview-32.png + :/images/preview-32.png:/images/preview-32.png &Preview @@ -694,10 +761,10 @@ - :/images/blackRender.png:/images/blackRender.png + :/images/render-32.png:/images/render-32.png - &Render + R&ender F6 @@ -705,12 +772,12 @@ - Check Validity + &Check Validity - Display &AST... + Display A&ST... @@ -720,19 +787,23 @@ - Display CSG &Products... + Display CSG Pr&oducts... - + - :/images/export.png:/images/export.png + :/images/STL.png:/images/STL.png Export as &STL... - + + + + :/images/OFF.png:/images/OFF.png + Export as &OFF... @@ -826,6 +897,18 @@ Ctrl+3 + + + true + + + + :/images/scalemarkers.png:/images/scalemarkers.png + + + Show Scale Markers + + true @@ -840,7 +923,7 @@ :/images/blackUp.png:/images/blackUp.png - Top + &Top Ctrl+4 @@ -852,7 +935,7 @@ :/images/blackbottom.png:/images/blackbottom.png - Bottom + &Bottom Ctrl+5 @@ -864,7 +947,7 @@ :/images/blackleft (copy).png:/images/blackleft (copy).png - Left + &Left Ctrl+6 @@ -876,7 +959,7 @@ :/images/rightright.png:/images/rightright.png - Right + &Right Ctrl+7 @@ -888,7 +971,7 @@ :/images/blackfront.png:/images/blackfront.png - Front + &Front Ctrl+8 @@ -900,7 +983,7 @@ :/images/blackback.png:/images/blackback.png - Back + Bac&k Ctrl+9 @@ -908,7 +991,7 @@ - Diagonal + &Diagonal Ctrl+0 @@ -916,7 +999,7 @@ - Center + Ce&nter @@ -928,7 +1011,7 @@ :/images/perspective1.png:/images/perspective1.png - Perspective + &Perspective @@ -940,7 +1023,7 @@ :/images/orthogonal.png:/images/orthogonal.png - Orthogonal + &Orthogonal @@ -948,7 +1031,7 @@ true - Hide console + H&ide console @@ -956,7 +1039,7 @@ true - About + &About QAction::AboutRole @@ -964,7 +1047,7 @@ - Documentation + &Documentation @@ -972,14 +1055,18 @@ Clear Recent - + + + + :/images/DXF.png:/images/DXF.png + - Export as DXF... + Export as &DXF... - Close + &Close Ctrl+W @@ -987,7 +1074,7 @@ - Preferences + &Preferences QAction::PreferencesRole @@ -995,7 +1082,7 @@ - Find... + &Find... Ctrl+F @@ -1003,7 +1090,7 @@ - Find and Replace... + Fin&d and Replace... Ctrl+Alt+F @@ -1011,7 +1098,7 @@ - Find Next + Find Ne&xt Ctrl+G @@ -1019,7 +1106,7 @@ - Find Previous + Find Pre&vious Ctrl+Shift+G @@ -1027,7 +1114,7 @@ - Use Selection for Find + Use Se&lection for Find Ctrl+E @@ -1035,12 +1122,12 @@ - Flush Caches + &Flush Caches - OpenSCAD Homepage + &OpenSCAD Homepage @@ -1048,47 +1135,67 @@ true - Automatic Reload and Preview + &Automatic Reload and Preview - + + + + :/images/PNG.png:/images/PNG.png + - Export as Image... + Export as &Image... - + + + + :/images/CSG.png:/images/CSG.png + - Export as CSG... + Export as &CSG... - Library info + &Library info - Show Library Folder... + Show &Library Folder... + + + :/images/Command-Reset-32.png:/images/Command-Reset-32.png + Reset View - Font List + &Font List - + + + + :/images/CSG.png:/images/CSG.png + - Export as SVG... + Export as S&VG... - + + + + :/images/AMF.png:/images/AMF.png + - Export as AMF... + Export as &AMF... @@ -1126,7 +1233,7 @@ - Convert Tabs to Spaces + Conv&ert Tabs to Spaces @@ -1137,6 +1244,23 @@ Hide toolbars + + + + :/images/Decrease-Indent-32.png:/images/Decrease-Indent-32.png + + + U&nindent + + + Ctrl+Shift+I + + + + + &Cheat Sheet + + diff --git a/src/PlatformUtils-win.cc b/src/PlatformUtils-win.cc index 2a54d8fd..c3cba45a 100644 --- a/src/PlatformUtils-win.cc +++ b/src/PlatformUtils-win.cc @@ -1,5 +1,6 @@ #include "PlatformUtils.h" #include "printutils.h" +#include "findversion.h" #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 #endif @@ -126,7 +127,8 @@ std::string PlatformUtils::sysinfo() OSVERSIONINFOEX osinfo; osinfo.dwOSVersionInfoSize = sizeof(osinfo); - if (GetVersionEx((OSVERSIONINFO*)&osinfo) == 0) { + + if (GetVersionExEx(&osinfo) == 0) { result += "Unknown Windows"; } else { unsigned int version = osinfo.dwMajorVersion * 1000 + osinfo.dwMinorVersion; @@ -154,9 +156,25 @@ std::string PlatformUtils::sysinfo() // For applications that have been manifested for Windows 8.1. result += (osinfo.wProductType == VER_NT_WORKSTATION ? "Windows 8.1" : "Windows Server 2012 R2"); break; + default: + result += "Unknown Windows"; + break; } - boost::format fmt(" (v%d.%d)"); - fmt % osinfo.dwMajorVersion % osinfo.dwMinorVersion; + + if (osinfo.wServicePackMajor > 0) { + boost::format fmtServicePack; + if (osinfo.wServicePackMinor == 0) { + fmtServicePack = boost::format(" SP%d"); + fmtServicePack % osinfo.wServicePackMajor; + } else { + fmtServicePack = boost::format(" SP%d.%d"); + fmtServicePack % osinfo.wServicePackMajor % osinfo.wServicePackMinor; + } + result += fmtServicePack.str(); + } + + boost::format fmt(" (v%d.%d.%d.%d)"); + fmt % osinfo.dwMajorVersion % osinfo.dwMinorVersion % osinfo.wServicePackMajor % osinfo.wServicePackMinor; result += fmt.str(); } else { boost::format fmt("Unknown Windows (dwPlatformId = %d, dwMajorVersion = %d, dwMinorVersion = %d"); diff --git a/src/Preferences.cc b/src/Preferences.cc index f133ffdc..0ad84324 100644 --- a/src/Preferences.cc +++ b/src/Preferences.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include "GeometryCache.h" #include "AutoUpdater.h" #include "feature.h" @@ -49,18 +50,27 @@ class SettingsReader : public Settings::Visitor { QSettings settings; const Value getValue(const Settings::SettingsEntry& entry, const std::string& value) const { - if (value.empty()) { + std::string trimmed_value(value); + boost::trim(trimmed_value); + + if (trimmed_value.empty()) { return entry.defaultValue(); } try { switch (entry.defaultValue().type()) { case Value::STRING: - return Value(value); + return Value(trimmed_value); case Value::NUMBER: - return Value(boost::lexical_cast(value)); + return Value(boost::lexical_cast(trimmed_value)); case Value::BOOL: - return Value(boost::lexical_cast(value)); + boost::to_lower(trimmed_value); + if ("false" == trimmed_value) { + return Value(false); + } else if ("true" == trimmed_value) { + return Value(true); + } + return Value(boost::lexical_cast(trimmed_value)); default: assert(false && "invalid value type for settings"); } @@ -74,7 +84,9 @@ class SettingsReader : public Settings::Visitor std::string key = entry.category() + "/" + entry.name(); std::string value = settings.value(QString::fromStdString(key)).toString().toStdString(); - s->set(entry, getValue(entry, value)); + const Value v = getValue(entry, value); + PRINTDB("SettingsReader R: %s = '%s' => '%s'", key.c_str() % value.c_str() % v.toString()); + s->set(entry, v); } }; @@ -87,9 +99,11 @@ class SettingsWriter : public Settings::Visitor QString key = QString::fromStdString(entry.category() + "/" + entry.name()); if (entry.is_default()) { settings.remove(key); + PRINTDB("SettingsWriter D: %s", key.toStdString().c_str()); } else { Value value = s->get(entry); settings.setValue(key, QString::fromStdString(value.toString())); + PRINTDB("SettingsWriter W: %s = '%s'", key.toStdString().c_str() % value.toString().c_str()); } } }; @@ -471,6 +485,12 @@ void Preferences::on_launcherBox_toggled(bool state) settings.setValue("launcher/showOnStartup", state); } +void Preferences::on_checkBoxShowWarningsIn3dView_toggled(bool val) +{ + Settings::Settings::inst()->set(Settings::Settings::showWarningsIn3dView, Value(val)); + writeSettings(); +} + void Preferences::on_spinBoxIndentationWidth_valueChanged(int val) { Settings::Settings::inst()->set(Settings::Settings::indentationWidth, Value(val)); @@ -669,6 +689,7 @@ void Preferences::updateGUI() this->checkBoxAutoIndent->setChecked(s->get(Settings::Settings::autoIndent).toBool()); this->checkBoxHighlightCurrentLine->setChecked(s->get(Settings::Settings::highlightCurrentLine).toBool()); this->checkBoxEnableBraceMatching->setChecked(s->get(Settings::Settings::enableBraceMatching).toBool()); + this->checkBoxShowWarningsIn3dView->setChecked(s->get(Settings::Settings::showWarningsIn3dView).toBool()); } void Preferences::initComboBox(QComboBox *comboBox, const Settings::SettingsEntry& entry) @@ -677,8 +698,9 @@ void Preferences::initComboBox(QComboBox *comboBox, const Settings::SettingsEntr Value::VectorType vector = entry.range().toVector(); for (Value::VectorType::iterator it = vector.begin();it != vector.end();it++) { QString val = QString::fromStdString((*it)[0].toString()); - QString text = QString::fromStdString((*it)[1].toString()); - comboBox->addItem(text, val); + std::string text((*it)[1].toString()); + QString qtext = QString::fromStdString(gettext(text.c_str())); + comboBox->addItem(qtext, val); } } diff --git a/src/Preferences.h b/src/Preferences.h index 82cced50..a29c5328 100644 --- a/src/Preferences.h +++ b/src/Preferences.h @@ -46,6 +46,7 @@ public slots: void on_launcherBox_toggled(bool); void on_editorType_editTextChanged(const QString &); + void on_checkBoxShowWarningsIn3dView_toggled(bool); // // editor settings // diff --git a/src/Preferences.ui b/src/Preferences.ui index 7c411229..df9a1733 100644 --- a/src/Preferences.ui +++ b/src/Preferences.ui @@ -6,8 +6,8 @@ 0 0 - 621 - 413 + 675 + 476 @@ -31,6 +31,9 @@ + + 0 + @@ -75,6 +78,16 @@ + + + + Show Warnings and Errors in 3D View + + + false + + + @@ -95,8 +108,8 @@ 0 0 - 659 - 769 + 605 + 662 @@ -213,7 +226,7 @@ - Liberation Sans + Helvetica 12 @@ -1147,8 +1160,8 @@ 0 0 - 100 - 30 + 98 + 36 @@ -1201,8 +1214,8 @@ 0 0 - 596 - 499 + 440 + 339 @@ -1376,9 +1389,6 @@ - - toolBar - false diff --git a/src/ProgressWidget.ui b/src/ProgressWidget.ui index 24aefdb2..1ed3e7ea 100644 --- a/src/ProgressWidget.ui +++ b/src/ProgressWidget.ui @@ -10,9 +10,6 @@ 20 - - Form - 5 diff --git a/src/QGLView.cc b/src/QGLView.cc index 25ca07a2..9c23cb96 100644 --- a/src/QGLView.cc +++ b/src/QGLView.cc @@ -108,7 +108,8 @@ std::string QGLView::getRendererInfo() const { std::string glewinfo = glew_dump(); std::string glextlist = glew_extensions_dump(); - return glewinfo + std::string(_("\nUsing QGLWidget\n\n")) + glextlist; + // Don't translate as translated text in the Library Info dialog is not wanted + return glewinfo + std::string("\nUsing QGLWidget\n\n") + glextlist; } #ifdef ENABLE_OPENCSG @@ -299,6 +300,8 @@ void QGLView::mouseReleaseEvent(QMouseEvent*) bool QGLView::save(const char *filename) { + // Force reading from front buffer. Some configurations will read from the back buffer here. + glReadBuffer(GL_FRONT); QImage img = grabFrameBuffer(); return img.save(filename, "PNG"); } diff --git a/src/QGLView.h b/src/QGLView.h index 21b6133d..3891ee51 100644 --- a/src/QGLView.h +++ b/src/QGLView.h @@ -17,6 +17,7 @@ class QGLView : public QGLWidget, public GLView Q_PROPERTY(bool showAxes READ showAxes WRITE setShowAxes); Q_PROPERTY(bool showCrosshairs READ showCrosshairs WRITE setShowCrosshairs); Q_PROPERTY(bool orthoMode READ orthoMode WRITE setOrthoMode); + Q_PROPERTY(double showScaleProportional READ showScaleProportional WRITE setShowScaleProportional); public: QGLView(QWidget *parent = NULL); @@ -35,6 +36,8 @@ public: void setShowCrosshairs(bool enabled) { this->showcrosshairs = enabled; } bool orthoMode() const { return (this->cam.projection == Camera::ORTHOGONAL); } void setOrthoMode(bool enabled); + bool showScaleProportional() const { return this->showscale; } + void setShowScaleProportional(bool enabled) { this->showscale = enabled; } std::string getRendererInfo() const; #if QT_VERSION >= 0x050100 float getDPI() { return this->devicePixelRatio(); } diff --git a/src/Reindexer.h b/src/Reindexer.h index 0dbfecaf..f7601e0d 100644 --- a/src/Reindexer.h +++ b/src/Reindexer.h @@ -51,10 +51,9 @@ public: /*! Copies the internal vector to the given destination */ - void copy(std::vector &dest) { + template void copy(OutputIterator dest) { this->getArray(); - dest.resize(this->vec.size()); - std::copy(this->vec.begin(), this->vec.end(), dest.begin()); + std::copy(this->vec.begin(), this->vec.end(), dest); } private: diff --git a/src/UIUtils.cc b/src/UIUtils.cc index 3e8c8c01..8b701c45 100644 --- a/src/UIUtils.cc +++ b/src/UIUtils.cc @@ -34,6 +34,7 @@ #include "qtgettext.h" #include "UIUtils.h" #include "PlatformUtils.h" +#include "openscad.h" QFileInfo UIUtils::openFile(QWidget *parent) { @@ -103,7 +104,17 @@ void UIUtils::openHomepageURL() QDesktopServices::openUrl(QUrl("http://openscad.org/")); } +static void openVersionedURL(QString url) +{ + QDesktopServices::openUrl(QUrl(url.arg(versionnumber.c_str()))); +} + void UIUtils::openUserManualURL() { - QDesktopServices::openUrl(QUrl("http://www.openscad.org/documentation.html")); + openVersionedURL("http://www.openscad.org/documentation.html?version=%1"); +} + +void UIUtils::openCheatSheetURL() +{ + openVersionedURL("http://www.openscad.org/cheatsheet/index.html?version=%1"); } diff --git a/src/UIUtils.h b/src/UIUtils.h index 4e26e35b..5ce87b28 100644 --- a/src/UIUtils.h +++ b/src/UIUtils.h @@ -42,4 +42,6 @@ namespace UIUtils { void openHomepageURL(); void openUserManualURL(); + + void openCheatSheetURL(); } diff --git a/src/cache.h b/src/cache.h index e0e3104a..20921eb7 100644 --- a/src/cache.h +++ b/src/cache.h @@ -177,7 +177,7 @@ void Cache::trim(int m) Node *u = n; n = n->p; #ifdef DEBUG - PRINTB("Trimming cache: %1% (%2% bytes)", *u->keyPtr % u->c); + PRINTB("Trimming cache: %1% (%2% bytes)", u->keyPtr->substr(0, 40) % u->c); #endif unlink(*u); } diff --git a/src/cgalutils-polyhedron.cc b/src/cgalutils-polyhedron.cc index 43ab72d6..c821f541 100644 --- a/src/cgalutils-polyhedron.cc +++ b/src/cgalutils-polyhedron.cc @@ -48,17 +48,22 @@ namespace /* anonymous */ { void operator()(HDS& hds) { CGAL_Polybuilder B(hds, true); - std::vector vertices; Grid3d grid(GRID_FINE); - std::vector indices(3); - + std::vector vertices; + std::vector > indices; + + // Align all vertices to grid and build vertex array in vertices BOOST_FOREACH(const Polygon &p, ps.polygons) { + indices.push_back(std::vector()); + indices.back().reserve(p.size()); BOOST_REVERSE_FOREACH(Vector3d v, p) { - if (!grid.has(v)) { - // align v to the grid; the CGALPoint will receive the aligned vertex - grid.align(v) = vertices.size(); - vertices.push_back(CGALPoint(v[0], v[1], v[2])); + // align v to the grid; the CGALPoint will receive the aligned vertex + size_t idx = grid.align(v); + if (idx == vertices.size()) { + CGALPoint p(v[0], v[1], v[2]); + vertices.push_back(p); } + indices.back().push_back(idx); } } @@ -70,28 +75,24 @@ namespace /* anonymous */ { BOOST_FOREACH(const CGALPoint &p, vertices) { B.add_vertex(p); } - BOOST_FOREACH(const Polygon &p, ps.polygons) { + BOOST_FOREACH(std::vector &pindices, indices) { #ifdef GEN_SURFACE_DEBUG if (pidx++ > 0) printf(","); #endif - indices.clear(); - BOOST_FOREACH(const Vector3d &v, p) { - indices.push_back(grid.data(v)); - } // We remove duplicate indices since there is a bug in CGAL's // Polyhedron_incremental_builder_3::test_facet() which fails to detect this - std::vector::iterator last = std::unique(indices.begin(), indices.end()); + std::vector::iterator last = std::unique(pindices.begin(), pindices.end()); std::advance(last, -1); - if (*last != indices.front()) last++; // In case the first & last are equal - indices.erase(last, indices.end()); - if (indices.size() >= 3 && B.test_facet(indices.begin(), indices.end())) { - B.add_facet(indices.begin(), indices.end()); + if (*last != pindices.front()) last++; // In case the first & last are equal + pindices.erase(last, pindices.end()); + if (pindices.size() >=3 && B.test_facet(pindices.begin(), pindices.end())) { + B.add_facet(pindices.begin(), pindices.end()); } #ifdef GEN_SURFACE_DEBUG printf("["); int fidx = 0; - BOOST_REVERSE_FOREACH(size_t i, indices) { + BOOST_REVERSE_FOREACH(size_t i, pindices) { if (fidx++ > 0) printf(","); printf("%ld", i); } @@ -295,6 +296,63 @@ namespace CGALUtils { template bool createPolySetFromPolyhedron(const CGAL::Polyhedron_3 &p, PolySet &ps); template bool createPolySetFromPolyhedron(const CGAL::Polyhedron_3 > &p, PolySet &ps); + class Polyhedron_writer { + std::ostream *out; + bool firstv; + std::vector indices; + public: + Polyhedron_writer() {} + void write_header(std::ostream &stream, + std::size_t vertices, + std::size_t halfedges, + std::size_t facets, + bool normals = false) { + this->out = &stream; + *out << "polyhedron(points=["; + firstv = true; + } + void write_footer() { + *out << "]);" << std::endl; + } + void write_vertex( const double& x, const double& y, const double& z) { + *out << (firstv ? "" : ",") << '[' << x << ',' << y << ',' << z << ']'; + firstv = false; + } + void write_facet_header() { + *out << "], faces=["; + firstv = true; + } + void write_facet_begin( std::size_t no) { + *out << (firstv ? "" : ",") << '['; + indices.clear(); + firstv = false; + } + void write_facet_vertex_index( std::size_t index) { + indices.push_back(index); + } + void write_facet_end() { + bool firsti = true; + BOOST_REVERSE_FOREACH(int i, indices) { + *out << (firsti ? "" : ",") << i; + firsti = false; + } + *out << ']'; + } + }; + + template + std::string printPolyhedron(const Polyhedron &p) { + std::stringstream sstream; + sstream.precision(20); + + Polyhedron_writer writer; + generic_print_polyhedron(sstream, p, writer); + + return sstream.str(); + } + + template std::string printPolyhedron(const CGAL_Polyhedron &p); + }; // namespace CGALUtils #endif /* ENABLE_CGAL */ diff --git a/src/cgalutils-tess.cc b/src/cgalutils-tess.cc index e230e9db..f602d7b1 100644 --- a/src/cgalutils-tess.cc +++ b/src/cgalutils-tess.cc @@ -108,6 +108,8 @@ namespace CGALUtils { // Calculate best guess at face normal using Newell's method CGAL::normal_vector_newell_3(polygons.front().begin(), polygons.front().end(), normalvec); } + double sqrl = normalvec.squared_length(); + if (sqrl > 0.0) normalvec = normalvec / sqrt(sqrl); // Pass the normal vector to the (undocumented) // CGAL::Triangulation_2_filtered_projection_traits_3. This @@ -163,6 +165,8 @@ namespace CGALUtils { // Calculate best guess at face normal using Newell's method CGAL::normal_vector_newell_3(polygon.begin(), polygon.end(), normalvec); } + double sqrl = normalvec.squared_length(); + if (sqrl > 0.0) normalvec = normalvec / sqrt(sqrl); // Pass the normal vector to the (undocumented) // CGAL::Triangulation_2_filtered_projection_traits_3. This diff --git a/src/cgalutils.cc b/src/cgalutils.cc index 971f12f7..a9466b54 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -9,26 +9,29 @@ #include "node.h" #include "cgal.h" -#include #include #include #include + +#include +#include + +// Apply CGAL bugfix for CGAL-4.5.x +#if CGAL_VERSION_NR > CGAL_VERSION_NUMBER(4,5,1) || CGAL_VERSION_NR < CGAL_VERSION_NUMBER(4,5,0) +#include +#else +#include "convex_hull_3_bugfix.h" +#endif + #include "svg.h" #include "Reindexer.h" +#include "GeometryUtils.h" #include #include #include #include -namespace Eigen { - size_t hash_value(Vector3d const &v) { - size_t seed = 0; - for (int i=0;i<3;i++) boost::hash_combine(seed, v[i]); - return seed; - } -} - namespace /* anonymous */ { template Result vector_convert(V const& v) { @@ -48,12 +51,15 @@ static CGAL_Nef_polyhedron *createNefPolyhedronFromPolySet(const PolySet &ps) PolySet ps_tri(3, psq.convexValue()); PolysetUtils::tessellate_faces(psq, ps_tri); if (ps_tri.is_convex()) { - typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + typedef CGAL::Epick K; // Collect point cloud - std::set points; - for (int i = 0; i < ps.polygons.size(); i++) { - for (int j = 0; j < ps.polygons[i].size(); j++) { - points.insert(vector_convert(ps.polygons[i][j])); + // FIXME: Use unordered container (need hash) + // NB! CGAL's convex_hull_3() doesn't like std::set iterators, so we use a list + // instead. + std::list points; + BOOST_FOREACH(const Polygon &poly, ps.polygons) { + BOOST_FOREACH(const Vector3d &p, poly) { + points.push_back(vector_convert(p)); } } @@ -72,7 +78,7 @@ static CGAL_Nef_polyhedron *createNefPolyhedronFromPolySet(const PolySet &ps) CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION); try { CGAL_Polyhedron P; - bool err = CGALUtils::createPolyhedronFromPolySet(ps, P); + bool err = CGALUtils::createPolyhedronFromPolySet(psq, P); if (!err) { PRINTDB("Polyhedron is closed: %d", P.is_closed()); PRINTDB("Polyhedron is valid: %d", P.is_valid(false, 0)); @@ -115,9 +121,11 @@ namespace CGALUtils { bool applyHull(const Geometry::ChildList &children, PolySet &result) { - typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + typedef CGAL::Epick K; // Collect point cloud - std::set points; + // NB! CGAL's convex_hull_3() doesn't like std::set iterators, so we use a list + // instead. + std::list points; BOOST_FOREACH(const Geometry::ChildItem &item, children) { const shared_ptr &chgeom = item.second; @@ -125,7 +133,7 @@ namespace CGALUtils { if (N) { if (!N->isEmpty()) { for (CGAL_Nef_polyhedron3::Vertex_const_iterator i = N->p3->vertices_begin(); i != N->p3->vertices_end(); ++i) { - points.insert(K::Point_3(to_double(i->point()[0]),to_double(i->point()[1]),to_double(i->point()[2]))); + points.push_back(vector_convert(i->point())); } } } else { @@ -133,7 +141,7 @@ namespace CGALUtils { if (ps) { BOOST_FOREACH(const Polygon &p, ps->polygons) { BOOST_FOREACH(const Vector3d &v, p) { - points.insert(K::Point_3(v[0], v[1], v[2])); + points.push_back(K::Point_3(v[0], v[1], v[2])); } } } @@ -149,6 +157,10 @@ namespace CGALUtils { try { CGAL::Polyhedron_3 r; CGAL::convex_hull_3(points.begin(), points.end(), r); + PRINTDB("After hull vertices: %d", r.size_of_vertices()); + PRINTDB("After hull facets: %d", r.size_of_facets()); + PRINTDB("After hull closed: %d", r.is_closed()); + PRINTDB("After hull valid: %d", r.is_valid()); success = !createPolySetFromPolyhedron(r, result); } catch (const CGAL::Assertion_exception &e) { @@ -195,6 +207,9 @@ namespace CGALUtils { return visited.size() == p.size_of_facets(); } + /*! + children cannot contain NULL objects + */ Geometry const * applyMinkowski(const Geometry::ChildList &children) { CGAL::Timer t,t_tot; @@ -206,7 +221,7 @@ namespace CGALUtils { while (++it != children.end()) { operands[1] = it->second.get(); - typedef CGAL::Exact_predicates_inexact_constructions_kernel Hull_kernel; + typedef CGAL::Epick Hull_kernel; std::list P[2]; std::list > result_parts; @@ -239,6 +254,7 @@ namespace CGALUtils { decomposed_nef = *nef->p3; } + t.start(); CGAL::convex_decomposition_3(decomposed_nef); // the first volume is the outer volume, which ignored in the decomposition @@ -253,14 +269,16 @@ namespace CGALUtils { PRINTDB("Minkowski: decomposed into %d convex parts", P[i].size()); + t.stop(); + PRINTDB("Minkowski: decomposition took %f s", t.time()); } } std::vector points[2]; std::vector minkowski_points; - for (int i = 0; i < P[0].size(); i++) { - for (int j = 0; j < P[1].size(); j++) { + for (size_t i = 0; i < P[0].size(); i++) { + for (size_t j = 0; j < P[1].size(); j++) { t.start(); points[0].clear(); points[1].clear(); @@ -463,7 +481,7 @@ namespace CGALUtils { } // union && difference assert triggered by testdata/scad/bugs/rotate-diff-nonmanifold-crash.scad and testdata/scad/bugs/issue204.scad catch (const CGAL::Failure_exception &e) { - std::string opstr = op == OPENSCAD_INTERSECTION ? "intersection" : op == OPENSCAD_DIFFERENCE ? "difference" : op == OPENSCAD_MINKOWSKI ? "minkowski" : "UNKNOWN"; + std::string opstr = op == OPENSCAD_INTERSECTION ? "intersection" : op == OPENSCAD_DIFFERENCE ? "difference" : op == OPENSCAD_UNION ? "union" : "UNKNOWN"; PRINTB("ERROR: CGAL error in CGALUtils::applyBinaryOperator %s: %s", opstr % e.what()); } CGAL::set_error_behaviour(old_behaviour); @@ -877,7 +895,72 @@ namespace CGALUtils { return err; } #endif -#if 1 +#if 0 + bool createPolySetFromNefPolyhedron3(const CGAL_Nef_polyhedron3 &N, PolySet &ps) + { + bool err = false; + // Grid all vertices in a Nef polyhedron to merge close vertices. + Grid3d grid(GRID_FINE); + CGAL_Nef_polyhedron3::Halffacet_const_iterator hfaceti; + CGAL_forall_halffacets(hfaceti, N) { + CGAL::Plane_3 plane(hfaceti->plane()); + PolyholeK polyholes; + // the 0-mark-volume is the 'empty' volume of space. skip it. + if (hfaceti->incident_volume()->mark()) continue; + CGAL_Nef_polyhedron3::Halffacet_cycle_const_iterator cyclei; + CGAL_forall_facet_cycles_of(cyclei, hfaceti) { + CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c1(cyclei); + CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c2(c1); + PolygonK polygon; + std::vector indices; // Vertex indices in one polygon + CGAL_For_all(c1, c2) { + CGAL_Point_3 p = c1->source()->center_vertex()->point(); + Vector3d v = vector_convert(p); + indices.push_back(grid.align(v)); + polygon.push_back(Vertex3K(v[0], v[1], v[2])); + } + // Remove consecutive duplicate vertices + PolygonK::iterator currp = polygon.begin(); + for (int i=0;i= 3) polyholes.push_back(polygon); + } + + /* at this stage, we have a sequence of polygons. the first + is the "outside edge' or 'body' or 'border', and the rest of the + polygons are 'holes' within the first. there are several + options here to get rid of the holes. we choose to go ahead + and let the tessellater deal with the holes, and then + just output the resulting 3d triangles*/ + + // We cannot trust the plane from Nef polyhedron to be correct. + // Passing an incorrect normal vector can cause a crash in the constrained delaunay triangulator + // See http://cgal-discuss.949826.n4.nabble.com/Nef3-Wrong-normal-vector-reported-causes-triangulator-crash-tt4660282.html + // CGAL::Vector_3 nvec = plane.orthogonal_vector(); + // K::Vector_3 normal(CGAL::to_double(nvec.x()), CGAL::to_double(nvec.y()), CGAL::to_double(nvec.z())); + std::vector triangles; + bool err = CGALUtils::tessellatePolygonWithHolesNew(polyholes, triangles, NULL); + if (!err) { + BOOST_FOREACH(const Polygon &p, triangles) { + if (p.size() != 3) { + PRINT("WARNING: triangle doesn't have 3 points. skipping"); + continue; + } + ps.append_poly(); + ps.append_vertex(p[0].x(), p[0].y(), p[0].z()); + ps.append_vertex(p[1].x(), p[1].y(), p[1].z()); + ps.append_vertex(p[2].x(), p[2].y(), p[2].z()); + } + } + } + return err; + } +#endif +#if 0 bool createPolySetFromNefPolyhedron3(const CGAL_Nef_polyhedron3 &N, PolySet &ps) { bool err = false; @@ -894,11 +977,21 @@ namespace CGALUtils { PolygonK polygon; CGAL_For_all(c1, c2) { CGAL_Point_3 p = c1->source()->center_vertex()->point(); - polygon.push_back(Vertex3K(CGAL::to_double(p.x()), CGAL::to_double(p.y()), CGAL::to_double(p.z()))); + float v[3] = { CGAL::to_double(p.x()), CGAL::to_double(p.y()), CGAL::to_double(p.z()) }; + polygon.push_back(Vertex3K(v[0], v[1], v[2])); } polyholes.push_back(polygon); } + std::cout << "---\n"; + BOOST_FOREACH(const PolygonK &poly, polyholes) { + BOOST_FOREACH(const Vertex3K &v, poly) { + std::cout << v.x() << "," << v.y() << "," << v.z() << "\n"; + } + std::cout << "\n"; + } + std::cout << "-\n"; + /* at this stage, we have a sequence of polygons. the first is the "outside edge' or 'body' or 'border', and the rest of the polygons are 'holes' within the first. there are several @@ -906,10 +999,13 @@ namespace CGALUtils { and let the tessellater deal with the holes, and then just output the resulting 3d triangles*/ - CGAL::Vector_3 nvec = plane.orthogonal_vector(); - K::Vector_3 normal(CGAL::to_double(nvec.x()), CGAL::to_double(nvec.y()), CGAL::to_double(nvec.z())); + // We cannot trust the plane from Nef polyhedron to be correct. + // Passing an incorrect normal vector can cause a crash in the constrained delaunay triangulator + // See http://cgal-discuss.949826.n4.nabble.com/Nef3-Wrong-normal-vector-reported-causes-triangulator-crash-tt4660282.html + // CGAL::Vector_3 nvec = plane.orthogonal_vector(); + // K::Vector_3 normal(CGAL::to_double(nvec.x()), CGAL::to_double(nvec.y()), CGAL::to_double(nvec.z())); std::vector triangles; - bool err = CGALUtils::tessellatePolygonWithHoles(polyholes, triangles, &normal); + bool err = CGALUtils::tessellatePolygonWithHolesNew(polyholes, triangles, NULL); if (!err) { BOOST_FOREACH(const Polygon &p, triangles) { if (p.size() != 3) { @@ -920,6 +1016,79 @@ namespace CGALUtils { ps.append_vertex(p[0].x(), p[0].y(), p[0].z()); ps.append_vertex(p[1].x(), p[1].y(), p[1].z()); ps.append_vertex(p[2].x(), p[2].y(), p[2].z()); + // std::cout << p[0].x() << "," << p[0].y() << "," << p[0].z() << "\n"; + // std::cout << p[1].x() << "," << p[1].y() << "," << p[1].z() << "\n"; + // std::cout << p[2].x() << "," << p[2].y() << "," << p[2].z() << "\n\n"; + } + } + } + return err; + } +#endif +#if 1 + bool createPolySetFromNefPolyhedron3(const CGAL_Nef_polyhedron3 &N, PolySet &ps) + { + bool err = false; + CGAL_Nef_polyhedron3::Halffacet_const_iterator hfaceti; + CGAL_forall_halffacets(hfaceti, N) { + CGAL::Plane_3 plane(hfaceti->plane()); + // Since we're downscaling to float, vertices might merge during this conversion. + // To avoid passing equal vertices to the tessellator, we remove consecutively identical + // vertices. + Reindexer uniqueVertices; + IndexedPolygons polyhole; + // the 0-mark-volume is the 'empty' volume of space. skip it. + if (hfaceti->incident_volume()->mark()) continue; + CGAL_Nef_polyhedron3::Halffacet_cycle_const_iterator cyclei; + CGAL_forall_facet_cycles_of(cyclei, hfaceti) { + CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c1(cyclei); + CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c2(c1); + polyhole.faces.push_back(IndexedFace()); + IndexedFace &currface = polyhole.faces.back(); + CGAL_For_all(c1, c2) { + CGAL_Point_3 p = c1->source()->center_vertex()->point(); + // Create vertex indices and remove consecutive duplicate vertices + int idx = uniqueVertices.lookup(vector_convert(p)); + if (currface.empty() || idx != currface.back()) currface.push_back(idx); + } + if (currface.front() == currface.back()) currface.pop_back(); + if (currface.size() < 3) polyhole.faces.pop_back(); // Cull empty triangles + } + uniqueVertices.copy(std::back_inserter(polyhole.vertices)); + +#if 0 // For debugging + std::cerr << "---\n"; + std::cerr.precision(20); + BOOST_FOREACH(const IndexedFace &poly, polyhole.faces) { + BOOST_FOREACH(int i, poly) { + std::cerr << polyhole.vertices[i][0] << "," << polyhole.vertices[i][1] << "," << polyhole.vertices[i][2] << "\n"; + } + std::cerr << "\n"; + } + std::cerr << "-\n"; +#endif + + /* at this stage, we have a sequence of polygons. the first + is the "outside edge' or 'body' or 'border', and the rest of the + polygons are 'holes' within the first. there are several + options here to get rid of the holes. we choose to go ahead + and let the tessellater deal with the holes, and then + just output the resulting 3d triangles*/ + + // We cannot trust the plane from Nef polyhedron to be correct. + // Passing an incorrect normal vector can cause a crash in the constrained delaunay triangulator + // See http://cgal-discuss.949826.n4.nabble.com/Nef3-Wrong-normal-vector-reported-causes-triangulator-crash-tt4660282.html + // CGAL::Vector_3 nvec = plane.orthogonal_vector(); + // K::Vector_3 normal(CGAL::to_double(nvec.x()), CGAL::to_double(nvec.y()), CGAL::to_double(nvec.z())); + std::vector triangles; + bool err = GeometryUtils::tessellatePolygonWithHoles(polyhole, triangles, NULL); + const Vector3f *verts = &polyhole.vertices.front(); + if (!err) { + BOOST_FOREACH(const Vector3i &t, triangles) { + ps.append_poly(); + ps.append_vertex(verts[t[0]]); + ps.append_vertex(verts[t[1]]); + ps.append_vertex(verts[t[2]]); } } } diff --git a/src/cgalutils.h b/src/cgalutils.h index c8eb69db..4939c9fb 100644 --- a/src/cgalutils.h +++ b/src/cgalutils.h @@ -21,6 +21,7 @@ namespace CGALUtils { bool is_approximately_convex(const PolySet &ps); Geometry const* applyMinkowski(const Geometry::ChildList &children); + template std::string printPolyhedron(const Polyhedron &p); template bool createPolySetFromPolyhedron(const Polyhedron &p, PolySet &ps); template bool createPolyhedronFromPolySet(const PolySet &ps, Polyhedron &p); template @@ -35,9 +36,6 @@ namespace CGALUtils { bool tessellatePolygonWithHoles(const PolyholeK &polygons, Polygons &triangles, const K::Vector_3 *normal = NULL); - bool tessellate3DFaceWithHolesNew(std::vector &polygons, - Polygons &triangles, - CGAL::Plane_3 &plane); bool tessellate3DFaceWithHoles(std::vector &polygons, std::vector &triangles, CGAL::Plane_3 &plane); diff --git a/src/control.cc b/src/control.cc index bcbae4a5..21a2fe4b 100644 --- a/src/control.cc +++ b/src/control.cc @@ -169,7 +169,7 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns switch (this->type) { case CHILD: { - printDeprecation("DEPRECATED: child() will be removed in future releases. Use children() instead."); + printDeprecation("child() will be removed in future releases. Use children() instead."); int n = 0; if (evalctx->numArgs() > 0) { double v; diff --git a/src/convex_hull_3_bugfix.h b/src/convex_hull_3_bugfix.h new file mode 100644 index 00000000..5fb7cd30 --- /dev/null +++ b/src/convex_hull_3_bugfix.h @@ -0,0 +1,960 @@ +/* + This file contains a bugfix against CGAL-4.5.1, see: + http://cgal-discuss.949826.n4.nabble.com/Epick-convex-hull-3-assertion-td4660264.html +*/ + +// Copyright (c) 2001,2011 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Susan Hert +// : Amol Prakash +// : Andreas Fabri + +#ifndef CGAL_CONVEX_HULL_3_H +#define CGAL_CONVEX_HULL_3_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifndef CGAL_CH_NO_POSTCONDITIONS +#include +#endif // CGAL_CH_NO_POSTCONDITIONS + + +namespace CGAL { + +namespace internal{ namespace Convex_hull_3{ + +//struct to select the default traits class for computing convex hull +template< class Point_3, + class Is_floating_point=typename boost::is_floating_point::Kernel::FT>::type, + class Has_filtered_predicates_tag=typename Kernel_traits::Kernel::Has_filtered_predicates_tag > +struct Default_traits_for_Chull_3{ + typedef typename Kernel_traits::Kernel type; +}; + +//FT is a floating point type and Kernel is a filtered kernel +template +struct Default_traits_for_Chull_3{ + typedef Convex_hull_traits_3< typename Kernel_traits::Kernel > type; +}; + +template +struct Default_polyhedron_for_Chull_3{ + typedef CGAL::Polyhedron_3 type; +}; + +template +struct Default_polyhedron_for_Chull_3 >{ + typedef typename Convex_hull_traits_3::Polyhedron_3 type; +}; + +//utility class to select the right version of internal predicate Is_on_positive_side_of_plane_3 +template ::Kernel::FT>::type, + class Has_filtered_predicates_tag=typename Kernel_traits::Kernel::Has_filtered_predicates_tag, + class Has_cartesian_tag=typename Kernel_traits::Kernel::Kernel_tag, + class Has_classical_point_type = + typename boost::is_same< + typename Kernel_traits::Kernel::Point_3, + typename Traits::Point_3 >::type + > +struct Use_advanced_filtering{ + typedef CGAL::Tag_false type; +}; + +template +struct Use_advanced_filtering{ + typedef typename Kernel_traits::Kernel K; + typedef CGAL::Boolean_tag type; +}; + +//Predicates internally used +template ::type > +class Is_on_positive_side_of_plane_3{ + typedef typename Traits::Point_3 Point_3; + typename Traits::Plane_3 plane; + typename Traits::Has_on_positive_side_3 has_on_positive_side; +public: + typedef Protect_FPU_rounding Protector; + + Is_on_positive_side_of_plane_3(const Traits& traits,const Point_3& p,const Point_3& q,const Point_3& r) + :plane(traits.construct_plane_3_object()(p,q,r)),has_on_positive_side(traits.has_on_positive_side_3_object()) {} + + bool operator() (const Point_3& s) const + { + return has_on_positive_side(plane,s); + } +}; + + +//This predicate uses copy of the code from the statically filtered version of +//Orientation_3. The rational is that the plane is a member of the functor +//so optimization are done to avoid doing several time operations on the plane. +//The main operator() first tries the static version of the predicate, then uses +//interval arithmetic (the protector must be created before using this predicate) +//and in case of failure, exact arithmetic is used. +template +class Is_on_positive_side_of_plane_3,Tag_true>{ + typedef Simple_cartesian::Type> PK; + typedef Simple_cartesian CK; + typedef Convex_hull_traits_3 Traits; + typedef typename Traits::Point_3 Point_3; + + Cartesian_converter to_CK; + Cartesian_converter to_PK; + + const Point_3& p,q,r; + mutable typename CK::Plane_3* ck_plane; + mutable typename PK::Plane_3* pk_plane; + + double m10,m20,m21,Maxx,Maxy,Maxz; + + static const int STATIC_FILTER_FAILURE = 555; + + //this function is a made from the statically filtered version of Orientation_3 + int static_filtered(double psx,double psy, double psz) const{ + + // Then semi-static filter. + double apsx = CGAL::abs(psx); + double apsy = CGAL::abs(psy); + double apsz = CGAL::abs(psz); + + double maxx = (Maxx < apsx)? apsx : Maxx; + double maxy = (Maxy < apsy)? apsy : Maxy; + double maxz = (Maxz < apsz)? apsz : Maxz; + + double det = psx*m10 - m20*psy + m21*psz; + + // Sort maxx < maxy < maxz. + if (maxx > maxz) + std::swap(maxx, maxz); + if (maxy > maxz) + std::swap(maxy, maxz); + else if (maxy < maxx) + std::swap(maxx, maxy); + + // Protect against underflow in the computation of eps. + if (maxx < 1e-97) /* cbrt(min_double/eps) */ { + if (maxx == 0) + return 0; + } + // Protect against overflow in the computation of det. + else if (maxz < 1e102) /* cbrt(max_double [hadamard]/4) */ { + double eps = 5.1107127829973299e-15 * maxx * maxy * maxz; + if (det > eps) return 1; + if (det < -eps) return -1; + } + return STATIC_FILTER_FAILURE; + } + +public: + typedef typename Interval_nt_advanced::Protector Protector; + + Is_on_positive_side_of_plane_3(const Traits&,const Point_3& p_,const Point_3& q_,const Point_3& r_) + :p(p_),q(q_),r(r_),ck_plane(NULL),pk_plane(NULL) + { + double pqx = q.x() - p.x(); + double pqy = q.y() - p.y(); + double pqz = q.z() - p.z(); + double prx = r.x() - p.x(); + double pry = r.y() - p.y(); + double prz = r.z() - p.z(); + + + m10 = pqy*prz - pry*pqz; + m20 = pqx*prz - prx*pqz; + m21 = pqx*pry - prx*pqy; + + double aprx = CGAL::abs(prx); + double apry = CGAL::abs(pry); + double aprz = CGAL::abs(prz); + + Maxx = CGAL::abs(pqx); + if (Maxx < aprx) Maxx = aprx; + Maxy = CGAL::abs(pqy); + if (Maxy < apry) Maxy = apry; + Maxz = CGAL::abs(pqz); + if (Maxz < aprz) Maxz = aprz; + } + + ~Is_on_positive_side_of_plane_3(){ + if (ck_plane!=NULL) delete ck_plane; + if (pk_plane!=NULL) delete pk_plane; + } + + bool operator() (const Point_3& s) const + { + double psx = s.x() - p.x(); + double psy = s.y() - p.y(); + double psz = s.z() - p.z(); + + int static_res = static_filtered(psx,psy,psz); + if (static_res != STATIC_FILTER_FAILURE) + return static_res == 1; + + try{ + if (ck_plane==NULL) + ck_plane=new typename CK::Plane_3(to_CK(p),to_CK(q),to_CK(r)); + return ck_plane->has_on_positive_side(to_CK(s)); + } + catch (Uncertain_conversion_exception){ + if (pk_plane==NULL) + pk_plane=new typename PK::Plane_3(to_PK(p),to_PK(q),to_PK(r)); + return pk_plane->has_on_positive_side(to_PK(s)); + } + } +}; + + +template +class Build_coplanar_poly : public Modifier_base { + public: + Build_coplanar_poly(ForwardIterator i, ForwardIterator j) + { + start = i; + end = j; + } + void operator()( HDS& hds) { + Polyhedron_incremental_builder_3 B(hds,true); + ForwardIterator iter = start; + int count = 0; + while (iter != end) + { + count++; + iter++; + } + B.begin_surface(count, 1, 2*count); + iter = start; + while (iter != end) + { + B.add_vertex(*iter); + iter++; + } + iter = start; + B.begin_facet(); + int p = 0; + while (p < count) + { + B.add_vertex_to_facet(p); + p++; + } + B.end_facet(); + B.end_surface(); + } + private: + ForwardIterator start; + ForwardIterator end; +}; + + +namespace internal { namespace Convex_hull_3{ + +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Traits_has_typedef_Traits_xy_3,Traits_xy_3,false) +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Traits_has_typedef_Traits_yz_3,Traits_xy_3,false) +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Traits_has_typedef_Traits_xz_3,Traits_xy_3,false) + +template ::value && + Traits_has_typedef_Traits_yz_3::value && + Traits_has_typedef_Traits_xz_3::value +> +struct Projection_traits{ + typedef typename Kernel_traits::Kernel K; + typedef CGAL::Projection_traits_xy_3 Traits_xy_3; + typedef CGAL::Projection_traits_yz_3 Traits_yz_3; + typedef CGAL::Projection_traits_xz_3 Traits_xz_3; +}; + +template +struct Projection_traits{ + typedef typename T::Traits_xy_3 Traits_xy_3; + typedef typename T::Traits_yz_3 Traits_yz_3; + typedef typename T::Traits_xz_3 Traits_xz_3; +}; + +} } //end of namespace internal::Convex_hull_3 + +template +void coplanar_3_hull(InputIterator first, InputIterator beyond, + const Point_3& p1, const Point_3& p2, const Point_3& p3, + Polyhedron_3& P, const Traits& /* traits */) +{ + typedef typename internal::Convex_hull_3::Projection_traits PTraits; + typedef typename PTraits::Traits_xy_3 Traits_xy_3; + typedef typename PTraits::Traits_yz_3 Traits_yz_3; + typedef typename PTraits::Traits_xz_3 Traits_xz_3; + + std::list CH_2; + typedef typename std::list::iterator CH_2_iterator; + + Traits_xy_3 traits_xy; + typename Traits_xy_3::Left_turn_2 left_turn_in_xy = traits_xy.left_turn_2_object(); + if ( left_turn_in_xy(p1,p2,p3) || left_turn_in_xy(p2,p1,p3) ) + convex_hull_points_2( first, beyond, + std::back_inserter(CH_2), + traits_xy ); + else{ + Traits_yz_3 traits_yz; + typename Traits_yz_3::Left_turn_2 left_turn_in_yz = traits_yz.left_turn_2_object(); + if ( left_turn_in_yz(p1,p2,p3) || left_turn_in_yz(p2,p1,p3) ) + convex_hull_points_2( first, beyond, + std::back_inserter(CH_2), + traits_yz ); + else{ + Traits_xz_3 traits_xz; + typename Traits_xz_3::Left_turn_2 left_turn_in_xz = traits_xz.left_turn_2_object(); + CGAL_assertion( left_turn_in_xz(p1,p2,p3) || left_turn_in_xz(p2,p1,p3) ); + convex_hull_points_2( first, beyond, + std::back_inserter(CH_2), + traits_xz ); + } + } + + typedef typename Polyhedron_3::Halfedge_data_structure HDS; + + Build_coplanar_poly poly(CH_2.begin(),CH_2.end()); + P.delegate(poly); +} + + +// +// visible is the set of facets visible from point and reachable from +// start_facet. +// +template +void +find_visible_set(TDS_2& tds, + const typename Traits::Point_3& point, + typename TDS_2::Face_handle start, + std::list& visible, + std::map& outside, + const Traits& traits) +{ + typedef typename Traits::Plane_3 Plane_3; + typedef typename TDS_2::Face_handle Face_handle; + typedef typename TDS_2::Vertex_handle Vertex_handle; + typename Traits::Has_on_positive_side_3 has_on_positive_side = + traits.has_on_positive_side_3_object(); + + std::vector vertices; + vertices.reserve(10); + int VISITED=1, BORDER=2; + visible.clear(); + typename std::list::iterator vis_it; + visible.push_back(start); + start->info() = VISITED; + vertices.push_back(start->vertex(0)); + vertices.push_back(start->vertex(1)); + vertices.push_back(start->vertex(2)); + start->vertex(0)->info() = start->vertex(1)->info() = start->vertex(2)->info() = VISITED; + + for (vis_it = visible.begin(); vis_it != visible.end(); vis_it++) + { + // check all the neighbors of the current face to see if they have + // already been visited or not and if not whether they are visible + // or not. + + for(int i=0; i < 3; i++) { + // the facet on the other side of the current halfedge + Face_handle f = (*vis_it)->neighbor(i); + // if haven't already seen this facet + if (f->info() == 0) { + f->info() = VISITED; + Plane_3 plane(f->vertex(0)->point(),f->vertex(1)->point(),f->vertex(2)->point()); + int ind = f->index(*vis_it); + if ( has_on_positive_side(plane, point) ){ // is visible + visible.push_back(f); + Vertex_handle vh = f->vertex(ind); + if(vh->info() == 0){ vertices.push_back(vh); vh->info() = VISITED;} + } else { + f->info() = BORDER; + f->vertex(TDS_2::cw(ind))->info() = BORDER; + f->vertex(TDS_2::ccw(ind))->info() = BORDER; + outside.insert(std::make_pair(f->vertex(TDS_2::cw(ind)), + typename TDS_2::Edge(f,ind))); + } + } else if(f->info() == BORDER) { + int ind = f->index(*vis_it); + f->vertex(TDS_2::cw(ind))->info() = BORDER; + f->vertex(TDS_2::ccw(ind))->info() = BORDER; + outside.insert(std::make_pair(f->vertex(TDS_2::cw(ind)), + typename TDS_2::Edge(f,ind))); + } + } + } + + for(typename std::vector::iterator vit = vertices.begin(); + vit != vertices.end(); + ++vit){ + if((*vit)->info() != BORDER){ + tds.delete_vertex(*vit); + } else { + (*vit)->info() = 0; + } + } + +} + +// using a third template parameter for the point instead of getting it from +// the traits class as it should be is required by M$VC6 +template +typename std::list::iterator +farthest_outside_point(Face_handle f, std::list& outside_set, + const Traits& traits) +{ + + typedef typename std::list::iterator Outside_set_iterator; + CGAL_ch_assertion(!outside_set.empty()); + + typename Traits::Plane_3 plane(f->vertex(0)->point(),f->vertex(1)->point(),f->vertex(2)->point()); + + typename Traits::Less_signed_distance_to_plane_3 less_dist_to_plane = + traits.less_signed_distance_to_plane_3_object(); + Outside_set_iterator farthest_it = + std::max_element(outside_set.begin(), + outside_set.end(), + boost::bind(less_dist_to_plane, plane, _1, _2)); + return farthest_it; +} + +template +void +partition_outside_sets(const std::list& new_facets, + std::list& vis_outside_set, + std::list& pending_facets, + const Traits& traits) +{ + typename std::list::const_iterator f_list_it; + typename std::list::iterator point_it, to_splice; + + // walk through all the new facets and check each unassigned outside point + // to see if it belongs to the outside set of this new facet. + for (f_list_it = new_facets.begin(); (f_list_it != new_facets.end()) && (! vis_outside_set.empty()); + ++f_list_it) + { + Face_handle f = *f_list_it; + Is_on_positive_side_of_plane_3 is_on_positive_side( + traits,f->vertex(0)->point(),f->vertex(1)->point(),f->vertex(2)->point()); + std::list& point_list = f->points; + + for (point_it = vis_outside_set.begin();point_it != vis_outside_set.end();){ + if( is_on_positive_side(*point_it) ) { + to_splice = point_it; + ++point_it; + point_list.splice(point_list.end(), vis_outside_set, to_splice); + } else { + ++point_it; + } + } + if(! point_list.empty()){ + pending_facets.push_back(f); + f->it = boost::prior(pending_facets.end()); + } else { + f->it = pending_facets.end(); + } + } + + + for (; f_list_it != new_facets.end();++f_list_it) + (*f_list_it)->it = pending_facets.end(); +} + + + +template +void +ch_quickhull_3_scan(TDS_2& tds, + std::list& pending_facets, + const Traits& traits) +{ + typedef typename TDS_2::Edge Edge; + typedef typename TDS_2::Face_handle Face_handle; + typedef typename TDS_2::Vertex_handle Vertex_handle; + typedef typename Traits::Point_3 Point_3; + typedef std::list Outside_set; + typedef typename std::list::iterator Outside_set_iterator; + typedef std::map Border_edges; + + std::list visible_set; + typename std::list::iterator vis_set_it; + Outside_set vis_outside_set; + Border_edges border; + + while (!pending_facets.empty()) + { + vis_outside_set.clear(); + + Face_handle f_handle = pending_facets.front(); + + Outside_set_iterator farthest_pt_it = farthest_outside_point(f_handle, f_handle->points, traits); + Point_3 farthest_pt = *farthest_pt_it; + f_handle->points.erase(farthest_pt_it); + find_visible_set(tds, farthest_pt, f_handle, visible_set, border, traits); + + // for each visible facet + for (vis_set_it = visible_set.begin(); vis_set_it != visible_set.end(); + vis_set_it++) + { + + // add its outside set to the global outside set list + std::list& point_list = (*vis_set_it)->points; + if(! point_list.empty()){ + vis_outside_set.splice(vis_outside_set.end(), point_list, point_list.begin(), point_list.end()); + } + + if((*vis_set_it)->it != pending_facets.end()){ + pending_facets.erase((*vis_set_it)->it); + } + (*vis_set_it)->info() = 0; + } + + std::vector edges; + edges.reserve(border.size()); + typename Border_edges::iterator it = border.begin(); + Edge e = it->second; + e.first->info() = 0; + edges.push_back(e); + border.erase(it); + while(! border.empty()){ + it = border.find(e.first->vertex(TDS_2::ccw(e.second))); + assert(it != border.end()); + e = it->second; + e.first->info() = 0; + edges.push_back(e); + border.erase(it); + } + + // If we want to reuse the faces we must only pass |edges| many, and call delete_face for the others. + // Also create facets if necessary + std::ptrdiff_t diff = visible_set.size() - edges.size(); + if(diff < 0){ + for(int i = 0; i<-diff;i++){ + visible_set.push_back(tds.create_face()); + } + } else { + for(int i = 0; ipoint() = farthest_pt; + vh->info() = 0; + + // now partition the set of outside set points among the new facets. + + partition_outside_sets(visible_set, vis_outside_set, + pending_facets, traits); + + } +} + +template +void non_coplanar_quickhull_3(std::list& points, + TDS_2& tds, const Traits& traits) +{ + typedef typename Traits::Point_3 Point_3; + + typedef typename TDS_2::Face_handle Face_handle; + typedef typename TDS_2::Face_iterator Face_iterator; + typedef typename std::list::iterator P3_iterator; + + std::list pending_facets; + + typename Is_on_positive_side_of_plane_3::Protector p; + + // for each facet, look at each unassigned point and decide if it belongs + // to the outside set of this facet. + for(Face_iterator fit = tds.faces_begin(); fit != tds.faces_end(); ++fit){ + Is_on_positive_side_of_plane_3 is_on_positive_side( + traits,fit->vertex(0)->point(),fit->vertex(1)->point(),fit->vertex(2)->point() ); + for (P3_iterator point_it = points.begin() ; point_it != points.end(); ) + { + if( is_on_positive_side(*point_it) ) { + P3_iterator to_splice = point_it; + ++point_it; + fit->points.splice(fit->points.end(), points, to_splice); + } else { + ++point_it; + } + } + } + // add all the facets with non-empty outside sets to the set of facets for + // further consideration + for(Face_iterator fit = tds.faces_begin(); fit != tds.faces_end(); ++fit){ + if (! fit->points.empty()){ + pending_facets.push_back(fit); + fit->it = boost::prior(pending_facets.end()); + } else { + fit->it = pending_facets.end(); + } + } + + + ch_quickhull_3_scan(tds, pending_facets, traits); + + //std::cout << "|V(tds)| = " << tds.number_of_vertices() << std::endl; +// CGAL_ch_expensive_postcondition(all_points_inside(points.begin(), +// points.end(),P,traits)); +// CGAL_ch_postcondition(is_strongly_convex_3(P, traits)); +} + + +namespace internal{ + +template +class Build_convex_hull_from_TDS_2 : public CGAL::Modifier_base { + typedef std::map Vertex_map; + + const TDS& t; + template + static unsigned get_vertex_index( Vertex_map& vertex_map, + typename TDS::Vertex_handle vh, + Builder& builder, + unsigned& vindex) + { + std::pair + res=vertex_map.insert(std::make_pair(vh,vindex)); + if (res.second){ + builder.add_vertex(vh->point()); + ++vindex; + } + return res.first->second; + } + +public: + Build_convex_hull_from_TDS_2(const TDS& t_):t(t_) + { + CGAL_assertion(t.dimension()==2); + } + void operator()( HDS& hds) { + // Postcondition: `hds' is a valid polyhedral surface. + + CGAL::Polyhedron_incremental_builder_3 B( hds, true); + Vertex_map vertex_map; + //start the surface + B.begin_surface( t.number_of_vertices(), t.number_of_faces()); + unsigned vindex=0; + for (typename TDS::Face_iterator it=t.faces_begin();it!=t.faces_end();++it) + { + unsigned i0=get_vertex_index(vertex_map,it->vertex(0),B,vindex); + unsigned i1=get_vertex_index(vertex_map,it->vertex(1),B,vindex); + unsigned i2=get_vertex_index(vertex_map,it->vertex(2),B,vindex); + B.begin_facet(); + B.add_vertex_to_facet( i0 ); + B.add_vertex_to_facet( i1 ); + B.add_vertex_to_facet( i2 ); + B.end_facet(); + } + B.end_surface(); + } +}; + +} //namespace internal + +template +void +ch_quickhull_polyhedron_3(std::list& points, + InputIterator point1_it, InputIterator point2_it, + InputIterator point3_it, Polyhedron_3& P, + const Traits& traits) +{ + typedef typename Traits::Point_3 Point_3; + typedef typename Traits::Plane_3 Plane_3; + typedef typename std::list::iterator P3_iterator; + + typedef Triangulation_data_structure_2< + Triangulation_vertex_base_with_info_2 >, + Convex_hull_face_base_2 > Tds; + typedef typename Tds::Vertex_handle Vertex_handle; + typedef typename Tds::Face_handle Face_handle; + + // found three points that are not collinear, so construct the plane defined + // by these points and then find a point that has maximum distance from this + // plane. + typename Traits::Construct_plane_3 construct_plane = + traits.construct_plane_3_object(); + Plane_3 plane = construct_plane(*point3_it, *point2_it, *point1_it); + typedef typename Traits::Less_signed_distance_to_plane_3 Dist_compare; + Dist_compare compare_dist = traits.less_signed_distance_to_plane_3_object(); + + typename Traits::Coplanar_3 coplanar = traits.coplanar_3_object(); + // find both min and max here since using signed distance. If all points + // are on the negative side of the plane, the max element will be on the + // plane. + std::pair min_max; + min_max = CGAL::min_max_element(points.begin(), points.end(), + boost::bind(compare_dist, plane, _1, _2), + boost::bind(compare_dist, plane, _1, _2)); + P3_iterator max_it; + if (coplanar(*point1_it, *point2_it, *point3_it, *min_max.second)) + { + max_it = min_max.first; + // want the orientation of the points defining the plane to be positive + // so have to reorder these points if all points were on negative side + // of plane + std::swap(*point1_it, *point3_it); + } + else + max_it = min_max.second; + + // if the maximum distance point is on the plane then all are coplanar + if (coplanar(*point1_it, *point2_it, *point3_it, *max_it)) { + coplanar_3_hull(points.begin(), points.end(), *point1_it, *point2_it, *point3_it, P, traits); + } else { + Tds tds; + Vertex_handle v0 = tds.create_vertex(); v0->set_point(*point1_it); + Vertex_handle v1 = tds.create_vertex(); v1->set_point(*point2_it); + Vertex_handle v2 = tds.create_vertex(); v2->set_point(*point3_it); + Vertex_handle v3 = tds.create_vertex(); v3->set_point(*max_it); + + v0->info() = v1->info() = v2->info() = v3->info() = 0; + Face_handle f0 = tds.create_face(v0,v1,v2); + Face_handle f1 = tds.create_face(v3,v1,v0); + Face_handle f2 = tds.create_face(v3,v2,v1); + Face_handle f3 = tds.create_face(v3,v0,v2); + tds.set_dimension(2); + f0->set_neighbors(f2, f3, f1); + f1->set_neighbors(f0, f3, f2); + f2->set_neighbors(f0, f1, f3); + f3->set_neighbors(f0, f2, f1); + + points.erase(point1_it); + points.erase(point2_it); + points.erase(point3_it); + points.erase(max_it); + if (!points.empty()){ + non_coplanar_quickhull_3(points, tds, traits); + internal::Build_convex_hull_from_TDS_2 builder(tds); + P.delegate(builder); + } + else + P.make_tetrahedron(v0->point(),v1->point(),v2->point(),v3->point()); + } + +} + +} } //namespace internal::Convex_hull_3 + +template +void +convex_hull_3(InputIterator first, InputIterator beyond, + Object& ch_object, const Traits& traits) +{ + typedef typename Traits::Point_3 Point_3; + typedef std::list Point_3_list; + typedef typename Point_3_list::iterator P3_iterator; + typedef std::pair P3_iterator_pair; + + if (first == beyond) // No point + return; + + // If the first and last point are equal the collinearity test some lines below will always be true. + Point_3_list points(first, beyond); + std::size_t size = points.size(); + while((size > 1) && (points.front() == points.back())){ + points.pop_back(); + --size; + } + + if ( size == 1 ) // 1 point + { + ch_object = make_object(*points.begin()); + return; + } + else if ( size == 2 ) // 2 points + { + typedef typename Traits::Segment_3 Segment_3; + typename Traits::Construct_segment_3 construct_segment = + traits.construct_segment_3_object(); + Segment_3 seg = construct_segment(*points.begin(), *(++points.begin())); + ch_object = make_object(seg); + return; + } + else if ( size == 3 ) // 3 points + { + typedef typename Traits::Triangle_3 Triangle_3; + typename Traits::Construct_triangle_3 construct_triangle = + traits.construct_triangle_3_object(); + Triangle_3 tri = construct_triangle(*(points.begin()), + *(++points.begin()), + *(--points.end())); + ch_object = make_object(tri); + return; + } + + // at least 4 points + typename Traits::Collinear_3 collinear = traits.collinear_3_object(); + + P3_iterator point1_it = points.begin(); + P3_iterator point2_it = points.begin(); + point2_it++; + P3_iterator point3_it = points.end(); + point3_it--; + + // find three that are not collinear + while (point2_it != points.end() && + collinear(*point1_it,*point2_it,*point3_it)) + point2_it++; + + + // all are collinear, so the answer is a segment + if (point2_it == points.end()) + { + typedef typename Traits::Less_distance_to_point_3 Less_dist; + + Less_dist less_dist = traits.less_distance_to_point_3_object(); + P3_iterator_pair endpoints = + min_max_element(points.begin(), points.end(), + boost::bind(less_dist, *points.begin(), _1, _2), + boost::bind(less_dist, *points.begin(), _1, _2)); + + typename Traits::Construct_segment_3 construct_segment = + traits.construct_segment_3_object(); + typedef typename Traits::Segment_3 Segment_3; + + Segment_3 seg = construct_segment(*endpoints.first, *endpoints.second); + ch_object = make_object(seg); + return; + } + + // result will be a polyhedron + typename internal::Convex_hull_3::Default_polyhedron_for_Chull_3::type P; + + P3_iterator minx, maxx, miny, it; + minx = maxx = miny = it = points.begin(); + ++it; + for(; it != points.end(); ++it){ + if(it->x() < minx->x()) minx = it; + if(it->x() > maxx->x()) maxx = it; + if(it->y() < miny->y()) miny = it; + } + if(! collinear(*minx, *maxx, *miny) ){ + internal::Convex_hull_3::ch_quickhull_polyhedron_3(points, minx, maxx, miny, P, traits); + } else { + internal::Convex_hull_3::ch_quickhull_polyhedron_3(points, point1_it, point2_it, point3_it, P, traits); + } + CGAL_assertion(P.size_of_vertices()>=3); + if (boost::next(P.vertices_begin(),3) == P.vertices_end()){ + typedef typename Traits::Triangle_3 Triangle_3; + typename Traits::Construct_triangle_3 construct_triangle = + traits.construct_triangle_3_object(); + Triangle_3 tri = construct_triangle(P.halfedges_begin()->vertex()->point(), + P.halfedges_begin()->next()->vertex()->point(), + P.halfedges_begin()->opposite()->vertex()->point()); + ch_object = make_object(tri); + } + else + ch_object = make_object(P); +} + + +template +void convex_hull_3(InputIterator first, InputIterator beyond, + Object& ch_object) +{ + typedef typename std::iterator_traits::value_type Point_3; + typedef typename internal::Convex_hull_3::Default_traits_for_Chull_3::type Traits; + convex_hull_3(first, beyond, ch_object, Traits()); +} + + + +template +void convex_hull_3(InputIterator first, InputIterator beyond, + Polyhedron_3& polyhedron, const Traits& traits) +{ + typedef typename Traits::Point_3 Point_3; + typedef std::list Point_3_list; + typedef typename Point_3_list::iterator P3_iterator; + + Point_3_list points(first, beyond); + CGAL_ch_precondition(points.size() > 3); + + // at least 4 points + typename Traits::Collinear_3 collinear = traits.collinear_3_object(); + typename Traits::Equal_3 equal = traits.equal_3_object(); + + P3_iterator point1_it = points.begin(); + P3_iterator point2_it = points.begin(); + point2_it++; + + // find three that are not collinear + while (point2_it != points.end() && equal(*point1_it,*point2_it)) + ++point2_it; + + CGAL_ch_precondition_msg(point2_it != points.end(), + "All points are equal; cannot construct polyhedron."); + + P3_iterator point3_it = point2_it; + ++point3_it; + + CGAL_ch_precondition_msg(point3_it != points.end(), + "Only two points with different coordinates; cannot construct polyhedron."); + + while (point3_it != points.end() && collinear(*point1_it,*point2_it,*point3_it)) + ++point3_it; + + CGAL_ch_precondition_msg(point3_it != points.end(), + "All points are collinear; cannot construct polyhedron."); + + polyhedron.clear(); + // result will be a polyhedron + internal::Convex_hull_3::ch_quickhull_polyhedron_3(points, point1_it, point2_it, point3_it, + polyhedron, traits); + +} + + +template +void convex_hull_3(InputIterator first, InputIterator beyond, + Polyhedron_3& polyhedron) +{ + typedef typename std::iterator_traits::value_type Point_3; + typedef typename internal::Convex_hull_3::Default_traits_for_Chull_3::type Traits; + convex_hull_3(first, beyond, polyhedron, Traits()); +} + +} // namespace CGAL + +#endif // CGAL_CONVEX_HULL_3_H diff --git a/src/fileutils.cc b/src/fileutils.cc index ac3144ea..621bb600 100644 --- a/src/fileutils.cc +++ b/src/fileutils.cc @@ -22,7 +22,7 @@ std::string lookup_file(const std::string &filename, if (!fs::exists(absfile) && fs::exists(absfile_fallback)) { resultfile = absfile_fallback.string(); - PRINT_DEPRECATION("DEPRECATED: Imported file (%s) found in document root instead of relative to the importing module. This behavior is deprecated", filename); + PRINT_DEPRECATION("Imported file (%s) found in document root instead of relative to the importing module. This behavior is deprecated", filename); } else { resultfile = absfile.string(); diff --git a/src/findversion.h b/src/findversion.h new file mode 100644 index 00000000..b027f68b --- /dev/null +++ b/src/findversion.h @@ -0,0 +1,120 @@ +/* +* Find Windows version using bisection method and VerifyVersionInfo. +* +* Author: M1xA, www.m1xa.com +* Date: 2013.07.07 +* Licence: MIT +* Version: 1.0 +* +* API: +* +* BOOL GetVersionExEx(OSVERSIONINFOEX * osVer); +* Returns: 0 if fails. +* +* Supported OS: Windows 2000 .. Windows 8.1. +*/ +#ifndef __FIND_VERSION__ +#define __FIND_VERSION__ + +#include + +#define FV_EQUAL 0 +#define FV_LESS -1 +#define FV_GREAT 1 +#define FV_MIN_VALUE 0 +#define FV_MINOR_VERSION_MAX_VALUE 16 + +int testValue(OSVERSIONINFOEX * value, DWORD verPart, DWORDLONG eq, DWORDLONG gt) +{ + if (VerifyVersionInfo(value, verPart, eq) == FALSE) + { + if (VerifyVersionInfo(value, verPart, gt) == TRUE) + return FV_GREAT; + return FV_LESS; + } + else + return FV_EQUAL; +} + +DWORDLONG gtFor(DWORD target) +{ + return VerSetConditionMask(0, target, VER_GREATER); +} + +DWORDLONG eqFor(DWORD target) +{ + return VerSetConditionMask(0, target, VER_EQUAL); +} + +#define findPartTemplate(T)\ +BOOL findPart##T(T * part, DWORD partType, OSVERSIONINFOEX * ret, T a, T b) \ +{ \ + int funx = FV_EQUAL; \ +\ + DWORDLONG const eq = eqFor(partType); \ + DWORDLONG const gt = gtFor(partType); \ +\ + T * p = part; \ +\ + *p = (a + b) / 2; \ +\ + while ((funx = testValue(ret, partType, eq, gt)) != FV_EQUAL) \ + { \ + switch (funx) \ + { \ + case FV_GREAT: a = *p; break; \ + case FV_LESS: b = *p; break; \ + } \ +\ + *p = (a + b) / 2; \ +\ + if (*p == a) \ + { \ + if (testValue(ret, partType, eq, gt) == FV_EQUAL) \ + return TRUE; \ +\ + *p = b; \ +\ + if (testValue(ret, partType, eq, gt) == FV_EQUAL) \ + return TRUE; \ +\ + a = 0; \ + b = 0; \ + *p = 0; \ + } \ +\ + if (a == b) \ + { \ + *p = 0; \ + return FALSE; \ + } \ + } \ +\ + return TRUE; \ +} + +findPartTemplate(DWORD) +findPartTemplate(WORD) +findPartTemplate(BYTE) + +BOOL GetVersionExEx(OSVERSIONINFOEX * osVer) +{ + BOOL ret = TRUE; + + ZeroMemory(osVer, sizeof(OSVERSIONINFOEX)); + + osVer->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + ret &= findPartDWORD(&osVer->dwPlatformId, VER_PLATFORMID, osVer, FV_MIN_VALUE, MAXDWORD); + ret &= findPartDWORD(&osVer->dwMajorVersion, VER_MAJORVERSION, osVer, FV_MIN_VALUE, MAXDWORD); + ret &= findPartDWORD(&osVer->dwMinorVersion, VER_MINORVERSION, osVer, FV_MIN_VALUE, FV_MINOR_VERSION_MAX_VALUE); + ret &= findPartDWORD(&osVer->dwBuildNumber, VER_BUILDNUMBER, osVer, FV_MIN_VALUE, MAXDWORD); + ret &= findPartWORD(&osVer->wServicePackMajor, VER_SERVICEPACKMAJOR, osVer, FV_MIN_VALUE, MAXWORD); + ret &= findPartWORD(&osVer->wServicePackMinor, VER_SERVICEPACKMINOR, osVer, FV_MIN_VALUE, MAXWORD); + ret &= findPartWORD(&osVer->wSuiteMask, VER_SUITENAME, osVer, FV_MIN_VALUE, MAXWORD); + ret &= findPartBYTE(&osVer->wProductType, VER_PRODUCT_TYPE, osVer, FV_MIN_VALUE, MAXBYTE); + + return ret; +} + +#endif diff --git a/src/func.cc b/src/func.cc index 75597720..d4e6cbbe 100644 --- a/src/func.cc +++ b/src/func.cc @@ -255,12 +255,12 @@ ValuePtr builtin_rands(const Context *, const EvalContext *evalctx) deterministic_rng.seed((unsigned int) v3->toDouble()); deterministic = true; } - boost::uniform_real<> distributor( min, max ); Value::VectorType vec; - if (min==max) { // workaround boost bug + if (min==max) { // Boost doesn't allow min == max for (size_t i=0; i < numresults; i++) vec.push_back( Value( min ) ); } else { + boost::uniform_real<> distributor( min, max ); for (size_t i=0; i < numresults; i++) { if ( deterministic ) { vec.push_back(Value(distributor(deterministic_rng))); @@ -712,7 +712,7 @@ ValuePtr builtin_lookup(const Context *, const EvalContext *evalctx) */ static Value::VectorType search(const std::string &find, const std::string &table, - unsigned int num_returns_per_match, unsigned int index_col_num) + unsigned int num_returns_per_match) { Value::VectorType returnvec; //Unicode glyph count for the length @@ -761,7 +761,12 @@ static Value::VectorType search(const std::string &find, const Value::VectorType Value::VectorType resultvec; const gchar *ptr_ft = g_utf8_offset_to_pointer(find.c_str(), i); for (size_t j = 0; j < searchTableSize; j++) { - const gchar *ptr_st = g_utf8_offset_to_pointer(table[j].toVector()[index_col_num].toString().c_str(), 0); + Value::VectorType entryVec = table[j].toVector(); + if (entryVec.size() <= index_col_num) { + PRINTB("WARNING: Invalid entry in search vector at index %d, required number of values in the entry: %d. Invalid entry: %s", j % (index_col_num + 1) % table[j]); + return Value::VectorType(); + } + const gchar *ptr_st = g_utf8_offset_to_pointer(entryVec[index_col_num].toString().c_str(), 0); if (ptr_ft && ptr_st && (g_utf8_get_char(ptr_ft) == g_utf8_get_char(ptr_st)) ) { matchCount++; if (num_returns_per_match == 1) { @@ -814,7 +819,7 @@ ValuePtr builtin_search(const Context *, const EvalContext *evalctx) } } else if (findThis->type() == Value::STRING) { if (searchTable->type() == Value::STRING) { - returnvec = search(findThis->toString(), searchTable->toString(), num_returns_per_match, index_col_num); + returnvec = search(findThis->toString(), searchTable->toString(), num_returns_per_match); } else { returnvec = search(findThis->toString(), searchTable->toVector(), num_returns_per_match, index_col_num); diff --git a/src/grid.cc b/src/grid.cc new file mode 100644 index 00000000..44a882aa --- /dev/null +++ b/src/grid.cc @@ -0,0 +1,19 @@ +#include "grid.h" + +namespace Eigen { + size_t hash_value(Vector3f const &v) { + size_t seed = 0; + for (int i=0;i<3;i++) boost::hash_combine(seed, v[i]); + return seed; + } + size_t hash_value(Vector3d const &v) { + size_t seed = 0; + for (int i=0;i<3;i++) boost::hash_combine(seed, v[i]); + return seed; + } + size_t hash_value(Eigen::Matrix const &v) { + size_t seed = 0; + for (int i=0;i<3;i++) boost::hash_combine(seed, v[i]); + return seed; + } +} diff --git a/src/grid.h b/src/grid.h index f9fe4d0e..55010aaf 100644 --- a/src/grid.h +++ b/src/grid.h @@ -87,59 +87,96 @@ public: } }; +typedef Eigen::Matrix Vector3l; + +namespace Eigen { + size_t hash_value(Vector3f const &v); + size_t hash_value(Vector3d const &v); + size_t hash_value(Vector3l const &v); +} + template class Grid3d { public: double res; - boost::unordered_map,int64_t>, T> db; + typedef Vector3l Key; + typedef boost::unordered_map GridContainer; + GridContainer db; Grid3d(double resolution) { res = resolution; } - T &align(Vector3d &v) { - int64_t ix = (int64_t)round(v[0] / res); - int64_t iy = (int64_t)round(v[1] / res); - int64_t iz = (int64_t)round(v[2] / res); - if (db.find(std::make_pair(std::make_pair(ix, iy), iz)) == db.end()) { - 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.find(std::make_pair(std::make_pair(jx, jy), jz)) == db.end()) - continue; - int d = abs(int(ix-jx)) + abs(int(iy-jy)) + abs(int(iz-jz)); + inline void createGridVertex(const Vector3d &v, Vector3l &i) { + i[0] = int64_t(v[0] / this->res); + i[1] = int64_t(v[1] / this->res); + i[2] = int64_t(v[2] / this->res); + } + + // Aligns vertex to the grid. Returns index of the vertex. + // Will automatically increase the index as new unique vertices are added. + T align(Vector3d &v) { + Vector3l key; + createGridVertex(v, key); + typename GridContainer::iterator iter = db.find(key); + if (iter == db.end()) { + float dist = 10.0f; // > max possible distance + for (int64_t jx = key[0] - 1; jx <= key[0] + 1; jx++) { + for (int64_t jy = key[1] - 1; jy <= key[1] + 1; jy++) { + for (int64_t jz = key[2] - 1; jz <= key[2] + 1; jz++) { + Vector3l k(jx, jy, jz); + typename GridContainer::iterator tmpiter = db.find(k); + if (tmpiter == db.end()) continue; + float d = sqrt((key-k).squaredNorm()); if (d < dist) { dist = d; - ix = jx; - iy = jy; - iz = jz; + iter = tmpiter; } } } } } - v[0] = ix * res, v[1] = iy * res, v[2] = iz * res; - return db[std::make_pair(std::make_pair(ix, iy), iz)]; + + T data; + if (iter == db.end()) { // Not found: insert using key + data = db.size(); + db[key] = data; + } + else { + // If found return existing data + key = iter->first; + data = iter->second; + } + + // Align vertex + v[0] = key[0] * this->res; + v[1] = key[1] * this->res; + v[2] = key[2] * this->res; + + return data; } - bool has(const Vector3d &v) { - int64_t ix = (int64_t)round(v[0] / res); - int64_t iy = (int64_t)round(v[1] / res); - int64_t iz = (int64_t)round(v[2] / res); - if (db.find(std::make_pair(std::make_pair(ix, iy), iz)) != db.end()) + bool has(const Vector3d &v, T *data = NULL) { + Vector3l key = createGridVertex(v); + typename GridContainer::iterator pos = db.find(key); + if (pos != db.end()) { + if (data) *data = pos->second; 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.find(std::make_pair(std::make_pair(jx, jy), jz)) != db.end()) - return true; } + for (int64_t jx = key[0] - 1; jx <= key[0] + 1; jx++) + for (int64_t jy = key[1] - 1; jy <= key[1] + 1; jy++) + for (int64_t jz = key[2] - 1; jz <= key[2] + 1; jz++) { + pos = db.find(Vector3l(jx, jy, jz)); + if (pos != db.end()) { + if (data) *data = pos->second; + return true; + } + } return false; } - T &data(Vector3d v) { + T data(Vector3d v) { return align(v); } diff --git a/src/import.cc b/src/import.cc index ddc4a950..1f1686d2 100644 --- a/src/import.cc +++ b/src/import.cc @@ -95,7 +95,7 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti if (v->isUndefined()) { v = c.lookup_variable("filename"); if (!v->isUndefined()) { - printDeprecation("DEPRECATED: filename= is deprecated. Please use file="); + printDeprecation("filename= is deprecated. Please use file="); } } std::string filename = lookup_file(v->isUndefined() ? "" : v->toString(), inst->path(), ctx->documentPath()); @@ -119,7 +119,7 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti if (layerval.isUndefined()) { layerval = *c.lookup_variable("layername"); if (!layerval.isUndefined()) { - printDeprecation("DEPRECATED: layername= is deprecated. Please use layer="); + printDeprecation("layername= is deprecated. Please use layer="); } } node->layername = layerval.isUndefined() ? "" : layerval.toString(); diff --git a/src/launchingscreen.cc b/src/launchingscreen.cc index 3a27f7e4..461ba701 100644 --- a/src/launchingscreen.cc +++ b/src/launchingscreen.cc @@ -25,8 +25,8 @@ LaunchingScreen::LaunchingScreen(QWidget *parent) : QDialog(parent) { LaunchingScreen::inst = this; setupUi(this); - this->setStyleSheet("QDialog {background-image:url(':/icons/background.png')}" - "QPushButton {color:white;}"); + + this->setStyleSheet("QDialog {background-image:url(':/icons/background.png')} QPushButton {color:white;}"); this->versionNumberLabel->setText(openscad_version.c_str()); diff --git a/src/lexer.l b/src/lexer.l index c873be8e..c968edd6 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -164,7 +164,7 @@ use[ \t\r\n>]*"<" { BEGIN(cond_use); } files on the cmd-line as in the editor. */%} -\xc2\xa0 +[\xc2\xa0]+ {UNICODE}+ { parser_error_pos -= strlen(yytext); return TOK_ERROR; } diff --git a/src/libtess2/Include/tesselator.h b/src/libtess2/Include/tesselator.h new file mode 100755 index 00000000..6e51e321 --- /dev/null +++ b/src/libtess2/Include/tesselator.h @@ -0,0 +1,226 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Mikko Mononen, July 2009. +*/ + +#ifndef TESSELATOR_H +#define TESSELATOR_H + +#ifdef __cplusplus +extern "C" { +#endif + +// See OpenGL Red Book for description of the winding rules +// http://www.glprogramming.com/red/chapter11.html +enum TessWindingRule +{ + TESS_WINDING_ODD, + TESS_WINDING_NONZERO, + TESS_WINDING_POSITIVE, + TESS_WINDING_NEGATIVE, + TESS_WINDING_ABS_GEQ_TWO, +}; + +// The contents of the tessGetElements() depends on element type being passed to tessTesselate(). +// Tesselation result element types: +// TESS_POLYGONS +// Each element in the element array is polygon defined as 'polySize' number of vertex indices. +// If a polygon has than 'polySize' vertices, the remaining indices are stored as TESS_UNDEF. +// Example, drawing a polygon: +// const int nelems = tessGetElementCount(tess); +// const TESSindex* elems = tessGetElements(tess); +// for (int i = 0; i < nelems; i++) { +// const TESSindex* poly = &elems[i * polySize]; +// glBegin(GL_POLYGON); +// for (int j = 0; j < polySize; j++) { +// if (poly[j] == TESS_UNDEF) break; +// glVertex2fv(&verts[poly[j]*vertexSize]); +// } +// glEnd(); +// } +// +// TESS_CONNECTED_POLYGONS +// Each element in the element array is polygon defined as 'polySize' number of vertex indices, +// followed by 'polySize' indices to neighour polygons, that is each element is 'polySize' * 2 indices. +// If a polygon has than 'polySize' vertices, the remaining indices are stored as TESS_UNDEF. +// If a polygon edge is a boundary, that is, not connected to another polygon, the neighbour index is TESS_UNDEF. +// Example, flood fill based on seed polygon: +// const int nelems = tessGetElementCount(tess); +// const TESSindex* elems = tessGetElements(tess); +// unsigned char* visited = (unsigned char*)calloc(nelems); +// TESSindex stack[50]; +// int nstack = 0; +// stack[nstack++] = seedPoly; +// visited[startPoly] = 1; +// while (nstack > 0) { +// TESSindex idx = stack[--nstack]; +// const TESSindex* poly = &elems[idx * polySize * 2]; +// const TESSindex* nei = &poly[polySize]; +// for (int i = 0; i < polySize; i++) { +// if (poly[i] == TESS_UNDEF) break; +// if (nei[i] != TESS_UNDEF && !visited[nei[i]]) +// stack[nstack++] = nei[i]; +// visited[nei[i]] = 1; +// } +// } +// } +// +// TESS_BOUNDARY_CONTOURS +// Each element in the element array is [base index, count] pair defining a range of vertices for a contour. +// The first value is index to first vertex in contour and the second value is number of vertices in the contour. +// Example, drawing contours: +// const int nelems = tessGetElementCount(tess); +// const TESSindex* elems = tessGetElements(tess); +// for (int i = 0; i < nelems; i++) { +// const TESSindex base = elems[i * 2]; +// const TESSindex count = elems[i * 2 + 1]; +// glBegin(GL_LINE_LOOP); +// for (int j = 0; j < count; j++) { +// glVertex2fv(&verts[(base+j) * vertexSize]); +// } +// glEnd(); +// } +// +// TESS_CONSTRAINED_DELAUNAY_TRIANGLES +// Similar to TESS_POLYGONS, but we output only triangles and we attempt to provide a valid +// Constrained Delaunay triangulation. + +enum TessElementType +{ + TESS_POLYGONS, + TESS_CONNECTED_POLYGONS, + TESS_BOUNDARY_CONTOURS, + TESS_CONSTRAINED_DELAUNAY_TRIANGLES +}; + +typedef float TESSreal; +typedef int TESSindex; +typedef struct TESStesselator TESStesselator; +typedef struct TESSalloc TESSalloc; + +#define TESS_UNDEF (~(TESSindex)0) + +#define TESS_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0) + +// Custom memory allocator interface. +// The internal memory allocator allocates mesh edges, vertices and faces +// as well as dictionary nodes and active regions in buckets and uses simple +// freelist to speed up the allocation. The bucket size should roughly match your +// expected input data. For example if you process only hundreds of vertices, +// a bucket size of 128 might be ok, where as when processing thousands of vertices +// bucket size of 1024 might be approproate. The bucket size is a compromise between +// how often to allocate memory from the system versus how much extra space the system +// should allocate. Reasonable defaults are show in commects below, they will be used if +// the bucket sizes are zero. +// +// The use may left the memrealloc to be null. In that case, the tesselator will not try to +// dynamically grow int's internal arrays. The tesselator only needs the reallocation when it +// has found intersecting segments and needs to add new vertex. This defency can be cured by +// allocating some extra vertices beforehand. The 'extraVertices' variable allows to specify +// number of expected extra vertices. +struct TESSalloc +{ + void *(*memalloc)( void *userData, unsigned int size ); + void *(*memrealloc)( void *userData, void* ptr, unsigned int size ); + void (*memfree)( void *userData, void *ptr ); + void* userData; // User data passed to the allocator functions. + int meshEdgeBucketSize; // 512 + int meshVertexBucketSize; // 512 + int meshFaceBucketSize; // 256 + int dictNodeBucketSize; // 512 + int regionBucketSize; // 256 + int extraVertices; // Number of extra vertices allocated for the priority queue. +}; + + +// +// Example use: +// +// +// +// + +// tessNewTess() - Creates a new tesselator. +// Use tessDeleteTess() to delete the tesselator. +// Parameters: +// alloc - pointer to a filled TESSalloc struct or NULL to use default malloc based allocator. +// Returns: +// new tesselator object. +TESStesselator* tessNewTess( TESSalloc* alloc ); + +// tessDeleteTess() - Deletes a tesselator. +// Parameters: +// tess - pointer to tesselator object to be deleted. +void tessDeleteTess( TESStesselator *tess ); + +// tessAddContour() - Adds a contour to be tesselated. +// The type of the vertex coordinates is assumed to be TESSreal. +// Parameters: +// tess - pointer to tesselator object. +// size - number of coordinates per vertex. Must be 2 or 3. +// pointer - pointer to the first coordinate of the first vertex in the array. +// stride - defines offset in bytes between consecutive vertices. +// count - number of vertices in contour. +void tessAddContour( TESStesselator *tess, int size, const void* pointer, int stride, int count ); + +// tessTesselate() - tesselate contours. +// Parameters: +// tess - pointer to tesselator object. +// windingRule - winding rules used for tesselation, must be one of TessWindingRule. +// elementType - defines the tesselation result element type, must be one of TessElementType. +// polySize - defines maximum vertices per polygons if output is polygons. If elementType is TESS_CONSTRAINED_DELAUNAY_TRIANGLES, this parameter is ignored. +// vertexSize - defines the number of coordinates in tesselation result vertex, must be 2 or 3. +// normal - defines the normal of the input contours, of null the normal is calculated automatically. +// Returns: +// 1 if succeed, 0 if failed. +int tessTesselate( TESStesselator *tess, int windingRule, int elementType, int polySize, int vertexSize, const TESSreal* normal ); + +// tessGetVertexCount() - Returns number of vertices in the tesselated output. +int tessGetVertexCount( TESStesselator *tess ); + +// tessGetVertices() - Returns pointer to first coordinate of first vertex. +const TESSreal* tessGetVertices( TESStesselator *tess ); + +// tessGetVertexIndices() - Returns pointer to first vertex index. +// Vertex indices can be used to map the generated vertices to the original vertices. +// Every point added using tessAddContour() will get a new index starting at 0. +// New vertices generated at the intersections of segments are assigned value TESS_UNDEF. +const TESSindex* tessGetVertexIndices( TESStesselator *tess ); + +// tessGetElementCount() - Returns number of elements in the the tesselated output. +int tessGetElementCount( TESStesselator *tess ); + +// tessGetElements() - Returns pointer to the first element. +const TESSindex* tessGetElements( TESStesselator *tess ); + +#ifdef __cplusplus +}; +#endif + +#endif // TESSELATOR_H diff --git a/src/libtess2/Source/bucketalloc.c b/src/libtess2/Source/bucketalloc.c new file mode 100755 index 00000000..420ebab5 --- /dev/null +++ b/src/libtess2/Source/bucketalloc.c @@ -0,0 +1,191 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Mikko Mononen, July 2009. +*/ + +#include +#include +#include "../Include/tesselator.h" + +//#define CHECK_BOUNDS + +typedef struct BucketAlloc BucketAlloc; +typedef struct Bucket Bucket; + +struct Bucket +{ + Bucket *next; +}; + +struct BucketAlloc +{ + void *freelist; + Bucket *buckets; + unsigned int itemSize; + unsigned int bucketSize; + const char *name; + TESSalloc* alloc; +}; + +static int CreateBucket( struct BucketAlloc* ba ) +{ + size_t size; + Bucket* bucket; + void* freelist; + unsigned char* head; + unsigned char* it; + + // Allocate memory for the bucket + size = sizeof(Bucket) + ba->itemSize * ba->bucketSize; + bucket = (Bucket*)ba->alloc->memalloc( ba->alloc->userData, size ); + if ( !bucket ) + return 0; + bucket->next = 0; + + // Add the bucket into the list of buckets. + bucket->next = ba->buckets; + ba->buckets = bucket; + + // Add new items to the free list. + freelist = ba->freelist; + head = (unsigned char*)bucket + sizeof(Bucket); + it = head + ba->itemSize * ba->bucketSize; + do + { + it -= ba->itemSize; + // Store pointer to next free item. + *((void**)it) = freelist; + // Pointer to next location containing a free item. + freelist = (void*)it; + } + while ( it != head ); + // Update pointer to next location containing a free item. + ba->freelist = (void*)it; + + return 1; +} + +static void *NextFreeItem( struct BucketAlloc *ba ) +{ + return *(void**)ba->freelist; +} + +struct BucketAlloc* createBucketAlloc( TESSalloc* alloc, const char* name, + unsigned int itemSize, unsigned int bucketSize ) +{ + BucketAlloc* ba = (BucketAlloc*)alloc->memalloc( alloc->userData, sizeof(BucketAlloc) ); + + ba->alloc = alloc; + ba->name = name; + ba->itemSize = itemSize; + if ( ba->itemSize < sizeof(void*) ) + ba->itemSize = sizeof(void*); + ba->bucketSize = bucketSize; + ba->freelist = 0; + ba->buckets = 0; + + if ( !CreateBucket( ba ) ) + { + alloc->memfree( alloc->userData, ba ); + return 0; + } + + return ba; +} + +void* bucketAlloc( struct BucketAlloc *ba ) +{ + void *it; + + // If running out of memory, allocate new bucket and update the freelist. + if ( !ba->freelist || !NextFreeItem( ba ) ) + { + if ( !CreateBucket( ba ) ) + return 0; + } + + // Pop item from in front of the free list. + it = ba->freelist; + ba->freelist = NextFreeItem( ba ); + + return it; +} + +void bucketFree( struct BucketAlloc *ba, void *ptr ) +{ +#ifdef CHECK_BOUNDS + int inBounds = 0; + Bucket *bucket; + + // Check that the pointer is allocated with this allocator. + bucket = ba->buckets; + while ( bucket ) + { + void *bucketMin = (void*)((unsigned char*)bucket + sizeof(Bucket)); + void *bucketMax = (void*)((unsigned char*)bucket + sizeof(Bucket) + ba->itemSize * ba->bucketSize); + if ( ptr >= bucketMin && ptr < bucketMax ) + { + inBounds = 1; + break; + } + bucket = bucket->next; + } + + if ( inBounds ) + { + // Add the node in front of the free list. + *(void**)ptr = ba->freelist; + ba->freelist = ptr; + } + else + { + printf("ERROR! pointer 0x%p does not belong to allocator '%s'\n", ba->name); + } +#else + // Add the node in front of the free list. + *(void**)ptr = ba->freelist; + ba->freelist = ptr; +#endif +} + +void deleteBucketAlloc( struct BucketAlloc *ba ) +{ + TESSalloc* alloc = ba->alloc; + Bucket *bucket = ba->buckets; + Bucket *next; + while ( bucket ) + { + next = bucket->next; + alloc->memfree( alloc->userData, bucket ); + bucket = next; + } + ba->freelist = 0; + ba->buckets = 0; + alloc->memfree( alloc->userData, ba ); +} diff --git a/src/libtess2/Source/bucketalloc.h b/src/libtess2/Source/bucketalloc.h new file mode 100755 index 00000000..c540951e --- /dev/null +++ b/src/libtess2/Source/bucketalloc.h @@ -0,0 +1,51 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Mikko Mononen, July 2009. +*/ + +#ifndef MEMALLOC_H +#define MEMALLOC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "tesselator.h" + +struct BucketAlloc *createBucketAlloc( TESSalloc* alloc, const char *name, + unsigned int itemSize, unsigned int bucketSize ); +void *bucketAlloc( struct BucketAlloc *ba); +void bucketFree( struct BucketAlloc *ba, void *ptr ); +void deleteBucketAlloc( struct BucketAlloc *ba ); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/src/libtess2/Source/dict.c b/src/libtess2/Source/dict.c new file mode 100755 index 00000000..650adda2 --- /dev/null +++ b/src/libtess2/Source/dict.c @@ -0,0 +1,109 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#include +#include "../Include/tesselator.h" +#include "bucketalloc.h" +#include "dict.h" + +/* really tessDictListNewDict */ +Dict *dictNewDict( TESSalloc* alloc, void *frame, int (*leq)(void *frame, DictKey key1, DictKey key2) ) +{ + Dict *dict = (Dict *)alloc->memalloc( alloc->userData, sizeof( Dict )); + DictNode *head; + + if (dict == NULL) return NULL; + + head = &dict->head; + + head->key = NULL; + head->next = head; + head->prev = head; + + dict->frame = frame; + dict->leq = leq; + + if (alloc->dictNodeBucketSize < 16) + alloc->dictNodeBucketSize = 16; + if (alloc->dictNodeBucketSize > 4096) + alloc->dictNodeBucketSize = 4096; + dict->nodePool = createBucketAlloc( alloc, "Dict", sizeof(DictNode), alloc->dictNodeBucketSize ); + + return dict; +} + +/* really tessDictListDeleteDict */ +void dictDeleteDict( TESSalloc* alloc, Dict *dict ) +{ + deleteBucketAlloc( dict->nodePool ); + alloc->memfree( alloc->userData, dict ); +} + +/* really tessDictListInsertBefore */ +DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key ) +{ + DictNode *newNode; + + do { + node = node->prev; + } while( node->key != NULL && ! (*dict->leq)(dict->frame, node->key, key)); + + newNode = (DictNode *)bucketAlloc( dict->nodePool ); + if (newNode == NULL) return NULL; + + newNode->key = key; + newNode->next = node->next; + node->next->prev = newNode; + newNode->prev = node; + node->next = newNode; + + return newNode; +} + +/* really tessDictListDelete */ +void dictDelete( Dict *dict, DictNode *node ) /*ARGSUSED*/ +{ + node->next->prev = node->prev; + node->prev->next = node->next; + bucketFree( dict->nodePool, node ); +} + +/* really tessDictListSearch */ +DictNode *dictSearch( Dict *dict, DictKey key ) +{ + DictNode *node = &dict->head; + + do { + node = node->next; + } while( node->key != NULL && ! (*dict->leq)(dict->frame, key, node->key)); + + return node; +} diff --git a/src/libtess2/Source/dict.h b/src/libtess2/Source/dict.h new file mode 100755 index 00000000..4cf32265 --- /dev/null +++ b/src/libtess2/Source/dict.h @@ -0,0 +1,74 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#ifndef DICT_LIST_H +#define DICT_LIST_H + +typedef void *DictKey; +typedef struct Dict Dict; +typedef struct DictNode DictNode; + +Dict *dictNewDict( TESSalloc* alloc, void *frame, int (*leq)(void *frame, DictKey key1, DictKey key2) ); + +void dictDeleteDict( TESSalloc* alloc, Dict *dict ); + +/* Search returns the node with the smallest key greater than or equal +* to the given key. If there is no such key, returns a node whose +* key is NULL. Similarly, Succ(Max(d)) has a NULL key, etc. +*/ +DictNode *dictSearch( Dict *dict, DictKey key ); +DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key ); +void dictDelete( Dict *dict, DictNode *node ); + +#define dictKey(n) ((n)->key) +#define dictSucc(n) ((n)->next) +#define dictPred(n) ((n)->prev) +#define dictMin(d) ((d)->head.next) +#define dictMax(d) ((d)->head.prev) +#define dictInsert(d,k) (dictInsertBefore((d),&(d)->head,(k))) + + +/*** Private data structures ***/ + +struct DictNode { + DictKey key; + DictNode *next; + DictNode *prev; +}; + +struct Dict { + DictNode head; + void *frame; + struct BucketAlloc *nodePool; + int (*leq)(void *frame, DictKey key1, DictKey key2); +}; + +#endif diff --git a/src/libtess2/Source/geom.c b/src/libtess2/Source/geom.c new file mode 100755 index 00000000..21156f3f --- /dev/null +++ b/src/libtess2/Source/geom.c @@ -0,0 +1,292 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +//#include "tesos.h" +#include +#include "mesh.h" +#include "geom.h" +#include + +int tesvertLeq( TESSvertex *u, TESSvertex *v ) +{ + /* Returns TRUE if u is lexicographically <= v. */ + + return VertLeq( u, v ); +} + +TESSreal tesedgeEval( TESSvertex *u, TESSvertex *v, TESSvertex *w ) +{ + /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w), + * evaluates the t-coord of the edge uw at the s-coord of the vertex v. + * Returns v->t - (uw)(v->s), ie. the signed distance from uw to v. + * If uw is vertical (and thus passes thru v), the result is zero. + * + * The calculation is extremely accurate and stable, even when v + * is very close to u or w. In particular if we set v->t = 0 and + * let r be the negated result (this evaluates (uw)(v->s)), then + * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t). + */ + TESSreal gapL, gapR; + + assert( VertLeq( u, v ) && VertLeq( v, w )); + + gapL = v->s - u->s; + gapR = w->s - v->s; + + if( gapL + gapR > 0 ) { + if( gapL < gapR ) { + return (v->t - u->t) + (u->t - w->t) * (gapL / (gapL + gapR)); + } else { + return (v->t - w->t) + (w->t - u->t) * (gapR / (gapL + gapR)); + } + } + /* vertical line */ + return 0; +} + +TESSreal tesedgeSign( TESSvertex *u, TESSvertex *v, TESSvertex *w ) +{ + /* Returns a number whose sign matches EdgeEval(u,v,w) but which + * is cheaper to evaluate. Returns > 0, == 0 , or < 0 + * as v is above, on, or below the edge uw. + */ + TESSreal gapL, gapR; + + assert( VertLeq( u, v ) && VertLeq( v, w )); + + gapL = v->s - u->s; + gapR = w->s - v->s; + + if( gapL + gapR > 0 ) { + return (v->t - w->t) * gapL + (v->t - u->t) * gapR; + } + /* vertical line */ + return 0; +} + + +/*********************************************************************** +* Define versions of EdgeSign, EdgeEval with s and t transposed. +*/ + +TESSreal testransEval( TESSvertex *u, TESSvertex *v, TESSvertex *w ) +{ + /* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w), + * evaluates the t-coord of the edge uw at the s-coord of the vertex v. + * Returns v->s - (uw)(v->t), ie. the signed distance from uw to v. + * If uw is vertical (and thus passes thru v), the result is zero. + * + * The calculation is extremely accurate and stable, even when v + * is very close to u or w. In particular if we set v->s = 0 and + * let r be the negated result (this evaluates (uw)(v->t)), then + * r is guaranteed to satisfy MIN(u->s,w->s) <= r <= MAX(u->s,w->s). + */ + TESSreal gapL, gapR; + + assert( TransLeq( u, v ) && TransLeq( v, w )); + + gapL = v->t - u->t; + gapR = w->t - v->t; + + if( gapL + gapR > 0 ) { + if( gapL < gapR ) { + return (v->s - u->s) + (u->s - w->s) * (gapL / (gapL + gapR)); + } else { + return (v->s - w->s) + (w->s - u->s) * (gapR / (gapL + gapR)); + } + } + /* vertical line */ + return 0; +} + +TESSreal testransSign( TESSvertex *u, TESSvertex *v, TESSvertex *w ) +{ + /* Returns a number whose sign matches TransEval(u,v,w) but which + * is cheaper to evaluate. Returns > 0, == 0 , or < 0 + * as v is above, on, or below the edge uw. + */ + TESSreal gapL, gapR; + + assert( TransLeq( u, v ) && TransLeq( v, w )); + + gapL = v->t - u->t; + gapR = w->t - v->t; + + if( gapL + gapR > 0 ) { + return (v->s - w->s) * gapL + (v->s - u->s) * gapR; + } + /* vertical line */ + return 0; +} + + +int tesvertCCW( TESSvertex *u, TESSvertex *v, TESSvertex *w ) +{ + /* For almost-degenerate situations, the results are not reliable. + * Unless the floating-point arithmetic can be performed without + * rounding errors, *any* implementation will give incorrect results + * on some degenerate inputs, so the client must have some way to + * handle this situation. + */ + return (u->s*(v->t - w->t) + v->s*(w->t - u->t) + w->s*(u->t - v->t)) >= 0; +} + +/* Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b), +* or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces +* this in the rare case that one argument is slightly negative. +* The implementation is extremely stable numerically. +* In particular it guarantees that the result r satisfies +* MIN(x,y) <= r <= MAX(x,y), and the results are very accurate +* even when a and b differ greatly in magnitude. +*/ +#define RealInterpolate(a,x,b,y) \ + (a = (a < 0) ? 0 : a, b = (b < 0) ? 0 : b, \ + ((a <= b) ? ((b == 0) ? ((x+y) / 2) \ + : (x + (y-x) * (a/(a+b)))) \ + : (y + (x-y) * (b/(a+b))))) + +#ifndef FOR_TRITE_TEST_PROGRAM +#define Interpolate(a,x,b,y) RealInterpolate(a,x,b,y) +#else + +/* Claim: the ONLY property the sweep algorithm relies on is that +* MIN(x,y) <= r <= MAX(x,y). This is a nasty way to test that. +*/ +#include +extern int RandomInterpolate; + +double Interpolate( double a, double x, double b, double y) +{ + printf("*********************%d\n",RandomInterpolate); + if( RandomInterpolate ) { + a = 1.2 * drand48() - 0.1; + a = (a < 0) ? 0 : ((a > 1) ? 1 : a); + b = 1.0 - a; + } + return RealInterpolate(a,x,b,y); +} + +#endif + +#define Swap(a,b) if (1) { TESSvertex *t = a; a = b; b = t; } else + +void tesedgeIntersect( TESSvertex *o1, TESSvertex *d1, + TESSvertex *o2, TESSvertex *d2, + TESSvertex *v ) + /* Given edges (o1,d1) and (o2,d2), compute their point of intersection. + * The computed point is guaranteed to lie in the intersection of the + * bounding rectangles defined by each edge. + */ +{ + TESSreal z1, z2; + + /* This is certainly not the most efficient way to find the intersection + * of two line segments, but it is very numerically stable. + * + * Strategy: find the two middle vertices in the VertLeq ordering, + * and interpolate the intersection s-value from these. Then repeat + * using the TransLeq ordering to find the intersection t-value. + */ + + if( ! VertLeq( o1, d1 )) { Swap( o1, d1 ); } + if( ! VertLeq( o2, d2 )) { Swap( o2, d2 ); } + if( ! VertLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); } + + if( ! VertLeq( o2, d1 )) { + /* Technically, no intersection -- do our best */ + v->s = (o2->s + d1->s) / 2; + } else if( VertLeq( d1, d2 )) { + /* Interpolate between o2 and d1 */ + z1 = EdgeEval( o1, o2, d1 ); + z2 = EdgeEval( o2, d1, d2 ); + if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } + v->s = Interpolate( z1, o2->s, z2, d1->s ); + } else { + /* Interpolate between o2 and d2 */ + z1 = EdgeSign( o1, o2, d1 ); + z2 = -EdgeSign( o1, d2, d1 ); + if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } + v->s = Interpolate( z1, o2->s, z2, d2->s ); + } + + /* Now repeat the process for t */ + + if( ! TransLeq( o1, d1 )) { Swap( o1, d1 ); } + if( ! TransLeq( o2, d2 )) { Swap( o2, d2 ); } + if( ! TransLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); } + + if( ! TransLeq( o2, d1 )) { + /* Technically, no intersection -- do our best */ + v->t = (o2->t + d1->t) / 2; + } else if( TransLeq( d1, d2 )) { + /* Interpolate between o2 and d1 */ + z1 = TransEval( o1, o2, d1 ); + z2 = TransEval( o2, d1, d2 ); + if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } + v->t = Interpolate( z1, o2->t, z2, d1->t ); + } else { + /* Interpolate between o2 and d2 */ + z1 = TransSign( o1, o2, d1 ); + z2 = -TransSign( o1, d2, d1 ); + if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } + v->t = Interpolate( z1, o2->t, z2, d2->t ); + } +} + +/* + Calculate the angle between v1-v2 and v1-v0 + */ +TESSreal calcAngle( TESSvertex *v0, TESSvertex *v1, TESSvertex *v2 ) +{ + TESSreal num; + TESSreal den; + TESSreal a[2]; + TESSreal b[2]; + a[0] = v2->s - v1->s; + a[1] = v2->t - v1->t; + b[0] = v0->s - v1->s; + b[1] = v0->t - v1->t; + num = a[0] * b[0] + a[1] * b[1]; + den = sqrt( a[0] * a[0] + a[1] * a[1] ) * sqrt( b[0] * b[0] + b[1] * b[1] ); + if ( den > 0.0 ) num /= den; + if ( num < -1.0 ) num = -1.0; + if ( num > 1.0 ) num = 1.0; + return acos( num ); +} + +/* + Returns 1 is edge is locally delaunay + */ +int tesedgeIsLocallyDelaunay( TESShalfEdge *e ) +{ + return (calcAngle(e->Lnext->Org, e->Lnext->Lnext->Org, e->Org) + + calcAngle(e->Sym->Lnext->Org, e->Sym->Lnext->Lnext->Org, e->Sym->Org)) < (M_PI + 0.01); +} diff --git a/src/libtess2/Source/geom.h b/src/libtess2/Source/geom.h new file mode 100755 index 00000000..1b93fd64 --- /dev/null +++ b/src/libtess2/Source/geom.h @@ -0,0 +1,78 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#ifndef GEOM_H +#define GEOM_H + +#include "mesh.h" + +#ifdef NO_BRANCH_CONDITIONS +/* MIPS architecture has special instructions to evaluate boolean +* conditions -- more efficient than branching, IF you can get the +* compiler to generate the right instructions (SGI compiler doesn't) +*/ +#define VertEq(u,v) (((u)->s == (v)->s) & ((u)->t == (v)->t)) +#define VertLeq(u,v) (((u)->s < (v)->s) | \ + ((u)->s == (v)->s & (u)->t <= (v)->t)) +#else +#define VertEq(u,v) ((u)->s == (v)->s && (u)->t == (v)->t) +#define VertLeq(u,v) (((u)->s < (v)->s) || ((u)->s == (v)->s && (u)->t <= (v)->t)) +#endif + +#define EdgeEval(u,v,w) tesedgeEval(u,v,w) +#define EdgeSign(u,v,w) tesedgeSign(u,v,w) + +/* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */ + +#define TransLeq(u,v) (((u)->t < (v)->t) || ((u)->t == (v)->t && (u)->s <= (v)->s)) +#define TransEval(u,v,w) testransEval(u,v,w) +#define TransSign(u,v,w) testransSign(u,v,w) + + +#define EdgeGoesLeft(e) VertLeq( (e)->Dst, (e)->Org ) +#define EdgeGoesRight(e) VertLeq( (e)->Org, (e)->Dst ) +#define EdgeIsInternal(e) e->Rface && e->Rface->inside + +#define ABS(x) ((x) < 0 ? -(x) : (x)) +#define VertL1dist(u,v) (ABS(u->s - v->s) + ABS(u->t - v->t)) + +#define VertCCW(u,v,w) tesvertCCW(u,v,w) + +int tesvertLeq( TESSvertex *u, TESSvertex *v ); +TESSreal tesedgeEval( TESSvertex *u, TESSvertex *v, TESSvertex *w ); +TESSreal tesedgeSign( TESSvertex *u, TESSvertex *v, TESSvertex *w ); +TESSreal testransEval( TESSvertex *u, TESSvertex *v, TESSvertex *w ); +TESSreal testransSign( TESSvertex *u, TESSvertex *v, TESSvertex *w ); +int tesvertCCW( TESSvertex *u, TESSvertex *v, TESSvertex *w ); +void tesedgeIntersect( TESSvertex *o1, TESSvertex *d1, TESSvertex *o2, TESSvertex *d2, TESSvertex *v ); +int tesedgeIsLocallyDelaunay( TESShalfEdge *e ); + +#endif diff --git a/src/libtess2/Source/mesh.c b/src/libtess2/Source/mesh.c new file mode 100755 index 00000000..15ce620d --- /dev/null +++ b/src/libtess2/Source/mesh.c @@ -0,0 +1,922 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +//#include "tesos.h" +#include +#include +#include "mesh.h" +#include "geom.h" +#include "bucketalloc.h" + +#define TRUE 1 +#define FALSE 0 + +/************************ Utility Routines ************************/ + +/* Allocate and free half-edges in pairs for efficiency. +* The *only* place that should use this fact is allocation/free. +*/ +typedef struct { TESShalfEdge e, eSym; } EdgePair; + +/* MakeEdge creates a new pair of half-edges which form their own loop. +* No vertex or face structures are allocated, but these must be assigned +* before the current edge operation is completed. +*/ +static TESShalfEdge *MakeEdge( TESSmesh* mesh, TESShalfEdge *eNext ) +{ + TESShalfEdge *e; + TESShalfEdge *eSym; + TESShalfEdge *ePrev; + EdgePair *pair = (EdgePair *)bucketAlloc( mesh->edgeBucket ); + if (pair == NULL) return NULL; + + e = &pair->e; + eSym = &pair->eSym; + + /* Make sure eNext points to the first edge of the edge pair */ + if( eNext->Sym < eNext ) { eNext = eNext->Sym; } + + /* Insert in circular doubly-linked list before eNext. + * Note that the prev pointer is stored in Sym->next. + */ + ePrev = eNext->Sym->next; + eSym->next = ePrev; + ePrev->Sym->next = e; + e->next = eNext; + eNext->Sym->next = eSym; + + e->Sym = eSym; + e->Onext = e; + e->Lnext = eSym; + e->Org = NULL; + e->Lface = NULL; + e->winding = 0; + e->activeRegion = NULL; + e->mark = 0; + + eSym->Sym = e; + eSym->Onext = eSym; + eSym->Lnext = e; + eSym->Org = NULL; + eSym->Lface = NULL; + eSym->winding = 0; + eSym->activeRegion = NULL; + eSym->mark = 0; + + return e; +} + +/* Splice( a, b ) is best described by the Guibas/Stolfi paper or the +* CS348a notes (see mesh.h). Basically it modifies the mesh so that +* a->Onext and b->Onext are exchanged. This can have various effects +* depending on whether a and b belong to different face or vertex rings. +* For more explanation see tessMeshSplice() below. +*/ +static void Splice( TESShalfEdge *a, TESShalfEdge *b ) +{ + TESShalfEdge *aOnext = a->Onext; + TESShalfEdge *bOnext = b->Onext; + + aOnext->Sym->Lnext = b; + bOnext->Sym->Lnext = a; + a->Onext = bOnext; + b->Onext = aOnext; +} + +/* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the +* origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives +* a place to insert the new vertex in the global vertex list. We insert +* the new vertex *before* vNext so that algorithms which walk the vertex +* list will not see the newly created vertices. +*/ +static void MakeVertex( TESSvertex *newVertex, + TESShalfEdge *eOrig, TESSvertex *vNext ) +{ + TESShalfEdge *e; + TESSvertex *vPrev; + TESSvertex *vNew = newVertex; + + assert(vNew != NULL); + + /* insert in circular doubly-linked list before vNext */ + vPrev = vNext->prev; + vNew->prev = vPrev; + vPrev->next = vNew; + vNew->next = vNext; + vNext->prev = vNew; + + vNew->anEdge = eOrig; + /* leave coords, s, t undefined */ + + /* fix other edges on this vertex loop */ + e = eOrig; + do { + e->Org = vNew; + e = e->Onext; + } while( e != eOrig ); +} + +/* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left +* face of all edges in the face loop to which eOrig belongs. "fNext" gives +* a place to insert the new face in the global face list. We insert +* the new face *before* fNext so that algorithms which walk the face +* list will not see the newly created faces. +*/ +static void MakeFace( TESSface *newFace, TESShalfEdge *eOrig, TESSface *fNext ) +{ + TESShalfEdge *e; + TESSface *fPrev; + TESSface *fNew = newFace; + + assert(fNew != NULL); + + /* insert in circular doubly-linked list before fNext */ + fPrev = fNext->prev; + fNew->prev = fPrev; + fPrev->next = fNew; + fNew->next = fNext; + fNext->prev = fNew; + + fNew->anEdge = eOrig; + fNew->trail = NULL; + fNew->marked = FALSE; + + /* The new face is marked "inside" if the old one was. This is a + * convenience for the common case where a face has been split in two. + */ + fNew->inside = fNext->inside; + + /* fix other edges on this face loop */ + e = eOrig; + do { + e->Lface = fNew; + e = e->Lnext; + } while( e != eOrig ); +} + +/* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym), +* and removes from the global edge list. +*/ +static void KillEdge( TESSmesh *mesh, TESShalfEdge *eDel ) +{ + TESShalfEdge *ePrev, *eNext; + + /* Half-edges are allocated in pairs, see EdgePair above */ + if( eDel->Sym < eDel ) { eDel = eDel->Sym; } + + /* delete from circular doubly-linked list */ + eNext = eDel->next; + ePrev = eDel->Sym->next; + eNext->Sym->next = ePrev; + ePrev->Sym->next = eNext; + + bucketFree( mesh->edgeBucket, eDel ); +} + + +/* KillVertex( vDel ) destroys a vertex and removes it from the global +* vertex list. It updates the vertex loop to point to a given new vertex. +*/ +static void KillVertex( TESSmesh *mesh, TESSvertex *vDel, TESSvertex *newOrg ) +{ + TESShalfEdge *e, *eStart = vDel->anEdge; + TESSvertex *vPrev, *vNext; + + /* change the origin of all affected edges */ + e = eStart; + do { + e->Org = newOrg; + e = e->Onext; + } while( e != eStart ); + + /* delete from circular doubly-linked list */ + vPrev = vDel->prev; + vNext = vDel->next; + vNext->prev = vPrev; + vPrev->next = vNext; + + bucketFree( mesh->vertexBucket, vDel ); +} + +/* KillFace( fDel ) destroys a face and removes it from the global face +* list. It updates the face loop to point to a given new face. +*/ +static void KillFace( TESSmesh *mesh, TESSface *fDel, TESSface *newLface ) +{ + TESShalfEdge *e, *eStart = fDel->anEdge; + TESSface *fPrev, *fNext; + + /* change the left face of all affected edges */ + e = eStart; + do { + e->Lface = newLface; + e = e->Lnext; + } while( e != eStart ); + + /* delete from circular doubly-linked list */ + fPrev = fDel->prev; + fNext = fDel->next; + fNext->prev = fPrev; + fPrev->next = fNext; + + bucketFree( mesh->faceBucket, fDel ); +} + + +/****************** Basic Edge Operations **********************/ + +/* tessMeshMakeEdge creates one edge, two vertices, and a loop (face). +* The loop consists of the two new half-edges. +*/ +TESShalfEdge *tessMeshMakeEdge( TESSmesh *mesh ) +{ + TESSvertex *newVertex1 = (TESSvertex*)bucketAlloc(mesh->vertexBucket); + TESSvertex *newVertex2 = (TESSvertex*)bucketAlloc(mesh->vertexBucket); + TESSface *newFace = (TESSface*)bucketAlloc(mesh->faceBucket); + TESShalfEdge *e; + + /* if any one is null then all get freed */ + if (newVertex1 == NULL || newVertex2 == NULL || newFace == NULL) { + if (newVertex1 != NULL) bucketFree( mesh->vertexBucket, newVertex1 ); + if (newVertex2 != NULL) bucketFree( mesh->vertexBucket, newVertex2 ); + if (newFace != NULL) bucketFree( mesh->faceBucket, newFace ); + return NULL; + } + + e = MakeEdge( mesh, &mesh->eHead ); + if (e == NULL) return NULL; + + MakeVertex( newVertex1, e, &mesh->vHead ); + MakeVertex( newVertex2, e->Sym, &mesh->vHead ); + MakeFace( newFace, e, &mesh->fHead ); + return e; +} + + +/* tessMeshSplice( eOrg, eDst ) is the basic operation for changing the +* mesh connectivity and topology. It changes the mesh so that +* eOrg->Onext <- OLD( eDst->Onext ) +* eDst->Onext <- OLD( eOrg->Onext ) +* where OLD(...) means the value before the meshSplice operation. +* +* This can have two effects on the vertex structure: +* - if eOrg->Org != eDst->Org, the two vertices are merged together +* - if eOrg->Org == eDst->Org, the origin is split into two vertices +* In both cases, eDst->Org is changed and eOrg->Org is untouched. +* +* Similarly (and independently) for the face structure, +* - if eOrg->Lface == eDst->Lface, one loop is split into two +* - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one +* In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. +* +* Some special cases: +* If eDst == eOrg, the operation has no effect. +* If eDst == eOrg->Lnext, the new face will have a single edge. +* If eDst == eOrg->Lprev, the old face will have a single edge. +* If eDst == eOrg->Onext, the new vertex will have a single edge. +* If eDst == eOrg->Oprev, the old vertex will have a single edge. +*/ +int tessMeshSplice( TESSmesh* mesh, TESShalfEdge *eOrg, TESShalfEdge *eDst ) +{ + int joiningLoops = FALSE; + int joiningVertices = FALSE; + + if( eOrg == eDst ) return 1; + + if( eDst->Org != eOrg->Org ) { + /* We are merging two disjoint vertices -- destroy eDst->Org */ + joiningVertices = TRUE; + KillVertex( mesh, eDst->Org, eOrg->Org ); + } + if( eDst->Lface != eOrg->Lface ) { + /* We are connecting two disjoint loops -- destroy eDst->Lface */ + joiningLoops = TRUE; + KillFace( mesh, eDst->Lface, eOrg->Lface ); + } + + /* Change the edge structure */ + Splice( eDst, eOrg ); + + if( ! joiningVertices ) { + TESSvertex *newVertex = (TESSvertex*)bucketAlloc( mesh->vertexBucket ); + if (newVertex == NULL) return 0; + + /* We split one vertex into two -- the new vertex is eDst->Org. + * Make sure the old vertex points to a valid half-edge. + */ + MakeVertex( newVertex, eDst, eOrg->Org ); + eOrg->Org->anEdge = eOrg; + } + if( ! joiningLoops ) { + TESSface *newFace = (TESSface*)bucketAlloc( mesh->faceBucket ); + if (newFace == NULL) return 0; + + /* We split one loop into two -- the new loop is eDst->Lface. + * Make sure the old face points to a valid half-edge. + */ + MakeFace( newFace, eDst, eOrg->Lface ); + eOrg->Lface->anEdge = eOrg; + } + + return 1; +} + + +/* tessMeshDelete( eDel ) removes the edge eDel. There are several cases: +* if (eDel->Lface != eDel->Rface), we join two loops into one; the loop +* eDel->Lface is deleted. Otherwise, we are splitting one loop into two; +* the newly created loop will contain eDel->Dst. If the deletion of eDel +* would create isolated vertices, those are deleted as well. +* +* This function could be implemented as two calls to tessMeshSplice +* plus a few calls to memFree, but this would allocate and delete +* unnecessary vertices and faces. +*/ +int tessMeshDelete( TESSmesh *mesh, TESShalfEdge *eDel ) +{ + TESShalfEdge *eDelSym = eDel->Sym; + int joiningLoops = FALSE; + + /* First step: disconnect the origin vertex eDel->Org. We make all + * changes to get a consistent mesh in this "intermediate" state. + */ + if( eDel->Lface != eDel->Rface ) { + /* We are joining two loops into one -- remove the left face */ + joiningLoops = TRUE; + KillFace( mesh, eDel->Lface, eDel->Rface ); + } + + if( eDel->Onext == eDel ) { + KillVertex( mesh, eDel->Org, NULL ); + } else { + /* Make sure that eDel->Org and eDel->Rface point to valid half-edges */ + eDel->Rface->anEdge = eDel->Oprev; + eDel->Org->anEdge = eDel->Onext; + + Splice( eDel, eDel->Oprev ); + if( ! joiningLoops ) { + TESSface *newFace= (TESSface*)bucketAlloc( mesh->faceBucket ); + if (newFace == NULL) return 0; + + /* We are splitting one loop into two -- create a new loop for eDel. */ + MakeFace( newFace, eDel, eDel->Lface ); + } + } + + /* Claim: the mesh is now in a consistent state, except that eDel->Org + * may have been deleted. Now we disconnect eDel->Dst. + */ + if( eDelSym->Onext == eDelSym ) { + KillVertex( mesh, eDelSym->Org, NULL ); + KillFace( mesh, eDelSym->Lface, NULL ); + } else { + /* Make sure that eDel->Dst and eDel->Lface point to valid half-edges */ + eDel->Lface->anEdge = eDelSym->Oprev; + eDelSym->Org->anEdge = eDelSym->Onext; + Splice( eDelSym, eDelSym->Oprev ); + } + + /* Any isolated vertices or faces have already been freed. */ + KillEdge( mesh, eDel ); + + return 1; +} + + +/******************** Other Edge Operations **********************/ + +/* All these routines can be implemented with the basic edge +* operations above. They are provided for convenience and efficiency. +*/ + + +/* tessMeshAddEdgeVertex( eOrg ) creates a new edge eNew such that +* eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex. +* eOrg and eNew will have the same left face. +*/ +TESShalfEdge *tessMeshAddEdgeVertex( TESSmesh *mesh, TESShalfEdge *eOrg ) +{ + TESShalfEdge *eNewSym; + TESShalfEdge *eNew = MakeEdge( mesh, eOrg ); + if (eNew == NULL) return NULL; + + eNewSym = eNew->Sym; + + /* Connect the new edge appropriately */ + Splice( eNew, eOrg->Lnext ); + + /* Set the vertex and face information */ + eNew->Org = eOrg->Dst; + { + TESSvertex *newVertex= (TESSvertex*)bucketAlloc( mesh->vertexBucket ); + if (newVertex == NULL) return NULL; + + MakeVertex( newVertex, eNewSym, eNew->Org ); + } + eNew->Lface = eNewSym->Lface = eOrg->Lface; + + return eNew; +} + + +/* tessMeshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew, +* such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org. +* eOrg and eNew will have the same left face. +*/ +TESShalfEdge *tessMeshSplitEdge( TESSmesh *mesh, TESShalfEdge *eOrg ) +{ + TESShalfEdge *eNew; + TESShalfEdge *tempHalfEdge= tessMeshAddEdgeVertex( mesh, eOrg ); + if (tempHalfEdge == NULL) return NULL; + + eNew = tempHalfEdge->Sym; + + /* Disconnect eOrg from eOrg->Dst and connect it to eNew->Org */ + Splice( eOrg->Sym, eOrg->Sym->Oprev ); + Splice( eOrg->Sym, eNew ); + + /* Set the vertex and face information */ + eOrg->Dst = eNew->Org; + eNew->Dst->anEdge = eNew->Sym; /* may have pointed to eOrg->Sym */ + eNew->Rface = eOrg->Rface; + eNew->winding = eOrg->winding; /* copy old winding information */ + eNew->Sym->winding = eOrg->Sym->winding; + + return eNew; +} + + +/* tessMeshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst +* to eDst->Org, and returns the corresponding half-edge eNew. +* If eOrg->Lface == eDst->Lface, this splits one loop into two, +* and the newly created loop is eNew->Lface. Otherwise, two disjoint +* loops are merged into one, and the loop eDst->Lface is destroyed. +* +* If (eOrg == eDst), the new face will have only two edges. +* If (eOrg->Lnext == eDst), the old face is reduced to a single edge. +* If (eOrg->Lnext->Lnext == eDst), the old face is reduced to two edges. +*/ +TESShalfEdge *tessMeshConnect( TESSmesh *mesh, TESShalfEdge *eOrg, TESShalfEdge *eDst ) +{ + TESShalfEdge *eNewSym; + int joiningLoops = FALSE; + TESShalfEdge *eNew = MakeEdge( mesh, eOrg ); + if (eNew == NULL) return NULL; + + eNewSym = eNew->Sym; + + if( eDst->Lface != eOrg->Lface ) { + /* We are connecting two disjoint loops -- destroy eDst->Lface */ + joiningLoops = TRUE; + KillFace( mesh, eDst->Lface, eOrg->Lface ); + } + + /* Connect the new edge appropriately */ + Splice( eNew, eOrg->Lnext ); + Splice( eNewSym, eDst ); + + /* Set the vertex and face information */ + eNew->Org = eOrg->Dst; + eNewSym->Org = eDst->Org; + eNew->Lface = eNewSym->Lface = eOrg->Lface; + + /* Make sure the old face points to a valid half-edge */ + eOrg->Lface->anEdge = eNewSym; + + if( ! joiningLoops ) { + TESSface *newFace= (TESSface*)bucketAlloc( mesh->faceBucket ); + if (newFace == NULL) return NULL; + + /* We split one loop into two -- the new loop is eNew->Lface */ + MakeFace( newFace, eNew, eOrg->Lface ); + } + return eNew; +} + + +/******************** Other Operations **********************/ + +/* tessMeshZapFace( fZap ) destroys a face and removes it from the +* global face list. All edges of fZap will have a NULL pointer as their +* left face. Any edges which also have a NULL pointer as their right face +* are deleted entirely (along with any isolated vertices this produces). +* An entire mesh can be deleted by zapping its faces, one at a time, +* in any order. Zapped faces cannot be used in further mesh operations! +*/ +void tessMeshZapFace( TESSmesh *mesh, TESSface *fZap ) +{ + TESShalfEdge *eStart = fZap->anEdge; + TESShalfEdge *e, *eNext, *eSym; + TESSface *fPrev, *fNext; + + /* walk around face, deleting edges whose right face is also NULL */ + eNext = eStart->Lnext; + do { + e = eNext; + eNext = e->Lnext; + + e->Lface = NULL; + if( e->Rface == NULL ) { + /* delete the edge -- see TESSmeshDelete above */ + + if( e->Onext == e ) { + KillVertex( mesh, e->Org, NULL ); + } else { + /* Make sure that e->Org points to a valid half-edge */ + e->Org->anEdge = e->Onext; + Splice( e, e->Oprev ); + } + eSym = e->Sym; + if( eSym->Onext == eSym ) { + KillVertex( mesh, eSym->Org, NULL ); + } else { + /* Make sure that eSym->Org points to a valid half-edge */ + eSym->Org->anEdge = eSym->Onext; + Splice( eSym, eSym->Oprev ); + } + KillEdge( mesh, e ); + } + } while( e != eStart ); + + /* delete from circular doubly-linked list */ + fPrev = fZap->prev; + fNext = fZap->next; + fNext->prev = fPrev; + fPrev->next = fNext; + + bucketFree( mesh->faceBucket, fZap ); +} + + +/* tessMeshNewMesh() creates a new mesh with no edges, no vertices, +* and no loops (what we usually call a "face"). +*/ +TESSmesh *tessMeshNewMesh( TESSalloc* alloc ) +{ + TESSvertex *v; + TESSface *f; + TESShalfEdge *e; + TESShalfEdge *eSym; + TESSmesh *mesh = (TESSmesh *)alloc->memalloc( alloc->userData, sizeof( TESSmesh )); + if (mesh == NULL) { + return NULL; + } + + if (alloc->meshEdgeBucketSize < 16) + alloc->meshEdgeBucketSize = 16; + if (alloc->meshEdgeBucketSize > 4096) + alloc->meshEdgeBucketSize = 4096; + + if (alloc->meshVertexBucketSize < 16) + alloc->meshVertexBucketSize = 16; + if (alloc->meshVertexBucketSize > 4096) + alloc->meshVertexBucketSize = 4096; + + if (alloc->meshFaceBucketSize < 16) + alloc->meshFaceBucketSize = 16; + if (alloc->meshFaceBucketSize > 4096) + alloc->meshFaceBucketSize = 4096; + + mesh->edgeBucket = createBucketAlloc( alloc, "Mesh Edges", sizeof(EdgePair), alloc->meshEdgeBucketSize ); + mesh->vertexBucket = createBucketAlloc( alloc, "Mesh Vertices", sizeof(TESSvertex), alloc->meshVertexBucketSize ); + mesh->faceBucket = createBucketAlloc( alloc, "Mesh Faces", sizeof(TESSface), alloc->meshFaceBucketSize ); + + v = &mesh->vHead; + f = &mesh->fHead; + e = &mesh->eHead; + eSym = &mesh->eHeadSym; + + v->next = v->prev = v; + v->anEdge = NULL; + + f->next = f->prev = f; + f->anEdge = NULL; + f->trail = NULL; + f->marked = FALSE; + f->inside = FALSE; + + e->next = e; + e->Sym = eSym; + e->Onext = NULL; + e->Lnext = NULL; + e->Org = NULL; + e->Lface = NULL; + e->winding = 0; + e->activeRegion = NULL; + + eSym->next = eSym; + eSym->Sym = e; + eSym->Onext = NULL; + eSym->Lnext = NULL; + eSym->Org = NULL; + eSym->Lface = NULL; + eSym->winding = 0; + eSym->activeRegion = NULL; + + return mesh; +} + + +/* tessMeshUnion( mesh1, mesh2 ) forms the union of all structures in +* both meshes, and returns the new mesh (the old meshes are destroyed). +*/ +TESSmesh *tessMeshUnion( TESSalloc* alloc, TESSmesh *mesh1, TESSmesh *mesh2 ) +{ + TESSface *f1 = &mesh1->fHead; + TESSvertex *v1 = &mesh1->vHead; + TESShalfEdge *e1 = &mesh1->eHead; + TESSface *f2 = &mesh2->fHead; + TESSvertex *v2 = &mesh2->vHead; + TESShalfEdge *e2 = &mesh2->eHead; + + /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */ + if( f2->next != f2 ) { + f1->prev->next = f2->next; + f2->next->prev = f1->prev; + f2->prev->next = f1; + f1->prev = f2->prev; + } + + if( v2->next != v2 ) { + v1->prev->next = v2->next; + v2->next->prev = v1->prev; + v2->prev->next = v1; + v1->prev = v2->prev; + } + + if( e2->next != e2 ) { + e1->Sym->next->Sym->next = e2->next; + e2->next->Sym->next = e1->Sym->next; + e2->Sym->next->Sym->next = e1; + e1->Sym->next = e2->Sym->next; + } + + alloc->memfree( alloc->userData, mesh2 ); + return mesh1; +} + + +static int CountFaceVerts( TESSface *f ) +{ + TESShalfEdge *eCur = f->anEdge; + int n = 0; + do + { + n++; + eCur = eCur->Lnext; + } + while (eCur != f->anEdge); + return n; +} + +int tessMeshMergeConvexFaces( TESSmesh *mesh, int maxVertsPerFace ) +{ + TESSface *f; + TESShalfEdge *eCur, *eNext, *eSym; + TESSvertex *vStart; + int curNv, symNv; + + for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) + { + // Skip faces which are outside the result. + if( !f->inside ) + continue; + + eCur = f->anEdge; + vStart = eCur->Org; + + while (1) + { + eNext = eCur->Lnext; + eSym = eCur->Sym; + + // Try to merge if the neighbour face is valid. + if( eSym && eSym->Lface && eSym->Lface->inside ) + { + // Try to merge the neighbour faces if the resulting polygons + // does not exceed maximum number of vertices. + curNv = CountFaceVerts( f ); + symNv = CountFaceVerts( eSym->Lface ); + if( (curNv+symNv-2) <= maxVertsPerFace ) + { + // Merge if the resulting poly is convex. + if( VertCCW( eCur->Lprev->Org, eCur->Org, eSym->Lnext->Lnext->Org ) && + VertCCW( eSym->Lprev->Org, eSym->Org, eCur->Lnext->Lnext->Org ) ) + { + eNext = eSym->Lnext; + if( !tessMeshDelete( mesh, eSym ) ) + return 0; + eCur = 0; + } + } + } + + if( eCur && eCur->Lnext->Org == vStart ) + break; + + // Continue to next edge. + eCur = eNext; + } + } + + return 1; +} + +void tessMeshFlipEdge( TESSmesh *mesh, TESShalfEdge *edge ) +{ + TESShalfEdge *a0 = edge; + TESShalfEdge *a1 = a0->Lnext; + TESShalfEdge *a2 = a1->Lnext; + TESShalfEdge *b0 = edge->Sym; + TESShalfEdge *b1 = b0->Lnext; + TESShalfEdge *b2 = b1->Lnext; + + TESSvertex *aOrg = a0->Org; + TESSvertex *aOpp = a2->Org; + TESSvertex *bOrg = b0->Org; + TESSvertex *bOpp = b2->Org; + + TESSface *fa = a0->Lface; + TESSface *fb = b0->Lface; + + assert(EdgeIsInternal(edge)); + assert(a2->Lnext == a0); + assert(b2->Lnext == b0); + + a0->Org = bOpp; + a0->Onext = b1->Sym; + b0->Org = aOpp; + b0->Onext = a1->Sym; + a2->Onext = b0; + b2->Onext = a0; + b1->Onext = a2->Sym; + a1->Onext = b2->Sym; + + a0->Lnext = a2; + a2->Lnext = b1; + b1->Lnext = a0; + + b0->Lnext = b2; + b2->Lnext = a1; + a1->Lnext = b0; + + a1->Lface = fb; + b1->Lface = fa; + + fa->anEdge = a0; + fb->anEdge = b0; + + if (aOrg->anEdge == a0) aOrg->anEdge = b1; + if (bOrg->anEdge == b0) bOrg->anEdge = a1; + + assert( a0->Lnext->Onext->Sym == a0 ); + assert( a0->Onext->Sym->Lnext == a0 ); + assert( a0->Org->anEdge->Org == a0->Org ); + + + assert( a1->Lnext->Onext->Sym == a1 ); + assert( a1->Onext->Sym->Lnext == a1 ); + assert( a1->Org->anEdge->Org == a1->Org ); + + assert( a2->Lnext->Onext->Sym == a2 ); + assert( a2->Onext->Sym->Lnext == a2 ); + assert( a2->Org->anEdge->Org == a2->Org ); + + assert( b0->Lnext->Onext->Sym == b0 ); + assert( b0->Onext->Sym->Lnext == b0 ); + assert( b0->Org->anEdge->Org == b0->Org ); + + assert( b1->Lnext->Onext->Sym == b1 ); + assert( b1->Onext->Sym->Lnext == b1 ); + assert( b1->Org->anEdge->Org == b1->Org ); + + assert( b2->Lnext->Onext->Sym == b2 ); + assert( b2->Onext->Sym->Lnext == b2 ); + assert( b2->Org->anEdge->Org == b2->Org ); + + assert(aOrg->anEdge->Org == aOrg); + assert(bOrg->anEdge->Org == bOrg); + + assert(a0->Oprev->Onext->Org == a0->Org); +} + +#ifdef DELETE_BY_ZAPPING + +/* tessMeshDeleteMesh( mesh ) will free all storage for any valid mesh. +*/ +void tessMeshDeleteMesh( TESSalloc* alloc, TESSmesh *mesh ) +{ + TESSface *fHead = &mesh->fHead; + + while( fHead->next != fHead ) { + tessMeshZapFace( fHead->next ); + } + assert( mesh->vHead.next == &mesh->vHead ); + + alloc->memfree( alloc->userData, mesh ); +} + +#else + +/* tessMeshDeleteMesh( mesh ) will free all storage for any valid mesh. +*/ +void tessMeshDeleteMesh( TESSalloc* alloc, TESSmesh *mesh ) +{ + deleteBucketAlloc(mesh->edgeBucket); + deleteBucketAlloc(mesh->vertexBucket); + deleteBucketAlloc(mesh->faceBucket); + + alloc->memfree( alloc->userData, mesh ); +} + +#endif + +#ifndef NDEBUG + +/* tessMeshCheckMesh( mesh ) checks a mesh for self-consistency. +*/ +void tessMeshCheckMesh( TESSmesh *mesh ) +{ + TESSface *fHead = &mesh->fHead; + TESSvertex *vHead = &mesh->vHead; + TESShalfEdge *eHead = &mesh->eHead; + TESSface *f, *fPrev; + TESSvertex *v, *vPrev; + TESShalfEdge *e, *ePrev; + + fPrev = fHead; + for( fPrev = fHead ; (f = fPrev->next) != fHead; fPrev = f) { + assert( f->prev == fPrev ); + e = f->anEdge; + do { + assert( e->Sym != e ); + assert( e->Sym->Sym == e ); + assert( e->Lnext->Onext->Sym == e ); + assert( e->Onext->Sym->Lnext == e ); + assert( e->Lface == f ); + e = e->Lnext; + } while( e != f->anEdge ); + } + assert( f->prev == fPrev && f->anEdge == NULL ); + + vPrev = vHead; + for( vPrev = vHead ; (v = vPrev->next) != vHead; vPrev = v) { + assert( v->prev == vPrev ); + e = v->anEdge; + do { + assert( e->Sym != e ); + assert( e->Sym->Sym == e ); + assert( e->Lnext->Onext->Sym == e ); + assert( e->Onext->Sym->Lnext == e ); + assert( e->Org == v ); + e = e->Onext; + } while( e != v->anEdge ); + } + assert( v->prev == vPrev && v->anEdge == NULL ); + + ePrev = eHead; + for( ePrev = eHead ; (e = ePrev->next) != eHead; ePrev = e) { + assert( e->Sym->next == ePrev->Sym ); + assert( e->Sym != e ); + assert( e->Sym->Sym == e ); + assert( e->Org != NULL ); + assert( e->Dst != NULL ); + assert( e->Lnext->Onext->Sym == e ); + assert( e->Onext->Sym->Lnext == e ); + } + assert( e->Sym->next == ePrev->Sym + && e->Sym == &mesh->eHeadSym + && e->Sym->Sym == e + && e->Org == NULL && e->Dst == NULL + && e->Lface == NULL && e->Rface == NULL ); +} + +#endif diff --git a/src/libtess2/Source/mesh.h b/src/libtess2/Source/mesh.h new file mode 100755 index 00000000..479c66f3 --- /dev/null +++ b/src/libtess2/Source/mesh.h @@ -0,0 +1,269 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#ifndef MESH_H +#define MESH_H + +#include "../Include/tesselator.h" + +typedef struct TESSmesh TESSmesh; +typedef struct TESSvertex TESSvertex; +typedef struct TESSface TESSface; +typedef struct TESShalfEdge TESShalfEdge; +typedef struct ActiveRegion ActiveRegion; + +/* The mesh structure is similar in spirit, notation, and operations +* to the "quad-edge" structure (see L. Guibas and J. Stolfi, Primitives +* for the manipulation of general subdivisions and the computation of +* Voronoi diagrams, ACM Transactions on Graphics, 4(2):74-123, April 1985). +* For a simplified description, see the course notes for CS348a, +* "Mathematical Foundations of Computer Graphics", available at the +* Stanford bookstore (and taught during the fall quarter). +* The implementation also borrows a tiny subset of the graph-based approach +* use in Mantyla's Geometric Work Bench (see M. Mantyla, An Introduction +* to Sold Modeling, Computer Science Press, Rockville, Maryland, 1988). +* +* The fundamental data structure is the "half-edge". Two half-edges +* go together to make an edge, but they point in opposite directions. +* Each half-edge has a pointer to its mate (the "symmetric" half-edge Sym), +* its origin vertex (Org), the face on its left side (Lface), and the +* adjacent half-edges in the CCW direction around the origin vertex +* (Onext) and around the left face (Lnext). There is also a "next" +* pointer for the global edge list (see below). +* +* The notation used for mesh navigation: +* Sym = the mate of a half-edge (same edge, but opposite direction) +* Onext = edge CCW around origin vertex (keep same origin) +* Dnext = edge CCW around destination vertex (keep same dest) +* Lnext = edge CCW around left face (dest becomes new origin) +* Rnext = edge CCW around right face (origin becomes new dest) +* +* "prev" means to substitute CW for CCW in the definitions above. +* +* The mesh keeps global lists of all vertices, faces, and edges, +* stored as doubly-linked circular lists with a dummy header node. +* The mesh stores pointers to these dummy headers (vHead, fHead, eHead). +* +* The circular edge list is special; since half-edges always occur +* in pairs (e and e->Sym), each half-edge stores a pointer in only +* one direction. Starting at eHead and following the e->next pointers +* will visit each *edge* once (ie. e or e->Sym, but not both). +* e->Sym stores a pointer in the opposite direction, thus it is +* always true that e->Sym->next->Sym->next == e. +* +* Each vertex has a pointer to next and previous vertices in the +* circular list, and a pointer to a half-edge with this vertex as +* the origin (NULL if this is the dummy header). There is also a +* field "data" for client data. +* +* Each face has a pointer to the next and previous faces in the +* circular list, and a pointer to a half-edge with this face as +* the left face (NULL if this is the dummy header). There is also +* a field "data" for client data. +* +* Note that what we call a "face" is really a loop; faces may consist +* of more than one loop (ie. not simply connected), but there is no +* record of this in the data structure. The mesh may consist of +* several disconnected regions, so it may not be possible to visit +* the entire mesh by starting at a half-edge and traversing the edge +* structure. +* +* The mesh does NOT support isolated vertices; a vertex is deleted along +* with its last edge. Similarly when two faces are merged, one of the +* faces is deleted (see tessMeshDelete below). For mesh operations, +* all face (loop) and vertex pointers must not be NULL. However, once +* mesh manipulation is finished, TESSmeshZapFace can be used to delete +* faces of the mesh, one at a time. All external faces can be "zapped" +* before the mesh is returned to the client; then a NULL face indicates +* a region which is not part of the output polygon. +*/ + +struct TESSvertex { + TESSvertex *next; /* next vertex (never NULL) */ + TESSvertex *prev; /* previous vertex (never NULL) */ + TESShalfEdge *anEdge; /* a half-edge with this origin */ + + /* Internal data (keep hidden) */ + TESSreal coords[3]; /* vertex location in 3D */ + TESSreal s, t; /* projection onto the sweep plane */ + int pqHandle; /* to allow deletion from priority queue */ + TESSindex n; /* to allow identify unique vertices */ + TESSindex idx; /* to allow map result to original verts */ +}; + +struct TESSface { + TESSface *next; /* next face (never NULL) */ + TESSface *prev; /* previous face (never NULL) */ + TESShalfEdge *anEdge; /* a half edge with this left face */ + + /* Internal data (keep hidden) */ + TESSface *trail; /* "stack" for conversion to strips */ + TESSindex n; /* to allow identiy unique faces */ + char marked; /* flag for conversion to strips */ + char inside; /* this face is in the polygon interior */ +}; + +struct TESShalfEdge { + TESShalfEdge *next; /* doubly-linked list (prev==Sym->next) */ + TESShalfEdge *Sym; /* same edge, opposite direction */ + TESShalfEdge *Onext; /* next edge CCW around origin */ + TESShalfEdge *Lnext; /* next edge CCW around left face */ + TESSvertex *Org; /* origin vertex (Overtex too long) */ + TESSface *Lface; /* left face */ + + /* Internal data (keep hidden) */ + ActiveRegion *activeRegion; /* a region with this upper edge (sweep.c) */ + int winding; /* change in winding number when crossing + from the right face to the left face */ + int mark; /* Used by the Edge Flip algorithm */ +}; + +#define Rface Sym->Lface +#define Dst Sym->Org + +#define Oprev Sym->Lnext +#define Lprev Onext->Sym +#define Dprev Lnext->Sym +#define Rprev Sym->Onext +#define Dnext Rprev->Sym /* 3 pointers */ +#define Rnext Oprev->Sym /* 3 pointers */ + +struct TESSmesh { + TESSvertex vHead; /* dummy header for vertex list */ + TESSface fHead; /* dummy header for face list */ + TESShalfEdge eHead; /* dummy header for edge list */ + TESShalfEdge eHeadSym; /* and its symmetric counterpart */ + + struct BucketAlloc* edgeBucket; + struct BucketAlloc* vertexBucket; + struct BucketAlloc* faceBucket; +}; + +/* The mesh operations below have three motivations: completeness, +* convenience, and efficiency. The basic mesh operations are MakeEdge, +* Splice, and Delete. All the other edge operations can be implemented +* in terms of these. The other operations are provided for convenience +* and/or efficiency. +* +* When a face is split or a vertex is added, they are inserted into the +* global list *before* the existing vertex or face (ie. e->Org or e->Lface). +* This makes it easier to process all vertices or faces in the global lists +* without worrying about processing the same data twice. As a convenience, +* when a face is split, the "inside" flag is copied from the old face. +* Other internal data (v->data, v->activeRegion, f->data, f->marked, +* f->trail, e->winding) is set to zero. +* +* ********************** Basic Edge Operations ************************** +* +* tessMeshMakeEdge( mesh ) creates one edge, two vertices, and a loop. +* The loop (face) consists of the two new half-edges. +* +* tessMeshSplice( eOrg, eDst ) is the basic operation for changing the +* mesh connectivity and topology. It changes the mesh so that +* eOrg->Onext <- OLD( eDst->Onext ) +* eDst->Onext <- OLD( eOrg->Onext ) +* where OLD(...) means the value before the meshSplice operation. +* +* This can have two effects on the vertex structure: +* - if eOrg->Org != eDst->Org, the two vertices are merged together +* - if eOrg->Org == eDst->Org, the origin is split into two vertices +* In both cases, eDst->Org is changed and eOrg->Org is untouched. +* +* Similarly (and independently) for the face structure, +* - if eOrg->Lface == eDst->Lface, one loop is split into two +* - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one +* In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. +* +* tessMeshDelete( eDel ) removes the edge eDel. There are several cases: +* if (eDel->Lface != eDel->Rface), we join two loops into one; the loop +* eDel->Lface is deleted. Otherwise, we are splitting one loop into two; +* the newly created loop will contain eDel->Dst. If the deletion of eDel +* would create isolated vertices, those are deleted as well. +* +* ********************** Other Edge Operations ************************** +* +* tessMeshAddEdgeVertex( eOrg ) creates a new edge eNew such that +* eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex. +* eOrg and eNew will have the same left face. +* +* tessMeshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew, +* such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org. +* eOrg and eNew will have the same left face. +* +* tessMeshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst +* to eDst->Org, and returns the corresponding half-edge eNew. +* If eOrg->Lface == eDst->Lface, this splits one loop into two, +* and the newly created loop is eNew->Lface. Otherwise, two disjoint +* loops are merged into one, and the loop eDst->Lface is destroyed. +* +* ************************ Other Operations ***************************** +* +* tessMeshNewMesh() creates a new mesh with no edges, no vertices, +* and no loops (what we usually call a "face"). +* +* tessMeshUnion( mesh1, mesh2 ) forms the union of all structures in +* both meshes, and returns the new mesh (the old meshes are destroyed). +* +* tessMeshDeleteMesh( mesh ) will free all storage for any valid mesh. +* +* tessMeshZapFace( fZap ) destroys a face and removes it from the +* global face list. All edges of fZap will have a NULL pointer as their +* left face. Any edges which also have a NULL pointer as their right face +* are deleted entirely (along with any isolated vertices this produces). +* An entire mesh can be deleted by zapping its faces, one at a time, +* in any order. Zapped faces cannot be used in further mesh operations! +* +* tessMeshCheckMesh( mesh ) checks a mesh for self-consistency. +*/ + +TESShalfEdge *tessMeshMakeEdge( TESSmesh *mesh ); +int tessMeshSplice( TESSmesh *mesh, TESShalfEdge *eOrg, TESShalfEdge *eDst ); +int tessMeshDelete( TESSmesh *mesh, TESShalfEdge *eDel ); + +TESShalfEdge *tessMeshAddEdgeVertex( TESSmesh *mesh, TESShalfEdge *eOrg ); +TESShalfEdge *tessMeshSplitEdge( TESSmesh *mesh, TESShalfEdge *eOrg ); +TESShalfEdge *tessMeshConnect( TESSmesh *mesh, TESShalfEdge *eOrg, TESShalfEdge *eDst ); + +TESSmesh *tessMeshNewMesh( TESSalloc* alloc ); +TESSmesh *tessMeshUnion( TESSalloc* alloc, TESSmesh *mesh1, TESSmesh *mesh2 ); +int tessMeshMergeConvexFaces( TESSmesh *mesh, int maxVertsPerFace ); +void tessMeshDeleteMesh( TESSalloc* alloc, TESSmesh *mesh ); +void tessMeshZapFace( TESSmesh *mesh, TESSface *fZap ); + +void tessMeshFlipEdge( TESSmesh *mesh, TESShalfEdge *edge ); + +#ifdef NDEBUG +#define tessMeshCheckMesh( mesh ) +#else +void tessMeshCheckMesh( TESSmesh *mesh ); +#endif + +#endif diff --git a/src/libtess2/Source/priorityq.c b/src/libtess2/Source/priorityq.c new file mode 100755 index 00000000..62a66545 --- /dev/null +++ b/src/libtess2/Source/priorityq.c @@ -0,0 +1,514 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +//#include "tesos.h" +#include +#include +#include "../Include/tesselator.h" +#include "priorityq.h" + + +#define INIT_SIZE 32 + +#define TRUE 1 +#define FALSE 0 + +#ifdef FOR_TRITE_TEST_PROGRAM +#define LEQ(x,y) (*pq->leq)(x,y) +#else +/* Violates modularity, but a little faster */ +#include "geom.h" +#define LEQ(x,y) VertLeq((TESSvertex *)x, (TESSvertex *)y) +#endif + + +/* Include all the code for the regular heap-based queue here. */ + +/* The basic operations are insertion of a new key (pqInsert), +* and examination/extraction of a key whose value is minimum +* (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete); +* for this purpose pqInsert returns a "handle" which is supplied +* as the argument. +* +* An initial heap may be created efficiently by calling pqInsert +* repeatedly, then calling pqInit. In any case pqInit must be called +* before any operations other than pqInsert are used. +* +* If the heap is empty, pqMinimum/pqExtractMin will return a NULL key. +* This may also be tested with pqIsEmpty. +*/ + + +/* Since we support deletion the data structure is a little more +* complicated than an ordinary heap. "nodes" is the heap itself; +* active nodes are stored in the range 1..pq->size. When the +* heap exceeds its allocated size (pq->max), its size doubles. +* The children of node i are nodes 2i and 2i+1. +* +* Each node stores an index into an array "handles". Each handle +* stores a key, plus a pointer back to the node which currently +* represents that key (ie. nodes[handles[i].node].handle == i). +*/ + + +#define pqHeapMinimum(pq) ((pq)->handles[(pq)->nodes[1].handle].key) +#define pqHeapIsEmpty(pq) ((pq)->size == 0) + + + +/* really pqHeapNewPriorityQHeap */ +PriorityQHeap *pqHeapNewPriorityQ( TESSalloc* alloc, int size, int (*leq)(PQkey key1, PQkey key2) ) +{ + PriorityQHeap *pq = (PriorityQHeap *)alloc->memalloc( alloc->userData, sizeof( PriorityQHeap )); + if (pq == NULL) return NULL; + + pq->size = 0; + pq->max = size; + pq->nodes = (PQnode *)alloc->memalloc( alloc->userData, (size + 1) * sizeof(pq->nodes[0]) ); + if (pq->nodes == NULL) { + alloc->memfree( alloc->userData, pq ); + return NULL; + } + + pq->handles = (PQhandleElem *)alloc->memalloc( alloc->userData, (size + 1) * sizeof(pq->handles[0]) ); + if (pq->handles == NULL) { + alloc->memfree( alloc->userData, pq->nodes ); + alloc->memfree( alloc->userData, pq ); + return NULL; + } + + pq->initialized = FALSE; + pq->freeList = 0; + pq->leq = leq; + + pq->nodes[1].handle = 1; /* so that Minimum() returns NULL */ + pq->handles[1].key = NULL; + return pq; +} + +/* really pqHeapDeletePriorityQHeap */ +void pqHeapDeletePriorityQ( TESSalloc* alloc, PriorityQHeap *pq ) +{ + alloc->memfree( alloc->userData, pq->handles ); + alloc->memfree( alloc->userData, pq->nodes ); + alloc->memfree( alloc->userData, pq ); +} + + +static void FloatDown( PriorityQHeap *pq, int curr ) +{ + PQnode *n = pq->nodes; + PQhandleElem *h = pq->handles; + PQhandle hCurr, hChild; + int child; + + hCurr = n[curr].handle; + for( ;; ) { + child = curr << 1; + if( child < pq->size && LEQ( h[n[child+1].handle].key, + h[n[child].handle].key )) { + ++child; + } + + assert(child <= pq->max); + + hChild = n[child].handle; + if( child > pq->size || LEQ( h[hCurr].key, h[hChild].key )) { + n[curr].handle = hCurr; + h[hCurr].node = curr; + break; + } + n[curr].handle = hChild; + h[hChild].node = curr; + curr = child; + } +} + + +static void FloatUp( PriorityQHeap *pq, int curr ) +{ + PQnode *n = pq->nodes; + PQhandleElem *h = pq->handles; + PQhandle hCurr, hParent; + int parent; + + hCurr = n[curr].handle; + for( ;; ) { + parent = curr >> 1; + hParent = n[parent].handle; + if( parent == 0 || LEQ( h[hParent].key, h[hCurr].key )) { + n[curr].handle = hCurr; + h[hCurr].node = curr; + break; + } + n[curr].handle = hParent; + h[hParent].node = curr; + curr = parent; + } +} + +/* really pqHeapInit */ +void pqHeapInit( PriorityQHeap *pq ) +{ + int i; + + /* This method of building a heap is O(n), rather than O(n lg n). */ + + for( i = pq->size; i >= 1; --i ) { + FloatDown( pq, i ); + } + pq->initialized = TRUE; +} + +/* really pqHeapInsert */ +/* returns INV_HANDLE iff out of memory */ +PQhandle pqHeapInsert( TESSalloc* alloc, PriorityQHeap *pq, PQkey keyNew ) +{ + int curr; + PQhandle free; + + curr = ++ pq->size; + if( (curr*2) > pq->max ) { + if (!alloc->memrealloc) + { + return INV_HANDLE; + } + else + { + PQnode *saveNodes= pq->nodes; + PQhandleElem *saveHandles= pq->handles; + + // If the heap overflows, double its size. + pq->max <<= 1; + pq->nodes = (PQnode *)alloc->memrealloc( alloc->userData, pq->nodes, + (size_t)((pq->max + 1) * sizeof( pq->nodes[0] ))); + if (pq->nodes == NULL) { + pq->nodes = saveNodes; // restore ptr to free upon return + return INV_HANDLE; + } + pq->handles = (PQhandleElem *)alloc->memrealloc( alloc->userData, pq->handles, + (size_t) ((pq->max + 1) * sizeof( pq->handles[0] ))); + if (pq->handles == NULL) { + pq->handles = saveHandles; // restore ptr to free upon return + return INV_HANDLE; + } + } + } + + if( pq->freeList == 0 ) { + free = curr; + } else { + free = pq->freeList; + pq->freeList = pq->handles[free].node; + } + + pq->nodes[curr].handle = free; + pq->handles[free].node = curr; + pq->handles[free].key = keyNew; + + if( pq->initialized ) { + FloatUp( pq, curr ); + } + assert(free != INV_HANDLE); + return free; +} + +/* really pqHeapExtractMin */ +PQkey pqHeapExtractMin( PriorityQHeap *pq ) +{ + PQnode *n = pq->nodes; + PQhandleElem *h = pq->handles; + PQhandle hMin = n[1].handle; + PQkey min = h[hMin].key; + + if( pq->size > 0 ) { + n[1].handle = n[pq->size].handle; + h[n[1].handle].node = 1; + + h[hMin].key = NULL; + h[hMin].node = pq->freeList; + pq->freeList = hMin; + + if( -- pq->size > 0 ) { + FloatDown( pq, 1 ); + } + } + return min; +} + +/* really pqHeapDelete */ +void pqHeapDelete( PriorityQHeap *pq, PQhandle hCurr ) +{ + PQnode *n = pq->nodes; + PQhandleElem *h = pq->handles; + int curr; + + assert( hCurr >= 1 && hCurr <= pq->max && h[hCurr].key != NULL ); + + curr = h[hCurr].node; + n[curr].handle = n[pq->size].handle; + h[n[curr].handle].node = curr; + + if( curr <= -- pq->size ) { + if( curr <= 1 || LEQ( h[n[curr>>1].handle].key, h[n[curr].handle].key )) { + FloatDown( pq, curr ); + } else { + FloatUp( pq, curr ); + } + } + h[hCurr].key = NULL; + h[hCurr].node = pq->freeList; + pq->freeList = hCurr; +} + + + +/* Now redefine all the function names to map to their "Sort" versions. */ + +/* really tessPqSortNewPriorityQ */ +PriorityQ *pqNewPriorityQ( TESSalloc* alloc, int size, int (*leq)(PQkey key1, PQkey key2) ) +{ + PriorityQ *pq = (PriorityQ *)alloc->memalloc( alloc->userData, sizeof( PriorityQ )); + if (pq == NULL) return NULL; + + pq->heap = pqHeapNewPriorityQ( alloc, size, leq ); + if (pq->heap == NULL) { + alloc->memfree( alloc->userData, pq ); + return NULL; + } + +// pq->keys = (PQkey *)memAlloc( INIT_SIZE * sizeof(pq->keys[0]) ); + pq->keys = (PQkey *)alloc->memalloc( alloc->userData, size * sizeof(pq->keys[0]) ); + if (pq->keys == NULL) { + pqHeapDeletePriorityQ( alloc, pq->heap ); + alloc->memfree( alloc->userData, pq ); + return NULL; + } + + pq->size = 0; + pq->max = size; //INIT_SIZE; + pq->initialized = FALSE; + pq->leq = leq; + + return pq; +} + +/* really tessPqSortDeletePriorityQ */ +void pqDeletePriorityQ( TESSalloc* alloc, PriorityQ *pq ) +{ + assert(pq != NULL); + if (pq->heap != NULL) pqHeapDeletePriorityQ( alloc, pq->heap ); + if (pq->order != NULL) alloc->memfree( alloc->userData, pq->order ); + if (pq->keys != NULL) alloc->memfree( alloc->userData, pq->keys ); + alloc->memfree( alloc->userData, pq ); +} + + +#define LT(x,y) (! LEQ(y,x)) +#define GT(x,y) (! LEQ(x,y)) +#define Swap(a,b) if(1){PQkey *tmp = *a; *a = *b; *b = tmp;}else + +/* really tessPqSortInit */ +int pqInit( TESSalloc* alloc, PriorityQ *pq ) +{ + PQkey **p, **r, **i, **j, *piv; + struct { PQkey **p, **r; } Stack[50], *top = Stack; + unsigned int seed = 2016473283; + + /* Create an array of indirect pointers to the keys, so that we + * the handles we have returned are still valid. + */ + /* + pq->order = (PQkey **)memAlloc( (size_t) + (pq->size * sizeof(pq->order[0])) ); + */ + pq->order = (PQkey **)alloc->memalloc( alloc->userData, + (size_t)((pq->size+1) * sizeof(pq->order[0])) ); + /* the previous line is a patch to compensate for the fact that IBM */ + /* machines return a null on a malloc of zero bytes (unlike SGI), */ + /* so we have to put in this defense to guard against a memory */ + /* fault four lines down. from fossum@austin.ibm.com. */ + if (pq->order == NULL) return 0; + + p = pq->order; + r = p + pq->size - 1; + for( piv = pq->keys, i = p; i <= r; ++piv, ++i ) { + *i = piv; + } + + /* Sort the indirect pointers in descending order, + * using randomized Quicksort + */ + top->p = p; top->r = r; ++top; + while( --top >= Stack ) { + p = top->p; + r = top->r; + while( r > p + 10 ) { + seed = seed * 1539415821 + 1; + i = p + seed % (r - p + 1); + piv = *i; + *i = *p; + *p = piv; + i = p - 1; + j = r + 1; + do { + do { ++i; } while( GT( **i, *piv )); + do { --j; } while( LT( **j, *piv )); + Swap( i, j ); + } while( i < j ); + Swap( i, j ); /* Undo last swap */ + if( i - p < r - j ) { + top->p = j+1; top->r = r; ++top; + r = i-1; + } else { + top->p = p; top->r = i-1; ++top; + p = j+1; + } + } + /* Insertion sort small lists */ + for( i = p+1; i <= r; ++i ) { + piv = *i; + for( j = i; j > p && LT( **(j-1), *piv ); --j ) { + *j = *(j-1); + } + *j = piv; + } + } + pq->max = pq->size; + pq->initialized = TRUE; + pqHeapInit( pq->heap ); /* always succeeds */ + +#ifndef NDEBUG + p = pq->order; + r = p + pq->size - 1; + for( i = p; i < r; ++i ) { + assert( LEQ( **(i+1), **i )); + } +#endif + + return 1; +} + +/* really tessPqSortInsert */ +/* returns INV_HANDLE iff out of memory */ +PQhandle pqInsert( TESSalloc* alloc, PriorityQ *pq, PQkey keyNew ) +{ + int curr; + + if( pq->initialized ) { + return pqHeapInsert( alloc, pq->heap, keyNew ); + } + curr = pq->size; + if( ++ pq->size >= pq->max ) { + if (!alloc->memrealloc) + { + return INV_HANDLE; + } + else + { + PQkey *saveKey= pq->keys; + // If the heap overflows, double its size. + pq->max <<= 1; + pq->keys = (PQkey *)alloc->memrealloc( alloc->userData, pq->keys, + (size_t)(pq->max * sizeof( pq->keys[0] ))); + if (pq->keys == NULL) { + pq->keys = saveKey; // restore ptr to free upon return + return INV_HANDLE; + } + } + } + assert(curr != INV_HANDLE); + pq->keys[curr] = keyNew; + + /* Negative handles index the sorted array. */ + return -(curr+1); +} + +/* really tessPqSortExtractMin */ +PQkey pqExtractMin( PriorityQ *pq ) +{ + PQkey sortMin, heapMin; + + if( pq->size == 0 ) { + return pqHeapExtractMin( pq->heap ); + } + sortMin = *(pq->order[pq->size-1]); + if( ! pqHeapIsEmpty( pq->heap )) { + heapMin = pqHeapMinimum( pq->heap ); + if( LEQ( heapMin, sortMin )) { + return pqHeapExtractMin( pq->heap ); + } + } + do { + -- pq->size; + } while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ); + return sortMin; +} + +/* really tessPqSortMinimum */ +PQkey pqMinimum( PriorityQ *pq ) +{ + PQkey sortMin, heapMin; + + if( pq->size == 0 ) { + return pqHeapMinimum( pq->heap ); + } + sortMin = *(pq->order[pq->size-1]); + if( ! pqHeapIsEmpty( pq->heap )) { + heapMin = pqHeapMinimum( pq->heap ); + if( LEQ( heapMin, sortMin )) { + return heapMin; + } + } + return sortMin; +} + +/* really tessPqSortIsEmpty */ +int pqIsEmpty( PriorityQ *pq ) +{ + return (pq->size == 0) && pqHeapIsEmpty( pq->heap ); +} + +/* really tessPqSortDelete */ +void pqDelete( PriorityQ *pq, PQhandle curr ) +{ + if( curr >= 0 ) { + pqHeapDelete( pq->heap, curr ); + return; + } + curr = -(curr+1); + assert( curr < pq->max && pq->keys[curr] != NULL ); + + pq->keys[curr] = NULL; + while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ) { + -- pq->size; + } +} diff --git a/src/libtess2/Source/priorityq.h b/src/libtess2/Source/priorityq.h new file mode 100755 index 00000000..6ef1c05f --- /dev/null +++ b/src/libtess2/Source/priorityq.h @@ -0,0 +1,104 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#ifndef PRIORITYQ_H +#define PRIORITYQ_H + +/* The basic operations are insertion of a new key (pqInsert), +* and examination/extraction of a key whose value is minimum +* (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete); +* for this purpose pqInsert returns a "handle" which is supplied +* as the argument. +* +* An initial heap may be created efficiently by calling pqInsert +* repeatedly, then calling pqInit. In any case pqInit must be called +* before any operations other than pqInsert are used. +* +* If the heap is empty, pqMinimum/pqExtractMin will return a NULL key. +* This may also be tested with pqIsEmpty. +*/ + +/* Since we support deletion the data structure is a little more +* complicated than an ordinary heap. "nodes" is the heap itself; +* active nodes are stored in the range 1..pq->size. When the +* heap exceeds its allocated size (pq->max), its size doubles. +* The children of node i are nodes 2i and 2i+1. +* +* Each node stores an index into an array "handles". Each handle +* stores a key, plus a pointer back to the node which currently +* represents that key (ie. nodes[handles[i].node].handle == i). +*/ + +typedef void *PQkey; +typedef int PQhandle; +typedef struct PriorityQHeap PriorityQHeap; + +#define INV_HANDLE 0x0fffffff + +typedef struct { PQhandle handle; } PQnode; +typedef struct { PQkey key; PQhandle node; } PQhandleElem; + +struct PriorityQHeap { + + PQnode *nodes; + PQhandleElem *handles; + int size, max; + PQhandle freeList; + int initialized; + + int (*leq)(PQkey key1, PQkey key2); +}; + +typedef struct PriorityQ PriorityQ; + +struct PriorityQ { + PriorityQHeap *heap; + + PQkey *keys; + PQkey **order; + PQhandle size, max; + int initialized; + + int (*leq)(PQkey key1, PQkey key2); +}; + +PriorityQ *pqNewPriorityQ( TESSalloc* alloc, int size, int (*leq)(PQkey key1, PQkey key2) ); +void pqDeletePriorityQ( TESSalloc* alloc, PriorityQ *pq ); + +int pqInit( TESSalloc* alloc, PriorityQ *pq ); +PQhandle pqInsert( TESSalloc* alloc, PriorityQ *pq, PQkey key ); +PQkey pqExtractMin( PriorityQ *pq ); +void pqDelete( PriorityQ *pq, PQhandle handle ); + +PQkey pqMinimum( PriorityQ *pq ); +int pqIsEmpty( PriorityQ *pq ); + +#endif diff --git a/src/libtess2/Source/sweep.c b/src/libtess2/Source/sweep.c new file mode 100755 index 00000000..6a927745 --- /dev/null +++ b/src/libtess2/Source/sweep.c @@ -0,0 +1,1326 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#include +#include +#include /* longjmp */ + +#include "mesh.h" +#include "geom.h" +#include "tess.h" +#include "dict.h" +#include "priorityq.h" +#include "bucketalloc.h" +#include "sweep.h" + +#define TRUE 1 +#define FALSE 0 + +#ifdef FOR_TRITE_TEST_PROGRAM +extern void DebugEvent( TESStesselator *tess ); +#else +#define DebugEvent( tess ) +#endif + +/* +* Invariants for the Edge Dictionary. +* - each pair of adjacent edges e2=Succ(e1) satisfies EdgeLeq(e1,e2) +* at any valid location of the sweep event +* - if EdgeLeq(e2,e1) as well (at any valid sweep event), then e1 and e2 +* share a common endpoint +* - for each e, e->Dst has been processed, but not e->Org +* - each edge e satisfies VertLeq(e->Dst,event) && VertLeq(event,e->Org) +* where "event" is the current sweep line event. +* - no edge e has zero length +* +* Invariants for the Mesh (the processed portion). +* - the portion of the mesh left of the sweep line is a planar graph, +* ie. there is *some* way to embed it in the plane +* - no processed edge has zero length +* - no two processed vertices have identical coordinates +* - each "inside" region is monotone, ie. can be broken into two chains +* of monotonically increasing vertices according to VertLeq(v1,v2) +* - a non-invariant: these chains may intersect (very slightly) +* +* Invariants for the Sweep. +* - if none of the edges incident to the event vertex have an activeRegion +* (ie. none of these edges are in the edge dictionary), then the vertex +* has only right-going edges. +* - if an edge is marked "fixUpperEdge" (it is a temporary edge introduced +* by ConnectRightVertex), then it is the only right-going edge from +* its associated vertex. (This says that these edges exist only +* when it is necessary.) +*/ + +#define MAX(x,y) ((x) >= (y) ? (x) : (y)) +#define MIN(x,y) ((x) <= (y) ? (x) : (y)) + +/* When we merge two edges into one, we need to compute the combined +* winding of the new edge. +*/ +#define AddWinding(eDst,eSrc) (eDst->winding += eSrc->winding, \ + eDst->Sym->winding += eSrc->Sym->winding) + +static void SweepEvent( TESStesselator *tess, TESSvertex *vEvent ); +static void WalkDirtyRegions( TESStesselator *tess, ActiveRegion *regUp ); +static int CheckForRightSplice( TESStesselator *tess, ActiveRegion *regUp ); + +static int EdgeLeq( TESStesselator *tess, ActiveRegion *reg1, ActiveRegion *reg2 ) +/* +* Both edges must be directed from right to left (this is the canonical +* direction for the upper edge of each region). +* +* The strategy is to evaluate a "t" value for each edge at the +* current sweep line position, given by tess->event. The calculations +* are designed to be very stable, but of course they are not perfect. +* +* Special case: if both edge destinations are at the sweep event, +* we sort the edges by slope (they would otherwise compare equally). +*/ +{ + TESSvertex *event = tess->event; + TESShalfEdge *e1, *e2; + TESSreal t1, t2; + + e1 = reg1->eUp; + e2 = reg2->eUp; + + if( e1->Dst == event ) { + if( e2->Dst == event ) { + /* Two edges right of the sweep line which meet at the sweep event. + * Sort them by slope. + */ + if( VertLeq( e1->Org, e2->Org )) { + return EdgeSign( e2->Dst, e1->Org, e2->Org ) <= 0; + } + return EdgeSign( e1->Dst, e2->Org, e1->Org ) >= 0; + } + return EdgeSign( e2->Dst, event, e2->Org ) <= 0; + } + if( e2->Dst == event ) { + return EdgeSign( e1->Dst, event, e1->Org ) >= 0; + } + + /* General case - compute signed distance *from* e1, e2 to event */ + t1 = EdgeEval( e1->Dst, event, e1->Org ); + t2 = EdgeEval( e2->Dst, event, e2->Org ); + return (t1 >= t2); +} + + +static void DeleteRegion( TESStesselator *tess, ActiveRegion *reg ) +{ + if( reg->fixUpperEdge ) { + /* It was created with zero winding number, so it better be + * deleted with zero winding number (ie. it better not get merged + * with a real edge). + */ + assert( reg->eUp->winding == 0 ); + } + reg->eUp->activeRegion = NULL; + dictDelete( tess->dict, reg->nodeUp ); + bucketFree( tess->regionPool, reg ); +} + + +static int FixUpperEdge( TESStesselator *tess, ActiveRegion *reg, TESShalfEdge *newEdge ) +/* +* Replace an upper edge which needs fixing (see ConnectRightVertex). +*/ +{ + assert( reg->fixUpperEdge ); + if ( !tessMeshDelete( tess->mesh, reg->eUp ) ) return 0; + reg->fixUpperEdge = FALSE; + reg->eUp = newEdge; + newEdge->activeRegion = reg; + + return 1; +} + +static ActiveRegion *TopLeftRegion( TESStesselator *tess, ActiveRegion *reg ) +{ + TESSvertex *org = reg->eUp->Org; + TESShalfEdge *e; + + /* Find the region above the uppermost edge with the same origin */ + do { + reg = RegionAbove( reg ); + } while( reg->eUp->Org == org ); + + /* If the edge above was a temporary edge introduced by ConnectRightVertex, + * now is the time to fix it. + */ + if( reg->fixUpperEdge ) { + e = tessMeshConnect( tess->mesh, RegionBelow(reg)->eUp->Sym, reg->eUp->Lnext ); + if (e == NULL) return NULL; + if ( !FixUpperEdge( tess, reg, e ) ) return NULL; + reg = RegionAbove( reg ); + } + return reg; +} + +static ActiveRegion *TopRightRegion( ActiveRegion *reg ) +{ + TESSvertex *dst = reg->eUp->Dst; + + /* Find the region above the uppermost edge with the same destination */ + do { + reg = RegionAbove( reg ); + } while( reg->eUp->Dst == dst ); + return reg; +} + +static ActiveRegion *AddRegionBelow( TESStesselator *tess, + ActiveRegion *regAbove, + TESShalfEdge *eNewUp ) +/* +* Add a new active region to the sweep line, *somewhere* below "regAbove" +* (according to where the new edge belongs in the sweep-line dictionary). +* The upper edge of the new region will be "eNewUp". +* Winding number and "inside" flag are not updated. +*/ +{ + ActiveRegion *regNew = (ActiveRegion *)bucketAlloc( tess->regionPool ); + if (regNew == NULL) longjmp(tess->env,1); + + regNew->eUp = eNewUp; + regNew->nodeUp = dictInsertBefore( tess->dict, regAbove->nodeUp, regNew ); + if (regNew->nodeUp == NULL) longjmp(tess->env,1); + regNew->fixUpperEdge = FALSE; + regNew->sentinel = FALSE; + regNew->dirty = FALSE; + + eNewUp->activeRegion = regNew; + return regNew; +} + +static int IsWindingInside( TESStesselator *tess, int n ) +{ + switch( tess->windingRule ) { + case TESS_WINDING_ODD: + return (n & 1); + case TESS_WINDING_NONZERO: + return (n != 0); + case TESS_WINDING_POSITIVE: + return (n > 0); + case TESS_WINDING_NEGATIVE: + return (n < 0); + case TESS_WINDING_ABS_GEQ_TWO: + return (n >= 2) || (n <= -2); + } + /*LINTED*/ + assert( FALSE ); + /*NOTREACHED*/ + + return( FALSE ); +} + + +static void ComputeWinding( TESStesselator *tess, ActiveRegion *reg ) +{ + reg->windingNumber = RegionAbove(reg)->windingNumber + reg->eUp->winding; + reg->inside = IsWindingInside( tess, reg->windingNumber ); +} + + +static void FinishRegion( TESStesselator *tess, ActiveRegion *reg ) +/* +* Delete a region from the sweep line. This happens when the upper +* and lower chains of a region meet (at a vertex on the sweep line). +* The "inside" flag is copied to the appropriate mesh face (we could +* not do this before -- since the structure of the mesh is always +* changing, this face may not have even existed until now). +*/ +{ + TESShalfEdge *e = reg->eUp; + TESSface *f = e->Lface; + + f->inside = reg->inside; + f->anEdge = e; /* optimization for tessMeshTessellateMonoRegion() */ + DeleteRegion( tess, reg ); +} + + +static TESShalfEdge *FinishLeftRegions( TESStesselator *tess, + ActiveRegion *regFirst, ActiveRegion *regLast ) +/* +* We are given a vertex with one or more left-going edges. All affected +* edges should be in the edge dictionary. Starting at regFirst->eUp, +* we walk down deleting all regions where both edges have the same +* origin vOrg. At the same time we copy the "inside" flag from the +* active region to the face, since at this point each face will belong +* to at most one region (this was not necessarily true until this point +* in the sweep). The walk stops at the region above regLast; if regLast +* is NULL we walk as far as possible. At the same time we relink the +* mesh if necessary, so that the ordering of edges around vOrg is the +* same as in the dictionary. +*/ +{ + ActiveRegion *reg, *regPrev; + TESShalfEdge *e, *ePrev; + + regPrev = regFirst; + ePrev = regFirst->eUp; + while( regPrev != regLast ) { + regPrev->fixUpperEdge = FALSE; /* placement was OK */ + reg = RegionBelow( regPrev ); + e = reg->eUp; + if( e->Org != ePrev->Org ) { + if( ! reg->fixUpperEdge ) { + /* Remove the last left-going edge. Even though there are no further + * edges in the dictionary with this origin, there may be further + * such edges in the mesh (if we are adding left edges to a vertex + * that has already been processed). Thus it is important to call + * FinishRegion rather than just DeleteRegion. + */ + FinishRegion( tess, regPrev ); + break; + } + /* If the edge below was a temporary edge introduced by + * ConnectRightVertex, now is the time to fix it. + */ + e = tessMeshConnect( tess->mesh, ePrev->Lprev, e->Sym ); + if (e == NULL) longjmp(tess->env,1); + if ( !FixUpperEdge( tess, reg, e ) ) longjmp(tess->env,1); + } + + /* Relink edges so that ePrev->Onext == e */ + if( ePrev->Onext != e ) { + if ( !tessMeshSplice( tess->mesh, e->Oprev, e ) ) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, ePrev, e ) ) longjmp(tess->env,1); + } + FinishRegion( tess, regPrev ); /* may change reg->eUp */ + ePrev = reg->eUp; + regPrev = reg; + } + return ePrev; +} + + +static void AddRightEdges( TESStesselator *tess, ActiveRegion *regUp, + TESShalfEdge *eFirst, TESShalfEdge *eLast, TESShalfEdge *eTopLeft, + int cleanUp ) +/* +* Purpose: insert right-going edges into the edge dictionary, and update +* winding numbers and mesh connectivity appropriately. All right-going +* edges share a common origin vOrg. Edges are inserted CCW starting at +* eFirst; the last edge inserted is eLast->Oprev. If vOrg has any +* left-going edges already processed, then eTopLeft must be the edge +* such that an imaginary upward vertical segment from vOrg would be +* contained between eTopLeft->Oprev and eTopLeft; otherwise eTopLeft +* should be NULL. +*/ +{ + ActiveRegion *reg, *regPrev; + TESShalfEdge *e, *ePrev; + int firstTime = TRUE; + + /* Insert the new right-going edges in the dictionary */ + e = eFirst; + do { + assert( VertLeq( e->Org, e->Dst )); + AddRegionBelow( tess, regUp, e->Sym ); + e = e->Onext; + } while ( e != eLast ); + + /* Walk *all* right-going edges from e->Org, in the dictionary order, + * updating the winding numbers of each region, and re-linking the mesh + * edges to match the dictionary ordering (if necessary). + */ + if( eTopLeft == NULL ) { + eTopLeft = RegionBelow( regUp )->eUp->Rprev; + } + regPrev = regUp; + ePrev = eTopLeft; + for( ;; ) { + reg = RegionBelow( regPrev ); + e = reg->eUp->Sym; + if( e->Org != ePrev->Org ) break; + + if( e->Onext != ePrev ) { + /* Unlink e from its current position, and relink below ePrev */ + if ( !tessMeshSplice( tess->mesh, e->Oprev, e ) ) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, ePrev->Oprev, e ) ) longjmp(tess->env,1); + } + /* Compute the winding number and "inside" flag for the new regions */ + reg->windingNumber = regPrev->windingNumber - e->winding; + reg->inside = IsWindingInside( tess, reg->windingNumber ); + + /* Check for two outgoing edges with same slope -- process these + * before any intersection tests (see example in tessComputeInterior). + */ + regPrev->dirty = TRUE; + if( ! firstTime && CheckForRightSplice( tess, regPrev )) { + AddWinding( e, ePrev ); + DeleteRegion( tess, regPrev ); + if ( !tessMeshDelete( tess->mesh, ePrev ) ) longjmp(tess->env,1); + } + firstTime = FALSE; + regPrev = reg; + ePrev = e; + } + regPrev->dirty = TRUE; + assert( regPrev->windingNumber - e->winding == reg->windingNumber ); + + if( cleanUp ) { + /* Check for intersections between newly adjacent edges. */ + WalkDirtyRegions( tess, regPrev ); + } +} + + +static void SpliceMergeVertices( TESStesselator *tess, TESShalfEdge *e1, + TESShalfEdge *e2 ) +/* +* Two vertices with idential coordinates are combined into one. +* e1->Org is kept, while e2->Org is discarded. +*/ +{ + if ( !tessMeshSplice( tess->mesh, e1, e2 ) ) longjmp(tess->env,1); +} + +static void VertexWeights( TESSvertex *isect, TESSvertex *org, TESSvertex *dst, + TESSreal *weights ) +/* +* Find some weights which describe how the intersection vertex is +* a linear combination of "org" and "dest". Each of the two edges +* which generated "isect" is allocated 50% of the weight; each edge +* splits the weight between its org and dst according to the +* relative distance to "isect". +*/ +{ + TESSreal t1 = VertL1dist( org, isect ); + TESSreal t2 = VertL1dist( dst, isect ); + + weights[0] = (TESSreal)0.5 * t2 / (t1 + t2); + weights[1] = (TESSreal)0.5 * t1 / (t1 + t2); + isect->coords[0] += weights[0]*org->coords[0] + weights[1]*dst->coords[0]; + isect->coords[1] += weights[0]*org->coords[1] + weights[1]*dst->coords[1]; + isect->coords[2] += weights[0]*org->coords[2] + weights[1]*dst->coords[2]; +} + + +static void GetIntersectData( TESStesselator *tess, TESSvertex *isect, + TESSvertex *orgUp, TESSvertex *dstUp, + TESSvertex *orgLo, TESSvertex *dstLo ) + /* + * We've computed a new intersection point, now we need a "data" pointer + * from the user so that we can refer to this new vertex in the + * rendering callbacks. + */ +{ + TESSreal weights[4]; + TESS_NOTUSED( tess ); + + isect->coords[0] = isect->coords[1] = isect->coords[2] = 0; + isect->idx = TESS_UNDEF; + VertexWeights( isect, orgUp, dstUp, &weights[0] ); + VertexWeights( isect, orgLo, dstLo, &weights[2] ); +} + +static int CheckForRightSplice( TESStesselator *tess, ActiveRegion *regUp ) +/* +* Check the upper and lower edge of "regUp", to make sure that the +* eUp->Org is above eLo, or eLo->Org is below eUp (depending on which +* origin is leftmost). +* +* The main purpose is to splice right-going edges with the same +* dest vertex and nearly identical slopes (ie. we can't distinguish +* the slopes numerically). However the splicing can also help us +* to recover from numerical errors. For example, suppose at one +* point we checked eUp and eLo, and decided that eUp->Org is barely +* above eLo. Then later, we split eLo into two edges (eg. from +* a splice operation like this one). This can change the result of +* our test so that now eUp->Org is incident to eLo, or barely below it. +* We must correct this condition to maintain the dictionary invariants. +* +* One possibility is to check these edges for intersection again +* (ie. CheckForIntersect). This is what we do if possible. However +* CheckForIntersect requires that tess->event lies between eUp and eLo, +* so that it has something to fall back on when the intersection +* calculation gives us an unusable answer. So, for those cases where +* we can't check for intersection, this routine fixes the problem +* by just splicing the offending vertex into the other edge. +* This is a guaranteed solution, no matter how degenerate things get. +* Basically this is a combinatorial solution to a numerical problem. +*/ +{ + ActiveRegion *regLo = RegionBelow(regUp); + TESShalfEdge *eUp = regUp->eUp; + TESShalfEdge *eLo = regLo->eUp; + + if( VertLeq( eUp->Org, eLo->Org )) { + if( EdgeSign( eLo->Dst, eUp->Org, eLo->Org ) > 0 ) return FALSE; + + /* eUp->Org appears to be below eLo */ + if( ! VertEq( eUp->Org, eLo->Org )) { + /* Splice eUp->Org into eLo */ + if ( tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eUp, eLo->Oprev ) ) longjmp(tess->env,1); + regUp->dirty = regLo->dirty = TRUE; + + } else if( eUp->Org != eLo->Org ) { + /* merge the two vertices, discarding eUp->Org */ + pqDelete( tess->pq, eUp->Org->pqHandle ); + SpliceMergeVertices( tess, eLo->Oprev, eUp ); + } + } else { + if( EdgeSign( eUp->Dst, eLo->Org, eUp->Org ) < 0 ) return FALSE; + + /* eLo->Org appears to be above eUp, so splice eLo->Org into eUp */ + RegionAbove(regUp)->dirty = regUp->dirty = TRUE; + if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eLo->Oprev, eUp ) ) longjmp(tess->env,1); + } + return TRUE; +} + +static int CheckForLeftSplice( TESStesselator *tess, ActiveRegion *regUp ) +/* +* Check the upper and lower edge of "regUp", to make sure that the +* eUp->Dst is above eLo, or eLo->Dst is below eUp (depending on which +* destination is rightmost). +* +* Theoretically, this should always be true. However, splitting an edge +* into two pieces can change the results of previous tests. For example, +* suppose at one point we checked eUp and eLo, and decided that eUp->Dst +* is barely above eLo. Then later, we split eLo into two edges (eg. from +* a splice operation like this one). This can change the result of +* the test so that now eUp->Dst is incident to eLo, or barely below it. +* We must correct this condition to maintain the dictionary invariants +* (otherwise new edges might get inserted in the wrong place in the +* dictionary, and bad stuff will happen). +* +* We fix the problem by just splicing the offending vertex into the +* other edge. +*/ +{ + ActiveRegion *regLo = RegionBelow(regUp); + TESShalfEdge *eUp = regUp->eUp; + TESShalfEdge *eLo = regLo->eUp; + TESShalfEdge *e; + + assert( ! VertEq( eUp->Dst, eLo->Dst )); + + if( VertLeq( eUp->Dst, eLo->Dst )) { + if( EdgeSign( eUp->Dst, eLo->Dst, eUp->Org ) < 0 ) return FALSE; + + /* eLo->Dst is above eUp, so splice eLo->Dst into eUp */ + RegionAbove(regUp)->dirty = regUp->dirty = TRUE; + e = tessMeshSplitEdge( tess->mesh, eUp ); + if (e == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eLo->Sym, e ) ) longjmp(tess->env,1); + e->Lface->inside = regUp->inside; + } else { + if( EdgeSign( eLo->Dst, eUp->Dst, eLo->Org ) > 0 ) return FALSE; + + /* eUp->Dst is below eLo, so splice eUp->Dst into eLo */ + regUp->dirty = regLo->dirty = TRUE; + e = tessMeshSplitEdge( tess->mesh, eLo ); + if (e == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eUp->Lnext, eLo->Sym ) ) longjmp(tess->env,1); + e->Rface->inside = regUp->inside; + } + return TRUE; +} + + +static int CheckForIntersect( TESStesselator *tess, ActiveRegion *regUp ) +/* +* Check the upper and lower edges of the given region to see if +* they intersect. If so, create the intersection and add it +* to the data structures. +* +* Returns TRUE if adding the new intersection resulted in a recursive +* call to AddRightEdges(); in this case all "dirty" regions have been +* checked for intersections, and possibly regUp has been deleted. +*/ +{ + ActiveRegion *regLo = RegionBelow(regUp); + TESShalfEdge *eUp = regUp->eUp; + TESShalfEdge *eLo = regLo->eUp; + TESSvertex *orgUp = eUp->Org; + TESSvertex *orgLo = eLo->Org; + TESSvertex *dstUp = eUp->Dst; + TESSvertex *dstLo = eLo->Dst; + TESSreal tMinUp, tMaxLo; + TESSvertex isect, *orgMin; + TESShalfEdge *e; + + assert( ! VertEq( dstLo, dstUp )); + assert( EdgeSign( dstUp, tess->event, orgUp ) <= 0 ); + assert( EdgeSign( dstLo, tess->event, orgLo ) >= 0 ); + assert( orgUp != tess->event && orgLo != tess->event ); + assert( ! regUp->fixUpperEdge && ! regLo->fixUpperEdge ); + + if( orgUp == orgLo ) return FALSE; /* right endpoints are the same */ + + tMinUp = MIN( orgUp->t, dstUp->t ); + tMaxLo = MAX( orgLo->t, dstLo->t ); + if( tMinUp > tMaxLo ) return FALSE; /* t ranges do not overlap */ + + if( VertLeq( orgUp, orgLo )) { + if( EdgeSign( dstLo, orgUp, orgLo ) > 0 ) return FALSE; + } else { + if( EdgeSign( dstUp, orgLo, orgUp ) < 0 ) return FALSE; + } + + /* At this point the edges intersect, at least marginally */ + DebugEvent( tess ); + + tesedgeIntersect( dstUp, orgUp, dstLo, orgLo, &isect ); + /* The following properties are guaranteed: */ + assert( MIN( orgUp->t, dstUp->t ) <= isect.t ); + assert( isect.t <= MAX( orgLo->t, dstLo->t )); + assert( MIN( dstLo->s, dstUp->s ) <= isect.s ); + assert( isect.s <= MAX( orgLo->s, orgUp->s )); + + if( VertLeq( &isect, tess->event )) { + /* The intersection point lies slightly to the left of the sweep line, + * so move it until it''s slightly to the right of the sweep line. + * (If we had perfect numerical precision, this would never happen + * in the first place). The easiest and safest thing to do is + * replace the intersection by tess->event. + */ + isect.s = tess->event->s; + isect.t = tess->event->t; + } + /* Similarly, if the computed intersection lies to the right of the + * rightmost origin (which should rarely happen), it can cause + * unbelievable inefficiency on sufficiently degenerate inputs. + * (If you have the test program, try running test54.d with the + * "X zoom" option turned on). + */ + orgMin = VertLeq( orgUp, orgLo ) ? orgUp : orgLo; + if( VertLeq( orgMin, &isect )) { + isect.s = orgMin->s; + isect.t = orgMin->t; + } + + if( VertEq( &isect, orgUp ) || VertEq( &isect, orgLo )) { + /* Easy case -- intersection at one of the right endpoints */ + (void) CheckForRightSplice( tess, regUp ); + return FALSE; + } + + if( (! VertEq( dstUp, tess->event ) + && EdgeSign( dstUp, tess->event, &isect ) >= 0) + || (! VertEq( dstLo, tess->event ) + && EdgeSign( dstLo, tess->event, &isect ) <= 0 )) + { + /* Very unusual -- the new upper or lower edge would pass on the + * wrong side of the sweep event, or through it. This can happen + * due to very small numerical errors in the intersection calculation. + */ + if( dstLo == tess->event ) { + /* Splice dstLo into eUp, and process the new region(s) */ + if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eLo->Sym, eUp ) ) longjmp(tess->env,1); + regUp = TopLeftRegion( tess, regUp ); + if (regUp == NULL) longjmp(tess->env,1); + eUp = RegionBelow(regUp)->eUp; + FinishLeftRegions( tess, RegionBelow(regUp), regLo ); + AddRightEdges( tess, regUp, eUp->Oprev, eUp, eUp, TRUE ); + return TRUE; + } + if( dstUp == tess->event ) { + /* Splice dstUp into eLo, and process the new region(s) */ + if (tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eUp->Lnext, eLo->Oprev ) ) longjmp(tess->env,1); + regLo = regUp; + regUp = TopRightRegion( regUp ); + e = RegionBelow(regUp)->eUp->Rprev; + regLo->eUp = eLo->Oprev; + eLo = FinishLeftRegions( tess, regLo, NULL ); + AddRightEdges( tess, regUp, eLo->Onext, eUp->Rprev, e, TRUE ); + return TRUE; + } + /* Special case: called from ConnectRightVertex. If either + * edge passes on the wrong side of tess->event, split it + * (and wait for ConnectRightVertex to splice it appropriately). + */ + if( EdgeSign( dstUp, tess->event, &isect ) >= 0 ) { + RegionAbove(regUp)->dirty = regUp->dirty = TRUE; + if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); + eUp->Org->s = tess->event->s; + eUp->Org->t = tess->event->t; + } + if( EdgeSign( dstLo, tess->event, &isect ) <= 0 ) { + regUp->dirty = regLo->dirty = TRUE; + if (tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); + eLo->Org->s = tess->event->s; + eLo->Org->t = tess->event->t; + } + /* leave the rest for ConnectRightVertex */ + return FALSE; + } + + /* General case -- split both edges, splice into new vertex. + * When we do the splice operation, the order of the arguments is + * arbitrary as far as correctness goes. However, when the operation + * creates a new face, the work done is proportional to the size of + * the new face. We expect the faces in the processed part of + * the mesh (ie. eUp->Lface) to be smaller than the faces in the + * unprocessed original contours (which will be eLo->Oprev->Lface). + */ + if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); + if (tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eLo->Oprev, eUp ) ) longjmp(tess->env,1); + eUp->Org->s = isect.s; + eUp->Org->t = isect.t; + eUp->Org->pqHandle = pqInsert( &tess->alloc, tess->pq, eUp->Org ); + if (eUp->Org->pqHandle == INV_HANDLE) { + pqDeletePriorityQ( &tess->alloc, tess->pq ); + tess->pq = NULL; + longjmp(tess->env,1); + } + GetIntersectData( tess, eUp->Org, orgUp, dstUp, orgLo, dstLo ); + RegionAbove(regUp)->dirty = regUp->dirty = regLo->dirty = TRUE; + return FALSE; +} + +static void WalkDirtyRegions( TESStesselator *tess, ActiveRegion *regUp ) +/* +* When the upper or lower edge of any region changes, the region is +* marked "dirty". This routine walks through all the dirty regions +* and makes sure that the dictionary invariants are satisfied +* (see the comments at the beginning of this file). Of course +* new dirty regions can be created as we make changes to restore +* the invariants. +*/ +{ + ActiveRegion *regLo = RegionBelow(regUp); + TESShalfEdge *eUp, *eLo; + + for( ;; ) { + /* Find the lowest dirty region (we walk from the bottom up). */ + while( regLo->dirty ) { + regUp = regLo; + regLo = RegionBelow(regLo); + } + if( ! regUp->dirty ) { + regLo = regUp; + regUp = RegionAbove( regUp ); + if( regUp == NULL || ! regUp->dirty ) { + /* We've walked all the dirty regions */ + return; + } + } + regUp->dirty = FALSE; + eUp = regUp->eUp; + eLo = regLo->eUp; + + if( eUp->Dst != eLo->Dst ) { + /* Check that the edge ordering is obeyed at the Dst vertices. */ + if( CheckForLeftSplice( tess, regUp )) { + + /* If the upper or lower edge was marked fixUpperEdge, then + * we no longer need it (since these edges are needed only for + * vertices which otherwise have no right-going edges). + */ + if( regLo->fixUpperEdge ) { + DeleteRegion( tess, regLo ); + if ( !tessMeshDelete( tess->mesh, eLo ) ) longjmp(tess->env,1); + regLo = RegionBelow( regUp ); + eLo = regLo->eUp; + } else if( regUp->fixUpperEdge ) { + DeleteRegion( tess, regUp ); + if ( !tessMeshDelete( tess->mesh, eUp ) ) longjmp(tess->env,1); + regUp = RegionAbove( regLo ); + eUp = regUp->eUp; + } + } + } + if( eUp->Org != eLo->Org ) { + if( eUp->Dst != eLo->Dst + && ! regUp->fixUpperEdge && ! regLo->fixUpperEdge + && (eUp->Dst == tess->event || eLo->Dst == tess->event) ) + { + /* When all else fails in CheckForIntersect(), it uses tess->event + * as the intersection location. To make this possible, it requires + * that tess->event lie between the upper and lower edges, and also + * that neither of these is marked fixUpperEdge (since in the worst + * case it might splice one of these edges into tess->event, and + * violate the invariant that fixable edges are the only right-going + * edge from their associated vertex). + */ + if( CheckForIntersect( tess, regUp )) { + /* WalkDirtyRegions() was called recursively; we're done */ + return; + } + } else { + /* Even though we can't use CheckForIntersect(), the Org vertices + * may violate the dictionary edge ordering. Check and correct this. + */ + (void) CheckForRightSplice( tess, regUp ); + } + } + if( eUp->Org == eLo->Org && eUp->Dst == eLo->Dst ) { + /* A degenerate loop consisting of only two edges -- delete it. */ + AddWinding( eLo, eUp ); + DeleteRegion( tess, regUp ); + if ( !tessMeshDelete( tess->mesh, eUp ) ) longjmp(tess->env,1); + regUp = RegionAbove( regLo ); + } + } +} + + +static void ConnectRightVertex( TESStesselator *tess, ActiveRegion *regUp, + TESShalfEdge *eBottomLeft ) +/* +* Purpose: connect a "right" vertex vEvent (one where all edges go left) +* to the unprocessed portion of the mesh. Since there are no right-going +* edges, two regions (one above vEvent and one below) are being merged +* into one. "regUp" is the upper of these two regions. +* +* There are two reasons for doing this (adding a right-going edge): +* - if the two regions being merged are "inside", we must add an edge +* to keep them separated (the combined region would not be monotone). +* - in any case, we must leave some record of vEvent in the dictionary, +* so that we can merge vEvent with features that we have not seen yet. +* For example, maybe there is a vertical edge which passes just to +* the right of vEvent; we would like to splice vEvent into this edge. +* +* However, we don't want to connect vEvent to just any vertex. We don''t +* want the new edge to cross any other edges; otherwise we will create +* intersection vertices even when the input data had no self-intersections. +* (This is a bad thing; if the user's input data has no intersections, +* we don't want to generate any false intersections ourselves.) +* +* Our eventual goal is to connect vEvent to the leftmost unprocessed +* vertex of the combined region (the union of regUp and regLo). +* But because of unseen vertices with all right-going edges, and also +* new vertices which may be created by edge intersections, we don''t +* know where that leftmost unprocessed vertex is. In the meantime, we +* connect vEvent to the closest vertex of either chain, and mark the region +* as "fixUpperEdge". This flag says to delete and reconnect this edge +* to the next processed vertex on the boundary of the combined region. +* Quite possibly the vertex we connected to will turn out to be the +* closest one, in which case we won''t need to make any changes. +*/ +{ + TESShalfEdge *eNew; + TESShalfEdge *eTopLeft = eBottomLeft->Onext; + ActiveRegion *regLo = RegionBelow(regUp); + TESShalfEdge *eUp = regUp->eUp; + TESShalfEdge *eLo = regLo->eUp; + int degenerate = FALSE; + + if( eUp->Dst != eLo->Dst ) { + (void) CheckForIntersect( tess, regUp ); + } + + /* Possible new degeneracies: upper or lower edge of regUp may pass + * through vEvent, or may coincide with new intersection vertex + */ + if( VertEq( eUp->Org, tess->event )) { + if ( !tessMeshSplice( tess->mesh, eTopLeft->Oprev, eUp ) ) longjmp(tess->env,1); + regUp = TopLeftRegion( tess, regUp ); + if (regUp == NULL) longjmp(tess->env,1); + eTopLeft = RegionBelow( regUp )->eUp; + FinishLeftRegions( tess, RegionBelow(regUp), regLo ); + degenerate = TRUE; + } + if( VertEq( eLo->Org, tess->event )) { + if ( !tessMeshSplice( tess->mesh, eBottomLeft, eLo->Oprev ) ) longjmp(tess->env,1); + eBottomLeft = FinishLeftRegions( tess, regLo, NULL ); + degenerate = TRUE; + } + if( degenerate ) { + AddRightEdges( tess, regUp, eBottomLeft->Onext, eTopLeft, eTopLeft, TRUE ); + return; + } + + /* Non-degenerate situation -- need to add a temporary, fixable edge. + * Connect to the closer of eLo->Org, eUp->Org. + */ + if( VertLeq( eLo->Org, eUp->Org )) { + eNew = eLo->Oprev; + } else { + eNew = eUp; + } + eNew = tessMeshConnect( tess->mesh, eBottomLeft->Lprev, eNew ); + if (eNew == NULL) longjmp(tess->env,1); + + /* Prevent cleanup, otherwise eNew might disappear before we've even + * had a chance to mark it as a temporary edge. + */ + AddRightEdges( tess, regUp, eNew, eNew->Onext, eNew->Onext, FALSE ); + eNew->Sym->activeRegion->fixUpperEdge = TRUE; + WalkDirtyRegions( tess, regUp ); +} + +/* Because vertices at exactly the same location are merged together +* before we process the sweep event, some degenerate cases can't occur. +* However if someone eventually makes the modifications required to +* merge features which are close together, the cases below marked +* TOLERANCE_NONZERO will be useful. They were debugged before the +* code to merge identical vertices in the main loop was added. +*/ +#define TOLERANCE_NONZERO FALSE + +static void ConnectLeftDegenerate( TESStesselator *tess, + ActiveRegion *regUp, TESSvertex *vEvent ) +/* +* The event vertex lies exacty on an already-processed edge or vertex. +* Adding the new vertex involves splicing it into the already-processed +* part of the mesh. +*/ +{ + TESShalfEdge *e, *eTopLeft, *eTopRight, *eLast; + ActiveRegion *reg; + + e = regUp->eUp; + if( VertEq( e->Org, vEvent )) { + /* e->Org is an unprocessed vertex - just combine them, and wait + * for e->Org to be pulled from the queue + */ + assert( TOLERANCE_NONZERO ); + SpliceMergeVertices( tess, e, vEvent->anEdge ); + return; + } + + if( ! VertEq( e->Dst, vEvent )) { + /* General case -- splice vEvent into edge e which passes through it */ + if (tessMeshSplitEdge( tess->mesh, e->Sym ) == NULL) longjmp(tess->env,1); + if( regUp->fixUpperEdge ) { + /* This edge was fixable -- delete unused portion of original edge */ + if ( !tessMeshDelete( tess->mesh, e->Onext ) ) longjmp(tess->env,1); + regUp->fixUpperEdge = FALSE; + } + if ( !tessMeshSplice( tess->mesh, vEvent->anEdge, e ) ) longjmp(tess->env,1); + SweepEvent( tess, vEvent ); /* recurse */ + return; + } + + /* vEvent coincides with e->Dst, which has already been processed. + * Splice in the additional right-going edges. + */ + assert( TOLERANCE_NONZERO ); + regUp = TopRightRegion( regUp ); + reg = RegionBelow( regUp ); + eTopRight = reg->eUp->Sym; + eTopLeft = eLast = eTopRight->Onext; + if( reg->fixUpperEdge ) { + /* Here e->Dst has only a single fixable edge going right. + * We can delete it since now we have some real right-going edges. + */ + assert( eTopLeft != eTopRight ); /* there are some left edges too */ + DeleteRegion( tess, reg ); + if ( !tessMeshDelete( tess->mesh, eTopRight ) ) longjmp(tess->env,1); + eTopRight = eTopLeft->Oprev; + } + if ( !tessMeshSplice( tess->mesh, vEvent->anEdge, eTopRight ) ) longjmp(tess->env,1); + if( ! EdgeGoesLeft( eTopLeft )) { + /* e->Dst had no left-going edges -- indicate this to AddRightEdges() */ + eTopLeft = NULL; + } + AddRightEdges( tess, regUp, eTopRight->Onext, eLast, eTopLeft, TRUE ); +} + + +static void ConnectLeftVertex( TESStesselator *tess, TESSvertex *vEvent ) +/* +* Purpose: connect a "left" vertex (one where both edges go right) +* to the processed portion of the mesh. Let R be the active region +* containing vEvent, and let U and L be the upper and lower edge +* chains of R. There are two possibilities: +* +* - the normal case: split R into two regions, by connecting vEvent to +* the rightmost vertex of U or L lying to the left of the sweep line +* +* - the degenerate case: if vEvent is close enough to U or L, we +* merge vEvent into that edge chain. The subcases are: +* - merging with the rightmost vertex of U or L +* - merging with the active edge of U or L +* - merging with an already-processed portion of U or L +*/ +{ + ActiveRegion *regUp, *regLo, *reg; + TESShalfEdge *eUp, *eLo, *eNew; + ActiveRegion tmp; + + /* assert( vEvent->anEdge->Onext->Onext == vEvent->anEdge ); */ + + /* Get a pointer to the active region containing vEvent */ + tmp.eUp = vEvent->anEdge->Sym; + /* __GL_DICTLISTKEY */ /* tessDictListSearch */ + regUp = (ActiveRegion *)dictKey( dictSearch( tess->dict, &tmp )); + regLo = RegionBelow( regUp ); + if( !regLo ) { + // This may happen if the input polygon is coplanar. + return; + } + eUp = regUp->eUp; + eLo = regLo->eUp; + + /* Try merging with U or L first */ + if( EdgeSign( eUp->Dst, vEvent, eUp->Org ) == 0 ) { + ConnectLeftDegenerate( tess, regUp, vEvent ); + return; + } + + /* Connect vEvent to rightmost processed vertex of either chain. + * e->Dst is the vertex that we will connect to vEvent. + */ + reg = VertLeq( eLo->Dst, eUp->Dst ) ? regUp : regLo; + + if( regUp->inside || reg->fixUpperEdge) { + if( reg == regUp ) { + eNew = tessMeshConnect( tess->mesh, vEvent->anEdge->Sym, eUp->Lnext ); + if (eNew == NULL) longjmp(tess->env,1); + } else { + TESShalfEdge *tempHalfEdge= tessMeshConnect( tess->mesh, eLo->Dnext, vEvent->anEdge); + if (tempHalfEdge == NULL) longjmp(tess->env,1); + + eNew = tempHalfEdge->Sym; + } + if( reg->fixUpperEdge ) { + if ( !FixUpperEdge( tess, reg, eNew ) ) longjmp(tess->env,1); + } else { + ComputeWinding( tess, AddRegionBelow( tess, regUp, eNew )); + } + SweepEvent( tess, vEvent ); + } else { + /* The new vertex is in a region which does not belong to the polygon. + * We don''t need to connect this vertex to the rest of the mesh. + */ + AddRightEdges( tess, regUp, vEvent->anEdge, vEvent->anEdge, NULL, TRUE ); + } +} + + +static void SweepEvent( TESStesselator *tess, TESSvertex *vEvent ) +/* +* Does everything necessary when the sweep line crosses a vertex. +* Updates the mesh and the edge dictionary. +*/ +{ + ActiveRegion *regUp, *reg; + TESShalfEdge *e, *eTopLeft, *eBottomLeft; + + tess->event = vEvent; /* for access in EdgeLeq() */ + DebugEvent( tess ); + + /* Check if this vertex is the right endpoint of an edge that is + * already in the dictionary. In this case we don't need to waste + * time searching for the location to insert new edges. + */ + e = vEvent->anEdge; + while( e->activeRegion == NULL ) { + e = e->Onext; + if( e == vEvent->anEdge ) { + /* All edges go right -- not incident to any processed edges */ + ConnectLeftVertex( tess, vEvent ); + return; + } + } + + /* Processing consists of two phases: first we "finish" all the + * active regions where both the upper and lower edges terminate + * at vEvent (ie. vEvent is closing off these regions). + * We mark these faces "inside" or "outside" the polygon according + * to their winding number, and delete the edges from the dictionary. + * This takes care of all the left-going edges from vEvent. + */ + regUp = TopLeftRegion( tess, e->activeRegion ); + if (regUp == NULL) longjmp(tess->env,1); + reg = RegionBelow( regUp ); + eTopLeft = reg->eUp; + eBottomLeft = FinishLeftRegions( tess, reg, NULL ); + + /* Next we process all the right-going edges from vEvent. This + * involves adding the edges to the dictionary, and creating the + * associated "active regions" which record information about the + * regions between adjacent dictionary edges. + */ + if( eBottomLeft->Onext == eTopLeft ) { + /* No right-going edges -- add a temporary "fixable" edge */ + ConnectRightVertex( tess, regUp, eBottomLeft ); + } else { + AddRightEdges( tess, regUp, eBottomLeft->Onext, eTopLeft, eTopLeft, TRUE ); + } +} + + +/* Make the sentinel coordinates big enough that they will never be +* merged with real input features. +*/ + +static void AddSentinel( TESStesselator *tess, TESSreal smin, TESSreal smax, TESSreal t ) +/* +* We add two sentinel edges above and below all other edges, +* to avoid special cases at the top and bottom. +*/ +{ + TESShalfEdge *e; + ActiveRegion *reg = (ActiveRegion *)bucketAlloc( tess->regionPool ); + if (reg == NULL) longjmp(tess->env,1); + + e = tessMeshMakeEdge( tess->mesh ); + if (e == NULL) longjmp(tess->env,1); + + e->Org->s = smax; + e->Org->t = t; + e->Dst->s = smin; + e->Dst->t = t; + tess->event = e->Dst; /* initialize it */ + + reg->eUp = e; + reg->windingNumber = 0; + reg->inside = FALSE; + reg->fixUpperEdge = FALSE; + reg->sentinel = TRUE; + reg->dirty = FALSE; + reg->nodeUp = dictInsert( tess->dict, reg ); + if (reg->nodeUp == NULL) longjmp(tess->env,1); +} + + +static void InitEdgeDict( TESStesselator *tess ) +/* +* We maintain an ordering of edge intersections with the sweep line. +* This order is maintained in a dynamic dictionary. +*/ +{ + TESSreal w, h; + TESSreal smin, smax, tmin, tmax; + + tess->dict = dictNewDict( &tess->alloc, tess, (int (*)(void *, DictKey, DictKey)) EdgeLeq ); + if (tess->dict == NULL) longjmp(tess->env,1); + + w = (tess->bmax[0] - tess->bmin[0]); + h = (tess->bmax[1] - tess->bmin[1]); + + /* If the bbox is empty, ensure that sentinels are not coincident by + slightly enlarging it. To avoid floating point precision issues, + make sure to enlarge by a minimal amount. */ + smin = tess->bmin[0] - (w > 0.01 ? w : 0.01); + smax = tess->bmax[0] + (w > 0.01 ? w : 0.01); + tmin = tess->bmin[1] - (h > 0.01 ? h : 0.01); + tmax = tess->bmax[1] + (h > 0.01 ? h : 0.01); + + AddSentinel( tess, smin, smax, tmin ); + AddSentinel( tess, smin, smax, tmax ); +} + + +static void DoneEdgeDict( TESStesselator *tess ) +{ + ActiveRegion *reg; + int fixedEdges = 0; + + while( (reg = (ActiveRegion *)dictKey( dictMin( tess->dict ))) != NULL ) { + /* + * At the end of all processing, the dictionary should contain + * only the two sentinel edges, plus at most one "fixable" edge + * created by ConnectRightVertex(). + */ + if( ! reg->sentinel ) { + assert( reg->fixUpperEdge ); + assert( ++fixedEdges == 1 ); + } + assert( reg->windingNumber == 0 ); + DeleteRegion( tess, reg ); + /* tessMeshDelete( reg->eUp );*/ + } + dictDeleteDict( &tess->alloc, tess->dict ); +} + + +static void RemoveDegenerateEdges( TESStesselator *tess ) +/* +* Remove zero-length edges, and contours with fewer than 3 vertices. +*/ +{ + TESShalfEdge *e, *eNext, *eLnext; + TESShalfEdge *eHead = &tess->mesh->eHead; + + /*LINTED*/ + for( e = eHead->next; e != eHead; e = eNext ) { + eNext = e->next; + eLnext = e->Lnext; + + if( VertEq( e->Org, e->Dst ) && e->Lnext->Lnext != e ) { + /* Zero-length edge, contour has at least 3 edges */ + + SpliceMergeVertices( tess, eLnext, e ); /* deletes e->Org */ + if ( !tessMeshDelete( tess->mesh, e ) ) longjmp(tess->env,1); /* e is a self-loop */ + e = eLnext; + eLnext = e->Lnext; + } + if( eLnext->Lnext == e ) { + /* Degenerate contour (one or two edges) */ + + if( eLnext != e ) { + if( eLnext == eNext || eLnext == eNext->Sym ) { eNext = eNext->next; } + if ( !tessMeshDelete( tess->mesh, eLnext ) ) longjmp(tess->env,1); + } + if( e == eNext || e == eNext->Sym ) { eNext = eNext->next; } + if ( !tessMeshDelete( tess->mesh, e ) ) longjmp(tess->env,1); + } + } +} + +static int InitPriorityQ( TESStesselator *tess ) +/* +* Insert all vertices into the priority queue which determines the +* order in which vertices cross the sweep line. +*/ +{ + PriorityQ *pq; + TESSvertex *v, *vHead; + int vertexCount = 0; + + vHead = &tess->mesh->vHead; + for( v = vHead->next; v != vHead; v = v->next ) { + vertexCount++; + } + /* Make sure there is enough space for sentinels. */ + vertexCount += MAX( 8, tess->alloc.extraVertices ); + + pq = tess->pq = pqNewPriorityQ( &tess->alloc, vertexCount, (int (*)(PQkey, PQkey)) tesvertLeq ); + if (pq == NULL) return 0; + + vHead = &tess->mesh->vHead; + for( v = vHead->next; v != vHead; v = v->next ) { + v->pqHandle = pqInsert( &tess->alloc, pq, v ); + if (v->pqHandle == INV_HANDLE) + break; + } + if (v != vHead || !pqInit( &tess->alloc, pq ) ) { + pqDeletePriorityQ( &tess->alloc, tess->pq ); + tess->pq = NULL; + return 0; + } + + return 1; +} + + +static void DonePriorityQ( TESStesselator *tess ) +{ + pqDeletePriorityQ( &tess->alloc, tess->pq ); +} + + +static int RemoveDegenerateFaces( TESStesselator *tess, TESSmesh *mesh ) +/* +* Delete any degenerate faces with only two edges. WalkDirtyRegions() +* will catch almost all of these, but it won't catch degenerate faces +* produced by splice operations on already-processed edges. +* The two places this can happen are in FinishLeftRegions(), when +* we splice in a "temporary" edge produced by ConnectRightVertex(), +* and in CheckForLeftSplice(), where we splice already-processed +* edges to ensure that our dictionary invariants are not violated +* by numerical errors. +* +* In both these cases it is *very* dangerous to delete the offending +* edge at the time, since one of the routines further up the stack +* will sometimes be keeping a pointer to that edge. +*/ +{ + TESSface *f, *fNext; + TESShalfEdge *e; + + /*LINTED*/ + for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) { + fNext = f->next; + e = f->anEdge; + assert( e->Lnext != e ); + + if( e->Lnext->Lnext == e ) { + /* A face with only two edges */ + AddWinding( e->Onext, e ); + if ( !tessMeshDelete( tess->mesh, e ) ) return 0; + } + } + return 1; +} + +int tessComputeInterior( TESStesselator *tess ) +/* +* tessComputeInterior( tess ) computes the planar arrangement specified +* by the given contours, and further subdivides this arrangement +* into regions. Each region is marked "inside" if it belongs +* to the polygon, according to the rule given by tess->windingRule. +* Each interior region is guaranteed be monotone. +*/ +{ + TESSvertex *v, *vNext; + + /* Each vertex defines an event for our sweep line. Start by inserting + * all the vertices in a priority queue. Events are processed in + * lexicographic order, ie. + * + * e1 < e2 iff e1.x < e2.x || (e1.x == e2.x && e1.y < e2.y) + */ + RemoveDegenerateEdges( tess ); + if ( !InitPriorityQ( tess ) ) return 0; /* if error */ + InitEdgeDict( tess ); + + while( (v = (TESSvertex *)pqExtractMin( tess->pq )) != NULL ) { + for( ;; ) { + vNext = (TESSvertex *)pqMinimum( tess->pq ); + if( vNext == NULL || ! VertEq( vNext, v )) break; + + /* Merge together all vertices at exactly the same location. + * This is more efficient than processing them one at a time, + * simplifies the code (see ConnectLeftDegenerate), and is also + * important for correct handling of certain degenerate cases. + * For example, suppose there are two identical edges A and B + * that belong to different contours (so without this code they would + * be processed by separate sweep events). Suppose another edge C + * crosses A and B from above. When A is processed, we split it + * at its intersection point with C. However this also splits C, + * so when we insert B we may compute a slightly different + * intersection point. This might leave two edges with a small + * gap between them. This kind of error is especially obvious + * when using boundary extraction (TESS_BOUNDARY_ONLY). + */ + vNext = (TESSvertex *)pqExtractMin( tess->pq ); + SpliceMergeVertices( tess, v->anEdge, vNext->anEdge ); + } + SweepEvent( tess, v ); + } + + /* Set tess->event for debugging purposes */ + tess->event = ((ActiveRegion *) dictKey( dictMin( tess->dict )))->eUp->Org; + DebugEvent( tess ); + DoneEdgeDict( tess ); + DonePriorityQ( tess ); + + if ( !RemoveDegenerateFaces( tess, tess->mesh ) ) return 0; + tessMeshCheckMesh( tess->mesh ); + + return 1; +} diff --git a/src/libtess2/Source/sweep.h b/src/libtess2/Source/sweep.h new file mode 100755 index 00000000..32f0f86d --- /dev/null +++ b/src/libtess2/Source/sweep.h @@ -0,0 +1,74 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#ifndef SWEEP_H +#define SWEEP_H + +#include "mesh.h" + +/* tessComputeInterior( tess ) computes the planar arrangement specified +* by the given contours, and further subdivides this arrangement +* into regions. Each region is marked "inside" if it belongs +* to the polygon, according to the rule given by tess->windingRule. +* Each interior region is guaranteed be monotone. +*/ +int tessComputeInterior( TESStesselator *tess ); + + +/* The following is here *only* for access by debugging routines */ + +#include "dict.h" + +/* For each pair of adjacent edges crossing the sweep line, there is +* an ActiveRegion to represent the region between them. The active +* regions are kept in sorted order in a dynamic dictionary. As the +* sweep line crosses each vertex, we update the affected regions. +*/ + +struct ActiveRegion { + TESShalfEdge *eUp; /* upper edge, directed right to left */ + DictNode *nodeUp; /* dictionary node corresponding to eUp */ + int windingNumber; /* used to determine which regions are + * inside the polygon */ + int inside; /* is this region inside the polygon? */ + int sentinel; /* marks fake edges at t = +/-infinity */ + int dirty; /* marks regions where the upper or lower + * edge has changed, but we haven't checked + * whether they intersect yet */ + int fixUpperEdge; /* marks temporary edges introduced when + * we process a "right vertex" (one without + * any edges leaving to the right) */ +}; + +#define RegionBelow(r) ((ActiveRegion *) dictKey(dictPred((r)->nodeUp))) +#define RegionAbove(r) ((ActiveRegion *) dictKey(dictSucc((r)->nodeUp))) + +#endif diff --git a/src/libtess2/Source/tess.c b/src/libtess2/Source/tess.c new file mode 100755 index 00000000..49e2c495 --- /dev/null +++ b/src/libtess2/Source/tess.c @@ -0,0 +1,1095 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#include +#include +#include +#include "bucketalloc.h" +#include "tess.h" +#include "mesh.h" +#include "sweep.h" +#include "geom.h" +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 + +#define Dot(u,v) (u[0]*v[0] + u[1]*v[1] + u[2]*v[2]) + +#if defined(FOR_TRITE_TEST_PROGRAM) || defined(TRUE_PROJECT) +static void Normalize( TESSreal v[3] ) +{ + TESSreal len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; + + assert( len > 0 ); + len = sqrtf( len ); + v[0] /= len; + v[1] /= len; + v[2] /= len; +} +#endif + +#define ABS(x) ((x) < 0 ? -(x) : (x)) + +static int LongAxis( TESSreal v[3] ) +{ + int i = 0; + + if( ABS(v[1]) > ABS(v[0]) ) { i = 1; } + if( ABS(v[2]) > ABS(v[i]) ) { i = 2; } + return i; +} + +static int ShortAxis( TESSreal v[3] ) +{ + int i = 0; + + if( ABS(v[1]) < ABS(v[0]) ) { i = 1; } + if( ABS(v[2]) < ABS(v[i]) ) { i = 2; } + return i; +} + +static void ComputeNormal( TESStesselator *tess, TESSreal norm[3] ) +{ + TESSvertex *v, *v1, *v2; + TESSreal c, tLen2, maxLen2; + TESSreal maxVal[3], minVal[3], d1[3], d2[3], tNorm[3]; + TESSvertex *maxVert[3], *minVert[3]; + TESSvertex *vHead = &tess->mesh->vHead; + int i; + + v = vHead->next; + for( i = 0; i < 3; ++i ) { + c = v->coords[i]; + minVal[i] = c; + minVert[i] = v; + maxVal[i] = c; + maxVert[i] = v; + } + + for( v = vHead->next; v != vHead; v = v->next ) { + for( i = 0; i < 3; ++i ) { + c = v->coords[i]; + if( c < minVal[i] ) { minVal[i] = c; minVert[i] = v; } + if( c > maxVal[i] ) { maxVal[i] = c; maxVert[i] = v; } + } + } + + /* Find two vertices separated by at least 1/sqrt(3) of the maximum + * distance between any two vertices + */ + i = 0; + if( maxVal[1] - minVal[1] > maxVal[0] - minVal[0] ) { i = 1; } + if( maxVal[2] - minVal[2] > maxVal[i] - minVal[i] ) { i = 2; } + if( minVal[i] >= maxVal[i] ) { + /* All vertices are the same -- normal doesn't matter */ + norm[0] = 0; norm[1] = 0; norm[2] = 1; + return; + } + + /* Look for a third vertex which forms the triangle with maximum area + * (Length of normal == twice the triangle area) + */ + maxLen2 = 0; + v1 = minVert[i]; + v2 = maxVert[i]; + d1[0] = v1->coords[0] - v2->coords[0]; + d1[1] = v1->coords[1] - v2->coords[1]; + d1[2] = v1->coords[2] - v2->coords[2]; + for( v = vHead->next; v != vHead; v = v->next ) { + d2[0] = v->coords[0] - v2->coords[0]; + d2[1] = v->coords[1] - v2->coords[1]; + d2[2] = v->coords[2] - v2->coords[2]; + tNorm[0] = d1[1]*d2[2] - d1[2]*d2[1]; + tNorm[1] = d1[2]*d2[0] - d1[0]*d2[2]; + tNorm[2] = d1[0]*d2[1] - d1[1]*d2[0]; + tLen2 = tNorm[0]*tNorm[0] + tNorm[1]*tNorm[1] + tNorm[2]*tNorm[2]; + if( tLen2 > maxLen2 ) { + maxLen2 = tLen2; + norm[0] = tNorm[0]; + norm[1] = tNorm[1]; + norm[2] = tNorm[2]; + } + } + + if( maxLen2 <= 0 ) { + /* All points lie on a single line -- any decent normal will do */ + norm[0] = norm[1] = norm[2] = 0; + norm[ShortAxis(d1)] = 1; + } +} + + +static void CheckOrientation( TESStesselator *tess ) +{ + TESSreal area; + TESSface *f, *fHead = &tess->mesh->fHead; + TESSvertex *v, *vHead = &tess->mesh->vHead; + TESShalfEdge *e; + + /* When we compute the normal automatically, we choose the orientation + * so that the the sum of the signed areas of all contours is non-negative. + */ + area = 0; + for( f = fHead->next; f != fHead; f = f->next ) { + e = f->anEdge; + if( e->winding <= 0 ) continue; + do { + area += (e->Org->s - e->Dst->s) * (e->Org->t + e->Dst->t); + e = e->Lnext; + } while( e != f->anEdge ); + } + if( area < 0 ) { + /* Reverse the orientation by flipping all the t-coordinates */ + for( v = vHead->next; v != vHead; v = v->next ) { + v->t = - v->t; + } + tess->tUnit[0] = - tess->tUnit[0]; + tess->tUnit[1] = - tess->tUnit[1]; + tess->tUnit[2] = - tess->tUnit[2]; + } +} + +#ifdef FOR_TRITE_TEST_PROGRAM +#include +extern int RandomSweep; +#define S_UNIT_X (RandomSweep ? (2*drand48()-1) : 1.0) +#define S_UNIT_Y (RandomSweep ? (2*drand48()-1) : 0.0) +#else +#if defined(SLANTED_SWEEP) +/* The "feature merging" is not intended to be complete. There are +* special cases where edges are nearly parallel to the sweep line +* which are not implemented. The algorithm should still behave +* robustly (ie. produce a reasonable tesselation) in the presence +* of such edges, however it may miss features which could have been +* merged. We could minimize this effect by choosing the sweep line +* direction to be something unusual (ie. not parallel to one of the +* coordinate axes). +*/ +#define S_UNIT_X (TESSreal)0.50941539564955385 /* Pre-normalized */ +#define S_UNIT_Y (TESSreal)0.86052074622010633 +#else +#define S_UNIT_X (TESSreal)1.0 +#define S_UNIT_Y (TESSreal)0.0 +#endif +#endif + +/* Determine the polygon normal and project vertices onto the plane +* of the polygon. +*/ +void tessProjectPolygon( TESStesselator *tess ) +{ + TESSvertex *v, *vHead = &tess->mesh->vHead; + TESSreal norm[3]; + TESSreal *sUnit, *tUnit; + int i, first, computedNormal = FALSE; + + norm[0] = tess->normal[0]; + norm[1] = tess->normal[1]; + norm[2] = tess->normal[2]; + if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) { + ComputeNormal( tess, norm ); + computedNormal = TRUE; + } + sUnit = tess->sUnit; + tUnit = tess->tUnit; + i = LongAxis( norm ); + +#if defined(FOR_TRITE_TEST_PROGRAM) || defined(TRUE_PROJECT) + /* Choose the initial sUnit vector to be approximately perpendicular + * to the normal. + */ + Normalize( norm ); + + sUnit[i] = 0; + sUnit[(i+1)%3] = S_UNIT_X; + sUnit[(i+2)%3] = S_UNIT_Y; + + /* Now make it exactly perpendicular */ + w = Dot( sUnit, norm ); + sUnit[0] -= w * norm[0]; + sUnit[1] -= w * norm[1]; + sUnit[2] -= w * norm[2]; + Normalize( sUnit ); + + /* Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame */ + tUnit[0] = norm[1]*sUnit[2] - norm[2]*sUnit[1]; + tUnit[1] = norm[2]*sUnit[0] - norm[0]*sUnit[2]; + tUnit[2] = norm[0]*sUnit[1] - norm[1]*sUnit[0]; + Normalize( tUnit ); +#else + /* Project perpendicular to a coordinate axis -- better numerically */ + sUnit[i] = 0; + sUnit[(i+1)%3] = S_UNIT_X; + sUnit[(i+2)%3] = S_UNIT_Y; + + tUnit[i] = 0; + tUnit[(i+1)%3] = (norm[i] > 0) ? -S_UNIT_Y : S_UNIT_Y; + tUnit[(i+2)%3] = (norm[i] > 0) ? S_UNIT_X : -S_UNIT_X; +#endif + + /* Project the vertices onto the sweep plane */ + for( v = vHead->next; v != vHead; v = v->next ) + { + v->s = Dot( v->coords, sUnit ); + v->t = Dot( v->coords, tUnit ); + } + if( computedNormal ) { + CheckOrientation( tess ); + } + + /* Compute ST bounds. */ + first = 1; + for( v = vHead->next; v != vHead; v = v->next ) + { + if (first) + { + tess->bmin[0] = tess->bmax[0] = v->s; + tess->bmin[1] = tess->bmax[1] = v->t; + first = 0; + } + else + { + if (v->s < tess->bmin[0]) tess->bmin[0] = v->s; + if (v->s > tess->bmax[0]) tess->bmax[0] = v->s; + if (v->t < tess->bmin[1]) tess->bmin[1] = v->t; + if (v->t > tess->bmax[1]) tess->bmax[1] = v->t; + } + } +} + +#define AddWinding(eDst,eSrc) (eDst->winding += eSrc->winding, \ + eDst->Sym->winding += eSrc->Sym->winding) + +/* tessMeshTessellateMonoRegion( face ) tessellates a monotone region +* (what else would it do??) The region must consist of a single +* loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this +* case means that any vertical line intersects the interior of the +* region in a single interval. +* +* Tessellation consists of adding interior edges (actually pairs of +* half-edges), to split the region into non-overlapping triangles. +* +* The basic idea is explained in Preparata and Shamos (which I don''t +* have handy right now), although their implementation is more +* complicated than this one. The are two edge chains, an upper chain +* and a lower chain. We process all vertices from both chains in order, +* from right to left. +* +* The algorithm ensures that the following invariant holds after each +* vertex is processed: the untessellated region consists of two +* chains, where one chain (say the upper) is a single edge, and +* the other chain is concave. The left vertex of the single edge +* is always to the left of all vertices in the concave chain. +* +* Each step consists of adding the rightmost unprocessed vertex to one +* of the two chains, and forming a fan of triangles from the rightmost +* of two chain endpoints. Determining whether we can add each triangle +* to the fan is a simple orientation test. By making the fan as large +* as possible, we restore the invariant (check it yourself). +*/ +int tessMeshTessellateMonoRegion( TESSmesh *mesh, TESSface *face ) +{ + TESShalfEdge *up, *lo; + + /* All edges are oriented CCW around the boundary of the region. + * First, find the half-edge whose origin vertex is rightmost. + * Since the sweep goes from left to right, face->anEdge should + * be close to the edge we want. + */ + up = face->anEdge; + assert( up->Lnext != up && up->Lnext->Lnext != up ); + + for( ; VertLeq( up->Dst, up->Org ); up = up->Lprev ) + ; + for( ; VertLeq( up->Org, up->Dst ); up = up->Lnext ) + ; + lo = up->Lprev; + + while( up->Lnext != lo ) { + if( VertLeq( up->Dst, lo->Org )) { + /* up->Dst is on the left. It is safe to form triangles from lo->Org. + * The EdgeGoesLeft test guarantees progress even when some triangles + * are CW, given that the upper and lower chains are truly monotone. + */ + while( lo->Lnext != up && (EdgeGoesLeft( lo->Lnext ) + || EdgeSign( lo->Org, lo->Dst, lo->Lnext->Dst ) <= 0 )) { + TESShalfEdge *tempHalfEdge= tessMeshConnect( mesh, lo->Lnext, lo ); + if (tempHalfEdge == NULL) return 0; + lo = tempHalfEdge->Sym; + } + lo = lo->Lprev; + } else { + /* lo->Org is on the left. We can make CCW triangles from up->Dst. */ + while( lo->Lnext != up && (EdgeGoesRight( up->Lprev ) + || EdgeSign( up->Dst, up->Org, up->Lprev->Org ) >= 0 )) { + TESShalfEdge *tempHalfEdge= tessMeshConnect( mesh, up, up->Lprev ); + if (tempHalfEdge == NULL) return 0; + up = tempHalfEdge->Sym; + } + up = up->Lnext; + } + } + + /* Now lo->Org == up->Dst == the leftmost vertex. The remaining region + * can be tessellated in a fan from this leftmost vertex. + */ + assert( lo->Lnext != up ); + while( lo->Lnext->Lnext != up ) { + TESShalfEdge *tempHalfEdge= tessMeshConnect( mesh, lo->Lnext, lo ); + if (tempHalfEdge == NULL) return 0; + lo = tempHalfEdge->Sym; + } + + return 1; +} + +/* tessMeshTessellateInterior( mesh ) tessellates each region of +* the mesh which is marked "inside" the polygon. Each such region +* must be monotone. +*/ +int tessMeshTessellateInterior( TESSmesh *mesh ) +{ + TESSface *f, *next; + + /*LINTED*/ + for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) { + /* Make sure we don''t try to tessellate the new triangles. */ + next = f->next; + if( f->inside ) { + if ( !tessMeshTessellateMonoRegion( mesh, f ) ) return 0; + } + } + return 1; +} + + +typedef struct EdgeStackNode EdgeStackNode; +typedef struct EdgeStack EdgeStack; + +struct EdgeStackNode { + TESShalfEdge *edge; + EdgeStackNode *next; +}; + +struct EdgeStack { + EdgeStackNode *top; + struct BucketAlloc *nodeBucket; +}; + +int stackInit( EdgeStack *stack, TESSalloc *alloc ) +{ + stack->top = NULL; + stack->nodeBucket = createBucketAlloc( alloc, "CDT nodes", sizeof(EdgeStackNode), 512 ); + return stack->nodeBucket != NULL; +} + +void stackDelete( EdgeStack *stack ) +{ + deleteBucketAlloc( stack->nodeBucket ); +} + +int stackEmpty( EdgeStack *stack ) +{ + return stack->top == NULL; +} + +void stackPush( EdgeStack *stack, TESShalfEdge *e ) +{ + EdgeStackNode *node = (EdgeStackNode *)bucketAlloc( stack->nodeBucket ); + if ( ! node ) return; + node->edge = e; + node->next = stack->top; + stack->top = node; +} + +TESShalfEdge *stackPop( EdgeStack *stack ) +{ + TESShalfEdge *e = NULL; + EdgeStackNode *node = stack->top; + if (node) { + stack->top = node->next; + e = node->edge; + bucketFree( stack->nodeBucket, node ); + } + return e; +} + +/* + Starting with a valid triangulation, uses the Edge Flip algorithm to + refine the triangulation into a Constrained Delaunay Triangulation. +*/ +int tessMeshRefineDelaunay( TESSmesh *mesh, TESSalloc *alloc ) +{ + /* At this point, we have a valid, but not optimal, triangulation. + We refine the triangulation using the Edge Flip algorithm */ + +/* + 1) Find all internal edges + 2) Mark all dual edges + 3) insert all dual edges into a queue +*/ + TESSface *f; + EdgeStack stack; + TESShalfEdge *e; + TESShalfEdge *edges[4]; + stackInit(&stack, alloc); + for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) { + if ( f->inside) { + e = f->anEdge; + do { + e->mark = EdgeIsInternal(e); /* Mark internal edges */ + if (e->mark && !e->Sym->mark) stackPush(&stack, e); /* Insert into queue */ + e = e->Lnext; + } while (e != f->anEdge); + } + } + + // Pop stack until we find a reversed edge + // Flip the reversed edge, and insert any of the four opposite edges + // which are internal and not already in the stack (!marked) + while (!stackEmpty(&stack)) { + e = stackPop(&stack); + e->mark = e->Sym->mark = 0; + if (!tesedgeIsLocallyDelaunay(e)) { + int i; + tessMeshFlipEdge(mesh, e); + // for each opposite edge + edges[0] = e->Lnext; + edges[1] = e->Lprev; + edges[2] = e->Sym->Lnext; + edges[3] = e->Sym->Lprev; + for (i=0;i<3;i++) { + if (!edges[i]->mark && EdgeIsInternal(edges[i])) { + edges[i]->mark = edges[i]->Sym->mark = 1; + stackPush(&stack, edges[i]); + } + } + } + } + + stackDelete(&stack); + + return 1; +} + + +/* tessMeshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces +* which are not marked "inside" the polygon. Since further mesh operations +* on NULL faces are not allowed, the main purpose is to clean up the +* mesh so that exterior loops are not represented in the data structure. +*/ +void tessMeshDiscardExterior( TESSmesh *mesh ) +{ + TESSface *f, *next; + + /*LINTED*/ + for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) { + /* Since f will be destroyed, save its next pointer. */ + next = f->next; + if( ! f->inside ) { + tessMeshZapFace( mesh, f ); + } + } +} + +/* tessMeshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the +* winding numbers on all edges so that regions marked "inside" the +* polygon have a winding number of "value", and regions outside +* have a winding number of 0. +* +* If keepOnlyBoundary is TRUE, it also deletes all edges which do not +* separate an interior region from an exterior one. +*/ +int tessMeshSetWindingNumber( TESSmesh *mesh, int value, + int keepOnlyBoundary ) +{ + TESShalfEdge *e, *eNext; + + for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) { + eNext = e->next; + if( e->Rface->inside != e->Lface->inside ) { + + /* This is a boundary edge (one side is interior, one is exterior). */ + e->winding = (e->Lface->inside) ? value : -value; + } else { + + /* Both regions are interior, or both are exterior. */ + if( ! keepOnlyBoundary ) { + e->winding = 0; + } else { + if ( !tessMeshDelete( mesh, e ) ) return 0; + } + } + } + return 1; +} + +void* heapAlloc( void* userData, unsigned int size ) +{ + TESS_NOTUSED( userData ); + return malloc( size ); +} + +void* heapRealloc( void *userData, void* ptr, unsigned int size ) +{ + TESS_NOTUSED( userData ); + return realloc( ptr, size ); +} + +void heapFree( void* userData, void* ptr ) +{ + TESS_NOTUSED( userData ); + free( ptr ); +} + +static TESSalloc defaulAlloc = +{ + heapAlloc, + heapRealloc, + heapFree, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +}; + +TESStesselator* tessNewTess( TESSalloc* alloc ) +{ + TESStesselator* tess; + + if (alloc == NULL) + alloc = &defaulAlloc; + + /* Only initialize fields which can be changed by the api. Other fields + * are initialized where they are used. + */ + + tess = (TESStesselator *)alloc->memalloc( alloc->userData, sizeof( TESStesselator )); + if ( tess == NULL ) { + return 0; /* out of memory */ + } + tess->alloc = *alloc; + /* Check and set defaults. */ + if (tess->alloc.meshEdgeBucketSize == 0) + tess->alloc.meshEdgeBucketSize = 512; + if (tess->alloc.meshVertexBucketSize == 0) + tess->alloc.meshVertexBucketSize = 512; + if (tess->alloc.meshFaceBucketSize == 0) + tess->alloc.meshFaceBucketSize = 256; + if (tess->alloc.dictNodeBucketSize == 0) + tess->alloc.dictNodeBucketSize = 512; + if (tess->alloc.regionBucketSize == 0) + tess->alloc.regionBucketSize = 256; + + tess->normal[0] = 0; + tess->normal[1] = 0; + tess->normal[2] = 0; + + tess->bmin[0] = 0; + tess->bmin[1] = 0; + tess->bmax[0] = 0; + tess->bmax[1] = 0; + + tess->windingRule = TESS_WINDING_ODD; + + if (tess->alloc.regionBucketSize < 16) + tess->alloc.regionBucketSize = 16; + if (tess->alloc.regionBucketSize > 4096) + tess->alloc.regionBucketSize = 4096; + tess->regionPool = createBucketAlloc( &tess->alloc, "Regions", + sizeof(ActiveRegion), tess->alloc.regionBucketSize ); + + // Initialize to begin polygon. + tess->mesh = NULL; + + tess->outOfMemory = 0; + tess->vertexIndexCounter = 0; + + tess->vertices = 0; + tess->vertexIndices = 0; + tess->vertexCount = 0; + tess->elements = 0; + tess->elementCount = 0; + + return tess; +} + +void tessDeleteTess( TESStesselator *tess ) +{ + + struct TESSalloc alloc = tess->alloc; + + deleteBucketAlloc( tess->regionPool ); + + if( tess->mesh != NULL ) { + tessMeshDeleteMesh( &alloc, tess->mesh ); + tess->mesh = NULL; + } + if (tess->vertices != NULL) { + alloc.memfree( alloc.userData, tess->vertices ); + tess->vertices = 0; + } + if (tess->vertexIndices != NULL) { + alloc.memfree( alloc.userData, tess->vertexIndices ); + tess->vertexIndices = 0; + } + if (tess->elements != NULL) { + alloc.memfree( alloc.userData, tess->elements ); + tess->elements = 0; + } + + alloc.memfree( alloc.userData, tess ); +} + + +static TESSindex GetNeighbourFace(TESShalfEdge* edge) +{ + if (!edge->Rface) + return TESS_UNDEF; + if (!edge->Rface->inside) + return TESS_UNDEF; + return edge->Rface->n; +} + +void OutputPolymesh( TESStesselator *tess, TESSmesh *mesh, int elementType, int polySize, int vertexSize ) +{ + TESSvertex* v = 0; + TESSface* f = 0; + TESShalfEdge* edge = 0; + int maxFaceCount = 0; + int maxVertexCount = 0; + int faceVerts, i; + TESSindex *elements = 0; + TESSreal *vert; + + // Assume that the input data is triangles now. + // Try to merge as many polygons as possible + if (polySize > 3) + { + if (!tessMeshMergeConvexFaces( mesh, polySize )) + { + tess->outOfMemory = 1; + return; + } + } + + // Mark unused + for ( v = mesh->vHead.next; v != &mesh->vHead; v = v->next ) + v->n = TESS_UNDEF; + + // Create unique IDs for all vertices and faces. + for ( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) + { + f->n = TESS_UNDEF; + if( !f->inside ) continue; + + edge = f->anEdge; + faceVerts = 0; + do + { + v = edge->Org; + if ( v->n == TESS_UNDEF ) + { + v->n = maxVertexCount; + maxVertexCount++; + } + faceVerts++; + edge = edge->Lnext; + } + while (edge != f->anEdge); + + assert( faceVerts <= polySize ); + + f->n = maxFaceCount; + ++maxFaceCount; + } + + tess->elementCount = maxFaceCount; + if (elementType == TESS_CONNECTED_POLYGONS) + maxFaceCount *= 2; + tess->elements = (TESSindex*)tess->alloc.memalloc( tess->alloc.userData, + sizeof(TESSindex) * maxFaceCount * polySize ); + if (!tess->elements) + { + tess->outOfMemory = 1; + return; + } + + tess->vertexCount = maxVertexCount; + tess->vertices = (TESSreal*)tess->alloc.memalloc( tess->alloc.userData, + sizeof(TESSreal) * tess->vertexCount * vertexSize ); + if (!tess->vertices) + { + tess->outOfMemory = 1; + return; + } + + tess->vertexIndices = (TESSindex*)tess->alloc.memalloc( tess->alloc.userData, + sizeof(TESSindex) * tess->vertexCount ); + if (!tess->vertexIndices) + { + tess->outOfMemory = 1; + return; + } + + // Output vertices. + for ( v = mesh->vHead.next; v != &mesh->vHead; v = v->next ) + { + if ( v->n != TESS_UNDEF ) + { + // Store coordinate + vert = &tess->vertices[v->n*vertexSize]; + vert[0] = v->coords[0]; + vert[1] = v->coords[1]; + if ( vertexSize > 2 ) + vert[2] = v->coords[2]; + // Store vertex index. + tess->vertexIndices[v->n] = v->idx; + } + } + + // Output indices. + elements = tess->elements; + for ( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) + { + if ( !f->inside ) continue; + + // Store polygon + edge = f->anEdge; + faceVerts = 0; + do + { + v = edge->Org; + *elements++ = v->n; + faceVerts++; + edge = edge->Lnext; + } + while (edge != f->anEdge); + // Fill unused. + for (i = faceVerts; i < polySize; ++i) + *elements++ = TESS_UNDEF; + + // Store polygon connectivity + if ( elementType == TESS_CONNECTED_POLYGONS ) + { + edge = f->anEdge; + do + { + *elements++ = GetNeighbourFace( edge ); + edge = edge->Lnext; + } + while (edge != f->anEdge); + // Fill unused. + for (i = faceVerts; i < polySize; ++i) + *elements++ = TESS_UNDEF; + } + } +} + +void OutputContours( TESStesselator *tess, TESSmesh *mesh, int vertexSize ) +{ + TESSface *f = 0; + TESShalfEdge *edge = 0; + TESShalfEdge *start = 0; + TESSreal *verts = 0; + TESSindex *elements = 0; + TESSindex *vertInds = 0; + int startVert = 0; + int vertCount = 0; + + tess->vertexCount = 0; + tess->elementCount = 0; + + for ( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) + { + if ( !f->inside ) continue; + + start = edge = f->anEdge; + do + { + ++tess->vertexCount; + edge = edge->Lnext; + } + while ( edge != start ); + + ++tess->elementCount; + } + + tess->elements = (TESSindex*)tess->alloc.memalloc( tess->alloc.userData, + sizeof(TESSindex) * tess->elementCount * 2 ); + if (!tess->elements) + { + tess->outOfMemory = 1; + return; + } + + tess->vertices = (TESSreal*)tess->alloc.memalloc( tess->alloc.userData, + sizeof(TESSreal) * tess->vertexCount * vertexSize ); + if (!tess->vertices) + { + tess->outOfMemory = 1; + return; + } + + tess->vertexIndices = (TESSindex*)tess->alloc.memalloc( tess->alloc.userData, + sizeof(TESSindex) * tess->vertexCount ); + if (!tess->vertexIndices) + { + tess->outOfMemory = 1; + return; + } + + verts = tess->vertices; + elements = tess->elements; + vertInds = tess->vertexIndices; + + startVert = 0; + + for ( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) + { + if ( !f->inside ) continue; + + vertCount = 0; + start = edge = f->anEdge; + do + { + *verts++ = edge->Org->coords[0]; + *verts++ = edge->Org->coords[1]; + if ( vertexSize > 2 ) + *verts++ = edge->Org->coords[2]; + *vertInds++ = edge->Org->idx; + ++vertCount; + edge = edge->Lnext; + } + while ( edge != start ); + + elements[0] = startVert; + elements[1] = vertCount; + elements += 2; + + startVert += vertCount; + } +} + +void tessAddContour( TESStesselator *tess, int size, const void* vertices, + int stride, int numVertices ) +{ + const unsigned char *src = (const unsigned char*)vertices; + TESShalfEdge *e; + int i; + + if ( tess->mesh == NULL ) + tess->mesh = tessMeshNewMesh( &tess->alloc ); + if ( tess->mesh == NULL ) { + tess->outOfMemory = 1; + return; + } + + if ( size < 2 ) + size = 2; + if ( size > 3 ) + size = 3; + + e = NULL; + + for( i = 0; i < numVertices; ++i ) + { + const TESSreal* coords = (const TESSreal*)src; + src += stride; + + if( e == NULL ) { + /* Make a self-loop (one vertex, one edge). */ + e = tessMeshMakeEdge( tess->mesh ); + if ( e == NULL ) { + tess->outOfMemory = 1; + return; + } + if ( !tessMeshSplice( tess->mesh, e, e->Sym ) ) { + tess->outOfMemory = 1; + return; + } + } else { + /* Create a new vertex and edge which immediately follow e + * in the ordering around the left face. + */ + if ( tessMeshSplitEdge( tess->mesh, e ) == NULL ) { + tess->outOfMemory = 1; + return; + } + e = e->Lnext; + } + + /* The new vertex is now e->Org. */ + e->Org->coords[0] = coords[0]; + e->Org->coords[1] = coords[1]; + if ( size > 2 ) + e->Org->coords[2] = coords[2]; + else + e->Org->coords[2] = 0; + /* Store the insertion number so that the vertex can be later recognized. */ + e->Org->idx = tess->vertexIndexCounter++; + + /* The winding of an edge says how the winding number changes as we + * cross from the edge''s right face to its left face. We add the + * vertices in such an order that a CCW contour will add +1 to + * the winding number of the region inside the contour. + */ + e->winding = 1; + e->Sym->winding = -1; + } +} + +int tessTesselate( TESStesselator *tess, int windingRule, int elementType, + int polySize, int vertexSize, const TESSreal* normal ) +{ + TESSmesh *mesh; + int rc = 1; + + if (tess->vertices != NULL) { + tess->alloc.memfree( tess->alloc.userData, tess->vertices ); + tess->vertices = 0; + } + if (tess->elements != NULL) { + tess->alloc.memfree( tess->alloc.userData, tess->elements ); + tess->elements = 0; + } + if (tess->vertexIndices != NULL) { + tess->alloc.memfree( tess->alloc.userData, tess->vertexIndices ); + tess->vertexIndices = 0; + } + + tess->vertexIndexCounter = 0; + + if (normal) + { + tess->normal[0] = normal[0]; + tess->normal[1] = normal[1]; + tess->normal[2] = normal[2]; + } + + tess->windingRule = windingRule; + + if (vertexSize < 2) + vertexSize = 2; + if (vertexSize > 3) + vertexSize = 3; + + if (setjmp(tess->env) != 0) { + /* come back here if out of memory */ + return 0; + } + + if (!tess->mesh) + { + return 0; + } + + /* Determine the polygon normal and project vertices onto the plane + * of the polygon. + */ + tessProjectPolygon( tess ); + + /* tessComputeInterior( tess ) computes the planar arrangement specified + * by the given contours, and further subdivides this arrangement + * into regions. Each region is marked "inside" if it belongs + * to the polygon, according to the rule given by tess->windingRule. + * Each interior region is guaranteed be monotone. + */ + if ( !tessComputeInterior( tess ) ) { + longjmp(tess->env,1); /* could've used a label */ + } + + mesh = tess->mesh; + + /* If the user wants only the boundary contours, we throw away all edges + * except those which separate the interior from the exterior. + * Otherwise we tessellate all the regions marked "inside". + */ + if (elementType == TESS_BOUNDARY_CONTOURS) { + rc = tessMeshSetWindingNumber( mesh, 1, TRUE ); + } else { + rc = tessMeshTessellateInterior( mesh ); + if (elementType == TESS_CONSTRAINED_DELAUNAY_TRIANGLES) { + rc = tessMeshRefineDelaunay( mesh, &tess->alloc ); + elementType = TESS_POLYGONS; + polySize = 3; + } + } + if (rc == 0) longjmp(tess->env,1); /* could've used a label */ + + tessMeshCheckMesh( mesh ); + + if (elementType == TESS_BOUNDARY_CONTOURS) { + OutputContours( tess, mesh, vertexSize ); /* output contours */ + } + else + { + OutputPolymesh( tess, mesh, elementType, polySize, vertexSize ); /* output polygons */ + } + + tessMeshDeleteMesh( &tess->alloc, mesh ); + tess->mesh = NULL; + + if (tess->outOfMemory) + return 0; + return 1; +} + +int tessGetVertexCount( TESStesselator *tess ) +{ + return tess->vertexCount; +} + +const TESSreal* tessGetVertices( TESStesselator *tess ) +{ + return tess->vertices; +} + +const TESSindex* tessGetVertexIndices( TESStesselator *tess ) +{ + return tess->vertexIndices; +} + +int tessGetElementCount( TESStesselator *tess ) +{ + return tess->elementCount; +} + +const int* tessGetElements( TESStesselator *tess ) +{ + return tess->elements; +} diff --git a/src/libtess2/Source/tess.h b/src/libtess2/Source/tess.h new file mode 100755 index 00000000..c8c747bf --- /dev/null +++ b/src/libtess2/Source/tess.h @@ -0,0 +1,90 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#ifndef TESS_H +#define TESS_H + +#include +#include "bucketalloc.h" +#include "mesh.h" +#include "dict.h" +#include "priorityq.h" +#include "../Include/tesselator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//typedef struct TESStesselator TESStesselator; + +struct TESStesselator { + + /*** state needed for collecting the input data ***/ + TESSmesh *mesh; /* stores the input contours, and eventually + the tessellation itself */ + int outOfMemory; + + /*** state needed for projecting onto the sweep plane ***/ + + TESSreal normal[3]; /* user-specified normal (if provided) */ + TESSreal sUnit[3]; /* unit vector in s-direction (debugging) */ + TESSreal tUnit[3]; /* unit vector in t-direction (debugging) */ + + TESSreal bmin[2]; + TESSreal bmax[2]; + + /*** state needed for the line sweep ***/ + int windingRule; /* rule for determining polygon interior */ + + Dict *dict; /* edge dictionary for sweep line */ + PriorityQ *pq; /* priority queue of vertex events */ + TESSvertex *event; /* current sweep event being processed */ + + struct BucketAlloc* regionPool; + + TESSindex vertexIndexCounter; + + TESSreal *vertices; + TESSindex *vertexIndices; + int vertexCount; + TESSindex *elements; + int elementCount; + + TESSalloc alloc; + + jmp_buf env; /* place to jump to when memAllocs fail */ +}; + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/src/linalg.h b/src/linalg.h index 9e7d9f94..54fd1235 100644 --- a/src/linalg.h +++ b/src/linalg.h @@ -9,6 +9,10 @@ EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector2d) using Eigen::Vector2d; EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector3d) using Eigen::Vector3d; +EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector3f) +using Eigen::Vector3f; +EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector3i) +using Eigen::Vector3i; typedef Eigen::AlignedBox BoundingBox; using Eigen::Matrix3f; @@ -17,9 +21,6 @@ using Eigen::Matrix4d; #define Transform3d Eigen::Affine3d #define Transform2d Eigen::Affine2d -typedef std::vector Polygon; -typedef std::vector Polygons; - bool matrix_contains_infinity( const Transform3d &m ); bool matrix_contains_nan( const Transform3d &m ); diff --git a/src/linearextrude.cc b/src/linearextrude.cc index e535c28d..cddbc314 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -75,7 +75,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI ValuePtr slices = c.lookup_variable("slices", true); if (!file->isUndefined() && file->type() == Value::STRING) { - printDeprecation("DEPRECATED: Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead."); + printDeprecation("Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead."); node->filename = lookup_file(file->toString(), inst->path(), c.documentPath()); } diff --git a/src/mainwin.cc b/src/mainwin.cc index 67bc93a8..5bea5e12 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -128,7 +128,7 @@ QSet *MainWindow::getWindows() unsigned int GuiLocker::gui_locked = 0; static char copyrighttext[] = - "Copyright (C) 2009-2014 The OpenSCAD Developers\n" + "Copyright (C) 2009-2015 The OpenSCAD Developers\n" "\n" "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 " @@ -170,6 +170,8 @@ bool MainWindow::mdiMode = false; bool MainWindow::undockMode = false; bool MainWindow::reorderMode = false; +QProgressDialog *MainWindow::fontCacheDialog = NULL; + MainWindow::MainWindow(const QString &filename) : root_inst("group"), library_info_dialog(NULL), font_list_dialog(NULL), tempFile(NULL), progresswidget(NULL), contentschanged(false) { @@ -256,7 +258,7 @@ MainWindow::MainWindow(const QString &filename) knownFileExtensions["scad"] = ""; knownFileExtensions["csg"] = ""; - editActionZoomIn->setShortcuts(QList() << editActionZoomIn->shortcuts() << QKeySequence("CTRL+=")); + editActionZoomTextIn->setShortcuts(QList() << editActionZoomTextIn->shortcuts() << QKeySequence("CTRL+=")); connect(this, SIGNAL(highlightError(int)), editor, SLOT(highlightError(int))); connect(this, SIGNAL(unhighlightLastError()), editor, SLOT(unhighlightLastError())); @@ -282,6 +284,9 @@ MainWindow::MainWindow(const QString &filename) animate_panel->hide(); find_panel->hide(); + frameCompileResult->hide(); + this->labelCompileResultMessage->setOpenExternalLinks(false); + connect(this->labelCompileResultMessage, SIGNAL(linkActivated(QString)), SLOT(showConsole())); // File menu connect(this->fileActionNew, SIGNAL(triggered()), this, SLOT(actionNew())); @@ -327,8 +332,8 @@ MainWindow::MainWindow(const QString &filename) connect(this->editActionConvertTabsToSpaces, SIGNAL(triggered()), this, SLOT(convertTabsToSpaces())); connect(this->editActionPasteVPT, SIGNAL(triggered()), this, SLOT(pasteViewportTranslation())); connect(this->editActionPasteVPR, SIGNAL(triggered()), this, SLOT(pasteViewportRotation())); - connect(this->editActionZoomIn, SIGNAL(triggered()), editor, SLOT(zoomIn())); - connect(this->editActionZoomOut, SIGNAL(triggered()), editor, SLOT(zoomOut())); + connect(this->editActionZoomTextIn, SIGNAL(triggered()), editor, SLOT(zoomIn())); + connect(this->editActionZoomTextOut, SIGNAL(triggered()), editor, SLOT(zoomOut())); connect(this->editActionPreferences, SIGNAL(triggered()), this, SLOT(preferences())); // Edit->Find connect(this->editActionFind, SIGNAL(triggered()), this, SLOT(find())); @@ -350,13 +355,13 @@ MainWindow::MainWindow(const QString &filename) connect(this->designActionDisplayAST, SIGNAL(triggered()), this, SLOT(actionDisplayAST())); connect(this->designActionDisplayCSGTree, SIGNAL(triggered()), this, SLOT(actionDisplayCSGTree())); connect(this->designActionDisplayCSGProducts, SIGNAL(triggered()), this, SLOT(actionDisplayCSGProducts())); - connect(this->designActionExportSTL, SIGNAL(triggered()), this, SLOT(actionExportSTL())); - connect(this->designActionExportOFF, SIGNAL(triggered()), this, SLOT(actionExportOFF())); - connect(this->designActionExportAMF, SIGNAL(triggered()), this, SLOT(actionExportAMF())); - connect(this->designActionExportDXF, SIGNAL(triggered()), this, SLOT(actionExportDXF())); - connect(this->designActionExportSVG, SIGNAL(triggered()), this, SLOT(actionExportSVG())); - connect(this->designActionExportCSG, SIGNAL(triggered()), this, SLOT(actionExportCSG())); - connect(this->designActionExportImage, SIGNAL(triggered()), this, SLOT(actionExportImage())); + connect(this->fileActionExportSTL, SIGNAL(triggered()), this, SLOT(actionExportSTL())); + connect(this->fileActionExportOFF, SIGNAL(triggered()), this, SLOT(actionExportOFF())); + connect(this->fileActionExportAMF, SIGNAL(triggered()), this, SLOT(actionExportAMF())); + connect(this->fileActionExportDXF, SIGNAL(triggered()), this, SLOT(actionExportDXF())); + connect(this->fileActionExportSVG, SIGNAL(triggered()), this, SLOT(actionExportSVG())); + connect(this->fileActionExportCSG, SIGNAL(triggered()), this, SLOT(actionExportCSG())); + connect(this->fileActionExportImage, SIGNAL(triggered()), this, SLOT(actionExportImage())); connect(this->designActionFlushCaches, SIGNAL(triggered()), this, SLOT(actionFlushCaches())); // View menu @@ -380,6 +385,7 @@ MainWindow::MainWindow(const QString &filename) connect(this->viewActionShowEdges, SIGNAL(triggered()), this, SLOT(viewModeShowEdges())); connect(this->viewActionShowAxes, SIGNAL(triggered()), this, SLOT(viewModeShowAxes())); connect(this->viewActionShowCrosshairs, SIGNAL(triggered()), this, SLOT(viewModeShowCrosshairs())); + connect(this->viewActionShowScaleProportional, SIGNAL(triggered()), this, SLOT(viewModeShowScaleProportional())); connect(this->viewActionAnimate, SIGNAL(triggered()), this, SLOT(viewModeAnimate())); connect(this->viewActionTop, SIGNAL(triggered()), this, SLOT(viewAngleTop())); connect(this->viewActionBottom, SIGNAL(triggered()), this, SLOT(viewAngleBottom())); @@ -403,6 +409,7 @@ MainWindow::MainWindow(const QString &filename) connect(this->helpActionAbout, SIGNAL(triggered()), this, SLOT(helpAbout())); connect(this->helpActionHomepage, SIGNAL(triggered()), this, SLOT(helpHomepage())); connect(this->helpActionManual, SIGNAL(triggered()), this, SLOT(helpManual())); + connect(this->helpActionCheatSheet, SIGNAL(triggered()), this, SLOT(helpCheatSheet())); connect(this->helpActionLibraryInfo, SIGNAL(triggered()), this, SLOT(helpLibrary())); connect(this->helpActionFontInfo, SIGNAL(triggered()), this, SLOT(helpFontInfo())); @@ -469,60 +476,43 @@ MainWindow::MainWindow(const QString &filename) addKeyboardShortCut(this->viewerToolBar->actions()); addKeyboardShortCut(this->editortoolbar->actions()); - //Toolbar - int defaultcolor = viewerToolBar->palette().background().color().lightness(); - - if (defaultcolor > 165) { - fileActionNew->setIcon(QIcon("://images/blackNew.png")); - fileActionOpen->setIcon(QIcon("://images/Open-32.png")); - fileActionSave->setIcon(QIcon("://images/Save-32.png")); - editActionZoomIn->setIcon(QIcon("://images/zoomin.png")); - editActionZoomOut->setIcon(QIcon("://images/zoomout.png")); - designActionRender->setIcon(QIcon("://images/blackRender.png")); - viewActionShowAxes->setIcon(QIcon("://images/blackaxes.png")); - viewActionShowEdges->setIcon(QIcon("://images/Rotation-32.png")); - viewActionZoomIn->setIcon(QIcon("://images/zoomin.png")); - viewActionZoomOut->setIcon(QIcon("://images/zoomout.png")); - viewActionTop->setIcon(QIcon("://images/blackUp.png")); - viewActionBottom->setIcon(QIcon("://images/blackbottom.png")); - viewActionLeft->setIcon(QIcon("://images/blackleft (copy).png")); - viewActionRight->setIcon(QIcon("://images/rightright.png")); - viewActionFront->setIcon(QIcon("://images/blackfront.png")); - viewActionBack->setIcon(QIcon("://images/blackback.png")); - viewActionSurfaces->setIcon(QIcon("://images/surface.png")); - viewActionWireframe->setIcon(QIcon("://images/wireframe1.png")); - viewActionShowCrosshairs->setIcon(QIcon("://images/cross.png")); - viewActionPerspective->setIcon(QIcon("://images/perspective1.png")); - viewActionOrthogonal->setIcon(QIcon("://images/orthogonal.png")); - viewActionPreview->setIcon(QIcon("://images/Preview-32.png")); - viewActionAnimate->setIcon(QIcon("://images/animate.png")); - } else { - fileActionNew->setIcon(QIcon("://images/Document-New-128.png")); - fileActionOpen->setIcon(QIcon("://images/Open-128.png")); - fileActionSave->setIcon(QIcon("://images/Save-128.png")); - editActionZoomIn->setIcon(QIcon("://images/Zoom-In-32.png")); - editActionZoomOut->setIcon(QIcon("://images/Zoom-Out-32.png")); - designActionRender->setIcon(QIcon("://images/Arrowhead-Right-32.png")); - viewActionZoomIn->setIcon(QIcon("://images/Zoom-In-32.png")); - viewActionZoomOut->setIcon(QIcon("://images/Zoom-Out-32.png")); - viewActionShowAxes->setIcon(QIcon("://images/axes.png")); - viewActionShowEdges->setIcon(QIcon("://images/grid.png")); - viewActionTop->setIcon(QIcon("://images/up.png")); - viewActionBottom->setIcon(QIcon("://images/bottom.png")); - viewActionLeft->setIcon(QIcon("://images/left.png")); - viewActionRight->setIcon(QIcon("://images/right.png")); - viewActionFront->setIcon(QIcon("://images/front.png")); - viewActionBack->setIcon(QIcon("://images/back.png")); - viewActionSurfaces->setIcon(QIcon("://images/surfaceWhite.png")); - viewActionWireframe->setIcon(QIcon("://images/wireframeWhite.png")); - viewActionShowCrosshairs->setIcon(QIcon("://images/crosswhite.png")); - viewActionPreview->setIcon(QIcon("://images/Preview-32(1).png")); - viewActionPerspective->setIcon(QIcon("://images/perspective1white.png")); - viewActionOrthogonal->setIcon(QIcon("://images/orthogonalwhite.png")); - viewActionAnimate->setIcon(QIcon("://images/animate.png")); - designActionExportSTL->setIcon(QIcon(":/images/export-white.png")); - viewActionViewAll->setIcon(QIcon(":/images/zoom-all-white.png")); - } + initActionIcon(fileActionNew, ":/images/blackNew.png", ":/images/Document-New-128.png"); + initActionIcon(fileActionOpen, ":/images/Open-32.png", ":/images/Open-128.png"); + initActionIcon(fileActionSave, ":/images/Save-32.png", ":/images/Save-128.png"); + initActionIcon(editActionZoomTextIn, ":/images/zoom-text-in.png", ":/images/zoom-text-in-white.png"); + initActionIcon(editActionZoomTextOut, ":/images/zoom-text-out.png", ":/images/zoom-text-out-white.png"); + initActionIcon(designActionRender, ":/images/render-32.png", ":/images/render-32-white.png"); + initActionIcon(viewActionShowAxes, ":/images/blackaxes.png", ":/images/axes.png"); + initActionIcon(viewActionShowEdges, ":/images/Rotation-32.png", ":/images/grid.png"); + initActionIcon(viewActionZoomIn, ":/images/zoomin.png", ":/images/Zoom-In-32.png"); + initActionIcon(viewActionZoomOut, ":/images/zoomout.png", ":/images/Zoom-Out-32.png"); + initActionIcon(viewActionTop, ":/images/blackUp.png", ":/images/up.png"); + initActionIcon(viewActionBottom, ":/images/blackbottom.png", ":/images/bottom.png"); + initActionIcon(viewActionLeft, ":/images/blackleft (copy).png", ":/images/left.png"); + initActionIcon(viewActionRight, ":/images/rightright.png", ":/images/right.png"); + initActionIcon(viewActionFront, ":/images/blackfront.png", ":/images/front.png"); + initActionIcon(viewActionBack, ":/images/blackback.png", ":/images/back.png"); + initActionIcon(viewActionSurfaces, ":/images/surface.png", ":/images/surfaceWhite.png"); + initActionIcon(viewActionWireframe, ":/images/wireframe1.png", ":/images/wireframeWhite.png"); + initActionIcon(viewActionShowCrosshairs, ":/images/cross.png", ":/images/crosswhite.png"); + initActionIcon(viewActionPerspective, ":/images/perspective1.png", ":/images/perspective1white.png"); + initActionIcon(viewActionOrthogonal, ":/images/orthogonal.png", ":/images/orthogonalwhite.png"); + initActionIcon(designActionPreview, ":/images/preview-32.png", ":/images/preview-32-white.png"); + initActionIcon(viewActionAnimate, ":/images/animate.png", ":/images/animate.png"); + initActionIcon(fileActionExportSTL, ":/images/STL.png", ":/images/STL-white.png"); + initActionIcon(fileActionExportAMF, ":/images/AMF.png", ":/images/AMF-white.png"); + initActionIcon(fileActionExportOFF, ":/images/OFF.png", ":/images/OFF-white.png"); + initActionIcon(fileActionExportDXF, ":/images/DXF.png", ":/images/DXF-white.png"); + initActionIcon(fileActionExportSVG, ":/images/SVG.png", ":/images/SVG-white.png"); + initActionIcon(fileActionExportCSG, ":/images/CSG.png", ":/images/CSG-white.png"); + initActionIcon(fileActionExportImage, ":/images/PNG.png", ":/images/PNG-white.png"); + initActionIcon(viewActionViewAll, ":/images/zoom-all.png", ":/images/zoom-all-white.png"); + initActionIcon(editActionUndo, ":/images/Command-Undo-32.png", ":/images/Command-Undo-32-white.png"); + initActionIcon(editActionRedo, ":/images/Command-Redo-32.png", ":/images/Command-Redo-32-white.png"); + initActionIcon(editActionUnindent, ":/images/Decrease-Indent-32.png", ":/images/Decrease-Indent-32-white.png"); + initActionIcon(editActionIndent, ":/images/Increase-Indent-32.png", ":/images/Increase-Indent-32-white.png"); + initActionIcon(viewActionResetView, ":/images/Command-Reset-32.png", ":/images/Command-Reset-32-white.png"); + initActionIcon(viewActionShowScaleProportional, ":/images/scalemarkers.png", ":/images/scalemarkers-white.png"); // make sure it looks nice.. QByteArray windowState = settings.value("window/state", QByteArray()).toByteArray(); @@ -583,6 +573,13 @@ MainWindow::MainWindow(const QString &filename) clearCurrentOutput(); } +void MainWindow::initActionIcon(QAction *action, const char *darkResource, const char *lightResource) +{ + int defaultcolor = viewerToolBar->palette().background().color().lightness(); + const char *resource = (defaultcolor > 165) ? darkResource : lightResource; + action->setIcon(QIcon(resource)); +} + void MainWindow::addKeyboardShortCut(const QList &actions) { foreach (QAction *action, actions) { @@ -607,7 +604,7 @@ void MainWindow::loadViewSettings(){ viewActionShowEdges->setChecked(true); viewModeShowEdges(); } - if (settings.value("view/showAxes").toBool()) { + if (settings.value("view/showAxes", true).toBool()) { viewActionShowAxes->setChecked(true); viewModeShowAxes(); } @@ -615,6 +612,10 @@ void MainWindow::loadViewSettings(){ viewActionShowCrosshairs->setChecked(true); viewModeShowCrosshairs(); } + if (settings.value("view/showScaleProportional", true).toBool()) { + viewActionShowScaleProportional->setChecked(true); + viewModeShowScaleProportional(); + } if (settings.value("view/orthogonalProjection").toBool()) { viewOrthogonal(); } else { @@ -634,7 +635,7 @@ void MainWindow::loadViewSettings(){ void MainWindow::loadDesignSettings() { QSettings settings; - if (settings.value("design/autoReload").toBool()) { + if (settings.value("design/autoReload", true).toBool()) { designActionAutoReload->setChecked(true); } uint polySetCacheSize = Preferences::inst()->getValue("advanced/polysetCacheSize").toUInt(); @@ -692,7 +693,7 @@ MainWindow::~MainWindow() if (MainWindow::getWindows()->size() == 0) { // Quit application even in case some other windows like // Preferences are still open. - qApp->quit(); + this->quit(); } } @@ -873,6 +874,9 @@ void MainWindow::compile(bool reload, bool forcedone) bool shouldcompiletoplevel = false; bool didcompile = false; + compileErrors = 0; + compileWarnings = 0; + this->renderingTime.start(); // Reload checks the timestamp of the toplevel file and refreshes if necessary, @@ -946,12 +950,55 @@ void MainWindow::waitAfterReload() } } +void MainWindow::on_toolButtonCompileResultClose_clicked() +{ + frameCompileResult->hide(); +} + +void MainWindow::updateCompileResult() +{ + if ((compileErrors == 0) && (compileWarnings == 0)) { + frameCompileResult->hide(); + return; + } + + Settings::Settings *s = Settings::Settings::inst(); + if (!s->get(Settings::Settings::showWarningsIn3dView).toBool()) { + return; + } + + QString msg; + if (compileErrors > 0) { + if (fileName.isEmpty()) { + msg = QString(_("Compile error.")); + } else { + QFileInfo fileInfo(fileName); + msg = QString(_("Error while compiling '%1'.")).arg(fileInfo.fileName()); + } + toolButtonCompileResultIcon->setIcon(QIcon(QString::fromUtf8(":/icons/information-icons-error.png"))); + } else { + const char *fmt = ngettext("Compilation generated %1 warning.", "Compilation generated %1 warnings.", compileWarnings); + msg = QString(fmt).arg(compileWarnings); + toolButtonCompileResultIcon->setIcon(QIcon(QString::fromUtf8(":/icons/information-icons-warning.png"))); + } + QFontMetrics fm(labelCompileResultMessage->font()); + int sizeIcon = std::max(12, std::min(32, fm.height())); + int sizeClose = std::max(10, std::min(32, fm.height()) - 4); + toolButtonCompileResultIcon->setIconSize(QSize(sizeIcon, sizeIcon)); + toolButtonCompileResultClose->setIconSize(QSize(sizeClose, sizeClose)); + + msg += _(" For details see console window."); + labelCompileResultMessage->setText(msg); + frameCompileResult->show(); +} + void MainWindow::compileDone(bool didchange) { const char *callslot; if (didchange) { instantiateRoot(); updateCamera(); + updateCompileResult(); callslot = afterCompileSlot; } else { @@ -1711,6 +1758,8 @@ void MainWindow::csgRender() } if (viewActionAnimate->isChecked() && e_dump->isChecked()) { + // Force reading from front buffer. Some configurations will read from the back buffer here. + glReadBuffer(GL_FRONT); QImage img = this->qglview->grabFrameBuffer(); QString filename; double s = this->e_fsteps->text().toDouble(); @@ -1776,14 +1825,18 @@ void MainWindow::actionRenderDone(shared_ptr root_geom) if (root_geom && !root_geom->isEmpty()) { if (const CGAL_Nef_polyhedron *N = dynamic_cast(root_geom.get())) { if (N->getDimension() == 3) { + bool simple = N->p3->is_simple(); PRINT(" Top level object is a 3D object:"); - PRINTB(" Simple: %6s", (N->p3->is_simple() ? "yes" : "no")); + PRINTB(" Simple: %6s", (simple ? "yes" : "no")); PRINTB(" Vertices: %6d", N->p3->number_of_vertices()); PRINTB(" Halfedges: %6d", N->p3->number_of_halfedges()); PRINTB(" Edges: %6d", N->p3->number_of_edges()); PRINTB(" Halffacets: %6d", N->p3->number_of_halffacets()); PRINTB(" Facets: %6d", N->p3->number_of_facets()); PRINTB(" Volumes: %6d", N->p3->number_of_volumes()); + if (!simple) { + PRINT("WARNING: Object may not be a valid 2-manifold and may need repair!"); + } } } else if (const PolySet *ps = dynamic_cast(root_geom.get())) { @@ -1950,7 +2003,7 @@ void MainWindow::actionExport(export_type_e, QString, QString) setCurrentOutput(); if (!this->root_geom) { - PRINT("Nothing to export! Try building first (press F6)."); + PRINT("WARNING: Nothing to export! Try building first (press F6)."); clearCurrentOutput(); return; } @@ -1989,7 +2042,6 @@ void MainWindow::actionExport(export_type_e, QString, QString) QString filename = this->fileName.isEmpty() ? QString(_("Untitled")) + suffix : QFileInfo(this->fileName).baseName() + suffix; QString export_filename = QFileDialog::getSaveFileName(this, title, filename, filter); if (export_filename.isEmpty()) { - PRINTB("No filename specified. %s export aborted.", type_name); clearCurrentOutput(); return; } @@ -2030,13 +2082,13 @@ QString MainWindow::get2dExportFilename(QString format, QString extension) { setCurrentOutput(); if (!this->root_geom) { - PRINT("Nothing to export! Try building first (press F6)."); + PRINT("WARNING: Nothing to export! Try building first (press F6)."); clearCurrentOutput(); return QString(); } if (this->root_geom->getDimension() != 2) { - PRINT("Current top level object is not a 2D object."); + PRINT("WARNING: Current top level object is not a 2D object."); clearCurrentOutput(); return QString(); } @@ -2089,7 +2141,7 @@ void MainWindow::actionExportCSG() setCurrentOutput(); if (!this->root_node) { - PRINT("Nothing to export. Please try compiling first..."); + PRINT("WARNING: Nothing to export. Please try compiling first..."); clearCurrentOutput(); return; } @@ -2232,6 +2284,14 @@ void MainWindow::viewModeShowCrosshairs() this->qglview->updateGL(); } +void MainWindow::viewModeShowScaleProportional() +{ + QSettings settings; + settings.setValue("view/showScaleProportional",viewActionShowScaleProportional->isChecked()); + this->qglview->setShowScaleProportional(viewActionShowScaleProportional->isChecked()); + this->qglview->updateGL(); +} + void MainWindow::viewModeAnimate() { if (viewActionAnimate->isChecked()) { @@ -2399,8 +2459,14 @@ void MainWindow::hideEditor() } } -void MainWindow::hideConsole() +void MainWindow::showConsole() +{ + viewActionHideConsole->setChecked(false); + consoleDock->show(); + frameCompileResult->hide(); +} +void MainWindow::hideConsole() { if (viewActionHideConsole->isChecked()) { consoleDock->hide(); @@ -2460,6 +2526,11 @@ void MainWindow::helpManual() UIUtils::openUserManualURL(); } +void MainWindow::helpCheatSheet() +{ + UIUtils::openCheatSheetURL(); +} + void MainWindow::helpLibrary() { if (!this->library_info_dialog) { @@ -2567,17 +2638,30 @@ void MainWindow::quit() void MainWindow::consoleOutput(const std::string &msg, void *userdata) { - // Invoke the append function in the main thread in case the output + // Invoke the method in the main thread in case the output // originates in a worker thread. MainWindow *thisp = static_cast(userdata); - QString qmsg = QString::fromUtf8(msg.c_str()); - if (qmsg.startsWith("WARNING:")) { - qmsg = "" + qmsg + ""; - } else if (qmsg.startsWith("ERROR:")) { - qmsg = "" + qmsg + ""; + QMetaObject::invokeMethod(thisp, "consoleOutput", Q_ARG(QString, QString::fromStdString(msg))); +} + +void MainWindow::consoleOutput(const QString &msg) +{ + QString qmsg; + if (msg.startsWith("WARNING:") || msg.startsWith("DEPRECATED:")) { + this->compileWarnings++; + qmsg = "" + msg + "\n"; + } else if (msg.startsWith("ERROR:")) { + this->compileErrors++; + qmsg = "" + msg + "\n"; } - QMetaObject::invokeMethod(thisp->console, "append", Qt::QueuedConnection, Q_ARG(QString, qmsg)); - if (thisp->procevents) QApplication::processEvents(); + else { + qmsg = msg; + } + QTextCursor c = this->console->textCursor(); + c.movePosition(QTextCursor::End); + this->console->setTextCursor(c); + this->console->append(qmsg); + if (this->procevents) QApplication::processEvents(); } void MainWindow::setCurrentOutput() @@ -2602,3 +2686,21 @@ void MainWindow::setContentsChanged() { this->contentschanged = true; } + +void MainWindow::showFontCacheDialog() +{ + if (!MainWindow::fontCacheDialog) MainWindow::fontCacheDialog = new QProgressDialog; + QProgressDialog *dialog = MainWindow::fontCacheDialog; + + dialog->setLabelText(_("Fontconfig needs to update its font cache.\nThis can take up to a couple of minutes.")); + dialog->setMinimum(0); + dialog->setMaximum(0); + dialog->setCancelButton(0); + dialog->exec(); +} + +void MainWindow::hideFontCacheDialog() +{ + assert(MainWindow::fontCacheDialog); + MainWindow::fontCacheDialog->reset(); +} diff --git a/src/modcontext.cc b/src/modcontext.cc index 04d46e60..90f04700 100644 --- a/src/modcontext.cc +++ b/src/modcontext.cc @@ -116,7 +116,7 @@ const AbstractModule *ModuleContext::findLocalModule(const std::string &name) co } std::string replacement = Builtins::instance()->isDeprecated(name); if (!replacement.empty()) { - PRINT_DEPRECATION("DEPRECATED: The %s() module will be removed in future releases. Use %s instead.", name % replacement); + PRINT_DEPRECATION("The %s() module will be removed in future releases. Use %s instead.", name % replacement); } return m; } diff --git a/src/module.cc b/src/module.cc index 8cf6498e..715cd337 100644 --- a/src/module.cc +++ b/src/module.cc @@ -349,15 +349,16 @@ AbstractNode *FileModule::instantiate(const Context *ctx, const ModuleInstantiat delete context; context = new FileContext(*this, ctx); - context->initializeModule(*this); + AbstractNode *node = new AbstractNode(inst); + + try { + context->initializeModule(*this); // FIXME: Set document path to the path of the module #if 0 && DEBUG - c.dump(this, inst); + c.dump(this, inst); #endif - AbstractNode *node = new AbstractNode(inst); - try { std::vector instantiatednodes = this->scope.instantiateChildren(context); node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); } diff --git a/src/openscad.cc b/src/openscad.cc index ab7e3acf..0953ffdb 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -93,6 +93,8 @@ static std::string arg_colorscheme; #define QUOTE(x__) # x__ #define QUOTED(x__) QUOTE(x__) +std::string versionnumber = QUOTED(OPENSCAD_VERSION); + std::string openscad_versionnumber = QUOTED(OPENSCAD_VERSION) #ifdef OPENSCAD_COMMIT " (git " QUOTED(OPENSCAD_COMMIT) ")" @@ -461,7 +463,8 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c if (renderer == Render::CGAL && root_geom->getDimension() == 3) { const CGAL_Nef_polyhedron *N = dynamic_cast(root_geom.get()); if (!N) { - root_geom.reset(CGALUtils::createNefPolyhedronFromGeometry(*root_geom)); + N = CGALUtils::createNefPolyhedronFromGeometry(*root_geom); + root_geom.reset(N); PRINT("Converted to Nef polyhedron"); } } @@ -597,24 +600,23 @@ void dialogThreadFunc(FontCacheInitializer *initializer) void dialogInitHandler(FontCacheInitializer *initializer, void *) { - QProgressDialog dialog; - dialog.setLabelText(_("Fontconfig needs to update its font cache.\nThis can take up to a couple of minutes.")); - dialog.setMinimum(0); - dialog.setMaximum(0); - dialog.setCancelButton(0); + MainWindow *mainw = *MainWindow::getWindows()->begin(); QFutureWatcher futureWatcher; - QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset())); - QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel())); - QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int))); - QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int))); + QObject::connect(&futureWatcher, SIGNAL(finished()), mainw, SLOT(hideFontCacheDialog())); QFuture future = QtConcurrent::run(boost::bind(dialogThreadFunc, initializer)); futureWatcher.setFuture(future); - dialog.exec(); + // We don't always get the started() signal, so we start manually + QMetaObject::invokeMethod(mainw, "showFontCacheDialog"); + // Block, in case we're in a separate thread, or the dialog was closed by the user futureWatcher.waitForFinished(); + + // We don't always receive the finished signal. We still need the signal to break + // out of the exec() though. + QMetaObject::invokeMethod(mainw, "hideFontCacheDialog"); } int gui(vector &inputFiles, const fs::path &original_path, int argc, char ** argv) @@ -640,6 +642,7 @@ int gui(vector &inputFiles, const fs::path &original_path, int argc, cha QCoreApplication::setApplicationVersion(TOSTRING(OPENSCAD_VERSION)); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) QGuiApplication::setApplicationDisplayName("OpenSCAD"); + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #else QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); #endif @@ -663,6 +666,12 @@ int gui(vector &inputFiles, const fs::path &original_path, int argc, cha installAppleEventHandlers(); #endif +#ifdef Q_OS_WIN + QSettings reg_setting(QLatin1String("HKEY_CURRENT_USER"), QSettings::NativeFormat); + QString appPath = QDir::toNativeSeparators(app.applicationFilePath() + QLatin1String(",1")); + reg_setting.setValue(QLatin1String("Software/Classes/OpenSCAD_File/DefaultIcon/Default"),QVariant(appPath)); +#endif + #ifdef OPENSCAD_UPDATER AutoUpdater *updater = new SparkleAutoUpdater; AutoUpdater::setUpdater(updater); @@ -830,12 +839,12 @@ int main(int argc, char **argv) output_file = vm["o"].as().c_str(); } if (vm.count("s")) { - printDeprecation("DEPRECATED: The -s option is deprecated. Use -o instead.\n"); + printDeprecation("The -s option is deprecated. Use -o instead.\n"); if (output_file) help(argv[0], true); output_file = vm["s"].as().c_str(); } if (vm.count("x")) { - printDeprecation("DEPRECATED: The -x option is deprecated. Use -o instead.\n"); + printDeprecation("The -x option is deprecated. Use -o instead.\n"); if (output_file) help(argv[0], true); output_file = vm["x"].as().c_str(); } @@ -900,4 +909,3 @@ int main(int argc, char **argv) return rc; } - diff --git a/src/openscad.h b/src/openscad.h index f37f0253..04f530ed 100644 --- a/src/openscad.h +++ b/src/openscad.h @@ -35,6 +35,7 @@ extern std::string commandline_commands; // doing this, use currentdir to get the original CWD. extern std::string currentdir; +// Version number without the git suffix. extern std::string versionnumber; // Just the number (might have the git commit as suffix), e.g. 2014.12.23. diff --git a/src/parser.y b/src/parser.y index 73c07504..1600e7c9 100644 --- a/src/parser.y +++ b/src/parser.y @@ -560,7 +560,7 @@ int parserlex(void) void yyerror (char const *s) { // FIXME: We leak memory on parser errors... - PRINTB("Parser error in line %d: %s\n", lexerget_lineno() % s); + PRINTB("ERROR: Parser error in line %d: %s\n", lexerget_lineno() % s); } FileModule *parse(const char *text, const char *path, int debug) diff --git a/src/polyset-utils.cc b/src/polyset-utils.cc index b3bba6d7..af31188e 100644 --- a/src/polyset-utils.cc +++ b/src/polyset-utils.cc @@ -2,6 +2,7 @@ #include "polyset.h" #include "Polygon2d.h" #include "printutils.h" +#include "GeometryUtils.h" #ifdef ENABLE_CGAL #include "cgalutils.h" #endif @@ -47,41 +48,30 @@ namespace PolysetUtils { The tessellation will be robust wrt. degenerate and self-intersecting */ void tessellate_faces(const PolySet &inps, PolySet &outps) { -#ifdef ENABLE_CGAL int degeneratePolygons = 0; for (size_t i = 0; i < inps.polygons.size(); i++) { - const Polygon pgon = inps.polygons[i]; + const Polygon &pgon = inps.polygons[i]; if (pgon.size() < 3) { degeneratePolygons++; - continue; - } - std::vector triangles; - if (pgon.size() == 3) { - triangles.push_back(pgon); } else { - // Build a data structure that CGAL accepts - PolygonK cgalpoints; - BOOST_FOREACH(const Vector3d &v, pgon) { - cgalpoints.push_back(Vertex3K(v[0], v[1], v[2])); + Polygons triangles; + bool err = GeometryUtils::tessellatePolygon(pgon, triangles); + // Empty triangles tend to happen quite often, + // probably due to previous floating point conversion, so + // we don't issue any warnings. + if (!triangles.empty()) { + // ..and pass to the output polyhedron + BOOST_FOREACH(const Polygon &t, triangles) { + outps.append_poly(); + outps.append_vertex(t[0]); + outps.append_vertex(t[1]); + outps.append_vertex(t[2]); + } } - - bool err = CGALUtils::tessellatePolygon(cgalpoints, triangles); - } - - // ..and pass to the output polyhedron - for (size_t j=0;j 0) PRINT("WARNING: PolySet has degenerate polygons"); -#else - assert(false); -#endif } bool is_approximately_convex(const PolySet &ps) { diff --git a/src/polyset.cc b/src/polyset.cc index ec31cd19..1ed10999 100644 --- a/src/polyset.cc +++ b/src/polyset.cc @@ -92,21 +92,31 @@ void PolySet::append_vertex(double x, double y, double z) append_vertex(Vector3d(x, y, z)); } -void PolySet::append_vertex(Vector3d v) +void PolySet::append_vertex(const Vector3d &v) { polygons.back().push_back(v); } +void PolySet::append_vertex(const Vector3f &v) +{ + polygons.back().push_back(v.cast()); +} + void PolySet::insert_vertex(double x, double y, double z) { insert_vertex(Vector3d(x, y, z)); } -void PolySet::insert_vertex(Vector3d v) +void PolySet::insert_vertex(const Vector3d &v) { polygons.back().insert(polygons.back().begin(), v); } +void PolySet::insert_vertex(const Vector3f &v) +{ + polygons.back().insert(polygons.back().begin(), v.cast()); +} + BoundingBox PolySet::getBoundingBox() const { BoundingBox bbox; @@ -136,10 +146,14 @@ void PolySet::append(const PolySet &ps) void PolySet::transform(const Transform3d &mat) { + // If mirroring transform, flip faces to avoid the object to end up being inside-out + bool mirrored = mat.matrix().determinant() < 0; + BOOST_FOREACH(Polygon &p, this->polygons) { BOOST_FOREACH(Vector3d &v, p) { v = mat * v; } + if (mirrored) std::reverse(p.begin(), p.end()); } } @@ -176,13 +190,35 @@ void PolySet::resize(Vector3d newsize, const Eigen::Matrix &autosize) this->transform(t); } +/*! + Quantizes vertices by gridding them as well as merges close vertices belonging to + neighboring grids. + May reduce the number of polygons if polygons collapse into < 3 vertices. +*/ void PolySet::quantizeVertices() { Grid3d grid(GRID_FINE); - BOOST_FOREACH(Polygon &p, this->polygons) { - BOOST_FOREACH(Vector3d &v, p) { - // align v to the grid - if (!grid.has(v)) grid.align(v); + int numverts = 0; + std::vector indices; // Vertex indices in one polygon + for (std::vector::iterator iter = this->polygons.begin(); iter != this->polygons.end();) { + Polygon &p = *iter; + indices.resize(p.size()); + // Quantize all vertices. Build index list + for (int i=0;ipolygons.erase(iter); + } + else { + iter++; } } } diff --git a/src/polyset.h b/src/polyset.h index cf151dbe..ed865e85 100644 --- a/src/polyset.h +++ b/src/polyset.h @@ -3,6 +3,7 @@ #include "Geometry.h" #include "system-gl.h" #include "linalg.h" +#include "GeometryUtils.h" #include "renderer.h" #include "Polygon2d.h" #include @@ -31,9 +32,11 @@ public: size_t numPolygons() const { return polygons.size(); } void append_poly(); void append_vertex(double x, double y, double z = 0.0); - void append_vertex(Vector3d v); + void append_vertex(const Vector3d &v); + void append_vertex(const Vector3f &v); void insert_vertex(double x, double y, double z = 0.0); - void insert_vertex(Vector3d v); + void insert_vertex(const Vector3d &v); + void insert_vertex(const Vector3f &v); void append(const PolySet &ps); void render_surface(Renderer::csgmode_e csgmode, const Transform3d &m, GLint *shaderinfo = NULL) const; diff --git a/src/primitives.cc b/src/primitives.cc index 5381db8c..0727c7aa 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -245,7 +245,7 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta // backwards compatible node->faces = c.lookup_variable("triangles", true); if (node->faces->type() != Value::UNDEFINED) { - printDeprecation("DEPRECATED: polyhedron(triangles=[]) will be removed in future releases. Use polyhedron(faces=[]) instead."); + printDeprecation("polyhedron(triangles=[]) will be removed in future releases. Use polyhedron(faces=[]) instead."); } } break; diff --git a/src/printutils.cc b/src/printutils.cc index 4e400ccb..ef1ace95 100644 --- a/src/printutils.cc +++ b/src/printutils.cc @@ -83,7 +83,7 @@ void PRINTDEBUG(const std::string &filename, const std::string &msg) boost::algorithm::to_lower( lowdebug ); if (OpenSCAD::debug=="all") { PRINT_NOCACHE( shortfname+": "+ msg ); - } else if (lowshortfname.find(lowdebug) != std::string::npos) { + } else if (lowdebug.find(lowshortfname) != std::string::npos) { PRINT_NOCACHE( shortfname+": "+ msg ); } } @@ -114,8 +114,9 @@ std::set printedDeprecations; void printDeprecation(const std::string &str) { if (printedDeprecations.find(str) == printedDeprecations.end()) { - PRINT(str); printedDeprecations.insert(str); + std::string msg = "DEPRECATED: " + str; + PRINT(msg); } } diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc index 700fb7c9..bbe84905 100644 --- a/src/rotateextrude.cc +++ b/src/rotateextrude.cc @@ -69,7 +69,7 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI ValuePtr scale = c.lookup_variable("scale", true); if (!file->isUndefined()) { - printDeprecation("DEPRECATED: Support for reading files in rotate_extrude will be removed in future releases. Use a child import() instead."); + printDeprecation("Support for reading files in rotate_extrude will be removed in future releases. Use a child import() instead."); node->filename = lookup_file(file->toString(), inst->path(), c.documentPath()); } @@ -79,7 +79,7 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI node->scale = scale->toDouble(); if (node->convexity <= 0) - node->convexity = 1; + node->convexity = 2; if (node->scale <= 0) node->scale = 1; diff --git a/src/scintillaeditor.cpp b/src/scintillaeditor.cpp index 43f36f01..bf6bb9e0 100644 --- a/src/scintillaeditor.cpp +++ b/src/scintillaeditor.cpp @@ -307,14 +307,14 @@ void ScintillaEditor::setColormap(const EditorColorScheme *colorScheme) qsci->setWhitespaceForegroundColor(readColor(colors, "whitespace-foreground", textColor)); qsci->setMarginsBackgroundColor(readColor(colors, "margin-background", paperColor)); qsci->setMarginsForegroundColor(readColor(colors, "margin-foreground", textColor)); + qsci->setFoldMarginColors(readColor(colors, "margin-background", paperColor), + readColor(colors, "margin-background", paperColor)); qsci->setMatchedBraceBackgroundColor(readColor(colors, "matched-brace-background", paperColor)); qsci->setMatchedBraceForegroundColor(readColor(colors, "matched-brace-foreground", textColor)); qsci->setUnmatchedBraceBackgroundColor(readColor(colors, "unmatched-brace-background", paperColor)); qsci->setUnmatchedBraceForegroundColor(readColor(colors, "unmatched-brace-foreground", textColor)); qsci->setSelectionForegroundColor(readColor(colors, "selection-foreground", paperColor)); qsci->setSelectionBackgroundColor(readColor(colors, "selection-background", textColor)); - qsci->setFoldMarginColors(readColor(colors, "margin-foreground", textColor), - readColor(colors, "margin-background", paperColor)); qsci->setEdgeColor(readColor(colors, "edge", textColor)); } catch (std::exception e) { noColor(); @@ -331,7 +331,6 @@ void ScintillaEditor::noColor() qsci->setIndicatorForegroundColor(QColor(255, 0, 0, 128), indicatorNumber); qsci->setIndicatorOutlineColor(QColor(0, 0, 0, 255), indicatorNumber); // only alpha part is used qsci->setCaretLineBackgroundColor(Qt::white); - qsci->setWhitespaceBackgroundColor(Qt::white); qsci->setWhitespaceForegroundColor(Qt::black); qsci->setMarginsBackgroundColor(Qt::white); qsci->setMarginsForegroundColor(Qt::black); diff --git a/src/settings.cc b/src/settings.cc index 8af5fea3..99a4ec05 100644 --- a/src/settings.cc +++ b/src/settings.cc @@ -121,6 +121,7 @@ Visitor::~Visitor() * external settings file. The second value is the display value that * can be translated. */ +SettingsEntry Settings::showWarningsIn3dView("3dview", "showWarningsIn3dView", Value(true), Value(true)); SettingsEntry Settings::indentationWidth("editor", "indentationWidth", Value(Value::RangeType(1, 16)), Value(4)); SettingsEntry Settings::tabWidth("editor", "tabWidth", Value(Value::RangeType(1, 16)), Value(8)); SettingsEntry Settings::lineWrap("editor", "lineWrap", values("None", _("None"), "Char", _("Wrap at character boundaries"), "Word", _("Wrap at word boundaries")), Value("Word")); diff --git a/src/settings.h b/src/settings.h index a3099fe8..2864bb2c 100644 --- a/src/settings.h +++ b/src/settings.h @@ -35,6 +35,7 @@ protected: class Settings { public: + static SettingsEntry showWarningsIn3dView; static SettingsEntry indentationWidth; static SettingsEntry tabWidth; static SettingsEntry lineWrap; diff --git a/src/state.h b/src/state.h index 7739ed37..f396622a 100644 --- a/src/state.h +++ b/src/state.h @@ -7,7 +7,7 @@ class State { public: State(const class AbstractNode *parent) - : parentnode(parent), isprefix(false), ispostfix(false), numchildren(0) { + : parentnode(parent), isprefix(false), ispostfix(false), numchildren(0), prefernef(false) { this->matrix_ = Transform3d::Identity(); this->color_.fill(-1.0f); } @@ -19,6 +19,8 @@ public: void setParent(const AbstractNode *parent) { this->parentnode = parent; } void setMatrix(const Transform3d &m) { this->matrix_ = m; } void setColor(const Color4f &c) { this->color_ = c; } + void setPreferNef(bool on) { this->prefernef = on; } + bool preferNef() const { return this->prefernef; } bool isPrefix() const { return this->isprefix; } bool isPostfix() const { return this->ispostfix; } @@ -33,6 +35,7 @@ private: bool ispostfix; unsigned int numchildren; + bool prefernef; // Transformation matrix and color. FIXME: Generalize such state variables? Transform3d matrix_; Color4f color_; diff --git a/src/value.cc b/src/value.cc index 4723b611..f519948c 100644 --- a/src/value.cc +++ b/src/value.cc @@ -707,7 +707,7 @@ Value Value::operator[](const Value &v) const void Value::RangeType::normalize() { if ((step_val>0) && (end_val < begin_val)) { std::swap(begin_val,end_val); - printDeprecation("DEPRECATED: Using ranges of the form [begin:end] with begin value greater than the end value is deprecated."); + printDeprecation("Using ranges of the form [begin:end] with begin value greater than the end value is deprecated."); } } diff --git a/testdata/scad/3D/features/mirror-tests.scad b/testdata/scad/3D/features/mirror-tests.scad new file mode 100644 index 00000000..93f064bc --- /dev/null +++ b/testdata/scad/3D/features/mirror-tests.scad @@ -0,0 +1 @@ +render() mirror([1,0,0]) cube(); \ No newline at end of file diff --git a/testdata/scad/3D/features/polyhedron-concave-test.scad b/testdata/scad/3D/features/polyhedron-concave-test.scad new file mode 100644 index 00000000..11943f79 --- /dev/null +++ b/testdata/scad/3D/features/polyhedron-concave-test.scad @@ -0,0 +1,2 @@ +polyhedron(points = [[0, 0, 0], [2, 4, 0], [8, 4, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0], [0, 0, 5], [2, 4, 5], [8, 4, 5], [10, 0, 5], [10, 10, 5], [0, 10, 5]], faces = [[0, 1, 2, 3, 4, 5], [0, 6, 7], [0, 7, 1], [1, 7, 8], [1, 8, 2], [2, 8, 9], [2, 9, 3], [3, 9, 10], [3, 10, 4], [4, 10, 11], [4, 11, 5], [5, 11, 6], [5, 6, 0], [11, 10, 9, 8, 7, 6]], convexity = 2); + \ No newline at end of file diff --git a/testdata/scad/3D/features/polyhedron-tests.scad b/testdata/scad/3D/features/polyhedron-tests.scad index 443619d0..d519c7d8 100644 --- a/testdata/scad/3D/features/polyhedron-tests.scad +++ b/testdata/scad/3D/features/polyhedron-tests.scad @@ -11,30 +11,6 @@ module polyhedrons() { translate([4,0,0]) polyhedron(points = [[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]], triangles = [[0,2,4],[0,5,2],[0,4,3],[0,3,5],[1,4,2],[1,2,5],[1,3,4], [1,5,3]]); - -// Containing concave polygons -translate([6,0,0]) -polyhedron(points=[ - [-0.8,-0.8,-0.8], - [0,0,-0.8], - [0.8,-0.8,-0.8], - [0.8,0.8,-0.8], - [-0.8,0.8,-0.8], - [-0.8,-0.8,0.8], - [0,0,0.8], - [0.8,-0.8,0.8], - [0.8,0.8,0.8], - [-0.8,0.8,0.8], - ], - triangles=[ - [0,1,2,3,4], - [5,6,1,0], - [6,7,2,1], - [7,8,3,2], - [8,9,4,3], - [9,5,0,4], - [9,8,7,6,5], - ], convexity=2); } polyhedrons(); diff --git a/testdata/scad/bugs/issue1089.scad b/testdata/scad/3D/issues/issue1089.scad similarity index 100% rename from testdata/scad/bugs/issue1089.scad rename to testdata/scad/3D/issues/issue1089.scad diff --git a/testdata/scad/3D/issues/issue1089b.scad b/testdata/scad/3D/issues/issue1089b.scad new file mode 100644 index 00000000..4cf13cb9 --- /dev/null +++ b/testdata/scad/3D/issues/issue1089b.scad @@ -0,0 +1,3 @@ +hull() { + polyhedron(points = [[21.015921990298082278, -9.6968661252791008565, 17.385898562432661407], [21.015921990298082278, 9.4292289939816065214, 11.538464467977924244], [21.245998787904895266, 9.1447008983105675384, 10.607815001220002316], [21.245998787904895266, -0.41834666131978626158, 13.531532048447369121], [21.245998787904895266, -9.9813942209501398395, 16.455249095674737703], [16.150059612458484537, -10.033205852946363024, 17.385898562432661407], [16.150059612458484537, 9.0928892663143443542, 11.538464467977924244], [16.380136410065297525, 8.8083611706433053712, 10.607815001220002316], [16.380136410065297525, -0.75468638898704798468, 13.531532048447369121], [16.380136410065297525, -10.317733948617402007, 16.455249095674737703], [15.17688713689056712, -10.100473798479814747, 17.165875026644524581], [15.17688713689056712, 9.0256213207808926313, 11.318440932189787418], [15.406963934497380109, 8.7410932251098536483, 10.38779146543186549], [15.406963934497380109, -0.82195433452049937451, 13.311508512659232295], [15.406963934497380109, -10.38500189415085373, 16.235225559886600877], [14.152135476691794835, -10.17119106380654614, 16.934569274178546294], [14.152135476691794835, 8.954904055454161238, 11.087135179723812684], [14.367990727181227939, 8.6694249043464353122, 10.153374950800477805], [14.367990727181227939, -0.89362265528391870983, 13.077091998027846387], [14.367990727181227939, -10.456670214914272066, 16.000809045255213192], [13.110820024653460081, -10.233961476664669377, 16.729256504918232906], [13.110820024653460081, 8.8921336425960380012, 10.881822410463495743], [13.309600712109528331, 8.6055965081559246954, 9.9446016739871083701], [13.309600712109528331, -0.95745105147442877147, 12.868318721214476952], [13.309600712109528331, -10.520498611104782682, 15.792035768441845534], [12.078282570414469177, -10.294222837947037519, 16.532150473574372285], [12.078282570414469177, 8.8318722813136698591, 10.684716379119635121], [12.262745467026753943, 8.5445178276236166681, 9.7448223118344454718], [12.262745467026753943, -1.0185297320067365767, 12.668539359061812277], [12.262745467026753943, -10.58157729163709071, 15.592256406289180859], [11.031163105767490151, -10.348029755406946251, 16.356155976708063093], [11.031163105767490151, 8.7780653638537611272, 10.508721882253327706], [11.198443837973723447, 8.4898133798050405829, 9.5658921254443249893], [11.198443837973723447, -1.0732341798253119958, 12.489609172671691795], [11.198443837973723447, -10.636281739455666795, 15.413326219899060376], [9.9920867282612331195, -10.397762464907449598, 16.193487613614035325], [9.9920867282612331195, 8.7283326543532577801, 10.346053519159298162], [10.144967804693861169, 8.4393978978853763095, 9.4009905143952519069], [10.144967804693861169, -1.1236496617449773794, 12.324707561622618712], [10.144967804693861169, -10.686697221375331068, 15.248424608849987294], [8.9400347163076823165, -10.442561786292975157, 16.046955635953878527], [8.9400347163076823165, 8.6835333329677322212, 10.199521541499144917], [9.0756439452541037838, 8.3938624405481636614, 9.2520507445299653426], [9.0756439452541037838, -1.1691851190821893614, 12.175767791757333924], [9.0756439452541037838, -10.732232678712543716, 15.09948483898470073], [7.8956741722639147696, -10.481705796269976005, 15.918921348422623296], [7.8956741722639147696, 8.6443893229907313724, 10.071487253967887909], [8.0168163367886453585, 8.3541708868691326728, 9.1222255222471790859], [8.0168163367886453585, -1.2088766727612223484, 12.045942569474547668], [8.0168163367886453585, -10.771924232391574705, 14.969659616701914473], [6.839564786514664263, -10.51746028460065574, 15.801973686643666639], [6.839564786514664263, 8.6086348346600516379, 9.9545395921889312518], [6.9433634354009168277, 8.3178424250433771192, 9.0034004777589125013], [6.9433634354009168277, -1.2452051345869770138, 11.927117524986281083], [6.9433634354009168277, -10.808252694217330259, 14.850834572213647888], [5.7911812064893624097, -10.545968319665455226, 15.708728105504132344], [5.7911812064893624097, 8.5801267995952521517, 9.861294011049396957], [5.8804599030361934808, 8.2889226275126546284, 8.9088080822795312486], [5.8804599030361934808, -1.2741249321176979503, 11.83252512950689983], [5.8804599030361934808, -10.837172491748052749, 14.756242176734266636], [4.7318927519149163174, -10.572647626142034127, 15.621464026055862817], [4.7318927519149163174, 8.5534474931186732505, 9.77402993160112743], [4.8037743563616075448, 8.2618321038161273151, 8.8201989719106297372], [4.8037743563616075448, -1.3012154558142254857, 11.743916019137996543], [4.8037743563616075448, -10.864263015444580063, 14.667633066365365124], [3.6807521204854736219, -10.590485240237288878, 15.563119819284901624], [3.6807521204854736219, 8.5356098790234185003, 9.7156857248301662366], [3.7380754567641063524, 8.2437189311402967462, 8.7609534536348423472], [3.7380754567641063524, -1.3193286284900567207, 11.684670500862209153], [3.7380754567641063524, -10.882376188120410632, 14.608387548089577734], [2.6191654551378640292, -10.608065925320802947, 15.505615989444741842], [2.6191654551378640292, 8.518029193939904431, 9.6581818949900064553], [2.659056271348898548, 8.2258902040489321195, 8.7026383149438082398], [2.659056271348898548, -1.3371573555814209033, 11.626355362171176822], [2.659056271348898548, -10.900204915211775258, 14.550072409398543627], [1.5571301313920737908, -10.615277603175528043, 15.482027654049947074], [1.5571301313920737908, 8.5108175160851793351, 9.634593559595211687], [1.5798452641030620303, 8.2185212496694965978, 8.6785355512163384617], [1.5798452641030620303, -1.3445263099608570911, 11.602252598443705267], [1.5798452641030620303, -10.90757386959121078, 14.525969645671073849], [0.5035077216434232783, -10.622159719563320834, 15.459517265642222839], [0.5035077216434232783, 8.5039353996973865435, 9.6120831711874892278], [0.5113668014119475691, 8.2115727243029539295, 8.6558079488265811108], [0.5113668014119475691, -1.3514748353273995374, 11.579524996053947916], [0.5113668014119475691, -10.914522394957753448, 14.503242043281314722], [-0.55969246949480999653, -10.620097256783905593, 15.466263277424799227], [-0.55969246949480999653, 8.5059978624768017852, 9.6188291829700638402], [-0.56928712712562057341, 8.2136396155613287107, 8.6625684455111535698], [-0.56928712712562057341, -1.3494079440690252003, 11.586285492738520375], [-0.56928712712562057341, -10.912455503699378667, 14.510002539965888957], [-1.6125195715995086498, -10.616272236324949318, 15.478774355608731383], [-1.6125195715995086498, 8.5098228829357580594, 9.6313402611539977727], [-1.6367003391161654147, 8.2175366669705987022, 8.6753151263175354302], [-1.6367003391161654147, -1.3455108926597549868, 11.599032173544902236], [-1.6367003391161654147, -10.908558452290108676, 14.522749220772269041], [-2.6750035922459902693, -10.605089410934800398, 15.515351729318147989], [-2.6750035922459902693, 8.5210057083259069799, 9.6679176348634126015], [-2.7166291222015424012, 8.2288874074141755699, 8.7124417254191364179], [-2.7166291222015424012, -1.334160152216178119, 11.636158772646505], [-2.7166291222015424012, -10.897207711846531808, 14.559875819873871805], [-3.7267390106727740218, -10.590568334550255258, 15.562848030033741509], [-3.7267390106727740218, 8.5355267847104521195, 9.7154139355790061217], [-3.7829348904509538798, 8.2436170965810333655, 8.7606203678000085233], [-3.7829348904509538798, -1.3194304630493196573, 11.684337415027377105], [-3.7829348904509538798, -10.882478022679674012, 14.60805446225474391], [-4.7876230981018181865, -10.570275178726245002, 15.629223951898024936], [-4.7876230981018181865, 8.5558199405344623756, 9.7817898574432895487], [-4.8612365692795815875, 8.2642414847358942609, 8.828079701800975343], [-4.8612365692795815875, -1.2988060748944600942, 11.751796749028343925], [-4.8612365692795815875, -10.861853634524813117, 14.67551379625571073], [-5.8369967953404051642, -10.545075590745145888, 15.711648090230719177], [-5.8369967953404051642, 8.5810195285155614897, 9.8642139957759837898], [-5.9251502312697619246, 8.2897860538008281139, 8.9116322224150632536], [-5.9251502312697619246, -1.2732615058295262411, 11.835349269642431835], [-5.9251502312697619246, -10.836309065459879264, 14.759066316869798641], [-6.895398463720493254, -10.515689075464781155, 15.807767050683622756], [-6.895398463720493254, 8.6104060437959262231, 9.9603329562288873689], [-7.0009241527878049993, 8.3196667739247160966, 9.0093676540744773718], [-7.0009241527878049993, -1.2433807857056371482, 11.933084701301844177], [-7.0009241527878049993, -10.806428345335991281, 14.856801748529212759], [-7.9411432512251920457, -10.47984140089607763, 15.925019510913235976], [-7.9411432512251920457, 8.6462537183646297478, 10.077585416458500589], [-8.0611639241462889061, 8.355995453894500713, 9.1281934120797192378], [-8.0611639241462889061, -1.2070521057358516437, 12.05191045930708782], [-8.0611639241462889061, -10.770099665366206665, 14.975627506534454625], [-8.9961818731247724656, -10.441385424593725872, 16.050803341698156146], [-8.9961818731247724656, 8.6847096946669815054, 10.203369247243418982], [-9.1335113425972984658, 8.3951080877002439706, 9.2561250727790511661], [-9.1335113425972984658, -1.1679394719301097183, 12.179842120006419748], [-9.1335113425972984658, -10.730987031560463407, 15.103559167233786553], [-10.037034938423907704, -10.394932932465536624, 16.202742597210743725], [-10.037034938423907704, 8.7311621867951707543, 10.355308502756006561], [-10.188799857367065727, 8.4421771354154273581, 9.4100809907477991345], [-10.188799857367065727, -1.120870424214927441, 12.33379803797516594], [-10.188799857367065727, -10.68391798384528002, 15.257515085202534522], [-11.087832325460665217, -10.347438306258311513, 16.358090519704578725], [-11.087832325460665217, 8.7786568130023958645, 10.510656425249845114], [-11.25682453492664159, 8.4904901774226715361, 9.5681058307041340072], [-11.25682453492664159, -1.0725573822076825969, 12.491822877931500813], [-11.25682453492664159, -10.635604941838035842, 15.415539925158867618], [-12.130826484007744881, -10.28998208592428476, 16.546021348432333298], [-12.130826484007744881, 8.8361130333364226175, 10.698587253977599687], [-12.316465776491348549, 8.5488233456115647613, 9.7589050266192529648], [-12.316465776491348549, -1.0142242140187893717, 12.68262207384661977], [-12.316465776491348549, -10.577271773649142617, 15.606339121073986576], [-13.167274479509028851, -10.232609601207819594, 16.733678290296118973], [-13.167274479509028851, 8.8934855180528877838, 10.886244195841383586], [-13.36775592988668393, 8.6070496903803430655, 9.9493548188709652891], [-13.36775592988668393, -0.9559978692500109565, 12.873071866098332094], [-13.36775592988668393, -10.519045428880364312, 15.796788913325700676], [-14.205661711313787521, -10.165804085335658158, 16.952189286815759317], [-14.205661711313787521, 8.96029103392504922, 11.104755192361025706], [-14.423211305781006075, 8.6749218454890240082, 10.171354635130359867], [-14.423211305781006075, -0.88812571414133034686, 13.095071682357726672], [-14.423211305781006075, -10.45117327377168337, 16.018788729585093478], [-15.232758954180525279, -10.098059861404790283, 17.173770659047207232], [-15.232758954180525279, 9.0280352578559170951, 11.326336564592470069], [-15.464523864863501501, 8.7436243006743357142, 10.396070240569519783], [-15.464523864863501501, -0.81942325895601786367, 13.319787287796886588], [-15.464523864863501501, -10.382470818586371664, 16.24350433502425517], [-16.263941232543412951, -10.022378056180794914, 17.421314689835732281], [-16.263941232543412951, 9.1037170630799124638, 11.573880595380996894], [-16.512649129623643063, 8.8205321051208152028, 10.647624334125161738], [-16.512649129623643063, -0.74251545450953948535, 13.571341381352528543], [-16.512649129623643063, -10.305563014139892175, 16.495058428579895349], [-17.249434174697078959, -9.946811825017595865, 17.668480694904857842], [-17.249434174697078959, 9.1792832942431115129, 11.821046600450122455], [-17.503165223042536525, 8.8964795095546467252, 10.896037100784631946], [-17.503165223042536525, -0.66656805007570774091, 13.819754148011998751], [-17.503165223042536525, -10.229615609706060653, 16.743471195239365557]], faces = [[0, 1, 6, 5], [1, 2, 7, 6], [2, 3, 8, 7], [3, 4, 9, 8], [4, 0, 5, 9], [5, 6, 11, 10], [6, 7, 12, 11], [7, 8, 13, 12], [8, 9, 14, 13], [9, 5, 10, 14], [10, 11, 16, 15], [11, 12, 17, 16], [12, 13, 18, 17], [13, 14, 19, 18], [14, 10, 15, 19], [15, 16, 21, 20], [16, 17, 22, 21], [17, 18, 23, 22], [18, 19, 24, 23], [19, 15, 20, 24], [20, 21, 26, 25], [21, 22, 27, 26], [22, 23, 28, 27], [23, 24, 29, 28], [24, 20, 25, 29], [25, 26, 31, 30], [26, 27, 32, 31], [27, 28, 33, 32], [28, 29, 34, 33], [29, 25, 30, 34], [30, 31, 36, 35], [31, 32, 37, 36], [32, 33, 38, 37], [33, 34, 39, 38], [34, 30, 35, 39], [35, 36, 41, 40], [36, 37, 42, 41], [37, 38, 43, 42], [38, 39, 44, 43], [39, 35, 40, 44], [40, 41, 46, 45], [41, 42, 47, 46], [42, 43, 48, 47], [43, 44, 49, 48], [44, 40, 45, 49], [45, 46, 51, 50], [46, 47, 52, 51], [47, 48, 53, 52], [48, 49, 54, 53], [49, 45, 50, 54], [50, 51, 56, 55], [51, 52, 57, 56], [52, 53, 58, 57], [53, 54, 59, 58], [54, 50, 55, 59], [55, 56, 61, 60], [56, 57, 62, 61], [57, 58, 63, 62], [58, 59, 64, 63], [59, 55, 60, 64], [60, 61, 66, 65], [61, 62, 67, 66], [62, 63, 68, 67], [63, 64, 69, 68], [64, 60, 65, 69], [65, 66, 71, 70], [66, 67, 72, 71], [67, 68, 73, 72], [68, 69, 74, 73], [69, 65, 70, 74], [70, 71, 76, 75], [71, 72, 77, 76], [72, 73, 78, 77], [73, 74, 79, 78], [74, 70, 75, 79], [75, 76, 81, 80], [76, 77, 82, 81], [77, 78, 83, 82], [78, 79, 84, 83], [79, 75, 80, 84], [80, 81, 86, 85], [81, 82, 87, 86], [82, 83, 88, 87], [83, 84, 89, 88], [84, 80, 85, 89], [85, 86, 91, 90], [86, 87, 92, 91], [87, 88, 93, 92], [88, 89, 94, 93], [89, 85, 90, 94], [90, 91, 96, 95], [91, 92, 97, 96], [92, 93, 98, 97], [93, 94, 99, 98], [94, 90, 95, 99], [95, 96, 101, 100], [96, 97, 102, 101], [97, 98, 103, 102], [98, 99, 104, 103], [99, 95, 100, 104], [100, 101, 106, 105], [101, 102, 107, 106], [102, 103, 108, 107], [103, 104, 109, 108], [104, 100, 105, 109], [105, 106, 111, 110], [106, 107, 112, 111], [107, 108, 113, 112], [108, 109, 114, 113], [109, 105, 110, 114], [110, 111, 116, 115], [111, 112, 117, 116], [112, 113, 118, 117], [113, 114, 119, 118], [114, 110, 115, 119], [115, 116, 121, 120], [116, 117, 122, 121], [117, 118, 123, 122], [118, 119, 124, 123], [119, 115, 120, 124], [120, 121, 126, 125], [121, 122, 127, 126], [122, 123, 128, 127], [123, 124, 129, 128], [124, 120, 125, 129], [125, 126, 131, 130], [126, 127, 132, 131], [127, 128, 133, 132], [128, 129, 134, 133], [129, 125, 130, 134], [130, 131, 136, 135], [131, 132, 137, 136], [132, 133, 138, 137], [133, 134, 139, 138], [134, 130, 135, 139], [135, 136, 141, 140], [136, 137, 142, 141], [137, 138, 143, 142], [138, 139, 144, 143], [139, 135, 140, 144], [140, 141, 146, 145], [141, 142, 147, 146], [142, 143, 148, 147], [143, 144, 149, 148], [144, 140, 145, 149], [145, 146, 151, 150], [146, 147, 152, 151], [147, 148, 153, 152], [148, 149, 154, 153], [149, 145, 150, 154], [150, 151, 156, 155], [151, 152, 157, 156], [152, 153, 158, 157], [153, 154, 159, 158], [154, 150, 155, 159], [155, 156, 161, 160], [156, 157, 162, 161], [157, 158, 163, 162], [158, 159, 164, 163], [159, 155, 160, 164], [160, 161, 166, 165], [161, 162, 167, 166], [162, 163, 168, 167], [163, 164, 169, 168], [164, 160, 165, 169], [4, 3, 2, 1, 0], [165, 166, 167, 168, 169]], convexity = 5); +} \ No newline at end of file diff --git a/testdata/scad/3D/issues/issue1165.scad b/testdata/scad/3D/issues/issue1165.scad new file mode 100644 index 00000000..9338b16a --- /dev/null +++ b/testdata/scad/3D/issues/issue1165.scad @@ -0,0 +1,5 @@ +translate([0,10,0]) difference() { + cube(10, center=true); + translate([6,5.5,0]) cube(11, center=true); + translate([6,-5.500000000088,0]) cube(11, center=true); +} \ No newline at end of file diff --git a/testdata/scad/3D/issues/issue1196.scad b/testdata/scad/3D/issues/issue1196.scad new file mode 100644 index 00000000..4bc1149c --- /dev/null +++ b/testdata/scad/3D/issues/issue1196.scad @@ -0,0 +1,20 @@ +minkowski() { + cube(); + linear_extrude() { + import("notfound.dxf"); + } + linear_extrude() { + import("notfound.dxf"); + } +} + +minkowski() { + linear_extrude() { + import("notfound.dxf"); + } + linear_extrude() { + import("notfound.dxf"); + } + cube(); + cube(); +} diff --git a/testdata/scad/3D/issues/issue1198.scad b/testdata/scad/3D/issues/issue1198.scad new file mode 100644 index 00000000..86600289 --- /dev/null +++ b/testdata/scad/3D/issues/issue1198.scad @@ -0,0 +1,23 @@ +polyhedron(points = [ + [6.46538, 45.0434, -0.5185], + [7.45793, 45.0119, -0.636215], + [7.45793, 45.9778, -0.895034], + [6.46538, 46.0094, -0.77732], + [6.46538, 45.5264, -0.64791], + [6.18882, 44.4605, -2.69418], + [7.18137, 44.4289, -2.8119], + [7.18137, 45.3948, -3.07072], + [6.18882, 45.4264, -2.953], + [6.18882, 44.9434, -2.82359]], + + faces = + + + + [[0, 1, 6, 5], + [1, 2, 7, 6], + [2, 3, 8, 7], + [3, 4, 9, 8], + [4, 0, 5, 9], + [4, 3, 2, 1, 0], + [5, 6, 7, 8, 9]]); diff --git a/testdata/scad/bugs/issue1105b.scad b/testdata/scad/bugs/issue1105b.scad new file mode 100644 index 00000000..3bfb3928 --- /dev/null +++ b/testdata/scad/bugs/issue1105b.scad @@ -0,0 +1,11 @@ +translate([54.5, -10, 2]) + rotate(90) + translate([2,30,26]) { + difference() { + cube(size = [4, 21.5, 4]); + translate([-0.1,-1.1,2]) cube(size = [2.1, 23.5, 2.1]); + } + } + +translate([-3,-8,12]) cube(size = [6, 3, 20]); +translate([0, -5, 2]) rotate(90) rotate_extrude($fn = 10) polygon(points = [[0, 18], [0, 30], [7, 26]]); diff --git a/testdata/scad/bugs/issue1105c.scad b/testdata/scad/bugs/issue1105c.scad new file mode 100644 index 00000000..527ee895 --- /dev/null +++ b/testdata/scad/bugs/issue1105c.scad @@ -0,0 +1,14 @@ +translate([59.5, -40, 2]) rotate(90) translate([2,31.5,26]) + cube(size = [4, 23, 4], center = false); + +translate([5,-35,2]) { + difference() { + rotate(90) { + translate([-3,-3,1]) cube(size = [3, 6, 30]); + rotate_extrude($fn = 14) { + polygon(points = [[0, 18], [0, 30], [7, 26]]); + } + } + cylinder(h = 30, r = 1); + } +} diff --git a/testdata/scad/bugs/issue1105d.scad b/testdata/scad/bugs/issue1105d.scad new file mode 100644 index 00000000..f37b6554 --- /dev/null +++ b/testdata/scad/bugs/issue1105d.scad @@ -0,0 +1,8 @@ +difference() { + rotate_extrude(convexity=2, $fn=8) + translate([5,0,0]) difference() { + circle(r=2); + circle(r=1); + } + translate([-5,-5,5]) cube(10, center=true); +} diff --git a/testdata/scad/bugs/issue1165.scad b/testdata/scad/bugs/issue1165.scad new file mode 100644 index 00000000..9338b16a --- /dev/null +++ b/testdata/scad/bugs/issue1165.scad @@ -0,0 +1,5 @@ +translate([0,10,0]) difference() { + cube(10, center=true); + translate([6,5.5,0]) cube(11, center=true); + translate([6,-5.500000000088,0]) cube(11, center=true); +} \ No newline at end of file diff --git a/testdata/scad/bugs/issue13.scad b/testdata/scad/bugs/issue13.scad new file mode 100644 index 00000000..5956e67e --- /dev/null +++ b/testdata/scad/bugs/issue13.scad @@ -0,0 +1,2 @@ +cube(size = [10,10,5]); +translate([5, 5, 8.1-9+0.9]) cube(size = [5,10,10]); diff --git a/testdata/scad/bugs/issue13b.scad b/testdata/scad/bugs/issue13b.scad new file mode 100644 index 00000000..a604027c --- /dev/null +++ b/testdata/scad/bugs/issue13b.scad @@ -0,0 +1,2 @@ +rotate([90,0,180]) translate ([0, 0, 8]) cube(10, center=true); +rotate([90,0,270]) translate ([0, 0, 8]) cube(10, center=true); diff --git a/testdata/scad/misc/nbsp-latin1-test.scad b/testdata/scad/misc/nbsp-latin1-test.scad new file mode 100644 index 00000000..3d8bbfe9 --- /dev/null +++ b/testdata/scad/misc/nbsp-latin1-test.scad @@ -0,0 +1,2 @@ +a=1;//Latin-1NBSP(no-breakspace) +echo(a); diff --git a/testdata/scad/misc/nbsp-utf8-test.scad b/testdata/scad/misc/nbsp-utf8-test.scad new file mode 100644 index 00000000..fd929422 --- /dev/null +++ b/testdata/scad/misc/nbsp-utf8-test.scad @@ -0,0 +1,2 @@ +a = 1;   // UTF-8 NBSP (no-break space) +echo(a); diff --git a/testdata/scad/misc/recursion-tests.scad b/testdata/scad/misc/recursion-test-function.scad similarity index 55% rename from testdata/scad/misc/recursion-tests.scad rename to testdata/scad/misc/recursion-test-function.scad index 78b31e35..d01ce36d 100644 --- a/testdata/scad/misc/recursion-tests.scad +++ b/testdata/scad/misc/recursion-test-function.scad @@ -1,5 +1,3 @@ function crash() = crash(); +// Recursion as module parameter echo(crash()); - -module crash() crash(); -crash(); diff --git a/testdata/scad/misc/recursion-test-function2.scad b/testdata/scad/misc/recursion-test-function2.scad new file mode 100644 index 00000000..369f3775 --- /dev/null +++ b/testdata/scad/misc/recursion-test-function2.scad @@ -0,0 +1,3 @@ +// Recursion as assignment +function crash() = crash(); +a = crash(); diff --git a/testdata/scad/misc/recursion-test-module.scad b/testdata/scad/misc/recursion-test-module.scad new file mode 100644 index 00000000..0ad24b88 --- /dev/null +++ b/testdata/scad/misc/recursion-test-module.scad @@ -0,0 +1,3 @@ +// Module recursion +module crash() crash(); +crash(); diff --git a/tests/.gitignore b/tests/.gitignore index 99ad0be3..2171c5e8 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -2,6 +2,7 @@ /*.a /*-output /*.scad +/*.png out.* /CMakeFiles /CMakeCache.txt @@ -18,3 +19,9 @@ out.* /sysinfo.txt /CTestCustom.cmake /openscad_nogui +/openscad_nogui +/diffpng +/test_pretty_print.log.txt +/csgtermtest +/echotest +/dumptest \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 608b60c1..f8546e4f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -264,7 +264,9 @@ if (EIGEN_DIR) endif() if (NOT EIGEN_INCLUDE_DIR) - find_path(EIGEN_INCLUDE_DIR Eigen/Core HINTS ${OPENSCAD_LIBDIR}/include/eigen3) + # The NO_CMAKE_SYSTEM_PATH is necessary to avoid OS X from picking up + # a stray Eigen from /Library/Framework + find_path(EIGEN_INCLUDE_DIR Eigen/Core HINTS ${OPENSCAD_LIBDIR}/include/eigen3 NO_CMAKE_SYSTEM_PATH) endif() if (NOT EIGEN_INCLUDE_DIR) @@ -553,7 +555,7 @@ else() endif() # Internal includes -include_directories(../src) +include_directories(../src ../src/libtess2/Include) # Handle OpenSCAD version based on VERSION env. variable. # Use current timestamp if not specified (development builds) @@ -617,6 +619,7 @@ set(CORE_SOURCES ../src/handle_dep.cc ../src/value.cc ../src/calc.cc + ../src/grid.cc ../src/expr.cc ../src/func.cc ../src/stackcheck.cc @@ -667,7 +670,8 @@ set(NOCGAL_SOURCES ../src/export.cc ../src/LibraryInfo.cc ../src/polyset.cc - ../src/polyset-utils.cc) + ../src/polyset-utils.cc + ../src/GeometryUtils.cc) set(CGAL_SOURCES @@ -677,7 +681,6 @@ set(CGAL_SOURCES ../src/cgalutils.cc ../src/cgalutils-tess.cc ../src/cgalutils-polyhedron.cc - ../src/cgalutils-tess-old.cc ../src/CGALCache.cc ../src/CGAL_Nef_polyhedron_DxfData.cc ../src/Polygon2d-CGAL.cc @@ -689,8 +692,15 @@ set(COMMON_SOURCES ../src/traverser.cc ../src/GeometryCache.cc ../src/clipper-utils.cc + ../src/Tree.cc ../src/polyclipping/clipper.cpp - ../src/Tree.cc) + ../src/libtess2/Source/bucketalloc.c + ../src/libtess2/Source/dict.c + ../src/libtess2/Source/geom.c + ../src/libtess2/Source/mesh.c + ../src/libtess2/Source/priorityq.c + ../src/libtess2/Source/sweep.c + ../src/libtess2/Source/tess.c) # # Offscreen OpenGL context source code @@ -773,6 +783,9 @@ add_executable(openscad_nogui ../src/openscad.cc) set_target_properties(openscad_nogui PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -DEIGEN_DONT_ALIGN ${ENABLE_OPENCSG_FLAG} -DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}") target_link_libraries(openscad_nogui tests-offscreen tests-cgal ${GLEW_LIBRARY} ${OPENCSG_LIBRARY} ${APP_SERVICES_LIBRARY}) +# also run translation compilation to verify the files are without syntax errors +add_custom_target(locale_files ALL COMMAND ${CMAKE_SOURCE_DIR}/../scripts/translation-make.sh) + # # GUI binary tests # @@ -1045,7 +1058,9 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES} ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/vector-values.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/search-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/search-tests-unicode.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-tests.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-test-function.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-test-function2.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-test-module.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/tail-recursion-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests2.scad @@ -1059,6 +1074,8 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES} ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/no-break-space-test.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/unicode-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/utf8-tests.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/nbsp-utf8-test.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/nbsp-latin1-test.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/concat-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/include-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/include-recursive-test.scad @@ -1112,6 +1129,7 @@ list(APPEND EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/features ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/features/polyhedron-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/features/rotate_extrude-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/features/union-coincident-test.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/features/mirror-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/null-polygons.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/internal-cavity.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/internal-cavity-polyhedron.scad @@ -1205,7 +1223,9 @@ set_test_config(Heavy cgalpngtest_rotate_extrude-tests # Bugs -list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue584.scad +list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue13.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue13b.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue584.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue591.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue666.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue791.scad @@ -1216,11 +1236,14 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue584.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945b.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945c.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945d.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1089.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105b.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105c.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105d.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) list(REMOVE_ITEM EXPORT3D_TEST_FILES - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1089.scad) #list(APPEND EXPORTCSG_TEST_FILES ) list(APPEND ALL_2D_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad) diff --git a/tests/regression/cgalpngtest/LetterBlock-expected.png b/tests/regression/cgalpngtest/LetterBlock-expected.png new file mode 100644 index 00000000..b976cc78 Binary files /dev/null and b/tests/regression/cgalpngtest/LetterBlock-expected.png differ diff --git a/tests/regression/cgalpngtest/chopped_blocks-expected.png b/tests/regression/cgalpngtest/chopped_blocks-expected.png index 70bd10d7..95678da2 100644 Binary files a/tests/regression/cgalpngtest/chopped_blocks-expected.png and b/tests/regression/cgalpngtest/chopped_blocks-expected.png differ diff --git a/tests/regression/cgalpngtest/issue1061-expected.png b/tests/regression/cgalpngtest/issue1061-expected.png index 78bd8525..ef40d783 100644 Binary files a/tests/regression/cgalpngtest/issue1061-expected.png and b/tests/regression/cgalpngtest/issue1061-expected.png differ diff --git a/tests/regression/cgalpngtest/issue1089b-expected.png b/tests/regression/cgalpngtest/issue1089b-expected.png new file mode 100644 index 00000000..f90390f0 Binary files /dev/null and b/tests/regression/cgalpngtest/issue1089b-expected.png differ diff --git a/tests/regression/cgalpngtest/issue1105b-expected.png b/tests/regression/cgalpngtest/issue1105b-expected.png new file mode 100644 index 00000000..40fe3763 Binary files /dev/null and b/tests/regression/cgalpngtest/issue1105b-expected.png differ diff --git a/tests/regression/cgalpngtest/issue1105c-expected.png b/tests/regression/cgalpngtest/issue1105c-expected.png new file mode 100644 index 00000000..9c1321cd Binary files /dev/null and b/tests/regression/cgalpngtest/issue1105c-expected.png differ diff --git a/tests/regression/cgalpngtest/issue1105d-expected.png b/tests/regression/cgalpngtest/issue1105d-expected.png new file mode 100644 index 00000000..b62fcca2 Binary files /dev/null and b/tests/regression/cgalpngtest/issue1105d-expected.png differ diff --git a/tests/regression/cgalpngtest/issue1165-expected.png b/tests/regression/cgalpngtest/issue1165-expected.png new file mode 100644 index 00000000..e3c21fb3 Binary files /dev/null and b/tests/regression/cgalpngtest/issue1165-expected.png differ diff --git a/tests/regression/cgalpngtest/issue1196-expected.png b/tests/regression/cgalpngtest/issue1196-expected.png new file mode 100644 index 00000000..677d52ca Binary files /dev/null and b/tests/regression/cgalpngtest/issue1196-expected.png differ diff --git a/tests/regression/cgalpngtest/issue1198-expected.png b/tests/regression/cgalpngtest/issue1198-expected.png new file mode 100644 index 00000000..ad9c8a86 Binary files /dev/null and b/tests/regression/cgalpngtest/issue1198-expected.png differ diff --git a/tests/regression/cgalpngtest/issue13-expected.png b/tests/regression/cgalpngtest/issue13-expected.png new file mode 100644 index 00000000..cb7fda75 Binary files /dev/null and b/tests/regression/cgalpngtest/issue13-expected.png differ diff --git a/tests/regression/cgalpngtest/issue13b-expected.png b/tests/regression/cgalpngtest/issue13b-expected.png new file mode 100644 index 00000000..2dcda55d Binary files /dev/null and b/tests/regression/cgalpngtest/issue13b-expected.png differ diff --git a/tests/regression/cgalpngtest/mirror-tests-expected.png b/tests/regression/cgalpngtest/mirror-tests-expected.png new file mode 100644 index 00000000..677d52ca Binary files /dev/null and b/tests/regression/cgalpngtest/mirror-tests-expected.png differ diff --git a/tests/regression/cgalpngtest/nullspace-minkowski-expected.png b/tests/regression/cgalpngtest/nullspace-minkowski-expected.png index 08ee92b2..677d52ca 100644 Binary files a/tests/regression/cgalpngtest/nullspace-minkowski-expected.png and b/tests/regression/cgalpngtest/nullspace-minkowski-expected.png differ diff --git a/tests/regression/cgalpngtest/nullspace-minkowski-intersection-expected.png b/tests/regression/cgalpngtest/nullspace-minkowski-intersection-expected.png index 08ee92b2..677d52ca 100644 Binary files a/tests/regression/cgalpngtest/nullspace-minkowski-intersection-expected.png and b/tests/regression/cgalpngtest/nullspace-minkowski-intersection-expected.png differ diff --git a/tests/regression/cgalpngtest/polyhedron-concave-test-expected.png b/tests/regression/cgalpngtest/polyhedron-concave-test-expected.png new file mode 100644 index 00000000..c45cc11c Binary files /dev/null and b/tests/regression/cgalpngtest/polyhedron-concave-test-expected.png differ diff --git a/tests/regression/cgalpngtest/polyhedron-tests-expected.png b/tests/regression/cgalpngtest/polyhedron-tests-expected.png index d2e3bad3..3125122f 100644 Binary files a/tests/regression/cgalpngtest/polyhedron-tests-expected.png and b/tests/regression/cgalpngtest/polyhedron-tests-expected.png differ diff --git a/tests/regression/cgalpngtest/sphere-expected.png b/tests/regression/cgalpngtest/sphere-expected.png index 8065e9c4..8acb26c3 100644 Binary files a/tests/regression/cgalpngtest/sphere-expected.png and b/tests/regression/cgalpngtest/sphere-expected.png differ diff --git a/tests/regression/dumptest-examples/LetterBlock-expected.csg b/tests/regression/dumptest-examples/LetterBlock-expected.csg new file mode 100644 index 00000000..3fbaf903 --- /dev/null +++ b/tests/regression/dumptest-examples/LetterBlock-expected.csg @@ -0,0 +1,15 @@ +group() { + group(); + group() { + difference() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 7.5], [0, 0, 0, 1]]) { + cube(size = [30, 30, 15], center = true); + } + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 5], [0, 0, 0, 1]]) { + linear_extrude(height = 30, center = false, convexity = 3, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { + text(text = "M", size = 22, spacing = 1, font = "Tahoma", direction = "ltr", language = "en", script = "latin", halign = "center", valign = "center", $fn = 0, $fa = 12, $fs = 2); + } + } + } + } +} diff --git a/tests/regression/dumptest-examples/chopped_blocks-expected.csg b/tests/regression/dumptest-examples/chopped_blocks-expected.csg index 816d33ef..93410a7b 100644 --- a/tests/regression/dumptest-examples/chopped_blocks-expected.csg +++ b/tests/regression/dumptest-examples/chopped_blocks-expected.csg @@ -17,7 +17,7 @@ group() { } } group() { - multmatrix([[1, 0, 0, -14], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + multmatrix([[1, 0, 0, -18], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { import(file = "chopped_blocks.stl", layer = "", origin = [0, 0], scale = 1, convexity = 12, $fn = 0, $fa = 12, $fs = 2); } } @@ -36,7 +36,7 @@ group() { } } group() { - multmatrix([[1, 0, 0, -14], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + multmatrix([[1, 0, 0, -18], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { import(file = "chopped_blocks.stl", layer = "", origin = [0, 0], scale = 1, convexity = 12, $fn = 0, $fa = 12, $fs = 2); } } @@ -55,7 +55,7 @@ group() { } } group() { - multmatrix([[1, 0, 0, -14], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + multmatrix([[1, 0, 0, -18], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { import(file = "chopped_blocks.stl", layer = "", origin = [0, 0], scale = 1, convexity = 12, $fn = 0, $fa = 12, $fs = 2); } } @@ -74,7 +74,7 @@ group() { } } group() { - multmatrix([[1, 0, 0, -14], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + multmatrix([[1, 0, 0, -18], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { import(file = "chopped_blocks.stl", layer = "", origin = [0, 0], scale = 1, convexity = 12, $fn = 0, $fa = 12, $fs = 2); } } diff --git a/tests/regression/dumptest-examples/sphere-expected.csg b/tests/regression/dumptest-examples/sphere-expected.csg index e6f46184..688301ea 100644 --- a/tests/regression/dumptest-examples/sphere-expected.csg +++ b/tests/regression/dumptest-examples/sphere-expected.csg @@ -2,9 +2,9 @@ group() { group(); difference() { sphere($fn = 0, $fa = 12, $fs = 2, r = 20); - multmatrix([[1, 0, 0, -2.92], [0, 1, 0, 0.5], [0, 0, 1, 20], [0, 0, 0, 1]]) { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0.5], [0, 0, 1, 20], [0, 0, 0, 1]]) { multmatrix([[-1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]]) { - import(file = "sphere.stl", layer = "", origin = [0, 0], scale = 1, convexity = 5, $fn = 0, $fa = 12, $fs = 2); + import(file = "M.stl", layer = "", origin = [0, 0], scale = 1, convexity = 5, $fn = 0, $fa = 12, $fs = 2); } } } diff --git a/tests/regression/dumptest/allmodules-expected.csg b/tests/regression/dumptest/allmodules-expected.csg index 9af5da4b..64bb2921 100644 --- a/tests/regression/dumptest/allmodules-expected.csg +++ b/tests/regression/dumptest/allmodules-expected.csg @@ -16,8 +16,8 @@ group() { intersection(); linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2); import(file = "", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); import(file = "", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); import(file = "", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); diff --git a/tests/regression/dumptest/linear_extrude-tests-expected.csg b/tests/regression/dumptest/linear_extrude-tests-expected.csg index 539412d6..23bdb899 100644 --- a/tests/regression/dumptest/linear_extrude-tests-expected.csg +++ b/tests/regression/dumptest/linear_extrude-tests-expected.csg @@ -1,7 +1,7 @@ group() { - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2) { cube(size = [1, 1, 1], center = false); } linear_extrude(height = 10, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { diff --git a/tests/regression/dumptest/localfiles-compatibility-test-expected.csg b/tests/regression/dumptest/localfiles-compatibility-test-expected.csg index e8dd8066..e3be61a8 100644 --- a/tests/regression/dumptest/localfiles-compatibility-test-expected.csg +++ b/tests/regression/dumptest/localfiles-compatibility-test-expected.csg @@ -7,7 +7,7 @@ group() { linear_extrude(file = "localfile.dxf", layer = "", origin = [0, 0], height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); } multmatrix([[1, 0, 0, 0], [0, 1, 0, 350], [0, 0, 1, 0], [0, 0, 0, 1]]) { - rotate_extrude(file = "localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(file = "localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 2, $fn = 0, $fa = 12, $fs = 2); } multmatrix([[1, 0, 0, 250], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { multmatrix([[200, 0, 0, 0], [0, 200, 0, 0], [0, 0, 50, 0], [0, 0, 0, 1]]) { diff --git a/tests/regression/dumptest/localfiles-test-expected.csg b/tests/regression/dumptest/localfiles-test-expected.csg index d4db2548..8649c3b8 100644 --- a/tests/regression/dumptest/localfiles-test-expected.csg +++ b/tests/regression/dumptest/localfiles-test-expected.csg @@ -7,7 +7,7 @@ group() { linear_extrude(file = "localfiles_dir/localfile.dxf", layer = "", origin = [0, 0], height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); } multmatrix([[1, 0, 0, 0], [0, 1, 0, 350], [0, 0, 1, 0], [0, 0, 0, 1]]) { - rotate_extrude(file = "localfiles_dir/localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(file = "localfiles_dir/localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 2, $fn = 0, $fa = 12, $fs = 2); } multmatrix([[1, 0, 0, 250], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { multmatrix([[200, 0, 0, 0], [0, 200, 0, 0], [0, 0, 50, 0], [0, 0, 0, 1]]) { diff --git a/tests/regression/dumptest/mirror-tests-expected.csg b/tests/regression/dumptest/mirror-tests-expected.csg new file mode 100644 index 00000000..3af81c1a --- /dev/null +++ b/tests/regression/dumptest/mirror-tests-expected.csg @@ -0,0 +1,7 @@ +group() { + render(convexity = 1) { + multmatrix([[-1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + cube(size = [1, 1, 1], center = false); + } + } +} diff --git a/tests/regression/dumptest/polyhedron-concave-test-expected.csg b/tests/regression/dumptest/polyhedron-concave-test-expected.csg new file mode 100644 index 00000000..864c01ee --- /dev/null +++ b/tests/regression/dumptest/polyhedron-concave-test-expected.csg @@ -0,0 +1,3 @@ +group() { + polyhedron(points = [[0, 0, 0], [2, 4, 0], [8, 4, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0], [0, 0, 5], [2, 4, 5], [8, 4, 5], [10, 0, 5], [10, 10, 5], [0, 10, 5]], faces = [[0, 1, 2, 3, 4, 5], [0, 6, 7], [0, 7, 1], [1, 7, 8], [1, 8, 2], [2, 8, 9], [2, 9, 3], [3, 9, 10], [3, 10, 4], [4, 10, 11], [4, 11, 5], [5, 11, 6], [5, 6, 0], [11, 10, 9, 8, 7, 6]], convexity = 2); +} diff --git a/tests/regression/dumptest/polyhedron-tests-expected.csg b/tests/regression/dumptest/polyhedron-tests-expected.csg index 82313982..93933444 100644 --- a/tests/regression/dumptest/polyhedron-tests-expected.csg +++ b/tests/regression/dumptest/polyhedron-tests-expected.csg @@ -7,9 +7,6 @@ group() { multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], faces = [[0, 2, 4], [0, 5, 2], [0, 4, 3], [0, 3, 5], [1, 4, 2], [1, 2, 5], [1, 3, 4], [1, 5, 3]], convexity = 1); } - multmatrix([[1, 0, 0, 6], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { - polyhedron(points = [[-0.8, -0.8, -0.8], [0, 0, -0.8], [0.8, -0.8, -0.8], [0.8, 0.8, -0.8], [-0.8, 0.8, -0.8], [-0.8, -0.8, 0.8], [0, 0, 0.8], [0.8, -0.8, 0.8], [0.8, 0.8, 0.8], [-0.8, 0.8, 0.8]], faces = [[0, 1, 2, 3, 4], [5, 6, 1, 0], [6, 7, 2, 1], [7, 8, 3, 2], [8, 9, 4, 3], [9, 5, 0, 4], [9, 8, 7, 6, 5]], convexity = 2); - } } multmatrix([[1, 0, 0, 0], [0, 1, 0, 2], [0, 0, 1, 0], [0, 0, 0, 1]]) { difference() { @@ -21,9 +18,6 @@ group() { multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], faces = [[0, 2, 4], [0, 5, 2], [0, 4, 3], [0, 3, 5], [1, 4, 2], [1, 2, 5], [1, 3, 4], [1, 5, 3]], convexity = 1); } - multmatrix([[1, 0, 0, 6], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { - polyhedron(points = [[-0.8, -0.8, -0.8], [0, 0, -0.8], [0.8, -0.8, -0.8], [0.8, 0.8, -0.8], [-0.8, 0.8, -0.8], [-0.8, -0.8, 0.8], [0, 0, 0.8], [0.8, -0.8, 0.8], [0.8, 0.8, 0.8], [-0.8, 0.8, 0.8]], faces = [[0, 1, 2, 3, 4], [5, 6, 1, 0], [6, 7, 2, 1], [7, 8, 3, 2], [8, 9, 4, 3], [9, 5, 0, 4], [9, 8, 7, 6, 5]], convexity = 2); - } } multmatrix([[1, 0, 0, 3], [0, 1, 0, 0], [0, 0, 1, 2], [0, 0, 0, 1]]) { cube(size = [8, 3, 3], center = true); diff --git a/tests/regression/dumptest/rotate_extrude-tests-expected.csg b/tests/regression/dumptest/rotate_extrude-tests-expected.csg index 23c8d6e9..d97d4376 100644 --- a/tests/regression/dumptest/rotate_extrude-tests-expected.csg +++ b/tests/regression/dumptest/rotate_extrude-tests-expected.csg @@ -1,10 +1,10 @@ group() { - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2) { cube(size = [1, 1, 1], center = false); } - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2) { multmatrix([[1, 0, 0, 20], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { circle($fn = 0, $fa = 12, $fs = 2, r = 10); } @@ -44,14 +44,14 @@ group() { } } multmatrix([[1, 0, 0, 0], [0, 1, 0, -60], [0, 0, 1, 0], [0, 0, 0, 1]]) { - rotate_extrude(convexity = 1, $fn = 1, $fa = 12, $fs = 2) { + rotate_extrude(convexity = 2, $fn = 1, $fa = 12, $fs = 2) { multmatrix([[1, 0, 0, 20], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { circle($fn = 1, $fa = 12, $fs = 2, r = 10); } } } multmatrix([[1, 0, 0, 0], [0, 1, 0, 60], [0, 0, 1, 0], [0, 0, 0, 1]]) { - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2) { multmatrix([[1, 0, 0, -20], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { square(size = [10, 10], center = false); } diff --git a/tests/regression/dumptest/rotate_extrude_dxf-tests-expected.csg b/tests/regression/dumptest/rotate_extrude_dxf-tests-expected.csg index 63c60ebe..5f4d6c9c 100644 --- a/tests/regression/dumptest/rotate_extrude_dxf-tests-expected.csg +++ b/tests/regression/dumptest/rotate_extrude_dxf-tests-expected.csg @@ -1,3 +1,3 @@ group() { - rotate_extrude(file = "../../../dxf/open-polyline.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(file = "../../../dxf/open-polyline.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 2, $fn = 0, $fa = 12, $fs = 2); } diff --git a/tests/regression/echotest/nbsp-latin1-test-expected.echo b/tests/regression/echotest/nbsp-latin1-test-expected.echo new file mode 100644 index 00000000..ee62791e --- /dev/null +++ b/tests/regression/echotest/nbsp-latin1-test-expected.echo @@ -0,0 +1 @@ +ECHO: 1 diff --git a/tests/regression/echotest/nbsp-utf8-test-expected.echo b/tests/regression/echotest/nbsp-utf8-test-expected.echo new file mode 100644 index 00000000..ee62791e --- /dev/null +++ b/tests/regression/echotest/nbsp-utf8-test-expected.echo @@ -0,0 +1 @@ +ECHO: 1 diff --git a/tests/regression/echotest/recursion-tests-expected.echo b/tests/regression/echotest/recursion-test-function-expected.echo similarity index 51% rename from tests/regression/echotest/recursion-tests-expected.echo rename to tests/regression/echotest/recursion-test-function-expected.echo index 747e6d47..ef9ebaaf 100644 --- a/tests/regression/echotest/recursion-tests-expected.echo +++ b/tests/regression/echotest/recursion-test-function-expected.echo @@ -1,2 +1 @@ ERROR: Recursion detected calling function 'crash' -ERROR: Recursion detected calling module 'crash' diff --git a/tests/regression/echotest/recursion-test-function2-expected.echo b/tests/regression/echotest/recursion-test-function2-expected.echo new file mode 100644 index 00000000..ef9ebaaf --- /dev/null +++ b/tests/regression/echotest/recursion-test-function2-expected.echo @@ -0,0 +1 @@ +ERROR: Recursion detected calling function 'crash' diff --git a/tests/regression/echotest/recursion-test-module-expected.echo b/tests/regression/echotest/recursion-test-module-expected.echo new file mode 100644 index 00000000..2840a9a9 --- /dev/null +++ b/tests/regression/echotest/recursion-test-module-expected.echo @@ -0,0 +1 @@ +ERROR: Recursion detected calling module 'crash' diff --git a/tests/regression/monotonepngtest/LetterBlock-expected.png b/tests/regression/monotonepngtest/LetterBlock-expected.png new file mode 100644 index 00000000..25fa03b0 Binary files /dev/null and b/tests/regression/monotonepngtest/LetterBlock-expected.png differ diff --git a/tests/regression/monotonepngtest/chopped_blocks-expected.png b/tests/regression/monotonepngtest/chopped_blocks-expected.png index 5ef9324b..50abe82f 100644 Binary files a/tests/regression/monotonepngtest/chopped_blocks-expected.png and b/tests/regression/monotonepngtest/chopped_blocks-expected.png differ diff --git a/tests/regression/monotonepngtest/issue1089b-expected.png b/tests/regression/monotonepngtest/issue1089b-expected.png new file mode 100644 index 00000000..da592fa2 Binary files /dev/null and b/tests/regression/monotonepngtest/issue1089b-expected.png differ diff --git a/tests/regression/monotonepngtest/issue1105b-expected.png b/tests/regression/monotonepngtest/issue1105b-expected.png new file mode 100644 index 00000000..86ca1284 Binary files /dev/null and b/tests/regression/monotonepngtest/issue1105b-expected.png differ diff --git a/tests/regression/monotonepngtest/issue1105c-expected.png b/tests/regression/monotonepngtest/issue1105c-expected.png new file mode 100644 index 00000000..9c1321cd Binary files /dev/null and b/tests/regression/monotonepngtest/issue1105c-expected.png differ diff --git a/tests/regression/monotonepngtest/issue1105d-expected.png b/tests/regression/monotonepngtest/issue1105d-expected.png new file mode 100644 index 00000000..b5c4e5e3 Binary files /dev/null and b/tests/regression/monotonepngtest/issue1105d-expected.png differ diff --git a/tests/regression/monotonepngtest/issue1165-expected.png b/tests/regression/monotonepngtest/issue1165-expected.png new file mode 100644 index 00000000..481e8873 Binary files /dev/null and b/tests/regression/monotonepngtest/issue1165-expected.png differ diff --git a/tests/regression/monotonepngtest/issue1196-expected.png b/tests/regression/monotonepngtest/issue1196-expected.png new file mode 100644 index 00000000..677d52ca Binary files /dev/null and b/tests/regression/monotonepngtest/issue1196-expected.png differ diff --git a/tests/regression/monotonepngtest/issue1198-expected.png b/tests/regression/monotonepngtest/issue1198-expected.png new file mode 100644 index 00000000..ad9c8a86 Binary files /dev/null and b/tests/regression/monotonepngtest/issue1198-expected.png differ diff --git a/tests/regression/monotonepngtest/issue13-expected.png b/tests/regression/monotonepngtest/issue13-expected.png new file mode 100644 index 00000000..cb7fda75 Binary files /dev/null and b/tests/regression/monotonepngtest/issue13-expected.png differ diff --git a/tests/regression/monotonepngtest/issue13b-expected.png b/tests/regression/monotonepngtest/issue13b-expected.png new file mode 100644 index 00000000..2dcda55d Binary files /dev/null and b/tests/regression/monotonepngtest/issue13b-expected.png differ diff --git a/tests/regression/monotonepngtest/issue591-expected.png b/tests/regression/monotonepngtest/issue591-expected.png new file mode 100644 index 00000000..07e1559f Binary files /dev/null and b/tests/regression/monotonepngtest/issue591-expected.png differ diff --git a/tests/regression/monotonepngtest/issue666-expected.png b/tests/regression/monotonepngtest/issue666-expected.png new file mode 100644 index 00000000..08ee92b2 Binary files /dev/null and b/tests/regression/monotonepngtest/issue666-expected.png differ diff --git a/tests/regression/monotonepngtest/mirror-tests-expected.png b/tests/regression/monotonepngtest/mirror-tests-expected.png new file mode 100644 index 00000000..677d52ca Binary files /dev/null and b/tests/regression/monotonepngtest/mirror-tests-expected.png differ diff --git a/tests/regression/monotonepngtest/polyhedron-tests-expected.png b/tests/regression/monotonepngtest/polyhedron-tests-expected.png index 78f524c0..aedcb8f2 100644 Binary files a/tests/regression/monotonepngtest/polyhedron-tests-expected.png and b/tests/regression/monotonepngtest/polyhedron-tests-expected.png differ diff --git a/tests/regression/monotonepngtest/sphere-expected.png b/tests/regression/monotonepngtest/sphere-expected.png index 87bb764a..2df4f90e 100644 Binary files a/tests/regression/monotonepngtest/sphere-expected.png and b/tests/regression/monotonepngtest/sphere-expected.png differ diff --git a/tests/regression/opencsgtest/LetterBlock-expected.png b/tests/regression/opencsgtest/LetterBlock-expected.png new file mode 100644 index 00000000..bc54e670 Binary files /dev/null and b/tests/regression/opencsgtest/LetterBlock-expected.png differ diff --git a/tests/regression/opencsgtest/chopped_blocks-expected.png b/tests/regression/opencsgtest/chopped_blocks-expected.png index 1288ff68..f20736ad 100644 Binary files a/tests/regression/opencsgtest/chopped_blocks-expected.png and b/tests/regression/opencsgtest/chopped_blocks-expected.png differ diff --git a/tests/regression/opencsgtest/issue1061-expected.png b/tests/regression/opencsgtest/issue1061-expected.png index fc626374..ca886ff2 100644 Binary files a/tests/regression/opencsgtest/issue1061-expected.png and b/tests/regression/opencsgtest/issue1061-expected.png differ diff --git a/tests/regression/opencsgtest/issue1089b-expected.png b/tests/regression/opencsgtest/issue1089b-expected.png new file mode 100644 index 00000000..c4475ab6 Binary files /dev/null and b/tests/regression/opencsgtest/issue1089b-expected.png differ diff --git a/tests/regression/opencsgtest/issue1105b-expected.png b/tests/regression/opencsgtest/issue1105b-expected.png new file mode 100644 index 00000000..d124af22 Binary files /dev/null and b/tests/regression/opencsgtest/issue1105b-expected.png differ diff --git a/tests/regression/opencsgtest/issue1105c-expected.png b/tests/regression/opencsgtest/issue1105c-expected.png new file mode 100644 index 00000000..521cb7a4 Binary files /dev/null and b/tests/regression/opencsgtest/issue1105c-expected.png differ diff --git a/tests/regression/opencsgtest/issue1105d-expected.png b/tests/regression/opencsgtest/issue1105d-expected.png new file mode 100644 index 00000000..e6d2c817 Binary files /dev/null and b/tests/regression/opencsgtest/issue1105d-expected.png differ diff --git a/tests/regression/opencsgtest/issue1165-expected.png b/tests/regression/opencsgtest/issue1165-expected.png new file mode 100644 index 00000000..608a9b80 Binary files /dev/null and b/tests/regression/opencsgtest/issue1165-expected.png differ diff --git a/tests/regression/opencsgtest/issue1196-expected.png b/tests/regression/opencsgtest/issue1196-expected.png new file mode 100644 index 00000000..989385ee Binary files /dev/null and b/tests/regression/opencsgtest/issue1196-expected.png differ diff --git a/tests/regression/opencsgtest/issue1198-expected.png b/tests/regression/opencsgtest/issue1198-expected.png new file mode 100644 index 00000000..32ecddb2 Binary files /dev/null and b/tests/regression/opencsgtest/issue1198-expected.png differ diff --git a/tests/regression/opencsgtest/issue13-expected.png b/tests/regression/opencsgtest/issue13-expected.png new file mode 100644 index 00000000..9863a793 Binary files /dev/null and b/tests/regression/opencsgtest/issue13-expected.png differ diff --git a/tests/regression/opencsgtest/issue13b-expected.png b/tests/regression/opencsgtest/issue13b-expected.png new file mode 100644 index 00000000..b02397d2 Binary files /dev/null and b/tests/regression/opencsgtest/issue13b-expected.png differ diff --git a/tests/regression/opencsgtest/mirror-tests-expected.png b/tests/regression/opencsgtest/mirror-tests-expected.png new file mode 100644 index 00000000..989385ee Binary files /dev/null and b/tests/regression/opencsgtest/mirror-tests-expected.png differ diff --git a/tests/regression/opencsgtest/nullspace-minkowski-expected.png b/tests/regression/opencsgtest/nullspace-minkowski-expected.png index 08ee92b2..989385ee 100644 Binary files a/tests/regression/opencsgtest/nullspace-minkowski-expected.png and b/tests/regression/opencsgtest/nullspace-minkowski-expected.png differ diff --git a/tests/regression/opencsgtest/nullspace-minkowski-intersection-expected.png b/tests/regression/opencsgtest/nullspace-minkowski-intersection-expected.png index 08ee92b2..989385ee 100644 Binary files a/tests/regression/opencsgtest/nullspace-minkowski-intersection-expected.png and b/tests/regression/opencsgtest/nullspace-minkowski-intersection-expected.png differ diff --git a/tests/regression/opencsgtest/polyhedron-concave-test-expected.png b/tests/regression/opencsgtest/polyhedron-concave-test-expected.png new file mode 100644 index 00000000..8e3dd762 Binary files /dev/null and b/tests/regression/opencsgtest/polyhedron-concave-test-expected.png differ diff --git a/tests/regression/opencsgtest/polyhedron-tests-expected.png b/tests/regression/opencsgtest/polyhedron-tests-expected.png index 35743720..7bc5a31e 100644 Binary files a/tests/regression/opencsgtest/polyhedron-tests-expected.png and b/tests/regression/opencsgtest/polyhedron-tests-expected.png differ diff --git a/tests/regression/opencsgtest/sphere-expected.png b/tests/regression/opencsgtest/sphere-expected.png index c705bc77..38ef1d3d 100644 Binary files a/tests/regression/opencsgtest/sphere-expected.png and b/tests/regression/opencsgtest/sphere-expected.png differ diff --git a/tests/regression/throwntogethertest/LetterBlock-expected.png b/tests/regression/throwntogethertest/LetterBlock-expected.png new file mode 100644 index 00000000..d75b3135 Binary files /dev/null and b/tests/regression/throwntogethertest/LetterBlock-expected.png differ diff --git a/tests/regression/throwntogethertest/chopped_blocks-expected.png b/tests/regression/throwntogethertest/chopped_blocks-expected.png index 9bc43066..11e0cbdb 100644 Binary files a/tests/regression/throwntogethertest/chopped_blocks-expected.png and b/tests/regression/throwntogethertest/chopped_blocks-expected.png differ diff --git a/tests/regression/throwntogethertest/issue1061-expected.png b/tests/regression/throwntogethertest/issue1061-expected.png index fc626374..ca886ff2 100644 Binary files a/tests/regression/throwntogethertest/issue1061-expected.png and b/tests/regression/throwntogethertest/issue1061-expected.png differ diff --git a/tests/regression/throwntogethertest/issue1089-expected.png b/tests/regression/throwntogethertest/issue1089-expected.png new file mode 100644 index 00000000..017bb85e Binary files /dev/null and b/tests/regression/throwntogethertest/issue1089-expected.png differ diff --git a/tests/regression/throwntogethertest/issue1089b-expected.png b/tests/regression/throwntogethertest/issue1089b-expected.png new file mode 100644 index 00000000..c4475ab6 Binary files /dev/null and b/tests/regression/throwntogethertest/issue1089b-expected.png differ diff --git a/tests/regression/throwntogethertest/issue1165-expected.png b/tests/regression/throwntogethertest/issue1165-expected.png new file mode 100644 index 00000000..e4c5c615 Binary files /dev/null and b/tests/regression/throwntogethertest/issue1165-expected.png differ diff --git a/tests/regression/throwntogethertest/issue1196-expected.png b/tests/regression/throwntogethertest/issue1196-expected.png new file mode 100644 index 00000000..989385ee Binary files /dev/null and b/tests/regression/throwntogethertest/issue1196-expected.png differ diff --git a/tests/regression/throwntogethertest/issue1198-expected.png b/tests/regression/throwntogethertest/issue1198-expected.png new file mode 100644 index 00000000..32ecddb2 Binary files /dev/null and b/tests/regression/throwntogethertest/issue1198-expected.png differ diff --git a/tests/regression/throwntogethertest/mirror-tests-expected.png b/tests/regression/throwntogethertest/mirror-tests-expected.png new file mode 100644 index 00000000..989385ee Binary files /dev/null and b/tests/regression/throwntogethertest/mirror-tests-expected.png differ diff --git a/tests/regression/throwntogethertest/nullspace-minkowski-expected.png b/tests/regression/throwntogethertest/nullspace-minkowski-expected.png index 08ee92b2..989385ee 100644 Binary files a/tests/regression/throwntogethertest/nullspace-minkowski-expected.png and b/tests/regression/throwntogethertest/nullspace-minkowski-expected.png differ diff --git a/tests/regression/throwntogethertest/nullspace-minkowski-intersection-expected.png b/tests/regression/throwntogethertest/nullspace-minkowski-intersection-expected.png index 08ee92b2..989385ee 100644 Binary files a/tests/regression/throwntogethertest/nullspace-minkowski-intersection-expected.png and b/tests/regression/throwntogethertest/nullspace-minkowski-intersection-expected.png differ diff --git a/tests/regression/throwntogethertest/polyhedron-concave-test-expected.png b/tests/regression/throwntogethertest/polyhedron-concave-test-expected.png new file mode 100644 index 00000000..8e3dd762 Binary files /dev/null and b/tests/regression/throwntogethertest/polyhedron-concave-test-expected.png differ diff --git a/tests/regression/throwntogethertest/polyhedron-tests-expected.png b/tests/regression/throwntogethertest/polyhedron-tests-expected.png index 15e083ec..6e5fb6d9 100644 Binary files a/tests/regression/throwntogethertest/polyhedron-tests-expected.png and b/tests/regression/throwntogethertest/polyhedron-tests-expected.png differ diff --git a/tests/regression/throwntogethertest/sphere-expected.png b/tests/regression/throwntogethertest/sphere-expected.png index 360d6eb5..0c85b238 100644 Binary files a/tests/regression/throwntogethertest/sphere-expected.png and b/tests/regression/throwntogethertest/sphere-expected.png differ diff --git a/up.png b/up.png deleted file mode 100644 index ec525008..00000000 Binary files a/up.png and /dev/null differ diff --git a/src/winconsole.c b/winconsole/winconsole.c similarity index 100% rename from src/winconsole.c rename to winconsole/winconsole.c diff --git a/winconsole.pro b/winconsole/winconsole.pro similarity index 83% rename from winconsole.pro rename to winconsole/winconsole.pro index 11078f36..8b423a6a 100644 --- a/winconsole.pro +++ b/winconsole/winconsole.pro @@ -11,13 +11,13 @@ # properly TEMPLATE = app -TARGET = openscad_winconsole +TARGET = winconsole FORMS = HEADERS = FLEXSOURCES = BISONSOURCES = RESOURCES = -SOURCES = src/winconsole.c +SOURCES = winconsole.c CONFIG -= qt CONFIG += console # sets IMAGE_SUBSYSTEM_WINDOWS_CUI in binary -QMAKE_POST_LINK = cd $(DESTDIR) && mv openscad_winconsole.exe openscad.com +QMAKE_POST_LINK = cd $(DESTDIR) && mv winconsole.exe openscad.com diff --git a/xcode/OpenSCAD.xcodeproj/project.pbxproj b/xcode/OpenSCAD.xcodeproj/project.pbxproj index 418fa3fc..9535d40b 100644 --- a/xcode/OpenSCAD.xcodeproj/project.pbxproj +++ b/xcode/OpenSCAD.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ E0034E2019AA8409009F0BD0 /* dummy.c in Sources */ = {isa = PBXBuildFile; fileRef = E0034E1F19AA8409009F0BD0 /* dummy.c */; }; E018B43619AA8AA1004C9DF7 /* dummy.c in Sources */ = {isa = PBXBuildFile; fileRef = E0034E1F19AA8409009F0BD0 /* dummy.c */; }; + E0ED6EC71A50B0F3007E979A /* Test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E0ED6EC51A50B0F3007E979A /* Test.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -262,6 +263,10 @@ E0BD020A1979C2D90020CC1B /* FontListDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FontListDialog.h; sourceTree = ""; }; E0BD020B1979C2D90020CC1B /* FreetypeRenderer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FreetypeRenderer.cc; sourceTree = ""; }; E0BD020C1979C2D90020CC1B /* FreetypeRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FreetypeRenderer.h; sourceTree = ""; }; + E0ED6EC51A50B0F3007E979A /* Test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Test.cpp; path = ../Test.cpp; sourceTree = ""; }; + E0ED6EC61A50B0F3007E979A /* Test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Test.h; path = ../Test.h; sourceTree = ""; }; + E0F8E5411A5B02AB004723C5 /* cgalutils-polyhedron.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "cgalutils-polyhedron.cc"; sourceTree = ""; }; + E0FCDD621A27B96C0024E633 /* clipper-utils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "clipper-utils.cc"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXGroup section */ @@ -276,6 +281,8 @@ E022640517C307FA00499974 = { isa = PBXGroup; children = ( + E0ED6EC51A50B0F3007E979A /* Test.cpp */, + E0ED6EC61A50B0F3007E979A /* Test.h */, E018B43719AA8B2D004C9DF7 /* dummy sources */, E05FBE6A17C30A05004F525B /* src */, E056783C19AA721200F5650C /* Products */, @@ -328,11 +335,13 @@ E05FBE8817C30A05004F525B /* CGALRenderer.cc */, E05FBE8917C30A05004F525B /* CGALRenderer.h */, E091574D19AA58C900D699E9 /* cgalutils-tess.cc */, + E0F8E5411A5B02AB004723C5 /* cgalutils-polyhedron.cc */, E05FBE8A17C30A05004F525B /* cgalutils.cc */, E05FBE8B17C30A05004F525B /* cgalutils.h */, E05FBE8C17C30A05004F525B /* cgalworker.cc */, E05FBE8D17C30A05004F525B /* cgalworker.h */, E091574E19AA58C900D699E9 /* clipper-utils.h */, + E0FCDD621A27B96C0024E633 /* clipper-utils.cc */, E05FBE8E17C30A05004F525B /* CocoaUtils.h */, E05FBE8F17C30A05004F525B /* CocoaUtils.mm */, E05FBE9017C30A05004F525B /* color.cc */, @@ -661,6 +670,7 @@ buildActionMask = 2147483647; files = ( E0034E2019AA8409009F0BD0 /* dummy.c in Sources */, + E0ED6EC71A50B0F3007E979A /* Test.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/OpenSCAD.app.xcscheme b/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/OpenSCAD.app.xcscheme index 34ad778b..4779571b 100644 --- a/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/OpenSCAD.app.xcscheme +++ b/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/OpenSCAD.app.xcscheme @@ -60,13 +60,41 @@ + + + + + + + + + + + + + + diff --git a/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/openscad_nogui.xcscheme b/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/openscad_nogui.xcscheme index f230c7fa..4e34982a 100644 --- a/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/openscad_nogui.xcscheme +++ b/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/openscad_nogui.xcscheme @@ -58,6 +58,16 @@ ReferencedContainer = "container:OpenSCAD.xcodeproj"> + + + + + +