diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 51c992b3d65bffe8670033265a1b3517612586fe..e0ce0d971c6af9c3f06333aa7202a5a7adaada58 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,4 +5,4 @@ ubuntu16.04: - cd build - cmake .. - make -j 4 - - ctest --output-on-failure + - ctest -j 4 --output-on-failure diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 60ce02d777a9cec74a3cd3e221b1cd4f0b19b58c..632a6624cd08369e8353efe019937b374a8073d4 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,7 @@ +3.0.2: improved handling of meshing constraints and entity numbering after +boolean operations; improved handling of fast coarseness transitions in +MeshAdapt. + 3.0.1 (April 14, 2017): fixed OpenCASCADE plane surfaces with holes. 3.0.0 (April 13, 2017): new constructive solid geometry features and boolean diff --git a/CREDITS.txt b/CREDITS.txt index 0f97a60a3a304113a62b36e71fe980bac07b073b..d18eee3cfc7f056f1cdf4359b6c0e0e803280d7f 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -42,6 +42,25 @@ specific, written prior permission. The University of California makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. +The picojson code (Common/picojson.h) is Copyright 2009-2010 Cybozu Labs, Inc., +Copyright 2011-2014 Kazuho Oku, All rights reserved. Redistribution and use in +source and binary forms, with or without modification, are permitted provided +that the following conditions are met: 1. Redistributions of source code must +retain the above copyright notice, this list of conditions and the following +disclaimer. 2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. THIS +SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + The trackball code (Graphics/Trackball.{cpp.h}) is copyright (C) 1993, 1994, Silicon Graphics, Inc. ALL RIGHTS RESERVED. Permission to use, copy, modify, and distribute this software for any purpose and without fee is hereby granted, diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp index d2fcb73b3640babdbca5f9b8b67085244b566522..1cb76601e4bb296cc083ae4200f291ea8e9521ef 100644 --- a/Common/CommandLine.cpp +++ b/Common/CommandLine.cpp @@ -184,9 +184,9 @@ std::vector<std::pair<std::string, std::string> > GetShortcutsUsage(const std::s s.push_back(mp("p", "Go to post-processing module")); s.push_back(mp("q", "Abort selection in geometry creation mode")); s.push_back(mp("s", "Go to solver module")); - s.push_back(mp("x", "Freeze x coordinate in geometry creation mode")); - s.push_back(mp("y", "Freeze y coordinate in geometry creation mode")); - s.push_back(mp("z", "Freeze z coordinate in geometry creation mode")); + s.push_back(mp("x", "Toogle x coordinate freeze in geometry creation mode")); + s.push_back(mp("y", "Toogle y coordinate freeze in geometry creation mode")); + s.push_back(mp("z", "Toogle z coordinate freeze in geometry creation mode")); s.push_back(mp("Shift+a", "Bring all windows to front")); s.push_back(mp("Shift+g", "Show geometry options")); s.push_back(mp("Shift+m", "Show mesh options")); @@ -195,6 +195,9 @@ std::vector<std::pair<std::string, std::string> > GetShortcutsUsage(const std::s s.push_back(mp("Shift+s", "Show solver options")); s.push_back(mp("Shift+u", "Show post-processing view plugins")); s.push_back(mp("Shift+w", "Show post-processing view options")); + s.push_back(mp("Shift+x", "Move only along x coordinate in geometry creation mode")); + s.push_back(mp("Shift+y", "Move only along y coordinate in geometry creation mode")); + s.push_back(mp("Shift+z", "Move only along z coordinate in geometry creation mode")); s.push_back(mp("Shift+Escape", "Enable full mouse selection")); s.push_back(mp(cc + "d", "Attach/detach menu")); s.push_back(mp(cc + "e", "Export project")); diff --git a/Common/Context.h b/Common/Context.h index 7613c162d64623ab46a610cf27aaabd01db6929e..3d021709dc5d4413aba63f9be5852f8c041399bc 100644 --- a/Common/Context.h +++ b/Common/Context.h @@ -75,7 +75,7 @@ struct contextGeometryOptions { int autoCoherence, highlightOrphans, clip, useTransform; double tolerance, toleranceBoolean, snap[3], transform[3][3], offset[3]; int occFixDegenerated, occFixSmallEdges, occFixSmallFaces; - int occSewFaces, occParallel; + int occSewFaces, occParallel, occBooleanPreserveNumbering; double occScaling; int copyMeshingMethod, exactExtrusion; int matchGeomAndMesh; diff --git a/Common/CreateFile.cpp b/Common/CreateFile.cpp index 721ba257217b6b62760a396c8b505b3a27b22bd2..f744e81f1ec5484322bf62cc01199dc48c4b51c5 100644 --- a/Common/CreateFile.cpp +++ b/Common/CreateFile.cpp @@ -71,6 +71,7 @@ int GetFileFormatFromExtension(const std::string &ext) else if(ext == ".pdf") return FORMAT_PDF; else if(ext == ".tex") return FORMAT_TEX; else if(ext == ".svg") return FORMAT_SVG; + else if(ext == ".tikz") return FORMAT_TIKZ; else if(ext == ".ppm") return FORMAT_PPM; else if(ext == ".yuv") return FORMAT_YUV; else if(ext == ".brep") return FORMAT_BREP; @@ -120,12 +121,13 @@ std::string GetDefaultFileName(int format) case FORMAT_JPEG: name += ".jpg"; break; case FORMAT_MPEG: name += ".mpg"; break; case FORMAT_PNG: name += ".png"; break; - case FORMAT_PGF: name += ".todo"; break; + case FORMAT_PGF: name += ".pgf"; break; case FORMAT_PS: name += ".ps"; break; case FORMAT_EPS: name += ".eps"; break; case FORMAT_PDF: name += ".pdf"; break; case FORMAT_TEX: name += ".tex"; break; case FORMAT_SVG: name += ".svg"; break; + case FORMAT_TIKZ: name += ".tikz"; break; case FORMAT_PPM: name += ".ppm"; break; case FORMAT_YUV: name += ".yuv"; break; case FORMAT_BREP: name += ".brep"; break; @@ -437,6 +439,7 @@ void CreateOutputFile(const std::string &fileName, int format, case FORMAT_EPS: case FORMAT_PDF: case FORMAT_SVG: + case FORMAT_TIKZ: { if(!FlGui::available()) break; @@ -460,6 +463,7 @@ void CreateOutputFile(const std::string &fileName, int format, (format == FORMAT_PDF) ? GL2PS_PDF : (format == FORMAT_PS) ? GL2PS_PS : (format == FORMAT_SVG) ? GL2PS_SVG : + (format == FORMAT_TIKZ) ? GL2PS_PGF : GL2PS_EPS; int pssort = (CTX::instance()->print.epsQuality == 3) ? GL2PS_NO_SORT : diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h index 7580d87431db8d595614a6ee8f42fb44124ec722..c4f89781352b3b984ccb3cc48b86cbcb62bd8330 100644 --- a/Common/DefaultOptions.h +++ b/Common/DefaultOptions.h @@ -870,6 +870,8 @@ StringXNumber GeometryOptions_Number[] = { "Sew faces in STEP, IGES and BRep models" }, { F|O, "OCCParallel" , opt_geometry_occ_parallel , 0. , "Use multi-threaded OCC boolean operators" }, + { F|O, "OCCBooleanPreserveNumbering" , opt_geometry_occ_boolean_preserve_numbering , 1. , + "Try to preserve numbering of entities through OCC boolean operations" }, { F|O, "OCCScaling" , opt_geometry_occ_scaling , 1. , "Scale STEP, IGES and BRep model by given factor" }, { F, "OffsetX" , opt_geometry_offset0 , 0. , diff --git a/Common/GmshDefines.h b/Common/GmshDefines.h index e80216beef89d4a488c5d2abaaa5db4c56d5844d..630462e3fd90e1cf2571754bc7be9ec00270d903 100644 --- a/Common/GmshDefines.h +++ b/Common/GmshDefines.h @@ -54,6 +54,7 @@ #define FORMAT_PVTU 45 #define FORMAT_X3D 46 #define FORMAT_TOCHNOG 47 +#define FORMAT_TIKZ 48 // Element types #define TYPE_PNT 1 diff --git a/Common/Options.cpp b/Common/Options.cpp index 54ff43da23b3bcb820f19e7bf673c9a4271495ba..e5fe4fe33a7ab6bbcabd51a5bd3397d19feb4c72 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -4741,6 +4741,13 @@ double opt_geometry_occ_parallel(OPT_ARGS_NUM) return CTX::instance()->geom.occParallel; } +double opt_geometry_occ_boolean_preserve_numbering(OPT_ARGS_NUM) +{ + if(action & GMSH_SET) + CTX::instance()->geom.occBooleanPreserveNumbering = (int)val; + return CTX::instance()->geom.occBooleanPreserveNumbering; +} + double opt_geometry_occ_scaling(OPT_ARGS_NUM) { if(action & GMSH_SET) diff --git a/Common/Options.h b/Common/Options.h index f9de4ad20b12302a4d5818d49d71a2781b204733..8a2e7791340e4887a731eca98a3eb4ff64597908 100644 --- a/Common/Options.h +++ b/Common/Options.h @@ -387,6 +387,7 @@ double opt_geometry_occ_fix_small_edges(OPT_ARGS_NUM); double opt_geometry_occ_fix_small_faces(OPT_ARGS_NUM); double opt_geometry_occ_sew_faces(OPT_ARGS_NUM); double opt_geometry_occ_parallel(OPT_ARGS_NUM); +double opt_geometry_occ_boolean_preserve_numbering(OPT_ARGS_NUM); double opt_geometry_occ_scaling(OPT_ARGS_NUM); double opt_geometry_old_circle(OPT_ARGS_NUM); double opt_geometry_old_newreg(OPT_ARGS_NUM); diff --git a/Common/onelab.h b/Common/onelab.h index 0a49bb04e8e004b3bfbfc556a9da2c7cd7ae2eac..6ae9071ef09ed4f49f2bdeaea0332fa75d73e46f 100644 --- a/Common/onelab.h +++ b/Common/onelab.h @@ -38,6 +38,7 @@ #include <algorithm> #include <sstream> #include "GmshSocket.h" +#include "picojson.h" namespace onelab{ @@ -346,11 +347,63 @@ namespace onelab{ it != getClients().end(); it++){ if(it != getClients().begin()) sstream << ", "; sstream << "\"" << sanitize(it->first) << "\":" - << (it->second ? "true" : "false"); + << it->second; } sstream << " }"; return sstream.str(); } + virtual bool fromJSON(const picojson::value::object& par) + { + for(picojson::value::object::const_iterator it = par.begin(); it != par.end(); ++it){ + if(it->first == "version"){ + if(!it->second.is<std::string>()) return false; + if(it->second.get<std::string>() != version()) return false; + } + else if(it->first == "name"){ + if(!it->second.is<std::string>()) return false; + setName(it->second.get<std::string>()); + } + else if(it->first == "label"){ + if(!it->second.is<std::string>()) return false; + setLabel(it->second.get<std::string>()); + } + else if(it->first == "help"){ + if(!it->second.is<std::string>()) return false; + setHelp(it->second.get<std::string>()); + } + else if(it->first == "changedValue"){ + if(!it->second.is<double>()) return false; + setChangedValue((int)it->second.get<double>()); + } + else if(it->first == "visible"){ + if(!it->second.is<bool>()) return false; + setVisible(it->second.get<bool>()); + } + else if(it->first == "readOnly"){ + if(!it->second.is<bool>()) return false; + setReadOnly(it->second.get<bool>()); + } + else if(it->first == "attributes"){ + if(!it->second.is<picojson::object>()) return false; + const picojson::value::object &obj = it->second.get<picojson::object>(); + for (picojson::value::object::const_iterator i = obj.begin(); i != obj.end(); ++i) { + std::string key(i->first); + if(!i->second.is<std::string>()) return false; + setAttribute(key, i->second.get<std::string>()); + } + } + else if(it->first == "clients"){ + if(!it->second.is<picojson::object>()) return false; + const picojson::value::object &obj = it->second.get<picojson::object>(); + for (picojson::value::object::const_iterator i = obj.begin(); i != obj.end(); ++i) { + std::string client(i->first); + if(!i->second.is<double>()) return false; + addClient(client, (int)i->second.get<double>()); + } + } + } + return true; + } }; class parameterLessThan{ @@ -515,6 +568,55 @@ namespace onelab{ sstream << " } }"; return sstream.str(); } + bool fromJSON(const picojson::value::object& par) + { + if(!parameter::fromJSON(par)) return false; + for(picojson::value::object::const_iterator it = par.begin(); it != par.end(); ++it){ + if(it->first == "values"){ + if(!it->second.is<picojson::array>()) return false; + const picojson::value::array &arr = it->second.get<picojson::array>(); + _values.resize(arr.size()); + for(unsigned int i = 0; i < arr.size(); i++){ + if(!arr[i].is<double>()) return false; + _values[i] = arr[i].get<double>(); + } + } + else if(it->first == "min"){ + if(!it->second.is<double>()) return false; + setMin(it->second.get<double>()); + } + else if(it->first == "max"){ + if(!it->second.is<double>()) return false; + setMax(it->second.get<double>()); + } + else if(it->first == "step"){ + if(!it->second.is<double>()) return false; + setStep(it->second.get<double>()); + } + else if(it->first == "index"){ + if(!it->second.is<double>()) return false; + setIndex((int)it->second.get<double>()); + } + else if(it->first == "choices"){ + if(!it->second.is<picojson::array>()) return false; + const picojson::value::array &arr = it->second.get<picojson::array>(); + _choices.resize(arr.size()); + for(unsigned int i = 0; i < arr.size(); i++){ + if(!arr[i].is<double>()) return false; + _choices[i] = arr[i].get<double>(); + } + } + else if(it->first == "valueLabels"){ + if(!it->second.is<picojson::object>()) return false; + const picojson::value::object &obj = it->second.get<picojson::object>(); + for (picojson::value::object::const_iterator i = obj.begin(); i != obj.end(); ++i) { + if(!i->second.is<double>()) return false; + _valueLabels[i->second.get<double>()] = i->first; + } + } + } + return true; + } }; // The string class. A string has a mutable "kind", that can be changed at @@ -610,6 +712,35 @@ namespace onelab{ sstream << " ] }"; return sstream.str(); } + bool fromJSON(const picojson::value::object& par) + { + if(!parameter::fromJSON(par)) return false; + for(picojson::value::object::const_iterator it = par.begin(); it != par.end(); ++it){ + if(it->first == "values"){ + if(!it->second.is<picojson::array>()) return false; + const picojson::value::array &arr = it->second.get<picojson::array>(); + _values.resize(arr.size()); + for(unsigned int i = 0; i < arr.size(); i++){ + if(!arr[i].is<std::string>()) return false; + _values[i] = arr[i].get<std::string>(); + } + } + else if(it->first == "kind"){ + if(!it->second.is<std::string>()) return false; + setKind(it->second.get<std::string>()); + } + else if(it->first == "choices"){ + if(!it->second.is<picojson::array>()) return false; + const picojson::value::array &arr = it->second.get<picojson::array>(); + _choices.resize(arr.size()); + for(unsigned int i = 0; i < arr.size(); i++){ + if(!arr[i].is<std::string>()) return false; + _choices[i] = arr[i].get<std::string>(); + } + } + } + return true; + } }; // The parameter space, i.e., the set of parameters stored and handled by the @@ -841,7 +972,7 @@ namespace onelab{ } return true; } - void toJSON(std::string &json, const std::string &creator="", + bool toJSON(std::string &json, const std::string &creator="", const std::string &client="") const { time_t now; @@ -865,6 +996,40 @@ namespace onelab{ } } json += "] }\n}\n"; + return true; + } + bool fromJSON(const std::string &json, const std::string &client="") + { + picojson::value v; + std::string err = picojson::parse(v, json); + if(err.size()) return false; + if(!v.is<picojson::object>()) return false; + const picojson::value::object &obj = v.get<picojson::object>(); + for (picojson::value::object::const_iterator i = obj.begin(); i != obj.end(); ++i) { + if(i->first == "onelab"){ // onelab database + if(!i->second.is<picojson::object>()) return false; + const picojson::value::object &db = i->second.get<picojson::object>(); + for (picojson::value::object::const_iterator j = db.begin(); j != db.end(); ++j) { + if(j->first == "parameters"){ + if(!j->second.is<picojson::array>()) return false; + const picojson::value::array &arr = j->second.get<picojson::array>(); + for(unsigned int k = 0; k < arr.size(); k++){ + if(!arr[k].is<picojson::object>()) return false; + const picojson::value::object &par = arr[k].get<picojson::object>(); + picojson::value::object::const_iterator it = par.find("type"); + if(it == par.end()) return false; + if(it->second.to_str() == "number"){ + number p; p.fromJSON(par); set(p, client); + } + else if(it->second.to_str() == "string"){ + string p; p.fromJSON(par); set(p, client); + } + } + } + } + } + } + return true; } }; @@ -1026,9 +1191,13 @@ namespace onelab{ if(parameter::fromFile(msg, fp)) return fromChar(msg, client); return false; } - void toJSON(std::string &json, const std::string &client="") + bool toJSON(std::string &json, const std::string &client="") + { + return _parameterSpace.toJSON(json, client); + } + bool fromJSON(const std::string &json, const std::string &client="") { - _parameterSpace.toJSON(json, client); + return _parameterSpace.fromJSON(json, client); } }; diff --git a/Common/picojson.h b/Common/picojson.h new file mode 100644 index 0000000000000000000000000000000000000000..f75c399b7e7380bdac4fbb25019e6ce499714f26 --- /dev/null +++ b/Common/picojson.h @@ -0,0 +1,1160 @@ +/* + * Copyright 2009-2010 Cybozu Labs, Inc. + * Copyright 2011-2014 Kazuho Oku + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef picojson_h +#define picojson_h + +#include <algorithm> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <cstddef> +#include <iostream> +#include <iterator> +#include <limits> +#include <map> +#include <stdexcept> +#include <string> +#include <vector> +#include <utility> + +// for isnan/isinf +#if __cplusplus >= 201103L +#include <cmath> +#else +extern "C" { +#ifdef _MSC_VER +#include <float.h> +#elif defined(__INTEL_COMPILER) +#include <mathimf.h> +#else +#include <math.h> +#endif +} +#endif + +#ifndef PICOJSON_USE_RVALUE_REFERENCE +#if (defined(__cpp_rvalue_references) && __cpp_rvalue_references >= 200610) || (defined(_MSC_VER) && _MSC_VER >= 1600) +#define PICOJSON_USE_RVALUE_REFERENCE 1 +#else +#define PICOJSON_USE_RVALUE_REFERENCE 0 +#endif +#endif // PICOJSON_USE_RVALUE_REFERENCE + +// experimental support for int64_t (see README.mkdn for detail) +#ifdef PICOJSON_USE_INT64 +#define __STDC_FORMAT_MACROS +#include <errno.h> +#include <inttypes.h> +#endif + +// to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0 +#ifndef PICOJSON_USE_LOCALE +#define PICOJSON_USE_LOCALE 1 +#endif +#if PICOJSON_USE_LOCALE +extern "C" { +#include <locale.h> +} +#endif + +#ifndef PICOJSON_ASSERT +#define PICOJSON_ASSERT(e) \ + do { \ + if (!(e)) \ + throw std::runtime_error(#e); \ + } while (0) +#endif + +#ifdef _MSC_VER +#define SNPRINTF _snprintf_s +#pragma warning(push) +#pragma warning(disable : 4244) // conversion from int to char +#pragma warning(disable : 4127) // conditional expression is constant +#pragma warning(disable : 4702) // unreachable code +#else +#define SNPRINTF snprintf +#endif + +namespace picojson { + +enum { + null_type, + boolean_type, + number_type, + string_type, + array_type, + object_type +#ifdef PICOJSON_USE_INT64 + , + int64_type +#endif +}; + +enum { INDENT_WIDTH = 2 }; + +struct null {}; + +class value { +public: + typedef std::vector<value> array; + typedef std::map<std::string, value> object; + union _storage { + bool boolean_; + double number_; +#ifdef PICOJSON_USE_INT64 + int64_t int64_; +#endif + std::string *string_; + array *array_; + object *object_; + }; + +protected: + int type_; + _storage u_; + +public: + value(); + value(int type, bool); + explicit value(bool b); +#ifdef PICOJSON_USE_INT64 + explicit value(int64_t i); +#endif + explicit value(double n); + explicit value(const std::string &s); + explicit value(const array &a); + explicit value(const object &o); +#if PICOJSON_USE_RVALUE_REFERENCE + explicit value(std::string &&s); + explicit value(array &&a); + explicit value(object &&o); +#endif + explicit value(const char *s); + value(const char *s, size_t len); + ~value(); + value(const value &x); + value &operator=(const value &x); +#if PICOJSON_USE_RVALUE_REFERENCE + value(value &&x) throw(); + value &operator=(value &&x) throw(); +#endif + void swap(value &x) throw(); + template <typename T> bool is() const; + template <typename T> const T &get() const; + template <typename T> T &get(); + template <typename T> void set(const T &); +#if PICOJSON_USE_RVALUE_REFERENCE + template <typename T> void set(T &&); +#endif + bool evaluate_as_boolean() const; + const value &get(const size_t idx) const; + const value &get(const std::string &key) const; + value &get(const size_t idx); + value &get(const std::string &key); + + bool contains(const size_t idx) const; + bool contains(const std::string &key) const; + std::string to_str() const; + template <typename Iter> void serialize(Iter os, bool prettify = false) const; + std::string serialize(bool prettify = false) const; + +private: + template <typename T> value(const T *); // intentionally defined to block implicit conversion of pointer to bool + template <typename Iter> static void _indent(Iter os, int indent); + template <typename Iter> void _serialize(Iter os, int indent) const; + std::string _serialize(int indent) const; + void clear(); +}; + +typedef value::array array; +typedef value::object object; + +inline value::value() : type_(null_type), u_() { +} + +inline value::value(int type, bool) : type_(type), u_() { + switch (type) { +#define INIT(p, v) \ + case p##type: \ + u_.p = v; \ + break + INIT(boolean_, false); + INIT(number_, 0.0); +#ifdef PICOJSON_USE_INT64 + INIT(int64_, 0); +#endif + INIT(string_, new std::string()); + INIT(array_, new array()); + INIT(object_, new object()); +#undef INIT + default: + break; + } +} + +inline value::value(bool b) : type_(boolean_type), u_() { + u_.boolean_ = b; +} + +#ifdef PICOJSON_USE_INT64 +inline value::value(int64_t i) : type_(int64_type), u_() { + u_.int64_ = i; +} +#endif + +inline value::value(double n) : type_(number_type), u_() { + if ( +#ifdef _MSC_VER + !_finite(n) +#elif __cplusplus >= 201103L || !(defined(isnan) && defined(isinf)) + std::isnan(n) || std::isinf(n) +#else + isnan(n) || isinf(n) +#endif + ) { + throw std::overflow_error(""); + } + u_.number_ = n; +} + +inline value::value(const std::string &s) : type_(string_type), u_() { + u_.string_ = new std::string(s); +} + +inline value::value(const array &a) : type_(array_type), u_() { + u_.array_ = new array(a); +} + +inline value::value(const object &o) : type_(object_type), u_() { + u_.object_ = new object(o); +} + +#if PICOJSON_USE_RVALUE_REFERENCE +inline value::value(std::string &&s) : type_(string_type), u_() { + u_.string_ = new std::string(std::move(s)); +} + +inline value::value(array &&a) : type_(array_type), u_() { + u_.array_ = new array(std::move(a)); +} + +inline value::value(object &&o) : type_(object_type), u_() { + u_.object_ = new object(std::move(o)); +} +#endif + +inline value::value(const char *s) : type_(string_type), u_() { + u_.string_ = new std::string(s); +} + +inline value::value(const char *s, size_t len) : type_(string_type), u_() { + u_.string_ = new std::string(s, len); +} + +inline void value::clear() { + switch (type_) { +#define DEINIT(p) \ + case p##type: \ + delete u_.p; \ + break + DEINIT(string_); + DEINIT(array_); + DEINIT(object_); +#undef DEINIT + default: + break; + } +} + +inline value::~value() { + clear(); +} + +inline value::value(const value &x) : type_(x.type_), u_() { + switch (type_) { +#define INIT(p, v) \ + case p##type: \ + u_.p = v; \ + break + INIT(string_, new std::string(*x.u_.string_)); + INIT(array_, new array(*x.u_.array_)); + INIT(object_, new object(*x.u_.object_)); +#undef INIT + default: + u_ = x.u_; + break; + } +} + +inline value &value::operator=(const value &x) { + if (this != &x) { + value t(x); + swap(t); + } + return *this; +} + +#if PICOJSON_USE_RVALUE_REFERENCE +inline value::value(value &&x) throw() : type_(null_type), u_() { + swap(x); +} +inline value &value::operator=(value &&x) throw() { + swap(x); + return *this; +} +#endif +inline void value::swap(value &x) throw() { + std::swap(type_, x.type_); + std::swap(u_, x.u_); +} + +#define IS(ctype, jtype) \ + template <> inline bool value::is<ctype>() const { \ + return type_ == jtype##_type; \ + } +IS(null, null) +IS(bool, boolean) +#ifdef PICOJSON_USE_INT64 +IS(int64_t, int64) +#endif +IS(std::string, string) +IS(array, array) +IS(object, object) +#undef IS +template <> inline bool value::is<double>() const { + return type_ == number_type +#ifdef PICOJSON_USE_INT64 + || type_ == int64_type +#endif + ; +} + +#define GET(ctype, var) \ + template <> inline const ctype &value::get<ctype>() const { \ + PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \ + return var; \ + } \ + template <> inline ctype &value::get<ctype>() { \ + PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \ + return var; \ + } +GET(bool, u_.boolean_) +GET(std::string, *u_.string_) +GET(array, *u_.array_) +GET(object, *u_.object_) +#ifdef PICOJSON_USE_INT64 +GET(double, + (type_ == int64_type && (const_cast<value *>(this)->type_ = number_type, const_cast<value *>(this)->u_.number_ = u_.int64_), + u_.number_)) +GET(int64_t, u_.int64_) +#else +GET(double, u_.number_) +#endif +#undef GET + +#define SET(ctype, jtype, setter) \ + template <> inline void value::set<ctype>(const ctype &_val) { \ + clear(); \ + type_ = jtype##_type; \ + setter \ + } +SET(bool, boolean, u_.boolean_ = _val;) +SET(std::string, string, u_.string_ = new std::string(_val);) +SET(array, array, u_.array_ = new array(_val);) +SET(object, object, u_.object_ = new object(_val);) +SET(double, number, u_.number_ = _val;) +#ifdef PICOJSON_USE_INT64 +SET(int64_t, int64, u_.int64_ = _val;) +#endif +#undef SET + +#if PICOJSON_USE_RVALUE_REFERENCE +#define MOVESET(ctype, jtype, setter) \ + template <> inline void value::set<ctype>(ctype && _val) { \ + clear(); \ + type_ = jtype##_type; \ + setter \ + } +MOVESET(std::string, string, u_.string_ = new std::string(std::move(_val));) +MOVESET(array, array, u_.array_ = new array(std::move(_val));) +MOVESET(object, object, u_.object_ = new object(std::move(_val));) +#undef MOVESET +#endif + +inline bool value::evaluate_as_boolean() const { + switch (type_) { + case null_type: + return false; + case boolean_type: + return u_.boolean_; + case number_type: + return u_.number_ != 0; +#ifdef PICOJSON_USE_INT64 + case int64_type: + return u_.int64_ != 0; +#endif + case string_type: + return !u_.string_->empty(); + default: + return true; + } +} + +inline const value &value::get(const size_t idx) const { + static value s_null; + PICOJSON_ASSERT(is<array>()); + return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; +} + +inline value &value::get(const size_t idx) { + static value s_null; + PICOJSON_ASSERT(is<array>()); + return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; +} + +inline const value &value::get(const std::string &key) const { + static value s_null; + PICOJSON_ASSERT(is<object>()); + object::const_iterator i = u_.object_->find(key); + return i != u_.object_->end() ? i->second : s_null; +} + +inline value &value::get(const std::string &key) { + static value s_null; + PICOJSON_ASSERT(is<object>()); + object::iterator i = u_.object_->find(key); + return i != u_.object_->end() ? i->second : s_null; +} + +inline bool value::contains(const size_t idx) const { + PICOJSON_ASSERT(is<array>()); + return idx < u_.array_->size(); +} + +inline bool value::contains(const std::string &key) const { + PICOJSON_ASSERT(is<object>()); + object::const_iterator i = u_.object_->find(key); + return i != u_.object_->end(); +} + +inline std::string value::to_str() const { + switch (type_) { + case null_type: + return "null"; + case boolean_type: + return u_.boolean_ ? "true" : "false"; +#ifdef PICOJSON_USE_INT64 + case int64_type: { + char buf[sizeof("-9223372036854775808")]; + SNPRINTF(buf, sizeof(buf), "%" PRId64, u_.int64_); + return buf; + } +#endif + case number_type: { + char buf[256]; + double tmp; + SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.17g", u_.number_); +#if PICOJSON_USE_LOCALE + char *decimal_point = localeconv()->decimal_point; + if (strcmp(decimal_point, ".") != 0) { + size_t decimal_point_len = strlen(decimal_point); + for (char *p = buf; *p != '\0'; ++p) { + if (strncmp(p, decimal_point, decimal_point_len) == 0) { + return std::string(buf, p) + "." + (p + decimal_point_len); + } + } + } +#endif + return buf; + } + case string_type: + return *u_.string_; + case array_type: + return "array"; + case object_type: + return "object"; + default: + PICOJSON_ASSERT(0); +#ifdef _MSC_VER + __assume(0); +#endif + } + return std::string(); +} + +template <typename Iter> void copy(const std::string &s, Iter oi) { + std::copy(s.begin(), s.end(), oi); +} + +template <typename Iter> struct serialize_str_char { + Iter oi; + void operator()(char c) { + switch (c) { +#define MAP(val, sym) \ + case val: \ + copy(sym, oi); \ + break + MAP('"', "\\\""); + MAP('\\', "\\\\"); + MAP('/', "\\/"); + MAP('\b', "\\b"); + MAP('\f', "\\f"); + MAP('\n', "\\n"); + MAP('\r', "\\r"); + MAP('\t', "\\t"); +#undef MAP + default: + if (static_cast<unsigned char>(c) < 0x20 || c == 0x7f) { + char buf[7]; + SNPRINTF(buf, sizeof(buf), "\\u%04x", c & 0xff); + copy(buf, buf + 6, oi); + } else { + *oi++ = c; + } + break; + } + } +}; + +template <typename Iter> void serialize_str(const std::string &s, Iter oi) { + *oi++ = '"'; + serialize_str_char<Iter> process_char = {oi}; + std::for_each(s.begin(), s.end(), process_char); + *oi++ = '"'; +} + +template <typename Iter> void value::serialize(Iter oi, bool prettify) const { + return _serialize(oi, prettify ? 0 : -1); +} + +inline std::string value::serialize(bool prettify) const { + return _serialize(prettify ? 0 : -1); +} + +template <typename Iter> void value::_indent(Iter oi, int indent) { + *oi++ = '\n'; + for (int i = 0; i < indent * INDENT_WIDTH; ++i) { + *oi++ = ' '; + } +} + +template <typename Iter> void value::_serialize(Iter oi, int indent) const { + switch (type_) { + case string_type: + serialize_str(*u_.string_, oi); + break; + case array_type: { + *oi++ = '['; + if (indent != -1) { + ++indent; + } + for (array::const_iterator i = u_.array_->begin(); i != u_.array_->end(); ++i) { + if (i != u_.array_->begin()) { + *oi++ = ','; + } + if (indent != -1) { + _indent(oi, indent); + } + i->_serialize(oi, indent); + } + if (indent != -1) { + --indent; + if (!u_.array_->empty()) { + _indent(oi, indent); + } + } + *oi++ = ']'; + break; + } + case object_type: { + *oi++ = '{'; + if (indent != -1) { + ++indent; + } + for (object::const_iterator i = u_.object_->begin(); i != u_.object_->end(); ++i) { + if (i != u_.object_->begin()) { + *oi++ = ','; + } + if (indent != -1) { + _indent(oi, indent); + } + serialize_str(i->first, oi); + *oi++ = ':'; + if (indent != -1) { + *oi++ = ' '; + } + i->second._serialize(oi, indent); + } + if (indent != -1) { + --indent; + if (!u_.object_->empty()) { + _indent(oi, indent); + } + } + *oi++ = '}'; + break; + } + default: + copy(to_str(), oi); + break; + } + if (indent == 0) { + *oi++ = '\n'; + } +} + +inline std::string value::_serialize(int indent) const { + std::string s; + _serialize(std::back_inserter(s), indent); + return s; +} + +template <typename Iter> class input { +protected: + Iter cur_, end_; + bool consumed_; + int line_; + +public: + input(const Iter &first, const Iter &last) : cur_(first), end_(last), consumed_(false), line_(1) { + } + int getc() { + if (consumed_) { + if (*cur_ == '\n') { + ++line_; + } + ++cur_; + } + if (cur_ == end_) { + consumed_ = false; + return -1; + } + consumed_ = true; + return *cur_ & 0xff; + } + void ungetc() { + consumed_ = false; + } + Iter cur() const { + if (consumed_) { + input<Iter> *self = const_cast<input<Iter> *>(this); + self->consumed_ = false; + ++self->cur_; + } + return cur_; + } + int line() const { + return line_; + } + void skip_ws() { + while (1) { + int ch = getc(); + if (!(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) { + ungetc(); + break; + } + } + } + bool expect(const int expected) { + skip_ws(); + if (getc() != expected) { + ungetc(); + return false; + } + return true; + } + bool match(const std::string &pattern) { + for (std::string::const_iterator pi(pattern.begin()); pi != pattern.end(); ++pi) { + if (getc() != *pi) { + ungetc(); + return false; + } + } + return true; + } +}; + +template <typename Iter> inline int _parse_quadhex(input<Iter> &in) { + int uni_ch = 0, hex; + for (int i = 0; i < 4; i++) { + if ((hex = in.getc()) == -1) { + return -1; + } + if ('0' <= hex && hex <= '9') { + hex -= '0'; + } else if ('A' <= hex && hex <= 'F') { + hex -= 'A' - 0xa; + } else if ('a' <= hex && hex <= 'f') { + hex -= 'a' - 0xa; + } else { + in.ungetc(); + return -1; + } + uni_ch = uni_ch * 16 + hex; + } + return uni_ch; +} + +template <typename String, typename Iter> inline bool _parse_codepoint(String &out, input<Iter> &in) { + int uni_ch; + if ((uni_ch = _parse_quadhex(in)) == -1) { + return false; + } + if (0xd800 <= uni_ch && uni_ch <= 0xdfff) { + if (0xdc00 <= uni_ch) { + // a second 16-bit of a surrogate pair appeared + return false; + } + // first 16-bit of surrogate pair, get the next one + if (in.getc() != '\\' || in.getc() != 'u') { + in.ungetc(); + return false; + } + int second = _parse_quadhex(in); + if (!(0xdc00 <= second && second <= 0xdfff)) { + return false; + } + uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff); + uni_ch += 0x10000; + } + if (uni_ch < 0x80) { + out.push_back(static_cast<char>(uni_ch)); + } else { + if (uni_ch < 0x800) { + out.push_back(static_cast<char>(0xc0 | (uni_ch >> 6))); + } else { + if (uni_ch < 0x10000) { + out.push_back(static_cast<char>(0xe0 | (uni_ch >> 12))); + } else { + out.push_back(static_cast<char>(0xf0 | (uni_ch >> 18))); + out.push_back(static_cast<char>(0x80 | ((uni_ch >> 12) & 0x3f))); + } + out.push_back(static_cast<char>(0x80 | ((uni_ch >> 6) & 0x3f))); + } + out.push_back(static_cast<char>(0x80 | (uni_ch & 0x3f))); + } + return true; +} + +template <typename String, typename Iter> inline bool _parse_string(String &out, input<Iter> &in) { + while (1) { + int ch = in.getc(); + if (ch < ' ') { + in.ungetc(); + return false; + } else if (ch == '"') { + return true; + } else if (ch == '\\') { + if ((ch = in.getc()) == -1) { + return false; + } + switch (ch) { +#define MAP(sym, val) \ + case sym: \ + out.push_back(val); \ + break + MAP('"', '\"'); + MAP('\\', '\\'); + MAP('/', '/'); + MAP('b', '\b'); + MAP('f', '\f'); + MAP('n', '\n'); + MAP('r', '\r'); + MAP('t', '\t'); +#undef MAP + case 'u': + if (!_parse_codepoint(out, in)) { + return false; + } + break; + default: + return false; + } + } else { + out.push_back(static_cast<char>(ch)); + } + } + return false; +} + +template <typename Context, typename Iter> inline bool _parse_array(Context &ctx, input<Iter> &in) { + if (!ctx.parse_array_start()) { + return false; + } + size_t idx = 0; + if (in.expect(']')) { + return ctx.parse_array_stop(idx); + } + do { + if (!ctx.parse_array_item(in, idx)) { + return false; + } + idx++; + } while (in.expect(',')); + return in.expect(']') && ctx.parse_array_stop(idx); +} + +template <typename Context, typename Iter> inline bool _parse_object(Context &ctx, input<Iter> &in) { + if (!ctx.parse_object_start()) { + return false; + } + if (in.expect('}')) { + return true; + } + do { + std::string key; + if (!in.expect('"') || !_parse_string(key, in) || !in.expect(':')) { + return false; + } + if (!ctx.parse_object_item(in, key)) { + return false; + } + } while (in.expect(',')); + return in.expect('}'); +} + +template <typename Iter> inline std::string _parse_number(input<Iter> &in) { + std::string num_str; + while (1) { + int ch = in.getc(); + if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == 'e' || ch == 'E') { + num_str.push_back(static_cast<char>(ch)); + } else if (ch == '.') { +#if PICOJSON_USE_LOCALE + num_str += localeconv()->decimal_point; +#else + num_str.push_back('.'); +#endif + } else { + in.ungetc(); + break; + } + } + return num_str; +} + +template <typename Context, typename Iter> inline bool _parse(Context &ctx, input<Iter> &in) { + in.skip_ws(); + int ch = in.getc(); + switch (ch) { +#define IS(ch, text, op) \ + case ch: \ + if (in.match(text) && op) { \ + return true; \ + } else { \ + return false; \ + } + IS('n', "ull", ctx.set_null()); + IS('f', "alse", ctx.set_bool(false)); + IS('t', "rue", ctx.set_bool(true)); +#undef IS + case '"': + return ctx.parse_string(in); + case '[': + return _parse_array(ctx, in); + case '{': + return _parse_object(ctx, in); + default: + if (('0' <= ch && ch <= '9') || ch == '-') { + double f; + char *endp; + in.ungetc(); + std::string num_str(_parse_number(in)); + if (num_str.empty()) { + return false; + } +#ifdef PICOJSON_USE_INT64 + { + errno = 0; + intmax_t ival = strtoimax(num_str.c_str(), &endp, 10); + if (errno == 0 && std::numeric_limits<int64_t>::min() <= ival && ival <= std::numeric_limits<int64_t>::max() && + endp == num_str.c_str() + num_str.size()) { + ctx.set_int64(ival); + return true; + } + } +#endif + f = strtod(num_str.c_str(), &endp); + if (endp == num_str.c_str() + num_str.size()) { + ctx.set_number(f); + return true; + } + return false; + } + break; + } + in.ungetc(); + return false; +} + +class deny_parse_context { +public: + bool set_null() { + return false; + } + bool set_bool(bool) { + return false; + } +#ifdef PICOJSON_USE_INT64 + bool set_int64(int64_t) { + return false; + } +#endif + bool set_number(double) { + return false; + } + template <typename Iter> bool parse_string(input<Iter> &) { + return false; + } + bool parse_array_start() { + return false; + } + template <typename Iter> bool parse_array_item(input<Iter> &, size_t) { + return false; + } + bool parse_array_stop(size_t) { + return false; + } + bool parse_object_start() { + return false; + } + template <typename Iter> bool parse_object_item(input<Iter> &, const std::string &) { + return false; + } +}; + +class default_parse_context { +protected: + value *out_; + +public: + default_parse_context(value *out) : out_(out) { + } + bool set_null() { + *out_ = value(); + return true; + } + bool set_bool(bool b) { + *out_ = value(b); + return true; + } +#ifdef PICOJSON_USE_INT64 + bool set_int64(int64_t i) { + *out_ = value(i); + return true; + } +#endif + bool set_number(double f) { + *out_ = value(f); + return true; + } + template <typename Iter> bool parse_string(input<Iter> &in) { + *out_ = value(string_type, false); + return _parse_string(out_->get<std::string>(), in); + } + bool parse_array_start() { + *out_ = value(array_type, false); + return true; + } + template <typename Iter> bool parse_array_item(input<Iter> &in, size_t) { + array &a = out_->get<array>(); + a.push_back(value()); + default_parse_context ctx(&a.back()); + return _parse(ctx, in); + } + bool parse_array_stop(size_t) { + return true; + } + bool parse_object_start() { + *out_ = value(object_type, false); + return true; + } + template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &key) { + object &o = out_->get<object>(); + default_parse_context ctx(&o[key]); + return _parse(ctx, in); + } + +private: + default_parse_context(const default_parse_context &); + default_parse_context &operator=(const default_parse_context &); +}; + +class null_parse_context { +public: + struct dummy_str { + void push_back(int) { + } + }; + +public: + null_parse_context() { + } + bool set_null() { + return true; + } + bool set_bool(bool) { + return true; + } +#ifdef PICOJSON_USE_INT64 + bool set_int64(int64_t) { + return true; + } +#endif + bool set_number(double) { + return true; + } + template <typename Iter> bool parse_string(input<Iter> &in) { + dummy_str s; + return _parse_string(s, in); + } + bool parse_array_start() { + return true; + } + template <typename Iter> bool parse_array_item(input<Iter> &in, size_t) { + return _parse(*this, in); + } + bool parse_array_stop(size_t) { + return true; + } + bool parse_object_start() { + return true; + } + template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &) { + return _parse(*this, in); + } + +private: + null_parse_context(const null_parse_context &); + null_parse_context &operator=(const null_parse_context &); +}; + +// obsolete, use the version below +template <typename Iter> inline std::string parse(value &out, Iter &pos, const Iter &last) { + std::string err; + pos = parse(out, pos, last, &err); + return err; +} + +template <typename Context, typename Iter> inline Iter _parse(Context &ctx, const Iter &first, const Iter &last, std::string *err) { + input<Iter> in(first, last); + if (!_parse(ctx, in) && err != NULL) { + char buf[64]; + SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line()); + *err = buf; + while (1) { + int ch = in.getc(); + if (ch == -1 || ch == '\n') { + break; + } else if (ch >= ' ') { + err->push_back(static_cast<char>(ch)); + } + } + } + return in.cur(); +} + +template <typename Iter> inline Iter parse(value &out, const Iter &first, const Iter &last, std::string *err) { + default_parse_context ctx(&out); + return _parse(ctx, first, last, err); +} + +inline std::string parse(value &out, const std::string &s) { + std::string err; + parse(out, s.begin(), s.end(), &err); + return err; +} + +inline std::string parse(value &out, std::istream &is) { + std::string err; + parse(out, std::istreambuf_iterator<char>(is.rdbuf()), std::istreambuf_iterator<char>(), &err); + return err; +} + +template <typename T> struct last_error_t { static std::string s; }; +template <typename T> std::string last_error_t<T>::s; + +inline void set_last_error(const std::string &s) { + last_error_t<bool>::s = s; +} + +inline const std::string &get_last_error() { + return last_error_t<bool>::s; +} + +inline bool operator==(const value &x, const value &y) { + if (x.is<null>()) + return y.is<null>(); +#define PICOJSON_CMP(type) \ + if (x.is<type>()) \ + return y.is<type>() && x.get<type>() == y.get<type>() + PICOJSON_CMP(bool); + PICOJSON_CMP(double); + PICOJSON_CMP(std::string); + PICOJSON_CMP(array); + PICOJSON_CMP(object); +#undef PICOJSON_CMP + PICOJSON_ASSERT(0); +#ifdef _MSC_VER + __assume(0); +#endif + return false; +} + +inline bool operator!=(const value &x, const value &y) { + return !(x == y); +} +} + +#if !PICOJSON_USE_RVALUE_REFERENCE +namespace std { +template <> inline void swap(picojson::value &x, picojson::value &y) { + x.swap(y); +} +} +#endif + +inline std::istream &operator>>(std::istream &is, picojson::value &x) { + picojson::set_last_error(std::string()); + const std::string err(picojson::parse(x, is)); + if (!err.empty()) { + picojson::set_last_error(err); + is.setstate(std::ios::failbit); + } + return is; +} + +inline std::ostream &operator<<(std::ostream &os, const picojson::value &x) { + x.serialize(std::ostream_iterator<char>(os)); + return os; +} +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif diff --git a/Fltk/FlGui.cpp b/Fltk/FlGui.cpp index d83e278f299fa0e9c2af1b162fafff4f97538668..728e8b2343da3d21382ed79812c8c1357bac7968 100644 --- a/Fltk/FlGui.cpp +++ b/Fltk/FlGui.cpp @@ -646,6 +646,24 @@ int FlGui::testGlobalShortcuts(int event) elementaryContext->butt[2]->value(!elementaryContext->butt[2]->value()); status = 1; // trick: do as if we didn't use it } + else if(Fl::test_shortcut(FL_SHIFT + 'x')) { + elementaryContext->butt[0]->value(0); + elementaryContext->butt[1]->value(1); + elementaryContext->butt[2]->value(1); + status = 1; // trick: do as if we didn't use it + } + else if(Fl::test_shortcut(FL_SHIFT + 'y')) { + elementaryContext->butt[0]->value(1); + elementaryContext->butt[1]->value(0); + elementaryContext->butt[2]->value(1); + status = 1; // trick: do as if we didn't use it + } + else if(Fl::test_shortcut(FL_SHIFT + 'z')) { + elementaryContext->butt[0]->value(1); + elementaryContext->butt[1]->value(1); + elementaryContext->butt[2]->value(0); + status = 1; // trick: do as if we didn't use it + } else if(Fl::test_shortcut(FL_Escape) || Fl::test_shortcut(FL_META + FL_Escape) || Fl::test_shortcut(FL_SHIFT + FL_Escape) || diff --git a/Fltk/contextWindow.cpp b/Fltk/contextWindow.cpp index 03c43364e4e9354cd89b21850b035359a1327ab3..916ddb7b67965589c8c288f8c0f95e26729b2629 100644 --- a/Fltk/contextWindow.cpp +++ b/Fltk/contextWindow.cpp @@ -935,11 +935,11 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize) value[i]->callback(elementary_snap_cb); } butt[0] = new Fl_Check_Button(width - 6 * BH, height - WB - BH, 1.2 * BH, BH, "X"); - butt[0]->tooltip("(x)"); + butt[0]->tooltip("Toggle (x) or exclusive unselect (Shift+x)"); butt[1] = new Fl_Check_Button(width - 6 * BH + 1.2 * BH, height - WB - BH, 1.2*BH, BH, "Y"); - butt[1]->tooltip("(y)"); + butt[1]->tooltip("Toggle (y) or exclusive unselect (Shift+y)"); butt[2] = new Fl_Check_Button(width - 6 * BH + 2.4 * BH, height - WB - BH, (6 - 2*1.2) * BH - WB, BH, "Z freeze"); - butt[2]->tooltip("(z)"); + butt[2]->tooltip("Toggle (z) or exclusive unselect (Shift+z)"); } tab1->show(); diff --git a/Fltk/fileDialogs.cpp b/Fltk/fileDialogs.cpp index 2dda82b3a82b3ef8741eb2633cb26e11307afd14..b0e7ce1e1c36e328819816fbb2a319dede208f61 100644 --- a/Fltk/fileDialogs.cpp +++ b/Fltk/fileDialogs.cpp @@ -688,26 +688,23 @@ static void activate_gl2ps_choices(int format, int quality, Fl_Check_Button *b[5 b[1]->deactivate(); b[2]->deactivate(); b[3]->deactivate(); - b[4]->deactivate(); break; case 1: // simple sort case 3: // unsorted b[1]->activate(); - b[2]->activate(); - b[3]->deactivate(); - if(format == FORMAT_PDF || format == FORMAT_SVG) - b[4]->deactivate(); + b[2]->deactivate(); + if(format == FORMAT_PS || format == FORMAT_EPS) + b[3]->activate(); else - b[4]->activate(); + b[3]->deactivate(); break; case 2: // bsp sort b[1]->activate(); b[2]->activate(); - b[3]->activate(); - if(format == FORMAT_PDF || format == FORMAT_SVG) - b[4]->deactivate(); + if(format == FORMAT_PS || format == FORMAT_EPS) + b[3]->activate(); else - b[4]->activate(); + b[3]->deactivate(); break; } } diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp index 7689c0d2ca0cbeb1ae6c411ecc04812bb458aa64..edc64013964b43f0fd61156db2f5a71e0d7c2fe4 100644 --- a/Fltk/graphicWindow.cpp +++ b/Fltk/graphicWindow.cpp @@ -335,6 +335,8 @@ static int _save_ppm(const char *name){ return genericBitmapFileDialog (name, "PPM Options", FORMAT_PPM); } static int _save_svg(const char *name){ return gl2psFileDialog (name, "SVG Options", FORMAT_SVG); } +static int _save_tikz(const char *name){ return gl2psFileDialog + (name, "TIKZ Options", FORMAT_TIKZ); } static int _save_yuv(const char *name){ return genericBitmapFileDialog (name, "YUV Options", FORMAT_YUV); } static int _save_view_pos(const char *name){ return posFileDialog(name); } @@ -389,6 +391,7 @@ static int _save_auto(const char *name) case FORMAT_PS : return _save_ps(name); case FORMAT_PPM : return _save_ppm(name); case FORMAT_SVG : return _save_svg(name); + case FORMAT_TIKZ : return _save_tikz(name); case FORMAT_YUV : return _save_yuv(name); default : CreateOutputFile(name, FORMAT_AUTO); @@ -455,6 +458,7 @@ static void file_export_cb(Fl_Widget *w, void *data) {"Image - PostScript" TT "*.ps", _save_ps}, {"Image - PPM" TT "*.ppm", _save_ppm}, {"Image - SVG" TT "*.svg", _save_svg}, + {"Image - TIKZ" TT "*.tikz", _save_tikz}, {"Image - YUV" TT "*.yuv", _save_yuv}, #if defined(HAVE_MPEG_ENCODE) {"Movie - MPEG" TT "*.mpg", _save_mpeg}, diff --git a/Fltk/onelabGroup.cpp b/Fltk/onelabGroup.cpp index bd1bd33898844b353340455d8a6b6ed3bec52f21..d0c25bcbf1da6fe635395092ca7fa15032474164 100644 --- a/Fltk/onelabGroup.cpp +++ b/Fltk/onelabGroup.cpp @@ -10,6 +10,8 @@ #elif defined(HAVE_NO_INTPTR_T) typedef unsigned long intptr_t; #endif +#include <fstream> +#include <streambuf> #include <ctype.h> #include "GmshMessage.h" #include "onelab.h" @@ -1204,6 +1206,12 @@ void onelabGroup::rebuildTree(bool deleteWidgets) for(unsigned int i = 0; i < delStrings.size(); i++) free(delStrings[i]); } + +#if 0 // test + std::ifstream t("test.db.json"); + std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>()); + onelab::server::instance()->fromJSON(str); +#endif } void onelabGroup::openTreeItem(const std::string &name) diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp index e511c231bd0b19bab066073d614000607bb4e69f..743ab8e73194dddb430d4fa89d5b7172030f4a1c 100644 --- a/Geo/GModel.cpp +++ b/Geo/GModel.cpp @@ -571,7 +571,7 @@ bool GModel::getBoundaryTags(const std::vector<std::pair<int, int> > &inDimTags, } } - if(combined || recursive){ + if(combined){ // compute boundary of the combined shapes std::set<int, AbsIntLessThan> c[3]; for(unsigned int i = 0; i < outDimTags.size(); i++){ diff --git a/Geo/GModelIO_BDF.cpp b/Geo/GModelIO_BDF.cpp index 0786ce58db228b95b3985416712baeb1c9629e4b..d0689270eb88fa45576af2fa730488141431ca07 100644 --- a/Geo/GModelIO_BDF.cpp +++ b/Geo/GModelIO_BDF.cpp @@ -17,9 +17,19 @@ static int getFormatBDF(char *buffer, int &keySize) { + for(unsigned int i = 0; i < strlen(buffer); i++){ + if(buffer[i] == ','){ // free fields + if(buffer[keySize] == '*'){ // will contine on next line + keySize = i; + return -1; + } + else{ + keySize = i; + return 0; + } + } + } if(buffer[keySize] == '*'){ keySize++; return 2; } // long fields - for(unsigned int i = 0; i < strlen(buffer); i++) - if(buffer[i] == ',') return 0; // free fields return 1; // small fields; } @@ -54,10 +64,11 @@ static int readVertexBDF(FILE *fp, char *buffer, int keySize, int *num, double *x, double *y, double *z) { char tmp[5][32]; + int format = getFormatBDF(buffer, keySize); int j = keySize; - - switch(getFormatBDF(buffer, keySize)){ + switch(format){ case 0: // free field + case -1: // free field with continuation for(int i = 0; i < 5; i++){ tmp[i][16] = '\0'; strncpy(tmp[i], &buffer[j + 1], 16); @@ -65,6 +76,13 @@ static int readVertexBDF(FILE *fp, char *buffer, int keySize, j++; while(j < (int)strlen(buffer) && buffer[j] != ',') j++; } + if(format == -1){ // continued on next line + char buffer2[256]; + if(!fgets(buffer2, sizeof(buffer2), fp)) return 0; + j = 0; + while(j < (int)strlen(buffer2) && buffer2[j] != ',') j++; + strncpy(tmp[4], &buffer2[j + 1], 16); + } break; case 1: // small field for(int i = 0; i < 5; i++) tmp[i][8] = '\0'; @@ -105,7 +123,7 @@ static void readLineBDF(char *buffer, int format, std::vector<char*> &fields) int cmax = (format == 2) ? 16 : 8; // max char per (center) field int nmax = (format == 2) ? 4 : 8; // max num of (center) fields per line - if(format == 0){ // free fields + if(format <= 0){ // free fields for(unsigned int i = 0; i < strlen(buffer); i++){ if(buffer[i] == ',') fields.push_back(&buffer[i + 1]); } diff --git a/Geo/GModelIO_OCC.cpp b/Geo/GModelIO_OCC.cpp index 822ccf924f49b13f05f3f96c294baa7639e03bd8..e9830c3ab0bbf22d6fc55af95b770e0c031db330 100644 --- a/Geo/GModelIO_OCC.cpp +++ b/Geo/GModelIO_OCC.cpp @@ -151,7 +151,8 @@ void OCC_Internals::bind(TopoDS_Vertex vertex, int tag, bool recursive) { if(vertex.IsNull()) return; if(_vertexTag.IsBound(vertex) && _vertexTag.Find(vertex) != tag){ - Msg::Debug("OpenCASCADE vertex %d is already bound to another tag", tag); + Msg::Info("Cannot bind existing OpenCASCADE vertex %d to second tag %d", + _vertexTag.Find(vertex), tag); } else{ _vertexTag.Bind(vertex, tag); @@ -166,7 +167,8 @@ void OCC_Internals::bind(TopoDS_Edge edge, int tag, bool recursive) { if(edge.IsNull()) return; if(_edgeTag.IsBound(edge) && _edgeTag.Find(edge) != tag){ - Msg::Debug("OpenCASCADE edge %d is already bound to another tag", tag); + Msg::Info("Cannot bind existing OpenCASCADE edge %d to second tag %d", + _edgeTag.Find(edge), tag); } else{ _edgeTag.Bind(edge, tag); @@ -191,7 +193,8 @@ void OCC_Internals::bind(TopoDS_Wire wire, int tag, bool recursive) { if(wire.IsNull()) return; if(_wireTag.IsBound(wire) && _wireTag.Find(wire) != tag){ - Msg::Debug("OpenCASCADE wire %d is already bound to anthor tag", tag); + Msg::Info("Cannot bind existing OpenCASCADE wire %d to second tag %d", + _wireTag.Find(wire), tag); } else{ _wireTag.Bind(wire, tag); @@ -215,7 +218,8 @@ void OCC_Internals::bind(TopoDS_Face face, int tag, bool recursive) { if(face.IsNull()) return; if(_faceTag.IsBound(face) && _faceTag.Find(face) != tag){ - Msg::Debug("OpenCASCADE face %d is already bound to another tag", tag); + Msg::Info("Cannot bind existing OpenCASCADE face %d to second tag %d", + _faceTag.Find(face), tag); } else{ _faceTag.Bind(face, tag); @@ -247,7 +251,8 @@ void OCC_Internals::bind(TopoDS_Shell shell, int tag, bool recursive) { if(shell.IsNull()) return; if(_shellTag.IsBound(shell) && _shellTag.Find(shell) != tag){ - Msg::Debug("OpenCASCADE shell %d is already bound to another tag", tag); + Msg::Info("Cannot bind existing OpenCASCADE shell %d to second tag %d", + _shellTag.Find(shell), tag); } else{ _shellTag.Bind(shell, tag); @@ -271,7 +276,8 @@ void OCC_Internals::bind(TopoDS_Solid solid, int tag, bool recursive) { if(solid.IsNull()) return; if(_solidTag.IsBound(solid) && _solidTag.Find(solid) != tag){ - Msg::Debug("OpenCASCADE solid %d is already bound to another tag", tag); + Msg::Info("Cannot bind existing OpenCASCADE solid %d to second tag %d", + _solidTag.Find(solid), tag); } else{ _solidTag.Bind(solid, tag); @@ -322,9 +328,11 @@ void OCC_Internals::unbind(TopoDS_Vertex vertex, int tag, bool recursive) if(exp1.Current().IsSame(vertex)) return; } } + std::pair<int, int> dimTag(0, tag); + if(_toPreserve.find(dimTag) != _toPreserve.end()) return; _vertexTag.UnBind(vertex); _tagVertex.UnBind(tag); - _toRemove.insert(std::pair<int, int>(0, tag)); + _toRemove.insert(dimTag); _recomputeMaxTag(0); _changed = true; } @@ -339,9 +347,11 @@ void OCC_Internals::unbind(TopoDS_Edge edge, int tag, bool recursive) if(exp1.Current().IsSame(edge)) return; } } + std::pair<int, int> dimTag(1, tag); + if(_toPreserve.find(dimTag) != _toPreserve.end()) return; _edgeTag.UnBind(edge); _tagEdge.UnBind(tag); - _toRemove.insert(std::pair<int, int>(1, tag)); + _toRemove.insert(dimTag); _recomputeMaxTag(1); if(recursive){ TopExp_Explorer exp0; @@ -366,9 +376,11 @@ void OCC_Internals::unbind(TopoDS_Wire wire, int tag, bool recursive) if(exp1.Current().IsSame(wire)) return; } } + std::pair<int, int> dimTag(-1, tag); + if(_toPreserve.find(dimTag) != _toPreserve.end()) return; _wireTag.UnBind(wire); _tagWire.UnBind(tag); - _toRemove.insert(std::pair<int, int>(-1, tag)); + _toRemove.insert(dimTag); _recomputeMaxTag(-1); if(recursive){ TopExp_Explorer exp0; @@ -393,9 +405,11 @@ void OCC_Internals::unbind(TopoDS_Face face, int tag, bool recursive) if(exp1.Current().IsSame(face)) return; } } + std::pair<int, int> dimTag(2, tag); + if(_toPreserve.find(dimTag) != _toPreserve.end()) return; _faceTag.UnBind(face); _tagFace.UnBind(tag); - _toRemove.insert(std::pair<int, int>(2, tag)); + _toRemove.insert(dimTag); _recomputeMaxTag(2); if(recursive){ TopExp_Explorer exp0; @@ -427,9 +441,11 @@ void OCC_Internals::unbind(TopoDS_Shell shell, int tag, bool recursive) if(exp1.Current().IsSame(shell)) return; } } + std::pair<int, int> dimTag(-2, tag); + if(_toPreserve.find(dimTag) != _toPreserve.end()) return; _shellTag.UnBind(shell); _tagShell.UnBind(tag); - _toRemove.insert(std::pair<int, int>(-2, tag)); + _toRemove.insert(dimTag); _recomputeMaxTag(-2); if(recursive){ TopExp_Explorer exp0; @@ -446,9 +462,11 @@ void OCC_Internals::unbind(TopoDS_Shell shell, int tag, bool recursive) void OCC_Internals::unbind(TopoDS_Solid solid, int tag, bool recursive) { + std::pair<int, int> dimTag(3, tag); + if(_toPreserve.find(dimTag) != _toPreserve.end()) return; _solidTag.UnBind(solid); _tagSolid.UnBind(tag); - _toRemove.insert(std::pair<int, int>(3, tag)); + _toRemove.insert(dimTag); _recomputeMaxTag(3); if(recursive){ TopExp_Explorer exp0; @@ -485,7 +503,7 @@ void OCC_Internals::unbind(TopoDS_Shape shape, int dim, int tag, bool recursive) void OCC_Internals::_multiBind(TopoDS_Shape shape, int tag, std::vector<std::pair<int, int> > &outDimTags, - bool returnHighestDimOnly, bool recursive, + bool highestDimOnly, bool recursive, bool returnNewOnly) { TopExp_Explorer exp0; @@ -512,7 +530,7 @@ void OCC_Internals::_multiBind(TopoDS_Shape shape, int tag, outDimTags.push_back(std::pair<int, int>(3, t)); count++; } - if(returnHighestDimOnly && count) return; + if(highestDimOnly && count) return; for(exp0.Init(shape, TopAbs_FACE); exp0.More(); exp0.Next()){ TopoDS_Face face = TopoDS::Face(exp0.Current()); bool exists = false; @@ -535,7 +553,7 @@ void OCC_Internals::_multiBind(TopoDS_Shape shape, int tag, outDimTags.push_back(std::pair<int, int>(2, t)); count++; } - if(returnHighestDimOnly && count) return; + if(highestDimOnly && count) return; for(exp0.Init(shape, TopAbs_EDGE); exp0.More(); exp0.Next()){ TopoDS_Edge edge = TopoDS::Edge(exp0.Current()); bool exists = false; @@ -558,7 +576,7 @@ void OCC_Internals::_multiBind(TopoDS_Shape shape, int tag, outDimTags.push_back(std::pair<int, int>(1, t)); count++; } - if(returnHighestDimOnly && count) return; + if(highestDimOnly && count) return; for(exp0.Init(shape, TopAbs_VERTEX); exp0.More(); exp0.Next()){ TopoDS_Vertex vertex = TopoDS::Vertex(exp0.Current()); bool exists = false; @@ -566,7 +584,7 @@ void OCC_Internals::_multiBind(TopoDS_Shape shape, int tag, if(t <= 0){ if(_vertexTag.IsBound(vertex)){ t = _vertexTag.Find(vertex); - exists = false; + exists = true; } t = getMaxTag(0) + 1; } @@ -1994,7 +2012,7 @@ bool OCC_Internals::fillet(const std::vector<int> ®ionTags, } TopoDS_Shape shape = _find(3, regionTags[i]); b.Add(c, shape); - if(removeRegion) unbind(shape, 3, regionTags[i], true); // recursive + if(removeRegion) unbind(shape, 3, regionTags[i], true); } TopoDS_Shape result; try{ @@ -2023,14 +2041,26 @@ bool OCC_Internals::fillet(const std::vector<int> ®ionTags, return true; } +static void _filterTags(std::vector<std::pair<int, int> > &outDimTags, int minDim) +{ + std::vector<std::pair<int, int> > tmp(outDimTags); + outDimTags.clear(); + for(unsigned int i = 0; i < tmp.size(); i++){ + if(tmp[i].first >= minDim) + outDimTags.push_back(tmp[i]); + } +} + bool OCC_Internals::booleanOperator(int tag, BooleanOperator op, const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool) { double tolerance = CTX::instance()->geom.toleranceBoolean; bool parallel = CTX::instance()->geom.occParallel; + bool preserveNumbering = CTX::instance()->geom.occBooleanPreserveNumbering; if(objectDimTags.empty()) return true; @@ -2039,6 +2069,7 @@ bool OCC_Internals::booleanOperator(int tag, BooleanOperator op, return false; } + int minDim = 3; TopTools_ListOfShape objectShapes, toolShapes; for(unsigned int i = 0; i < objectDimTags.size(); i++){ int dim = objectDimTags[i].first; @@ -2051,6 +2082,7 @@ bool OCC_Internals::booleanOperator(int tag, BooleanOperator op, TopoDS_Shape object = _find(dim, t); objectShapes.Append(object); } + minDim = std::min(minDim, dim); } for(unsigned int i = 0; i < toolDimTags.size(); i++){ int dim = toolDimTags[i].first; @@ -2063,9 +2095,11 @@ bool OCC_Internals::booleanOperator(int tag, BooleanOperator op, TopoDS_Shape tool = _find(dim, t); toolShapes.Append(tool); } + minDim = std::min(minDim, dim); } TopoDS_Shape result; + std::vector<TopoDS_Shape> mapOriginal; std::vector<TopTools_ListOfShape> mapModified, mapGenerated; std::vector<bool> mapDeleted; try{ @@ -2086,12 +2120,14 @@ bool OCC_Internals::booleanOperator(int tag, BooleanOperator op, result = fuse.Shape(); TopTools_ListIteratorOfListOfShape it(objectShapes); for(; it.More(); it.Next()){ + mapOriginal.push_back(it.Value()); mapModified.push_back(fuse.Modified(it.Value())); mapDeleted.push_back(fuse.IsDeleted(it.Value())); mapGenerated.push_back(fuse.Generated(it.Value())); } TopTools_ListIteratorOfListOfShape it2(toolShapes); for(; it2.More(); it2.Next()){ + mapOriginal.push_back(it2.Value()); mapModified.push_back(fuse.Modified(it2.Value())); mapDeleted.push_back(fuse.IsDeleted(it2.Value())); mapGenerated.push_back(fuse.Generated(it2.Value())); @@ -2114,12 +2150,14 @@ bool OCC_Internals::booleanOperator(int tag, BooleanOperator op, result = common.Shape(); TopTools_ListIteratorOfListOfShape it(objectShapes); for(; it.More(); it.Next()){ + mapOriginal.push_back(it.Value()); mapModified.push_back(common.Modified(it.Value())); mapDeleted.push_back(common.IsDeleted(it.Value())); mapGenerated.push_back(common.Generated(it.Value())); } TopTools_ListIteratorOfListOfShape it2(toolShapes); for(; it2.More(); it2.Next()){ + mapOriginal.push_back(it2.Value()); mapModified.push_back(common.Modified(it2.Value())); mapDeleted.push_back(common.IsDeleted(it2.Value())); mapGenerated.push_back(common.Generated(it2.Value())); @@ -2143,12 +2181,14 @@ bool OCC_Internals::booleanOperator(int tag, BooleanOperator op, result = cut.Shape(); TopTools_ListIteratorOfListOfShape it(objectShapes); for(; it.More(); it.Next()){ + mapOriginal.push_back(it.Value()); mapModified.push_back(cut.Modified(it.Value())); mapDeleted.push_back(cut.IsDeleted(it.Value())); mapGenerated.push_back(cut.Generated(it.Value())); } TopTools_ListIteratorOfListOfShape it2(toolShapes); for(; it2.More(); it2.Next()){ + mapOriginal.push_back(it2.Value()); mapModified.push_back(cut.Modified(it2.Value())); mapDeleted.push_back(cut.IsDeleted(it2.Value())); mapGenerated.push_back(cut.Generated(it2.Value())); @@ -2174,6 +2214,7 @@ bool OCC_Internals::booleanOperator(int tag, BooleanOperator op, result = fragments.Shape(); TopTools_ListIteratorOfListOfShape it(objectShapes); for(; it.More(); it.Next()){ + mapOriginal.push_back(it.Value()); mapModified.push_back(fragments.Modified(it.Value())); mapDeleted.push_back(fragments.IsDeleted(it.Value())); mapGenerated.push_back(fragments.Generated(it.Value())); @@ -2187,135 +2228,101 @@ bool OCC_Internals::booleanOperator(int tag, BooleanOperator op, return false; } - // don't try to preserve numbering if we specify the tag explicitly, or if - // there is a problem - bool bug1 = (objectDimTags.size() + toolDimTags.size() != mapModified.size()); - bool bug2 = (op == OCC_Internals::Union); // steange fuse behavior in OCC 7.1 - if(tag >= 0 || bug1 || bug2){ - if(bug1) Msg::Error("Wrong shape count in boolean operation"); - if(removeObject){ - for(unsigned int i = 0; i < objectDimTags.size(); i++){ - int d = objectDimTags[i].first; - int t = objectDimTags[i].second; - if(_isBound(d, t)) unbind(_find(d, t), d, t, true); // recursive - } - } - if(removeTool){ - for(unsigned int i = 0; i < toolDimTags.size(); i++){ - int d = toolDimTags[i].first; - int t = toolDimTags[i].second; - if(_isBound(d, t)) unbind(_find(d, t), d, t, true); // recursive + std::vector<std::pair<int, int> > inDimTags; + inDimTags.insert(inDimTags.end(), objectDimTags.begin(), objectDimTags.end()); + inDimTags.insert(inDimTags.end(), toolDimTags.begin(), toolDimTags.end()); + unsigned int numObjects = objectDimTags.size(); + + if(tag >= 0 || !preserveNumbering){ + // if we specify the tag explicitly, or if we don't care about preserving + // the numering, just go ahead and bind the resulting shape (and sub-shapes) + for(unsigned int i = 0; i < inDimTags.size(); i++){ + bool remove = (i < numObjects) ? removeObject : removeTool; + if(remove){ + int d = inDimTags[i].first; + int t = inDimTags[i].second; + if(_isBound(d, t)) unbind(_find(d, t), d, t, true); } } _multiBind(result, tag, outDimTags, true, true); - return true; + _filterTags(outDimTags, minDim); } - - // otherwise, try to preserve the numbering - std::vector<TopoDS_Shape> toBind; - for(unsigned int i = 0; i < objectDimTags.size(); i++){ - int dim = objectDimTags[i].first; - int tag = objectDimTags[i].second; - if(mapDeleted[i] && !mapGenerated[i].Extent()){ - // the shape has been deleted - if(removeObject && _isBound(dim, tag)){ - unbind(_find(dim, tag), dim, tag, true); - } - } - else if(mapModified[i].Extent() == 0){ - // the shape has not been modified - outDimTags.push_back(std::pair<int, int>(dim, tag)); - // FIXME: since we currently don't guarantee that the tags of the entities - // on the boundary will be preserved, we must force a re-sync of the - // shape, by unbinding (which will add it in _toRemove) and re-binding it - if(removeObject && _isBound(dim, tag)){ - TopoDS_Shape shape = _find(dim, tag); - unbind(shape, dim, tag, true); - bind(shape, dim, tag, true); - } - } - else if(mapModified[i].Extent() == 1){ - if(removeObject){ - // the shape has been replaced by a single shape, keep the same tag - if(_isBound(dim, tag)){ - unbind(_find(dim, tag), dim, tag, true); - } - bind(mapModified[i].First(), dim, tag, true); + else{ + // otherwise, try to preserve the numbering of the input shapes that did not + // change, or that were replaced by a single shape. Note that to preserve + // the numbering of smaller dimension entities (on boundaries) they should + // appear *before* higher dimensional entities in the object/tool lists. + _toPreserve.clear(); + for(unsigned int i = 0; i < inDimTags.size(); i++){ + int dim = inDimTags[i].first; + int tag = inDimTags[i].second; + bool remove = (i < numObjects) ? removeObject : removeTool; + if(mapDeleted[i]){ // deleted + if(remove) unbind(mapOriginal[i], dim, tag, true); + Msg::Debug("BOOL (%d,%d) deleted", dim, tag); + } + else if(mapModified[i].Extent() == 0){ // not modified outDimTags.push_back(std::pair<int, int>(dim, tag)); + _toPreserve.insert(std::pair<int, int>(dim, tag)); + Msg::Debug("BOOL (%d,%d) not modified", dim, tag); + } + else if(mapModified[i].Extent() == 1){ // replaced by single one + if(remove){ + unbind(mapOriginal[i], dim, tag, true); + bind(mapModified[i].First(), dim, tag, false); // not recursive! + int t = _find(dim, mapModified[i].First()); + if(tag != t) + Msg::Info("Could not preserve tag of %dD object %d (->%d)", dim, tag, t); + outDimTags.push_back(std::pair<int, int>(dim, t)); + _toPreserve.insert(std::pair<int, int>(dim, t)); + } + Msg::Debug("BOOL (%d,%d) replaced by 1", dim, tag); } else{ - toBind.push_back(mapModified[i].First()); + if(remove) unbind(mapOriginal[i], dim, tag, true); + Msg::Debug("BOOL (%d,%d) other", dim, tag); } } - else{ - if(removeObject && _isBound(dim, tag)){ - unbind(_find(dim, tag), dim, tag, true); - } - TopTools_ListIteratorOfListOfShape it(mapModified[i]); - for(; it.More(); it.Next()) - toBind.push_back(it.Value()); - } - { - TopTools_ListIteratorOfListOfShape it(mapGenerated[i]); - for(; it.More(); it.Next()) - toBind.push_back(it.Value()); - } + for(int dim = -2; dim <= 3; dim++) _recomputeMaxTag(dim); + // bind all remaining entities and add the new ones to the returned list + _multiBind(result, -1, outDimTags, false, true, true); + _filterTags(outDimTags, minDim); + _toPreserve.clear(); } - for(unsigned int i = 0; i < toolDimTags.size(); i++){ - int k = objectDimTags.size() + i; - int dim = toolDimTags[i].first; - int tag = toolDimTags[i].second; - if(mapDeleted[k] && !mapGenerated[k].Extent()){ - // the shape has been deleted - if(removeTool && _isBound(dim, tag)){ - unbind(_find(dim, tag), dim, tag, true); // recursive - } - } - else if(mapModified[k].Extent() == 0){ - // the shape has not been modified - outDimTags.push_back(std::pair<int, int>(dim, tag)); - // FIXME: since we currently don't guarantee that the tags of the entities - // on the boundary will be preserved, we must force a re-sync of the - // shape, by unbinding (which will add it in _toRemove) and re-binding it - if(removeTool && _isBound(dim, tag)){ - TopoDS_Shape shape = _find(dim, tag); - unbind(shape, dim, tag, true); - bind(shape, dim, tag, true); - } - } - else if(mapModified[k].Extent() == 1){ - if(removeTool){ - // the shape has been replaced by a single shape, keep the same tag - if(_isBound(dim, tag)){ - unbind(_find(dim, tag), dim, tag, true); // recursive - } - bind(mapModified[k].First(), dim, tag, true); // recursive - outDimTags.push_back(std::pair<int, int>(dim, tag)); - } - else{ - toBind.push_back(mapModified[k].First()); - } + // return input/output correspondance maps + for(unsigned int i = 0; i < inDimTags.size(); i++){ + int dim = inDimTags[i].first; + int tag = inDimTags[i].second; + std::pair<int, int> dimTag(dim, tag); + std::vector<std::pair<int, int> > dimTags; + if(mapDeleted[i]){ // deleted + } + else if(mapModified[i].Extent() == 0){ // not modified + dimTags.push_back(dimTag); } else{ - if(removeTool && _isBound(dim, tag)){ - unbind(_find(dim, tag), dim, tag, true); // recursive + TopTools_ListIteratorOfListOfShape it(mapModified[i]); + for(; it.More(); it.Next()){ + if(_isBound(dim, it.Value())){ + int t = _find(dim, it.Value()); + dimTags.push_back(std::pair<int, int>(dim, t)); + } + } + TopTools_ListIteratorOfListOfShape it2(mapGenerated[i]); + for(; it2.More(); it2.Next()){ + if(_isBound(dim, it2.Value())){ + int t = _find(dim, it2.Value()); + dimTags.push_back(std::pair<int, int>(dim, t)); + } } - TopTools_ListIteratorOfListOfShape it(mapModified[k]); - for(; it.More(); it.Next()) - toBind.push_back(it.Value()); - } - { - TopTools_ListIteratorOfListOfShape it(mapGenerated[k]); - for(; it.More(); it.Next()) - toBind.push_back(it.Value()); } - } - - for(unsigned int i = 0; i < toBind.size(); i++){ - // bind all remaining entities (and only return the new ones, as modified - // entities can appear as "Modified()" subshapes of both object and tool) - _multiBind(toBind[i], -1, outDimTags, true, true, true); + std::ostringstream sstream; + sstream << "BOOL in (" << dim << "," << tag << ") -> out"; + for(unsigned int j = 0; j < dimTags.size(); j++) + sstream << " (" << dimTags[j].first << "," << dimTags[j].second << ")"; + Msg::Debug("%s", sstream.str().c_str()); + outDimTagsMap.push_back(dimTags); } return true; @@ -2325,40 +2332,44 @@ bool OCC_Internals::booleanUnion(int tag, const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool) { return booleanOperator(tag, OCC_Internals::Union, objectDimTags, toolDimTags, - outDimTags, removeObject, removeTool); + outDimTags, outDimTagsMap, removeObject, removeTool); } bool OCC_Internals::booleanIntersection(int tag, const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool) { return booleanOperator(tag, OCC_Internals::Intersection, objectDimTags, toolDimTags, - outDimTags, removeObject, removeTool); + outDimTags, outDimTagsMap, removeObject, removeTool); } bool OCC_Internals::booleanDifference(int tag, const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool) { return booleanOperator(tag, OCC_Internals::Difference, objectDimTags, toolDimTags, - outDimTags, removeObject, removeTool); + outDimTags, outDimTagsMap, removeObject, removeTool); } bool OCC_Internals::booleanFragments(int tag, const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool) { return booleanOperator(tag, OCC_Internals::Fragments, objectDimTags, toolDimTags, - outDimTags, removeObject, removeTool); + outDimTags, outDimTagsMap, removeObject, removeTool); } bool OCC_Internals::_transform(const std::vector<std::pair<int, int> > &inDimTags, @@ -2390,6 +2401,8 @@ bool OCC_Internals::_transform(const std::vector<std::pair<int, int> > &inDimTag } result = gtfo->Shape(); } + // FIXME we should implement rebind(object, result, dim) which would + // unbind/bind all subshapes to the same tags unbind(object, dim, tag, true); bind(result, dim, tag, true); } diff --git a/Geo/GModelIO_OCC.h b/Geo/GModelIO_OCC.h index 47f40ef8e8d0d17e2bf1fe0b0ff4553709b33584..2f4c5c2b0f4297d0c50355b1d26638ce73cbbf10 100644 --- a/Geo/GModelIO_OCC.h +++ b/Geo/GModelIO_OCC.h @@ -62,6 +62,10 @@ class OCC_Internals { // remove from the model at the next synchronization std::set<std::pair<int, int> > _toRemove; + // cache of <dim,tag> pairs corresponding to entities that should not be + // unbound during boolean operations + std::set<std::pair<int, int> > _toPreserve; + // mesh attributes OCCMeshAttributesRTree *_meshAttributes; @@ -74,11 +78,14 @@ class OCC_Internals { // bind (potentially) mutliple entities in shape and return the tags in // outTags. If tag > 0 and a single entity if found, use that; if - // highestDimOnly is true, only return the entities of the highest dimension + // highestDimOnly is true, only bind the entities (and sub-entities, if + // recursive is set) of the highest dimension; if returnNewOnly is set, only + // return newly bound entities in outDimTags. void _multiBind(TopoDS_Shape shape, int tag, std::vector<std::pair<int, int> > &outDimTags, bool returnHighestDimOnly, bool recursive=false, bool returnNewOnly=false); + // is the entity of a given dimension and tag bound? bool _isBound(int dim, int tag); @@ -247,26 +254,31 @@ class OCC_Internals { const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool); bool booleanUnion(int tag, const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool); bool booleanIntersection(int tag, const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool); bool booleanDifference(int tag, const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool); bool booleanFragments(int tag, const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool); // apply transformations @@ -536,6 +548,7 @@ public: const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool) { return _error("apply boolean operator"); @@ -544,6 +557,7 @@ public: const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool) { return _error("apply boolean union"); @@ -552,6 +566,7 @@ public: const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool) { return _error("apply boolean intersection"); @@ -560,6 +575,7 @@ public: const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool) { return _error("apply boolean difference"); @@ -568,6 +584,7 @@ public: const std::vector<std::pair<int, int> > &objectDimTags, const std::vector<std::pair<int, int> > &toolDimTags, std::vector<std::pair<int, int> > &outDimTags, + std::vector<std::vector<std::pair<int, int> > > &outDimTagsMap, bool removeObject, bool removeTool) { return _error("apply boolean fragments"); diff --git a/Geo/Geo.cpp b/Geo/Geo.cpp index 79d1fcf002be4cd3779c867c10e33526abbf2c9d..e60ec2cd62ae8160da0ab252ed7d68402ccfaae9 100644 --- a/Geo/Geo.cpp +++ b/Geo/Geo.cpp @@ -345,8 +345,9 @@ void EndCurve(Curve *c) } else if(!v[3] && fabs((R - R2) / (R + R2)) > 0.1){ // check cocircular pts (allow 10% error) - Msg::Error("Control points of circle with tag %d are not cocircular (%g, %g)", - c->Num, R, R2); + Msg::Error("Control points of circle with tag %d are not cocircular: " + "R1=%g, R2=%g, n=[%g,%g,%g]", + c->Num, R, R2, n[0], n[1], n[2]); } // A1 = angle first pt // A3 = angle last pt diff --git a/Geo/OCCFace.cpp b/Geo/OCCFace.cpp index 3bc647e3db577bf958ea5afd1575fabfbf6c9cd7..c9628090372666b55bac8fc90159c88105961e01 100644 --- a/Geo/OCCFace.cpp +++ b/Geo/OCCFace.cpp @@ -73,7 +73,7 @@ void OCCFace::setup() Msg::Error("Unknown edge in face %d", tag()); } else if(edge.Orientation() == TopAbs_INTERNAL){ - Msg::Info("Adding embedded edge %d in face %d", e->tag(), tag()); + Msg::Debug("Adding embedded edge %d in face %d", e->tag(), tag()); embedded_edges.push_back(e); OCCEdge *occe = (OCCEdge*)e; occe->setTrimmed(this); @@ -134,7 +134,7 @@ void OCCFace::setup() Msg::Error("Unknown vertex in face %d", tag()); } else if(vertex.Orientation() == TopAbs_INTERNAL){ - Msg::Info("Adding embedded vertex %d in face %d", v->tag(), tag()); + Msg::Debug("Adding embedded vertex %d in face %d", v->tag(), tag()); embedded_vertices.push_back(v); } } diff --git a/Geo/OCCRegion.cpp b/Geo/OCCRegion.cpp index 388d4fe9e66da9e1577e5559a976634057898e33..2ebcb241cd18db8584244079ef44f35c4366c043 100644 --- a/Geo/OCCRegion.cpp +++ b/Geo/OCCRegion.cpp @@ -51,7 +51,7 @@ void OCCRegion::setup() Msg::Error("Unknown face in region %d", tag()); } else if (face.Orientation() == TopAbs_INTERNAL){ - Msg::Info("Adding embedded face %d in region %d", f->tag(), tag()); + Msg::Debug("Adding embedded face %d in region %d", f->tag(), tag()); embedded_faces.push_back(f); } else{ @@ -70,7 +70,7 @@ void OCCRegion::setup() Msg::Error("Unknown edge in region %d", tag()); } else if (edge.Orientation() == TopAbs_INTERNAL){ - Msg::Info("Adding embedded edge %d in region %d", e->tag(), tag()); + Msg::Debug("Adding embedded edge %d in region %d", e->tag(), tag()); embedded_edges.push_back(e); //OCCEdge *occe = (OCCEdge*)e; //occe->setTrimmed(this); @@ -86,7 +86,7 @@ void OCCRegion::setup() Msg::Error("Unknown vertex in region %d", tag()); } else if (vertex.Orientation() == TopAbs_INTERNAL){ - Msg::Info("Adding embedded vertex %d in region %d", v->tag(), tag()); + Msg::Debug("Adding embedded vertex %d in region %d", v->tag(), tag()); embedded_vertices.push_back(v); } } diff --git a/Graphics/drawGlyph.cpp b/Graphics/drawGlyph.cpp index 5834e8934baa4cbc95abc34aac76b76a58407d5d..557e59f4e99f432377f18b94fbbf33de873996d1 100644 --- a/Graphics/drawGlyph.cpp +++ b/Graphics/drawGlyph.cpp @@ -86,7 +86,8 @@ void drawContext::drawString(const std::string &s, double x, double y, double z, (CTX::instance()->print.fileFormat == FORMAT_PS || CTX::instance()->print.fileFormat == FORMAT_EPS || CTX::instance()->print.fileFormat == FORMAT_PDF || - CTX::instance()->print.fileFormat == FORMAT_SVG)){ + CTX::instance()->print.fileFormat == FORMAT_SVG || + CTX::instance()->print.fileFormat == FORMAT_TIKZ)){ gl2psText(s.c_str(), font_name.c_str(), font_size); } else{ diff --git a/Mesh/meshGFaceBDS.cpp b/Mesh/meshGFaceBDS.cpp index 7b697dc3ca3f4a9d78b2468c275694462f575550..65a703375ecd701d4a8cdb125a6647cded00f790 100644 --- a/Mesh/meshGFaceBDS.cpp +++ b/Mesh/meshGFaceBDS.cpp @@ -318,7 +318,7 @@ bool edgeSwapTestDelaunay(BDS_Edge *e, GFace *gf) fourthPoint(p1x, p2x, op1x, fourth); double result = robustPredicates::insphere(p1x, p2x, op1x, fourth, op2x) * robustPredicates::orient3d(p1x, p2x, op1x, fourth); - return result > 0.; + return result > 1e-12; } bool edgeSwapTestHighOrder(BDS_Edge *e,GFace *gf) diff --git a/Parser/Gmsh.tab.cpp b/Parser/Gmsh.tab.cpp index 4baaad7aaff4adab9b0b53bc7159b369e33227b1..b9b9d48e1c19c1efae5003611ad83bc81d053e3e 100644 --- a/Parser/Gmsh.tab.cpp +++ b/Parser/Gmsh.tab.cpp @@ -1444,34 +1444,34 @@ static const yytype_uint16 yyrline[] = 3643, 3662, 3661, 3686, 3685, 3712, 3711, 3736, 3735, 3758, 3774, 3791, 3808, 3831, 3834, 3840, 3852, 3872, 3876, 3880, 3884, 3888, 3892, 3896, 3900, 3909, 3922, 3923, 3924, 3925, - 3926, 3930, 3931, 3932, 3933, 3934, 3937, 3960, 3979, 4001, - 4004, 4020, 4023, 4040, 4043, 4049, 4052, 4059, 4062, 4069, - 4086, 4127, 4171, 4210, 4235, 4244, 4274, 4300, 4326, 4358, - 4385, 4411, 4437, 4463, 4489, 4511, 4522, 4570, 4619, 4631, - 4642, 4646, 4656, 4667, 4668, 4669, 4673, 4679, 4691, 4709, - 4737, 4738, 4739, 4740, 4741, 4742, 4743, 4744, 4745, 4752, - 4753, 4754, 4755, 4756, 4757, 4758, 4759, 4760, 4761, 4762, - 4763, 4764, 4765, 4766, 4767, 4768, 4769, 4770, 4771, 4772, - 4773, 4774, 4775, 4776, 4777, 4778, 4779, 4780, 4781, 4782, - 4783, 4784, 4785, 4786, 4787, 4788, 4789, 4798, 4799, 4800, - 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4813, 4812, - 4820, 4822, 4827, 4832, 4836, 4841, 4846, 4850, 4854, 4858, - 4862, 4866, 4870, 4876, 4892, 4897, 4903, 4909, 4928, 4949, - 4982, 4986, 4991, 4995, 4999, 5003, 5008, 5013, 5023, 5033, - 5038, 5049, 5058, 5063, 5068, 5096, 5097, 5103, 5104, 5110, - 5109, 5132, 5134, 5139, 5148, 5150, 5156, 5157, 5162, 5166, - 5170, 5174, 5178, 5185, 5189, 5193, 5197, 5204, 5209, 5216, - 5221, 5225, 5230, 5234, 5242, 5253, 5257, 5269, 5277, 5285, - 5292, 5302, 5325, 5331, 5342, 5348, 5358, 5368, 5378, 5390, - 5394, 5399, 5411, 5415, 5419, 5423, 5441, 5449, 5457, 5486, - 5496, 5512, 5523, 5528, 5532, 5536, 5548, 5552, 5564, 5581, - 5591, 5595, 5610, 5615, 5622, 5626, 5631, 5645, 5661, 5665, - 5669, 5673, 5677, 5685, 5691, 5697, 5703, 5712, 5716, 5720, - 5728, 5734, 5740, 5744, 5752, 5760, 5767, 5776, 5780, 5784, - 5799, 5813, 5827, 5839, 5855, 5864, 5873, 5883, 5894, 5902, - 5910, 5914, 5933, 5940, 5946, 5953, 5961, 5960, 5970, 5994, - 5996, 6002, 6007, 6009, 6014, 6019, 6024, 6026, 6030, 6042, - 6056, 6060, 6067, 6075, 6083, 6094, 6096, 6099 + 3926, 3930, 3931, 3932, 3933, 3934, 3937, 3961, 3980, 4003, + 4006, 4022, 4025, 4042, 4045, 4051, 4054, 4061, 4064, 4071, + 4088, 4129, 4173, 4212, 4237, 4246, 4276, 4302, 4328, 4360, + 4387, 4413, 4439, 4465, 4491, 4513, 4524, 4572, 4621, 4633, + 4644, 4648, 4658, 4669, 4670, 4671, 4675, 4681, 4693, 4711, + 4739, 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4754, + 4755, 4756, 4757, 4758, 4759, 4760, 4761, 4762, 4763, 4764, + 4765, 4766, 4767, 4768, 4769, 4770, 4771, 4772, 4773, 4774, + 4775, 4776, 4777, 4778, 4779, 4780, 4781, 4782, 4783, 4784, + 4785, 4786, 4787, 4788, 4789, 4790, 4791, 4800, 4801, 4802, + 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4815, 4814, + 4822, 4824, 4829, 4834, 4838, 4843, 4848, 4852, 4856, 4860, + 4864, 4868, 4872, 4878, 4894, 4899, 4905, 4911, 4930, 4951, + 4984, 4988, 4993, 4997, 5001, 5005, 5010, 5015, 5025, 5035, + 5040, 5051, 5060, 5065, 5070, 5098, 5099, 5105, 5106, 5112, + 5111, 5134, 5136, 5141, 5150, 5152, 5158, 5159, 5164, 5168, + 5172, 5176, 5180, 5187, 5191, 5195, 5199, 5206, 5211, 5218, + 5223, 5227, 5232, 5236, 5244, 5255, 5259, 5271, 5279, 5287, + 5294, 5304, 5327, 5333, 5344, 5350, 5360, 5370, 5380, 5392, + 5396, 5401, 5413, 5417, 5421, 5425, 5443, 5451, 5459, 5488, + 5498, 5514, 5525, 5530, 5534, 5538, 5550, 5554, 5566, 5583, + 5593, 5597, 5612, 5617, 5624, 5628, 5633, 5647, 5663, 5667, + 5671, 5675, 5679, 5687, 5693, 5699, 5705, 5714, 5718, 5722, + 5730, 5736, 5742, 5746, 5754, 5762, 5769, 5778, 5782, 5786, + 5801, 5815, 5829, 5841, 5857, 5866, 5875, 5885, 5896, 5904, + 5912, 5916, 5935, 5942, 5948, 5955, 5963, 5962, 5972, 5996, + 5998, 6004, 6009, 6011, 6016, 6021, 6026, 6028, 6032, 6044, + 6058, 6062, 6069, 6077, 6085, 6096, 6098, 6101 }; #endif @@ -10478,13 +10478,14 @@ yyreduce: bool r = true; if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){ std::vector<std::pair<int, int > > object, tool, out; + std::vector<std::vector<std::pair<int, int > > > outMap; ListOfShapes2VectorOfPairs((yyvsp[(3) - (9)].l), object); ListOfShapes2VectorOfPairs((yyvsp[(7) - (9)].l), tool); // currently we don't distinguish between Delete and Recursive Delete: // we always delete recursively. Let us know if you have examples where // having the choice would be interesting r = GModel::current()->getOCCInternals()->booleanOperator - (-1, (OCC_Internals::BooleanOperator)(yyvsp[(1) - (9)].i), object, tool, out, (yyvsp[(4) - (9)].i), (yyvsp[(8) - (9)].i)); + (-1, (OCC_Internals::BooleanOperator)(yyvsp[(1) - (9)].i), object, tool, out, outMap, (yyvsp[(4) - (9)].i), (yyvsp[(8) - (9)].i)); VectorOfPairs2ListOfShapes(out, (yyval.l)); } else{ @@ -10497,7 +10498,7 @@ yyreduce: break; case 317: -#line 3961 "Gmsh.y" +#line 3962 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(Shape)); bool r = true; @@ -10516,18 +10517,19 @@ yyreduce: break; case 318: -#line 3981 "Gmsh.y" +#line 3982 "Gmsh.y" { bool r = true; if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){ std::vector<std::pair<int, int> > object, tool, out; + std::vector<std::vector<std::pair<int, int > > > outMap; ListOfShapes2VectorOfPairs((yyvsp[(7) - (14)].l), object); ListOfShapes2VectorOfPairs((yyvsp[(11) - (14)].l), tool); // currently we don't distinguish between Delete and Recursive Delete: // we always delete recursively. Let us know if you have examples where // having the choice would be interesting r = GModel::current()->getOCCInternals()->booleanOperator - ((int)(yyvsp[(3) - (14)].d), (OCC_Internals::BooleanOperator)(yyvsp[(1) - (14)].i), object, tool, out, (yyvsp[(8) - (14)].i), (yyvsp[(12) - (14)].i)); + ((int)(yyvsp[(3) - (14)].d), (OCC_Internals::BooleanOperator)(yyvsp[(1) - (14)].i), object, tool, out, outMap, (yyvsp[(8) - (14)].i), (yyvsp[(12) - (14)].i)); } if(!r) yymsg(0, "Could not apply boolean operator"); List_Delete((yyvsp[(7) - (14)].l)); @@ -10536,14 +10538,14 @@ yyreduce: break; case 319: -#line 4001 "Gmsh.y" +#line 4003 "Gmsh.y" { (yyval.v)[0] = (yyval.v)[1] = 1.; ;} break; case 320: -#line 4005 "Gmsh.y" +#line 4007 "Gmsh.y" { if(!strcmp((yyvsp[(2) - (3)].c), "Progression") || !strcmp((yyvsp[(2) - (3)].c), "Power")) (yyval.v)[0] = 1.; @@ -10559,14 +10561,14 @@ yyreduce: break; case 321: -#line 4020 "Gmsh.y" +#line 4022 "Gmsh.y" { (yyval.i) = -1; // left ;} break; case 322: -#line 4024 "Gmsh.y" +#line 4026 "Gmsh.y" { if(!strcmp((yyvsp[(1) - (1)].c), "Right")) (yyval.i) = 1; @@ -10583,49 +10585,49 @@ yyreduce: break; case 323: -#line 4040 "Gmsh.y" +#line 4042 "Gmsh.y" { (yyval.l) = List_Create(1, 1, sizeof(double)); ;} break; case 324: -#line 4044 "Gmsh.y" +#line 4046 "Gmsh.y" { (yyval.l) = (yyvsp[(2) - (2)].l); ;} break; case 325: -#line 4049 "Gmsh.y" +#line 4051 "Gmsh.y" { (yyval.i) = 45; ;} break; case 326: -#line 4053 "Gmsh.y" +#line 4055 "Gmsh.y" { (yyval.i) = (int)(yyvsp[(2) - (2)].d); ;} break; case 327: -#line 4059 "Gmsh.y" +#line 4061 "Gmsh.y" { (yyval.l) = List_Create(1, 1, sizeof(double)); ;} break; case 328: -#line 4063 "Gmsh.y" +#line 4065 "Gmsh.y" { (yyval.l) = (yyvsp[(2) - (2)].l); ;} break; case 329: -#line 4070 "Gmsh.y" +#line 4072 "Gmsh.y" { // mesh sizes at vertices are stored in internal CAD data, as they can be // specified during vertex creation and copied around during CAD @@ -10645,7 +10647,7 @@ yyreduce: break; case 330: -#line 4087 "Gmsh.y" +#line 4089 "Gmsh.y" { // transfinite constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -10689,7 +10691,7 @@ yyreduce: break; case 331: -#line 4128 "Gmsh.y" +#line 4130 "Gmsh.y" { // transfinite constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -10736,7 +10738,7 @@ yyreduce: break; case 332: -#line 4172 "Gmsh.y" +#line 4174 "Gmsh.y" { // transfinite constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -10778,7 +10780,7 @@ yyreduce: break; case 333: -#line 4211 "Gmsh.y" +#line 4213 "Gmsh.y" { // transfinite constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -10806,7 +10808,7 @@ yyreduce: break; case 334: -#line 4236 "Gmsh.y" +#line 4238 "Gmsh.y" { for(int i = 0; i < List_Nbr((yyvsp[(4) - (8)].l)); i++){ double d; @@ -10818,7 +10820,7 @@ yyreduce: break; case 335: -#line 4245 "Gmsh.y" +#line 4247 "Gmsh.y" { // recombine constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -10851,7 +10853,7 @@ yyreduce: break; case 336: -#line 4275 "Gmsh.y" +#line 4277 "Gmsh.y" { // recombine constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -10880,7 +10882,7 @@ yyreduce: break; case 337: -#line 4301 "Gmsh.y" +#line 4303 "Gmsh.y" { // smoothing constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -10909,7 +10911,7 @@ yyreduce: break; case 338: -#line 4328 "Gmsh.y" +#line 4330 "Gmsh.y" { if (List_Nbr((yyvsp[(4) - (11)].l)) != List_Nbr((yyvsp[(8) - (11)].l))){ yymsg(0, "Number of master lines (%d) different from number of " @@ -10943,7 +10945,7 @@ yyreduce: break; case 339: -#line 4360 "Gmsh.y" +#line 4362 "Gmsh.y" { if (List_Nbr((yyvsp[(4) - (11)].l)) != List_Nbr((yyvsp[(8) - (11)].l))){ yymsg(0, "Number of master faces (%d) different from number of " @@ -10972,7 +10974,7 @@ yyreduce: break; case 340: -#line 4387 "Gmsh.y" +#line 4389 "Gmsh.y" { if (List_Nbr((yyvsp[(4) - (18)].l)) != List_Nbr((yyvsp[(8) - (18)].l))){ yymsg(0, "Number of master edges (%d) different from number of " @@ -11000,7 +11002,7 @@ yyreduce: break; case 341: -#line 4413 "Gmsh.y" +#line 4415 "Gmsh.y" { if (List_Nbr((yyvsp[(4) - (18)].l)) != List_Nbr((yyvsp[(8) - (18)].l))){ yymsg(0, "Number of master faces (%d) different from number of " @@ -11028,7 +11030,7 @@ yyreduce: break; case 342: -#line 4439 "Gmsh.y" +#line 4441 "Gmsh.y" { if (List_Nbr((yyvsp[(4) - (12)].l)) != List_Nbr((yyvsp[(8) - (12)].l))){ yymsg(0, "Number of master edges (%d) different from number of " @@ -11056,7 +11058,7 @@ yyreduce: break; case 343: -#line 4465 "Gmsh.y" +#line 4467 "Gmsh.y" { if (List_Nbr((yyvsp[(4) - (12)].l)) != List_Nbr((yyvsp[(8) - (12)].l))){ yymsg(0, "Number of master faces (%d) different from number of " @@ -11084,7 +11086,7 @@ yyreduce: break; case 344: -#line 4491 "Gmsh.y" +#line 4493 "Gmsh.y" { if (List_Nbr((yyvsp[(5) - (12)].l)) != List_Nbr((yyvsp[(10) - (12)].l))){ yymsg(0, "Number of master surface edges (%d) different from number of " @@ -11108,7 +11110,7 @@ yyreduce: break; case 345: -#line 4512 "Gmsh.y" +#line 4514 "Gmsh.y" { if (((yyvsp[(6) - (10)].i)==2 || (yyvsp[(6) - (10)].i)==3) && (yyvsp[(1) - (10)].i)<(yyvsp[(6) - (10)].i) ) { std::vector<int> tags; ListOfDouble2Vector((yyvsp[(3) - (10)].l), tags); @@ -11122,7 +11124,7 @@ yyreduce: break; case 346: -#line 4523 "Gmsh.y" +#line 4525 "Gmsh.y" { // reverse mesh constraints are stored in GEO internals in addition to // GModel, as they can be copied around during GEO operations @@ -11173,7 +11175,7 @@ yyreduce: break; case 347: -#line 4571 "Gmsh.y" +#line 4573 "Gmsh.y" { if(!(yyvsp[(3) - (4)].l)){ switch ((yyvsp[(2) - (4)].i)) { @@ -11225,7 +11227,7 @@ yyreduce: break; case 348: -#line 4620 "Gmsh.y" +#line 4622 "Gmsh.y" { for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++){ double dnum; @@ -11240,7 +11242,7 @@ yyreduce: break; case 349: -#line 4632 "Gmsh.y" +#line 4634 "Gmsh.y" { std::vector<int> tags; ListOfDouble2Vector((yyvsp[(3) - (4)].l), tags); GModel::current()->getGEOInternals()->setCompoundMesh((yyvsp[(2) - (4)].i), tags); @@ -11249,14 +11251,14 @@ yyreduce: break; case 350: -#line 4643 "Gmsh.y" +#line 4645 "Gmsh.y" { GModel::current()->getGEOInternals()->removeAllDuplicates(); ;} break; case 351: -#line 4647 "Gmsh.y" +#line 4649 "Gmsh.y" { if(!strcmp((yyvsp[(2) - (3)].c), "Geometry")) GModel::current()->getGEOInternals()->removeAllDuplicates(); @@ -11269,7 +11271,7 @@ yyreduce: break; case 352: -#line 4657 "Gmsh.y" +#line 4659 "Gmsh.y" { std::vector<int> tags; ListOfDouble2Vector((yyvsp[(4) - (6)].l), tags); GModel::current()->getGEOInternals()->mergeVertices(tags); @@ -11278,22 +11280,22 @@ yyreduce: break; case 353: -#line 4667 "Gmsh.y" +#line 4669 "Gmsh.y" { (yyval.c) = (char*)"Homology"; ;} break; case 354: -#line 4668 "Gmsh.y" +#line 4670 "Gmsh.y" { (yyval.c) = (char*)"Cohomology"; ;} break; case 355: -#line 4669 "Gmsh.y" +#line 4671 "Gmsh.y" { (yyval.c) = (char*)"Betti"; ;} break; case 356: -#line 4674 "Gmsh.y" +#line 4676 "Gmsh.y" { std::vector<int> domain, subdomain, dim; for(int i = 0; i < 4; i++) dim.push_back(i); @@ -11302,7 +11304,7 @@ yyreduce: break; case 357: -#line 4680 "Gmsh.y" +#line 4682 "Gmsh.y" { std::vector<int> domain, subdomain, dim; for(int i = 0; i < List_Nbr((yyvsp[(3) - (5)].l)); i++){ @@ -11317,7 +11319,7 @@ yyreduce: break; case 358: -#line 4692 "Gmsh.y" +#line 4694 "Gmsh.y" { std::vector<int> domain, subdomain, dim; for(int i = 0; i < List_Nbr((yyvsp[(3) - (7)].l)); i++){ @@ -11338,7 +11340,7 @@ yyreduce: break; case 359: -#line 4710 "Gmsh.y" +#line 4712 "Gmsh.y" { std::vector<int> domain, subdomain, dim; for(int i = 0; i < List_Nbr((yyvsp[(6) - (10)].l)); i++){ @@ -11364,47 +11366,47 @@ yyreduce: break; case 360: -#line 4737 "Gmsh.y" +#line 4739 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (1)].d); ;} break; case 361: -#line 4738 "Gmsh.y" +#line 4740 "Gmsh.y" { (yyval.d) = (yyvsp[(2) - (3)].d); ;} break; case 362: -#line 4739 "Gmsh.y" +#line 4741 "Gmsh.y" { (yyval.d) = -(yyvsp[(2) - (2)].d); ;} break; case 363: -#line 4740 "Gmsh.y" +#line 4742 "Gmsh.y" { (yyval.d) = (yyvsp[(2) - (2)].d); ;} break; case 364: -#line 4741 "Gmsh.y" +#line 4743 "Gmsh.y" { (yyval.d) = !(yyvsp[(2) - (2)].d); ;} break; case 365: -#line 4742 "Gmsh.y" +#line 4744 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) - (yyvsp[(3) - (3)].d); ;} break; case 366: -#line 4743 "Gmsh.y" +#line 4745 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) + (yyvsp[(3) - (3)].d); ;} break; case 367: -#line 4744 "Gmsh.y" +#line 4746 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) * (yyvsp[(3) - (3)].d); ;} break; case 368: -#line 4746 "Gmsh.y" +#line 4748 "Gmsh.y" { if(!(yyvsp[(3) - (3)].d)) yymsg(0, "Division by zero in '%g / %g'", (yyvsp[(1) - (3)].d), (yyvsp[(3) - (3)].d)); @@ -11414,257 +11416,257 @@ yyreduce: break; case 369: -#line 4752 "Gmsh.y" +#line 4754 "Gmsh.y" { (yyval.d) = (int)(yyvsp[(1) - (3)].d) | (int)(yyvsp[(3) - (3)].d); ;} break; case 370: -#line 4753 "Gmsh.y" +#line 4755 "Gmsh.y" { (yyval.d) = (int)(yyvsp[(1) - (3)].d) & (int)(yyvsp[(3) - (3)].d); ;} break; case 371: -#line 4754 "Gmsh.y" +#line 4756 "Gmsh.y" { (yyval.d) = (int)(yyvsp[(1) - (3)].d) % (int)(yyvsp[(3) - (3)].d); ;} break; case 372: -#line 4755 "Gmsh.y" +#line 4757 "Gmsh.y" { (yyval.d) = pow((yyvsp[(1) - (3)].d), (yyvsp[(3) - (3)].d)); ;} break; case 373: -#line 4756 "Gmsh.y" +#line 4758 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) < (yyvsp[(3) - (3)].d); ;} break; case 374: -#line 4757 "Gmsh.y" +#line 4759 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) > (yyvsp[(3) - (3)].d); ;} break; case 375: -#line 4758 "Gmsh.y" +#line 4760 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) <= (yyvsp[(3) - (3)].d); ;} break; case 376: -#line 4759 "Gmsh.y" +#line 4761 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) >= (yyvsp[(3) - (3)].d); ;} break; case 377: -#line 4760 "Gmsh.y" +#line 4762 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) == (yyvsp[(3) - (3)].d); ;} break; case 378: -#line 4761 "Gmsh.y" +#line 4763 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) != (yyvsp[(3) - (3)].d); ;} break; case 379: -#line 4762 "Gmsh.y" +#line 4764 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) && (yyvsp[(3) - (3)].d); ;} break; case 380: -#line 4763 "Gmsh.y" +#line 4765 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (3)].d) || (yyvsp[(3) - (3)].d); ;} break; case 381: -#line 4764 "Gmsh.y" +#line 4766 "Gmsh.y" { (yyval.d) = ((int)(yyvsp[(1) - (3)].d) >> (int)(yyvsp[(3) - (3)].d)); ;} break; case 382: -#line 4765 "Gmsh.y" +#line 4767 "Gmsh.y" { (yyval.d) = ((int)(yyvsp[(1) - (3)].d) << (int)(yyvsp[(3) - (3)].d)); ;} break; case 383: -#line 4766 "Gmsh.y" +#line 4768 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (5)].d) ? (yyvsp[(3) - (5)].d) : (yyvsp[(5) - (5)].d); ;} break; case 384: -#line 4767 "Gmsh.y" +#line 4769 "Gmsh.y" { (yyval.d) = exp((yyvsp[(3) - (4)].d)); ;} break; case 385: -#line 4768 "Gmsh.y" +#line 4770 "Gmsh.y" { (yyval.d) = log((yyvsp[(3) - (4)].d)); ;} break; case 386: -#line 4769 "Gmsh.y" +#line 4771 "Gmsh.y" { (yyval.d) = log10((yyvsp[(3) - (4)].d)); ;} break; case 387: -#line 4770 "Gmsh.y" +#line 4772 "Gmsh.y" { (yyval.d) = sqrt((yyvsp[(3) - (4)].d)); ;} break; case 388: -#line 4771 "Gmsh.y" +#line 4773 "Gmsh.y" { (yyval.d) = sin((yyvsp[(3) - (4)].d)); ;} break; case 389: -#line 4772 "Gmsh.y" +#line 4774 "Gmsh.y" { (yyval.d) = asin((yyvsp[(3) - (4)].d)); ;} break; case 390: -#line 4773 "Gmsh.y" +#line 4775 "Gmsh.y" { (yyval.d) = cos((yyvsp[(3) - (4)].d)); ;} break; case 391: -#line 4774 "Gmsh.y" +#line 4776 "Gmsh.y" { (yyval.d) = acos((yyvsp[(3) - (4)].d)); ;} break; case 392: -#line 4775 "Gmsh.y" +#line 4777 "Gmsh.y" { (yyval.d) = tan((yyvsp[(3) - (4)].d)); ;} break; case 393: -#line 4776 "Gmsh.y" +#line 4778 "Gmsh.y" { (yyval.d) = atan((yyvsp[(3) - (4)].d)); ;} break; case 394: -#line 4777 "Gmsh.y" +#line 4779 "Gmsh.y" { (yyval.d) = atan2((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d));;} break; case 395: -#line 4778 "Gmsh.y" +#line 4780 "Gmsh.y" { (yyval.d) = sinh((yyvsp[(3) - (4)].d)); ;} break; case 396: -#line 4779 "Gmsh.y" +#line 4781 "Gmsh.y" { (yyval.d) = cosh((yyvsp[(3) - (4)].d)); ;} break; case 397: -#line 4780 "Gmsh.y" +#line 4782 "Gmsh.y" { (yyval.d) = tanh((yyvsp[(3) - (4)].d)); ;} break; case 398: -#line 4781 "Gmsh.y" +#line 4783 "Gmsh.y" { (yyval.d) = fabs((yyvsp[(3) - (4)].d)); ;} break; case 399: -#line 4782 "Gmsh.y" +#line 4784 "Gmsh.y" { (yyval.d) = std::abs((yyvsp[(3) - (4)].d)); ;} break; case 400: -#line 4783 "Gmsh.y" +#line 4785 "Gmsh.y" { (yyval.d) = floor((yyvsp[(3) - (4)].d)); ;} break; case 401: -#line 4784 "Gmsh.y" +#line 4786 "Gmsh.y" { (yyval.d) = ceil((yyvsp[(3) - (4)].d)); ;} break; case 402: -#line 4785 "Gmsh.y" +#line 4787 "Gmsh.y" { (yyval.d) = floor((yyvsp[(3) - (4)].d) + 0.5); ;} break; case 403: -#line 4786 "Gmsh.y" +#line 4788 "Gmsh.y" { (yyval.d) = fmod((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d)); ;} break; case 404: -#line 4787 "Gmsh.y" +#line 4789 "Gmsh.y" { (yyval.d) = fmod((yyvsp[(3) - (6)].d), (yyvsp[(5) - (6)].d)); ;} break; case 405: -#line 4788 "Gmsh.y" +#line 4790 "Gmsh.y" { (yyval.d) = sqrt((yyvsp[(3) - (6)].d) * (yyvsp[(3) - (6)].d) + (yyvsp[(5) - (6)].d) * (yyvsp[(5) - (6)].d)); ;} break; case 406: -#line 4789 "Gmsh.y" +#line 4791 "Gmsh.y" { (yyval.d) = (yyvsp[(3) - (4)].d) * (double)rand() / (double)RAND_MAX; ;} break; case 407: -#line 4798 "Gmsh.y" +#line 4800 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (1)].d); ;} break; case 408: -#line 4799 "Gmsh.y" +#line 4801 "Gmsh.y" { (yyval.d) = 3.141592653589793; ;} break; case 409: -#line 4800 "Gmsh.y" +#line 4802 "Gmsh.y" { (yyval.d) = (double)ImbricatedTest; ;} break; case 410: -#line 4801 "Gmsh.y" +#line 4803 "Gmsh.y" { (yyval.d) = Msg::GetCommRank(); ;} break; case 411: -#line 4802 "Gmsh.y" +#line 4804 "Gmsh.y" { (yyval.d) = Msg::GetCommSize(); ;} break; case 412: -#line 4803 "Gmsh.y" +#line 4805 "Gmsh.y" { (yyval.d) = GetGmshMajorVersion(); ;} break; case 413: -#line 4804 "Gmsh.y" +#line 4806 "Gmsh.y" { (yyval.d) = GetGmshMinorVersion(); ;} break; case 414: -#line 4805 "Gmsh.y" +#line 4807 "Gmsh.y" { (yyval.d) = GetGmshPatchVersion(); ;} break; case 415: -#line 4806 "Gmsh.y" +#line 4808 "Gmsh.y" { (yyval.d) = Cpu(); ;} break; case 416: -#line 4807 "Gmsh.y" +#line 4809 "Gmsh.y" { (yyval.d) = GetMemoryUsage()/1024./1024.; ;} break; case 417: -#line 4808 "Gmsh.y" +#line 4810 "Gmsh.y" { (yyval.d) = TotalRam(); ;} break; case 418: -#line 4813 "Gmsh.y" +#line 4815 "Gmsh.y" { init_options(); ;} break; case 419: -#line 4815 "Gmsh.y" +#line 4817 "Gmsh.y" { std::vector<double> val(1, (yyvsp[(3) - (6)].d)); Msg::ExchangeOnelabParameter("", val, floatOptions, charOptions); @@ -11673,12 +11675,12 @@ yyreduce: break; case 420: -#line 4821 "Gmsh.y" +#line 4823 "Gmsh.y" { (yyval.d) = (yyvsp[(1) - (1)].d); ;} break; case 421: -#line 4823 "Gmsh.y" +#line 4825 "Gmsh.y" { (yyval.d) = Msg::GetOnelabNumber((yyvsp[(3) - (4)].c)); Free((yyvsp[(3) - (4)].c)); @@ -11686,7 +11688,7 @@ yyreduce: break; case 422: -#line 4828 "Gmsh.y" +#line 4830 "Gmsh.y" { (yyval.d) = Msg::GetOnelabNumber((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].d)); Free((yyvsp[(3) - (6)].c)); @@ -11694,70 +11696,70 @@ yyreduce: break; case 423: -#line 4833 "Gmsh.y" +#line 4835 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_Float((yyvsp[(1) - (1)].c2).char1, (yyvsp[(1) - (1)].c2).char2); ;} break; case 424: -#line 4838 "Gmsh.y" +#line 4840 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_Float(NULL, (yyvsp[(1) - (4)].c), 2, (int)(yyvsp[(3) - (4)].d)); ;} break; case 425: -#line 4843 "Gmsh.y" +#line 4845 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_Float(NULL, (yyvsp[(1) - (4)].c), 2, (int)(yyvsp[(3) - (4)].d)); ;} break; case 426: -#line 4847 "Gmsh.y" +#line 4849 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_Float((yyvsp[(3) - (4)].c2).char1, (yyvsp[(3) - (4)].c2).char2, 1, 0, 0., 1); ;} break; case 427: -#line 4851 "Gmsh.y" +#line 4853 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(3) - (6)].c2).char1, (yyvsp[(3) - (6)].c2).char2, (yyvsp[(5) - (6)].c), 0, 0., 1); ;} break; case 428: -#line 4855 "Gmsh.y" +#line 4857 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_Float((yyvsp[(3) - (5)].c2).char1, (yyvsp[(3) - (5)].c2).char2, 1, 0, (yyvsp[(4) - (5)].d), 2); ;} break; case 429: -#line 4859 "Gmsh.y" +#line 4861 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(3) - (7)].c2).char1, (yyvsp[(3) - (7)].c2).char2, (yyvsp[(5) - (7)].c), 0, (yyvsp[(6) - (7)].d), 2); ;} break; case 430: -#line 4863 "Gmsh.y" +#line 4865 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_Float((yyvsp[(3) - (8)].c2).char1, (yyvsp[(3) - (8)].c2).char2, 2, (int)(yyvsp[(5) - (8)].d), (yyvsp[(7) - (8)].d), 2); ;} break; case 431: -#line 4867 "Gmsh.y" +#line 4869 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(3) - (10)].c2).char1, (yyvsp[(3) - (10)].c2).char2, (yyvsp[(5) - (10)].c), (int)(yyvsp[(7) - (10)].d), (yyvsp[(9) - (10)].d), 2); ;} break; case 432: -#line 4871 "Gmsh.y" +#line 4873 "Gmsh.y" { std::string tmp = FixRelativePath(gmsh_yyname, (yyvsp[(3) - (4)].c)); (yyval.d) = !StatFile(tmp); @@ -11766,7 +11768,7 @@ yyreduce: break; case 433: -#line 4877 "Gmsh.y" +#line 4879 "Gmsh.y" { if(gmsh_yysymbols.count((yyvsp[(2) - (4)].c))){ gmsh_yysymbol &s(gmsh_yysymbols[(yyvsp[(2) - (4)].c)]); @@ -11784,14 +11786,14 @@ yyreduce: break; case 434: -#line 4893 "Gmsh.y" +#line 4895 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float_getDim((yyvsp[(2) - (6)].c2).char1, (yyvsp[(2) - (6)].c2).char2, (yyvsp[(4) - (6)].c)); ;} break; case 435: -#line 4898 "Gmsh.y" +#line 4900 "Gmsh.y" { std::string struct_namespace((yyvsp[(3) - (4)].c)); (yyval.d) = (double)gmsh_yynamespaces[struct_namespace].size(); @@ -11800,7 +11802,7 @@ yyreduce: break; case 436: -#line 4904 "Gmsh.y" +#line 4906 "Gmsh.y" { std::string struct_namespace(std::string("")); (yyval.d) = (double)gmsh_yynamespaces[struct_namespace].size(); @@ -11808,7 +11810,7 @@ yyreduce: break; case 437: -#line 4910 "Gmsh.y" +#line 4912 "Gmsh.y" { if(!gmsh_yysymbols.count((yyvsp[(1) - (2)].c))){ yymsg(0, "Unknown variable '%s'", (yyvsp[(1) - (2)].c)); @@ -11830,7 +11832,7 @@ yyreduce: break; case 438: -#line 4929 "Gmsh.y" +#line 4931 "Gmsh.y" { int index = (int)(yyvsp[(3) - (5)].d); if(!gmsh_yysymbols.count((yyvsp[(1) - (5)].c))){ @@ -11853,7 +11855,7 @@ yyreduce: break; case 439: -#line 4950 "Gmsh.y" +#line 4952 "Gmsh.y" { int index = (int)(yyvsp[(3) - (5)].d); if(!gmsh_yysymbols.count((yyvsp[(1) - (5)].c))){ @@ -11876,49 +11878,49 @@ yyreduce: break; case 440: -#line 4983 "Gmsh.y" +#line 4985 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float(NULL, (yyvsp[(1) - (3)].c), (yyvsp[(3) - (3)].c)); ;} break; case 441: -#line 4987 "Gmsh.y" +#line 4989 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(1) - (5)].c), (yyvsp[(3) - (5)].c), (yyvsp[(5) - (5)].c)); ;} break; case 442: -#line 4992 "Gmsh.y" +#line 4994 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float(NULL, (yyvsp[(1) - (6)].c), (yyvsp[(3) - (6)].c), (int)(yyvsp[(5) - (6)].d)); ;} break; case 443: -#line 4996 "Gmsh.y" +#line 4998 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(1) - (8)].c), (yyvsp[(3) - (8)].c), (yyvsp[(5) - (8)].c), (int)(yyvsp[(7) - (8)].d)); ;} break; case 444: -#line 5000 "Gmsh.y" +#line 5002 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float(NULL, (yyvsp[(1) - (6)].c), (yyvsp[(3) - (6)].c), (int)(yyvsp[(5) - (6)].d)); ;} break; case 445: -#line 5004 "Gmsh.y" +#line 5006 "Gmsh.y" { (yyval.d) = treat_Struct_FullName_dot_tSTRING_Float((yyvsp[(1) - (8)].c), (yyvsp[(3) - (8)].c), (yyvsp[(5) - (8)].c), (int)(yyvsp[(7) - (8)].d)); ;} break; case 446: -#line 5009 "Gmsh.y" +#line 5011 "Gmsh.y" { NumberOption(GMSH_GET, (yyvsp[(1) - (6)].c), (int)(yyvsp[(3) - (6)].d), (yyvsp[(6) - (6)].c), (yyval.d)); Free((yyvsp[(1) - (6)].c)); Free((yyvsp[(6) - (6)].c)); @@ -11926,7 +11928,7 @@ yyreduce: break; case 447: -#line 5014 "Gmsh.y" +#line 5016 "Gmsh.y" { double d = 0.; if(NumberOption(GMSH_GET, (yyvsp[(1) - (4)].c), 0, (yyvsp[(3) - (4)].c), d)){ @@ -11939,7 +11941,7 @@ yyreduce: break; case 448: -#line 5024 "Gmsh.y" +#line 5026 "Gmsh.y" { double d = 0.; if(NumberOption(GMSH_GET, (yyvsp[(1) - (7)].c), (int)(yyvsp[(3) - (7)].d), (yyvsp[(6) - (7)].c), d)){ @@ -11952,7 +11954,7 @@ yyreduce: break; case 449: -#line 5034 "Gmsh.y" +#line 5036 "Gmsh.y" { (yyval.d) = Msg::GetValue((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].d)); Free((yyvsp[(3) - (6)].c)); @@ -11960,7 +11962,7 @@ yyreduce: break; case 450: -#line 5039 "Gmsh.y" +#line 5041 "Gmsh.y" { int matches = 0; for(int i = 0; i < List_Nbr((yyvsp[(3) - (6)].l)); i++){ @@ -11974,7 +11976,7 @@ yyreduce: break; case 451: -#line 5050 "Gmsh.y" +#line 5052 "Gmsh.y" { std::string s((yyvsp[(3) - (6)].c)), substr((yyvsp[(5) - (6)].c)); if(s.find(substr) != std::string::npos) @@ -11986,7 +11988,7 @@ yyreduce: break; case 452: -#line 5059 "Gmsh.y" +#line 5061 "Gmsh.y" { (yyval.d) = strlen((yyvsp[(3) - (4)].c)); Free((yyvsp[(3) - (4)].c)); @@ -11994,7 +11996,7 @@ yyreduce: break; case 453: -#line 5064 "Gmsh.y" +#line 5066 "Gmsh.y" { (yyval.d) = strcmp((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].c)); Free((yyvsp[(3) - (6)].c)); Free((yyvsp[(5) - (6)].c)); @@ -12002,7 +12004,7 @@ yyreduce: break; case 454: -#line 5069 "Gmsh.y" +#line 5071 "Gmsh.y" { int align = 0, font = 0, fontsize = CTX::instance()->glFontSize; if(List_Nbr((yyvsp[(3) - (4)].l)) % 2){ @@ -12029,27 +12031,27 @@ yyreduce: break; case 455: -#line 5096 "Gmsh.y" +#line 5098 "Gmsh.y" { (yyval.d) = 0.; ;} break; case 456: -#line 5098 "Gmsh.y" +#line 5100 "Gmsh.y" { (yyval.d) = (yyvsp[(2) - (2)].d);;} break; case 457: -#line 5103 "Gmsh.y" +#line 5105 "Gmsh.y" { (yyval.c) = NULL; ;} break; case 458: -#line 5105 "Gmsh.y" +#line 5107 "Gmsh.y" { (yyval.c) = (yyvsp[(2) - (2)].c);;} break; case 459: -#line 5110 "Gmsh.y" +#line 5112 "Gmsh.y" { std::string struct_namespace((yyvsp[(2) - (3)].c2).char1? (yyvsp[(2) - (3)].c2).char1 : std::string("")), struct_name((yyvsp[(2) - (3)].c2).char2); @@ -12059,7 +12061,7 @@ yyreduce: break; case 460: -#line 5117 "Gmsh.y" +#line 5119 "Gmsh.y" { std::string struct_namespace((yyvsp[(2) - (7)].c2).char1? (yyvsp[(2) - (7)].c2).char1 : std::string("")), struct_name((yyvsp[(2) - (7)].c2).char2); @@ -12075,105 +12077,105 @@ yyreduce: break; case 461: -#line 5133 "Gmsh.y" +#line 5135 "Gmsh.y" { (yyval.c2).char1 = NULL; (yyval.c2).char2 = (yyvsp[(1) - (1)].c); ;} break; case 462: -#line 5135 "Gmsh.y" +#line 5137 "Gmsh.y" { (yyval.c2).char1 = (yyvsp[(1) - (3)].c); (yyval.c2).char2 = (yyvsp[(3) - (3)].c); ;} break; case 463: -#line 5140 "Gmsh.y" +#line 5142 "Gmsh.y" { (yyval.c) = (yyvsp[(1) - (1)].c); flag_tSTRING_alloc = 1; ;} break; case 464: -#line 5149 "Gmsh.y" +#line 5151 "Gmsh.y" { (yyval.i) = 99; ;} break; case 465: -#line 5151 "Gmsh.y" +#line 5153 "Gmsh.y" { (yyval.i) = (int)(yyvsp[(2) - (2)].d); ;} break; case 466: -#line 5156 "Gmsh.y" +#line 5158 "Gmsh.y" { (yyval.i) = 0; ;} break; case 467: -#line 5158 "Gmsh.y" +#line 5160 "Gmsh.y" { (yyval.i) = (yyvsp[(2) - (3)].i); ;} break; case 468: -#line 5163 "Gmsh.y" +#line 5165 "Gmsh.y" { memcpy((yyval.v), (yyvsp[(1) - (1)].v), 5*sizeof(double)); ;} break; case 469: -#line 5167 "Gmsh.y" +#line 5169 "Gmsh.y" { for(int i = 0; i < 5; i++) (yyval.v)[i] = -(yyvsp[(2) - (2)].v)[i]; ;} break; case 470: -#line 5171 "Gmsh.y" +#line 5173 "Gmsh.y" { for(int i = 0; i < 5; i++) (yyval.v)[i] = (yyvsp[(2) - (2)].v)[i]; ;} break; case 471: -#line 5175 "Gmsh.y" +#line 5177 "Gmsh.y" { for(int i = 0; i < 5; i++) (yyval.v)[i] = (yyvsp[(1) - (3)].v)[i] - (yyvsp[(3) - (3)].v)[i]; ;} break; case 472: -#line 5179 "Gmsh.y" +#line 5181 "Gmsh.y" { for(int i = 0; i < 5; i++) (yyval.v)[i] = (yyvsp[(1) - (3)].v)[i] + (yyvsp[(3) - (3)].v)[i]; ;} break; case 473: -#line 5186 "Gmsh.y" +#line 5188 "Gmsh.y" { (yyval.v)[0] = (yyvsp[(2) - (11)].d); (yyval.v)[1] = (yyvsp[(4) - (11)].d); (yyval.v)[2] = (yyvsp[(6) - (11)].d); (yyval.v)[3] = (yyvsp[(8) - (11)].d); (yyval.v)[4] = (yyvsp[(10) - (11)].d); ;} break; case 474: -#line 5190 "Gmsh.y" +#line 5192 "Gmsh.y" { (yyval.v)[0] = (yyvsp[(2) - (9)].d); (yyval.v)[1] = (yyvsp[(4) - (9)].d); (yyval.v)[2] = (yyvsp[(6) - (9)].d); (yyval.v)[3] = (yyvsp[(8) - (9)].d); (yyval.v)[4] = 1.0; ;} break; case 475: -#line 5194 "Gmsh.y" +#line 5196 "Gmsh.y" { (yyval.v)[0] = (yyvsp[(2) - (7)].d); (yyval.v)[1] = (yyvsp[(4) - (7)].d); (yyval.v)[2] = (yyvsp[(6) - (7)].d); (yyval.v)[3] = 0.0; (yyval.v)[4] = 1.0; ;} break; case 476: -#line 5198 "Gmsh.y" +#line 5200 "Gmsh.y" { (yyval.v)[0] = (yyvsp[(2) - (7)].d); (yyval.v)[1] = (yyvsp[(4) - (7)].d); (yyval.v)[2] = (yyvsp[(6) - (7)].d); (yyval.v)[3] = 0.0; (yyval.v)[4] = 1.0; ;} break; case 477: -#line 5205 "Gmsh.y" +#line 5207 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(List_T*)); List_Add((yyval.l), &((yyvsp[(1) - (1)].l))); @@ -12181,14 +12183,14 @@ yyreduce: break; case 478: -#line 5210 "Gmsh.y" +#line 5212 "Gmsh.y" { List_Add((yyval.l), &((yyvsp[(3) - (3)].l))); ;} break; case 479: -#line 5217 "Gmsh.y" +#line 5219 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(double)); List_Add((yyval.l), &((yyvsp[(1) - (1)].d))); @@ -12196,14 +12198,14 @@ yyreduce: break; case 480: -#line 5222 "Gmsh.y" +#line 5224 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 481: -#line 5226 "Gmsh.y" +#line 5228 "Gmsh.y" { // creates an empty list (yyval.l) = List_Create(2, 1, sizeof(double)); @@ -12211,14 +12213,14 @@ yyreduce: break; case 482: -#line 5231 "Gmsh.y" +#line 5233 "Gmsh.y" { (yyval.l) = (yyvsp[(2) - (3)].l); ;} break; case 483: -#line 5235 "Gmsh.y" +#line 5237 "Gmsh.y" { (yyval.l) = (yyvsp[(3) - (4)].l); for(int i = 0; i < List_Nbr((yyval.l)); i++){ @@ -12229,7 +12231,7 @@ yyreduce: break; case 484: -#line 5243 "Gmsh.y" +#line 5245 "Gmsh.y" { (yyval.l) = (yyvsp[(4) - (5)].l); for(int i = 0; i < List_Nbr((yyval.l)); i++){ @@ -12240,14 +12242,14 @@ yyreduce: break; case 485: -#line 5254 "Gmsh.y" +#line 5256 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 486: -#line 5258 "Gmsh.y" +#line 5260 "Gmsh.y" { if(!strcmp((yyvsp[(1) - (1)].c), "*") || !strcmp((yyvsp[(1) - (1)].c), "all")) (yyval.l) = 0; @@ -12259,7 +12261,7 @@ yyreduce: break; case 487: -#line 5270 "Gmsh.y" +#line 5272 "Gmsh.y" { (yyval.l) = (yyvsp[(2) - (2)].l); for(int i = 0; i < List_Nbr((yyval.l)); i++){ @@ -12270,7 +12272,7 @@ yyreduce: break; case 488: -#line 5278 "Gmsh.y" +#line 5280 "Gmsh.y" { (yyval.l) = (yyvsp[(3) - (3)].l); for(int i = 0; i < List_Nbr((yyval.l)); i++){ @@ -12281,7 +12283,7 @@ yyreduce: break; case 489: -#line 5286 "Gmsh.y" +#line 5288 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(double)); for(double d = (yyvsp[(1) - (3)].d); ((yyvsp[(1) - (3)].d) < (yyvsp[(3) - (3)].d)) ? (d <= (yyvsp[(3) - (3)].d)) : (d >= (yyvsp[(3) - (3)].d)); @@ -12291,7 +12293,7 @@ yyreduce: break; case 490: -#line 5293 "Gmsh.y" +#line 5295 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(double)); if(!(yyvsp[(5) - (5)].d)){ //|| ($1 < $3 && $5 < 0) || ($1 > $3 && $5 > 0) @@ -12304,7 +12306,7 @@ yyreduce: break; case 491: -#line 5303 "Gmsh.y" +#line 5305 "Gmsh.y" { (yyval.l) = List_Create(3, 1, sizeof(double)); int tag = (int)(yyvsp[(3) - (4)].d); @@ -12330,7 +12332,7 @@ yyreduce: break; case 492: -#line 5326 "Gmsh.y" +#line 5328 "Gmsh.y" { (yyval.l) = List_Create(10, 10, sizeof(double)); getAllElementaryTags((yyvsp[(1) - (2)].i), (yyval.l)); @@ -12339,7 +12341,7 @@ yyreduce: break; case 493: -#line 5332 "Gmsh.y" +#line 5334 "Gmsh.y" { (yyval.l) = List_Create(10, 10, sizeof(double)); if(!(yyvsp[(3) - (3)].l)){ @@ -12353,7 +12355,7 @@ yyreduce: break; case 494: -#line 5344 "Gmsh.y" +#line 5346 "Gmsh.y" { (yyval.l) = List_Create(10, 10, sizeof(double)); getElementaryTagsInBoundingBox((yyvsp[(1) - (16)].i), (yyvsp[(5) - (16)].d), (yyvsp[(7) - (16)].d), (yyvsp[(9) - (16)].d), (yyvsp[(11) - (16)].d), (yyvsp[(13) - (16)].d), (yyvsp[(15) - (16)].d), (yyval.l)); @@ -12361,7 +12363,7 @@ yyreduce: break; case 495: -#line 5349 "Gmsh.y" +#line 5351 "Gmsh.y" { (yyval.l) = List_Create(List_Nbr((yyvsp[(1) - (1)].l)), 1, sizeof(double)); for(int i = 0; i < List_Nbr((yyvsp[(1) - (1)].l)); i++){ @@ -12374,7 +12376,7 @@ yyreduce: break; case 496: -#line 5359 "Gmsh.y" +#line 5361 "Gmsh.y" { (yyval.l) = List_Create(List_Nbr((yyvsp[(1) - (1)].l)), 1, sizeof(double)); for(int i = 0; i < List_Nbr((yyvsp[(1) - (1)].l)); i++){ @@ -12387,7 +12389,7 @@ yyreduce: break; case 497: -#line 5369 "Gmsh.y" +#line 5371 "Gmsh.y" { (yyval.l) = List_Create(List_Nbr((yyvsp[(1) - (1)].l)), 1, sizeof(double)); for(int i = 0; i < List_Nbr((yyvsp[(1) - (1)].l)); i++){ @@ -12400,7 +12402,7 @@ yyreduce: break; case 498: -#line 5379 "Gmsh.y" +#line 5381 "Gmsh.y" { (yyval.l) = List_Create(20, 20, sizeof(double)); if(!gmsh_yysymbols.count((yyvsp[(1) - (3)].c))) @@ -12415,21 +12417,21 @@ yyreduce: break; case 499: -#line 5391 "Gmsh.y" +#line 5393 "Gmsh.y" { (yyval.l) = treat_Struct_FullName_dot_tSTRING_ListOfFloat(NULL, (yyvsp[(1) - (5)].c), (yyvsp[(3) - (5)].c)); ;} break; case 500: -#line 5395 "Gmsh.y" +#line 5397 "Gmsh.y" { (yyval.l) = treat_Struct_FullName_dot_tSTRING_ListOfFloat((yyvsp[(1) - (7)].c), (yyvsp[(3) - (7)].c), (yyvsp[(5) - (7)].c)); ;} break; case 501: -#line 5400 "Gmsh.y" +#line 5402 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(double)); if(!gmsh_yysymbols.count((yyvsp[(3) - (4)].c))) @@ -12444,28 +12446,28 @@ yyreduce: break; case 502: -#line 5412 "Gmsh.y" +#line 5414 "Gmsh.y" { (yyval.l) = (yyvsp[(3) - (4)].l); ;} break; case 503: -#line 5416 "Gmsh.y" +#line 5418 "Gmsh.y" { (yyval.l) = (yyvsp[(3) - (4)].l); ;} break; case 504: -#line 5420 "Gmsh.y" +#line 5422 "Gmsh.y" { (yyval.l) = (yyvsp[(4) - (6)].l); ;} break; case 505: -#line 5424 "Gmsh.y" +#line 5426 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(double)); if(!gmsh_yysymbols.count((yyvsp[(1) - (6)].c))) @@ -12486,7 +12488,7 @@ yyreduce: break; case 506: -#line 5442 "Gmsh.y" +#line 5444 "Gmsh.y" { (yyval.l) = List_Create(20,20,sizeof(double)); for(int i = 0; i < (int)(yyvsp[(7) - (8)].d); i++) { @@ -12497,7 +12499,7 @@ yyreduce: break; case 507: -#line 5450 "Gmsh.y" +#line 5452 "Gmsh.y" { (yyval.l) = List_Create(20,20,sizeof(double)); for(int i = 0; i < (int)(yyvsp[(7) - (8)].d); i++) { @@ -12508,7 +12510,7 @@ yyreduce: break; case 508: -#line 5458 "Gmsh.y" +#line 5460 "Gmsh.y" { Msg::Barrier(); FILE *File; @@ -12540,7 +12542,7 @@ yyreduce: break; case 509: -#line 5487 "Gmsh.y" +#line 5489 "Gmsh.y" { double x0 = (yyvsp[(3) - (14)].d), x1 = (yyvsp[(5) - (14)].d), y0 = (yyvsp[(7) - (14)].d), y1 = (yyvsp[(9) - (14)].d), ys = (yyvsp[(11) - (14)].d); int N = (int)(yyvsp[(13) - (14)].d); @@ -12553,7 +12555,7 @@ yyreduce: break; case 510: -#line 5497 "Gmsh.y" +#line 5499 "Gmsh.y" { std::vector<double> tmp; for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++){ @@ -12572,7 +12574,7 @@ yyreduce: break; case 511: -#line 5513 "Gmsh.y" +#line 5515 "Gmsh.y" { for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++){ double *d = (double*)List_Pointer((yyvsp[(3) - (4)].l), i); @@ -12583,7 +12585,7 @@ yyreduce: break; case 512: -#line 5524 "Gmsh.y" +#line 5526 "Gmsh.y" { (yyval.l) = List_Create(2, 1, sizeof(double)); List_Add((yyval.l), &((yyvsp[(1) - (1)].d))); @@ -12591,21 +12593,21 @@ yyreduce: break; case 513: -#line 5529 "Gmsh.y" +#line 5531 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 514: -#line 5533 "Gmsh.y" +#line 5535 "Gmsh.y" { List_Add((yyval.l), &((yyvsp[(3) - (3)].d))); ;} break; case 515: -#line 5537 "Gmsh.y" +#line 5539 "Gmsh.y" { for(int i = 0; i < List_Nbr((yyvsp[(3) - (3)].l)); i++){ double d; @@ -12617,21 +12619,21 @@ yyreduce: break; case 516: -#line 5549 "Gmsh.y" +#line 5551 "Gmsh.y" { (yyval.u) = CTX::instance()->packColor((int)(yyvsp[(2) - (9)].d), (int)(yyvsp[(4) - (9)].d), (int)(yyvsp[(6) - (9)].d), (int)(yyvsp[(8) - (9)].d)); ;} break; case 517: -#line 5553 "Gmsh.y" +#line 5555 "Gmsh.y" { (yyval.u) = CTX::instance()->packColor((int)(yyvsp[(2) - (7)].d), (int)(yyvsp[(4) - (7)].d), (int)(yyvsp[(6) - (7)].d), 255); ;} break; case 518: -#line 5565 "Gmsh.y" +#line 5567 "Gmsh.y" { int flag = 0; if(gmsh_yystringsymbols.count((yyvsp[(1) - (1)].c))){ @@ -12651,7 +12653,7 @@ yyreduce: break; case 519: -#line 5582 "Gmsh.y" +#line 5584 "Gmsh.y" { unsigned int val = 0; ColorOption(GMSH_GET, (yyvsp[(1) - (5)].c), 0, (yyvsp[(5) - (5)].c), val); @@ -12661,14 +12663,14 @@ yyreduce: break; case 520: -#line 5592 "Gmsh.y" +#line 5594 "Gmsh.y" { (yyval.l) = (yyvsp[(2) - (3)].l); ;} break; case 521: -#line 5596 "Gmsh.y" +#line 5598 "Gmsh.y" { (yyval.l) = List_Create(256, 10, sizeof(unsigned int)); GmshColorTable *ct = GetColorTable((int)(yyvsp[(3) - (6)].d)); @@ -12683,7 +12685,7 @@ yyreduce: break; case 522: -#line 5611 "Gmsh.y" +#line 5613 "Gmsh.y" { (yyval.l) = List_Create(256, 10, sizeof(unsigned int)); List_Add((yyval.l), &((yyvsp[(1) - (1)].u))); @@ -12691,21 +12693,21 @@ yyreduce: break; case 523: -#line 5616 "Gmsh.y" +#line 5618 "Gmsh.y" { List_Add((yyval.l), &((yyvsp[(3) - (3)].u))); ;} break; case 524: -#line 5623 "Gmsh.y" +#line 5625 "Gmsh.y" { (yyval.c) = (yyvsp[(1) - (1)].c); ;} break; case 525: -#line 5627 "Gmsh.y" +#line 5629 "Gmsh.y" { // No need to extend to Struct_FullName (a Tag is not a String) (yyval.c) = treat_Struct_FullName_String(NULL, (yyvsp[(1) - (1)].c)); @@ -12713,7 +12715,7 @@ yyreduce: break; case 526: -#line 5632 "Gmsh.y" +#line 5634 "Gmsh.y" { std::string val; int j = (int)(yyvsp[(3) - (4)].d); @@ -12730,7 +12732,7 @@ yyreduce: break; case 527: -#line 5646 "Gmsh.y" +#line 5648 "Gmsh.y" { std::string val; int j = (int)(yyvsp[(3) - (4)].d); @@ -12747,35 +12749,35 @@ yyreduce: break; case 528: -#line 5662 "Gmsh.y" +#line 5664 "Gmsh.y" { (yyval.c) = treat_Struct_FullName_dot_tSTRING_String(NULL, (yyvsp[(1) - (3)].c), (yyvsp[(3) - (3)].c)); ;} break; case 529: -#line 5666 "Gmsh.y" +#line 5668 "Gmsh.y" { (yyval.c) = treat_Struct_FullName_dot_tSTRING_String((yyvsp[(1) - (5)].c), (yyvsp[(3) - (5)].c), (yyvsp[(5) - (5)].c)); ;} break; case 530: -#line 5670 "Gmsh.y" +#line 5672 "Gmsh.y" { (yyval.c) = treat_Struct_FullName_dot_tSTRING_String(NULL, (yyvsp[(1) - (6)].c), (yyvsp[(3) - (6)].c), (int)(yyvsp[(5) - (6)].d)); ;} break; case 531: -#line 5674 "Gmsh.y" +#line 5676 "Gmsh.y" { (yyval.c) = treat_Struct_FullName_dot_tSTRING_String((yyvsp[(1) - (8)].c), (yyvsp[(3) - (8)].c), (yyvsp[(5) - (8)].c), (int)(yyvsp[(7) - (8)].d)); ;} break; case 532: -#line 5678 "Gmsh.y" +#line 5680 "Gmsh.y" { std::string out; StringOption(GMSH_GET, (yyvsp[(1) - (6)].c), (int)(yyvsp[(3) - (6)].d), (yyvsp[(6) - (6)].c), out); @@ -12786,7 +12788,7 @@ yyreduce: break; case 533: -#line 5686 "Gmsh.y" +#line 5688 "Gmsh.y" { std::string name = GModel::current()->getPhysicalName(0, (int)(yyvsp[(4) - (5)].d)); (yyval.c) = (char*)Malloc((name.size() + 1) * sizeof(char)); @@ -12795,7 +12797,7 @@ yyreduce: break; case 534: -#line 5692 "Gmsh.y" +#line 5694 "Gmsh.y" { std::string name = GModel::current()->getPhysicalName(1, (int)(yyvsp[(4) - (5)].d)); (yyval.c) = (char*)Malloc((name.size() + 1) * sizeof(char)); @@ -12804,7 +12806,7 @@ yyreduce: break; case 535: -#line 5698 "Gmsh.y" +#line 5700 "Gmsh.y" { std::string name = GModel::current()->getPhysicalName(2, (int)(yyvsp[(4) - (5)].d)); (yyval.c) = (char*)Malloc((name.size() + 1) * sizeof(char)); @@ -12813,7 +12815,7 @@ yyreduce: break; case 536: -#line 5704 "Gmsh.y" +#line 5706 "Gmsh.y" { std::string name = GModel::current()->getPhysicalName(3, (int)(yyvsp[(4) - (5)].d)); (yyval.c) = (char*)Malloc((name.size() + 1) * sizeof(char)); @@ -12822,21 +12824,21 @@ yyreduce: break; case 537: -#line 5713 "Gmsh.y" +#line 5715 "Gmsh.y" { (yyval.c) = (yyvsp[(1) - (1)].c); ;} break; case 538: -#line 5717 "Gmsh.y" +#line 5719 "Gmsh.y" { (yyval.c) = (yyvsp[(3) - (4)].c); ;} break; case 539: -#line 5721 "Gmsh.y" +#line 5723 "Gmsh.y" { (yyval.c) = (char *)Malloc(32 * sizeof(char)); time_t now; @@ -12847,7 +12849,7 @@ yyreduce: break; case 540: -#line 5729 "Gmsh.y" +#line 5731 "Gmsh.y" { std::string exe = Msg::GetExecutableName(); (yyval.c) = (char *)Malloc(exe.size() + 1); @@ -12856,7 +12858,7 @@ yyreduce: break; case 541: -#line 5735 "Gmsh.y" +#line 5737 "Gmsh.y" { std::string action = Msg::GetOnelabAction(); (yyval.c) = (char *)Malloc(action.size() + 1); @@ -12865,14 +12867,14 @@ yyreduce: break; case 542: -#line 5741 "Gmsh.y" +#line 5743 "Gmsh.y" { (yyval.c) = strsave((char*)"Gmsh"); ;} break; case 543: -#line 5745 "Gmsh.y" +#line 5747 "Gmsh.y" { const char *env = GetEnvironmentVar((yyvsp[(3) - (4)].c)); if(!env) env = ""; @@ -12883,7 +12885,7 @@ yyreduce: break; case 544: -#line 5753 "Gmsh.y" +#line 5755 "Gmsh.y" { std::string s = Msg::GetString((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].c)); (yyval.c) = (char *)Malloc((s.size() + 1) * sizeof(char)); @@ -12894,7 +12896,7 @@ yyreduce: break; case 545: -#line 5761 "Gmsh.y" +#line 5763 "Gmsh.y" { std::string s = Msg::GetOnelabString((yyvsp[(3) - (4)].c)); (yyval.c) = (char *)Malloc((s.size() + 1) * sizeof(char)); @@ -12904,7 +12906,7 @@ yyreduce: break; case 546: -#line 5768 "Gmsh.y" +#line 5770 "Gmsh.y" { std::string s = Msg::GetOnelabString((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].c)); (yyval.c) = (char *)Malloc((s.size() + 1) * sizeof(char)); @@ -12915,21 +12917,21 @@ yyreduce: break; case 547: -#line 5777 "Gmsh.y" +#line 5779 "Gmsh.y" { (yyval.c) = treat_Struct_FullName_String(NULL, (yyvsp[(3) - (5)].c2).char2, 1, 0, (yyvsp[(4) - (5)].c), 2); ;} break; case 548: -#line 5781 "Gmsh.y" +#line 5783 "Gmsh.y" { (yyval.c) = treat_Struct_FullName_dot_tSTRING_String((yyvsp[(3) - (7)].c2).char1, (yyvsp[(3) - (7)].c2).char2, (yyvsp[(5) - (7)].c), 0, (yyvsp[(6) - (7)].c), 2); ;} break; case 549: -#line 5785 "Gmsh.y" +#line 5787 "Gmsh.y" { int size = 1; for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++) @@ -12947,7 +12949,7 @@ yyreduce: break; case 550: -#line 5800 "Gmsh.y" +#line 5802 "Gmsh.y" { (yyval.c) = (char *)Malloc((strlen((yyvsp[(3) - (4)].c)) + 1) * sizeof(char)); int i; @@ -12964,7 +12966,7 @@ yyreduce: break; case 551: -#line 5814 "Gmsh.y" +#line 5816 "Gmsh.y" { (yyval.c) = (char *)Malloc((strlen((yyvsp[(3) - (4)].c)) + 1) * sizeof(char)); int i; @@ -12981,7 +12983,7 @@ yyreduce: break; case 552: -#line 5828 "Gmsh.y" +#line 5830 "Gmsh.y" { std::string input = (yyvsp[(3) - (8)].c); std::string substr_old = (yyvsp[(5) - (8)].c); @@ -12996,7 +12998,7 @@ yyreduce: break; case 553: -#line 5840 "Gmsh.y" +#line 5842 "Gmsh.y" { int size = 1; for(int i = 0; i < List_Nbr((yyvsp[(3) - (4)].l)); i++) @@ -13015,7 +13017,7 @@ yyreduce: break; case 554: -#line 5856 "Gmsh.y" +#line 5858 "Gmsh.y" { int i = 0; while ((yyvsp[(3) - (4)].c)[i]) { @@ -13027,7 +13029,7 @@ yyreduce: break; case 555: -#line 5865 "Gmsh.y" +#line 5867 "Gmsh.y" { int i = 0; while ((yyvsp[(3) - (4)].c)[i]) { @@ -13039,7 +13041,7 @@ yyreduce: break; case 556: -#line 5874 "Gmsh.y" +#line 5876 "Gmsh.y" { int i = 0; while ((yyvsp[(3) - (4)].c)[i]) { @@ -13052,7 +13054,7 @@ yyreduce: break; case 557: -#line 5884 "Gmsh.y" +#line 5886 "Gmsh.y" { if((yyvsp[(3) - (8)].d)){ (yyval.c) = (yyvsp[(5) - (8)].c); @@ -13066,7 +13068,7 @@ yyreduce: break; case 558: -#line 5895 "Gmsh.y" +#line 5897 "Gmsh.y" { std::string in = (yyvsp[(3) - (8)].c); std::string out = in.substr((int)(yyvsp[(5) - (8)].d), (int)(yyvsp[(7) - (8)].d)); @@ -13077,7 +13079,7 @@ yyreduce: break; case 559: -#line 5903 "Gmsh.y" +#line 5905 "Gmsh.y" { std::string in = (yyvsp[(3) - (6)].c); std::string out = in.substr((int)(yyvsp[(5) - (6)].d), std::string::npos); @@ -13088,14 +13090,14 @@ yyreduce: break; case 560: -#line 5911 "Gmsh.y" +#line 5913 "Gmsh.y" { (yyval.c) = (yyvsp[(3) - (4)].c); ;} break; case 561: -#line 5915 "Gmsh.y" +#line 5917 "Gmsh.y" { char tmpstring[5000]; int i = printListOfDouble((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].l), tmpstring); @@ -13117,7 +13119,7 @@ yyreduce: break; case 562: -#line 5934 "Gmsh.y" +#line 5936 "Gmsh.y" { std::string tmp = FixRelativePath(gmsh_yyname, (yyvsp[(3) - (4)].c)); (yyval.c) = (char*)Malloc((tmp.size() + 1) * sizeof(char)); @@ -13127,7 +13129,7 @@ yyreduce: break; case 563: -#line 5941 "Gmsh.y" +#line 5943 "Gmsh.y" { std::string tmp = SplitFileName(GetAbsolutePath(gmsh_yyname))[0]; (yyval.c) = (char*)Malloc((tmp.size() + 1) * sizeof(char)); @@ -13136,7 +13138,7 @@ yyreduce: break; case 564: -#line 5947 "Gmsh.y" +#line 5949 "Gmsh.y" { std::string tmp = SplitFileName((yyvsp[(3) - (4)].c))[0]; (yyval.c) = (char*)Malloc((tmp.size() + 1) * sizeof(char)); @@ -13146,7 +13148,7 @@ yyreduce: break; case 565: -#line 5954 "Gmsh.y" +#line 5956 "Gmsh.y" { std::string tmp = GetAbsolutePath((yyvsp[(3) - (4)].c)); (yyval.c) = (char*)Malloc((tmp.size() + 1) * sizeof(char)); @@ -13156,12 +13158,12 @@ yyreduce: break; case 566: -#line 5961 "Gmsh.y" +#line 5963 "Gmsh.y" { init_options(); ;} break; case 567: -#line 5963 "Gmsh.y" +#line 5965 "Gmsh.y" { std::string val((yyvsp[(3) - (6)].c)); Msg::ExchangeOnelabParameter("", val, floatOptions, charOptions); @@ -13172,7 +13174,7 @@ yyreduce: break; case 568: -#line 5971 "Gmsh.y" +#line 5973 "Gmsh.y" { std::string out; const std::string * key_struct = NULL; @@ -13196,37 +13198,37 @@ yyreduce: break; case 569: -#line 5995 "Gmsh.y" +#line 5997 "Gmsh.y" { struct_namespace = std::string(""); (yyval.d) = (yyvsp[(2) - (2)].d); ;} break; case 570: -#line 5997 "Gmsh.y" +#line 5999 "Gmsh.y" { struct_namespace = (yyvsp[(1) - (4)].c); Free((yyvsp[(1) - (4)].c)); (yyval.d) = (yyvsp[(4) - (4)].d); ;} break; case 571: -#line 6003 "Gmsh.y" +#line 6005 "Gmsh.y" { (yyval.l) = (yyvsp[(3) - (4)].l); ;} break; case 572: -#line 6008 "Gmsh.y" +#line 6010 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 573: -#line 6010 "Gmsh.y" +#line 6012 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 574: -#line 6015 "Gmsh.y" +#line 6017 "Gmsh.y" { (yyval.l) = (yyvsp[(2) - (3)].l); ;} break; case 575: -#line 6020 "Gmsh.y" +#line 6022 "Gmsh.y" { (yyval.l) = List_Create(20,20,sizeof(char*)); List_Add((yyval.l), &((yyvsp[(1) - (1)].c))); @@ -13234,19 +13236,19 @@ yyreduce: break; case 576: -#line 6025 "Gmsh.y" +#line 6027 "Gmsh.y" { (yyval.l) = (yyvsp[(1) - (1)].l); ;} break; case 577: -#line 6027 "Gmsh.y" +#line 6029 "Gmsh.y" { List_Add((yyval.l), &((yyvsp[(3) - (3)].c))); ;} break; case 578: -#line 6031 "Gmsh.y" +#line 6033 "Gmsh.y" { for(int i = 0; i < List_Nbr((yyvsp[(3) - (3)].l)); i++){ char* c; @@ -13258,7 +13260,7 @@ yyreduce: break; case 579: -#line 6043 "Gmsh.y" +#line 6045 "Gmsh.y" { (yyval.l) = List_Create(20, 20, sizeof(char *)); if(!gmsh_yystringsymbols.count((yyvsp[(1) - (3)].c))) @@ -13275,21 +13277,21 @@ yyreduce: break; case 580: -#line 6057 "Gmsh.y" +#line 6059 "Gmsh.y" { (yyval.l) = treat_Struct_FullName_dot_tSTRING_ListOfString(NULL, (yyvsp[(1) - (5)].c), (yyvsp[(3) - (5)].c)); ;} break; case 581: -#line 6061 "Gmsh.y" +#line 6063 "Gmsh.y" { (yyval.l) = treat_Struct_FullName_dot_tSTRING_ListOfString((yyvsp[(1) - (7)].c), (yyvsp[(3) - (7)].c), (yyvsp[(5) - (7)].c)); ;} break; case 582: -#line 6068 "Gmsh.y" +#line 6070 "Gmsh.y" { char tmpstr[256]; sprintf(tmpstr, "_%d", (int)(yyvsp[(4) - (5)].d)); @@ -13300,7 +13302,7 @@ yyreduce: break; case 583: -#line 6076 "Gmsh.y" +#line 6078 "Gmsh.y" { char tmpstr[256]; sprintf(tmpstr, "_%d", (int)(yyvsp[(4) - (5)].d)); @@ -13311,7 +13313,7 @@ yyreduce: break; case 584: -#line 6084 "Gmsh.y" +#line 6086 "Gmsh.y" { char tmpstr[256]; sprintf(tmpstr, "_%d", (int)(yyvsp[(7) - (8)].d)); @@ -13322,23 +13324,23 @@ yyreduce: break; case 585: -#line 6095 "Gmsh.y" +#line 6097 "Gmsh.y" { (yyval.c) = (yyvsp[(1) - (1)].c); ;} break; case 586: -#line 6097 "Gmsh.y" +#line 6099 "Gmsh.y" { (yyval.c) = (yyvsp[(1) - (1)].c); ;} break; case 587: -#line 6100 "Gmsh.y" +#line 6102 "Gmsh.y" { (yyval.c) = (yyvsp[(3) - (4)].c); ;} break; /* Line 1267 of yacc.c. */ -#line 13342 "Gmsh.tab.cpp" +#line 13344 "Gmsh.tab.cpp" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -13552,7 +13554,7 @@ yyreturn: } -#line 6103 "Gmsh.y" +#line 6105 "Gmsh.y" void assignVariable(const std::string &name, int index, int assignType, diff --git a/Parser/Gmsh.y b/Parser/Gmsh.y index 4c50dcd5faffad144709786a41ee914cd7df41cc..f733ad39e9a82a6640c034be1e7e041da9abd479 100644 --- a/Parser/Gmsh.y +++ b/Parser/Gmsh.y @@ -3941,13 +3941,14 @@ Boolean : bool r = true; if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){ std::vector<std::pair<int, int > > object, tool, out; + std::vector<std::vector<std::pair<int, int > > > outMap; ListOfShapes2VectorOfPairs($3, object); ListOfShapes2VectorOfPairs($7, tool); // currently we don't distinguish between Delete and Recursive Delete: // we always delete recursively. Let us know if you have examples where // having the choice would be interesting r = GModel::current()->getOCCInternals()->booleanOperator - (-1, (OCC_Internals::BooleanOperator)$1, object, tool, out, $4, $8); + (-1, (OCC_Internals::BooleanOperator)$1, object, tool, out, outMap, $4, $8); VectorOfPairs2ListOfShapes(out, $$); } else{ @@ -3982,13 +3983,14 @@ BooleanShape : bool r = true; if(gmsh_yyfactory == "OpenCASCADE" && GModel::current()->getOCCInternals()){ std::vector<std::pair<int, int> > object, tool, out; + std::vector<std::vector<std::pair<int, int > > > outMap; ListOfShapes2VectorOfPairs($7, object); ListOfShapes2VectorOfPairs($11, tool); // currently we don't distinguish between Delete and Recursive Delete: // we always delete recursively. Let us know if you have examples where // having the choice would be interesting r = GModel::current()->getOCCInternals()->booleanOperator - ((int)$3, (OCC_Internals::BooleanOperator)$1, object, tool, out, $8, $12); + ((int)$3, (OCC_Internals::BooleanOperator)$1, object, tool, out, outMap, $8, $12); } if(!r) yymsg(0, "Could not apply boolean operator"); List_Delete($7); diff --git a/Post/PViewVertexArrays.cpp b/Post/PViewVertexArrays.cpp index e6a9b56609d011f4dcc7b22c57f493220480e562..bcd22f7a74ed61dcf2a2101a9aa623a5a551c050 100644 --- a/Post/PViewVertexArrays.cpp +++ b/Post/PViewVertexArrays.cpp @@ -806,8 +806,7 @@ static void addScalarPrism(PView *p, double **xyz, double **val, bool pre) PViewOptions *opt = p->getOptions(); const int iq[3][4] = {{0, 1, 4, 3}, {0, 3, 5, 2}, {1, 2, 5, 4}}; const int it[2][3] = {{0, 2, 1}, {3, 4, 5}}; - // const int is[3][4] = {{0, 1, 2, 3}, {3, 4, 5, 2}, {1, 2, 4, 3}}; - const int is[3][4] = {{0,1,2,4}, {0,2,4,5}, {0,3,4,5}}; + const int is[3][4] = {{0, 1, 2, 4}, {0, 4, 2, 5}, {0, 3, 4, 5}}; if(opt->boundary > 0){ opt->boundary--; @@ -839,8 +838,7 @@ static void addScalarPyramid(PView *p, double **xyz, PViewOptions *opt = p->getOptions(); const int it[4][3] = {{0, 1, 4}, {3, 0, 4}, {1, 2, 4}, {2, 3, 4}}; - //const int is[2][4] = {{0, 1, 2, 4}, {2, 3, 0, 4}}; - const int is[2][4] = {{0,1,3,4}, {1,2,3,4}}; + const int is[2][4] = {{0, 1, 3, 4}, {1, 2, 3, 4}}; if(opt->boundary > 0){ opt->boundary--; diff --git a/benchmarks/3d/Cube-05.geo b/benchmarks/3d/Cube-05.geo index 12e4015f450909bc919860a9191fd9346cc00ce0..720725b92804e7648635f4a553a7bb5f6237e472 100644 --- a/benchmarks/3d/Cube-05.geo +++ b/benchmarks/3d/Cube-05.geo @@ -1,5 +1,5 @@ -lv = .1; -lc = .1; +lv = .15; +lc = .12; Point(1) = {0.0,0.0,0.0,lv}; Point(2) = {1,0.0,0.0,lv}; Point(3) = {1,1,0.0,lv}; diff --git a/demos/boolean/baffles.geo b/demos/boolean/baffles.geo index 17399104a333a5d81d7226130705a7df32f4e4d6..64d43c444214f5fce9ee51a2d9a3f04ec38bae71 100644 --- a/demos/boolean/baffles.geo +++ b/demos/boolean/baffles.geo @@ -1,12 +1,16 @@ SetFactory("OpenCASCADE"); + Block(1) = {-0, 0, 0, 1, 1, 1}; -// intersecting: +p() = PointsOf{ Volume{1}; }; +Characteristic Length{p()} = 0.2; + Rectangle(7) = {0.4, 0.7, 0.2, 0.3, 0.3, 0}; Rectangle(8) = {-0.2, 0.3, 0.5, 0.3, 0.3, 0}; Rectangle(9) = {0.8, -0.2, 0.5, 0.3, 0.3, 0}; -BooleanFragments{ Volume{1}; Delete; }{ Surface{7:9}; Delete; } +Rectangle(10) = {0.3, 0.3, 0.5, 0.3, 0.3, 0}; + +b() = BooleanFragments{ Volume{1}; Delete; }{ Surface{7:10}; Delete; }; -// fully inside -Rectangle(30) = {0.3, 0.3, 0.5, 0.3, 0.3, 0}; -Surface {30} In Volume{1}; +p() = PointsOf{ Surface{b({1:6})}; }; +Characteristic Length{p()} = 0.04; diff --git a/demos/boolean/fragment_numbering.geo b/demos/boolean/fragment_numbering.geo index 40c6f09ac990aa74f1b8f8c291899254c8d5539a..e627c69ea6d4af220c61c09c2b61a478e6d50dad 100644 --- a/demos/boolean/fragment_numbering.geo +++ b/demos/boolean/fragment_numbering.geo @@ -1,5 +1,6 @@ SetFactory("OpenCASCADE"); +//Geometry.LineNumbers = 1; Geometry.SurfaceNumbers = 1; DefineConstant[ @@ -17,6 +18,10 @@ Translate {2*w, 0, 0} { Duplicata { Surface{4}; } } Rectangle(6) = {-6*w, 0, 0, 12*w, 5*w, 0}; +b() = Boundary{ Surface{6}; }; +t = b(2); +Printf("top line tag: ", t); + b() = {}; For i In {1:N} s = news; b() += s; Disk(s) = {-w-R-spacing, (2*R+spacing)*i, 0, R}; @@ -24,6 +29,6 @@ EndFor Printf("disk tags: ", b()); -c() = BooleanFragments{ Surface{1:6}; Delete; }{ Surface{b()}; Delete; }; +c() = BooleanFragments{ Line{t}; Surface{1:6}; Delete; }{ Surface{b()}; Delete; }; -Printf("all tags (disk tags should be unchanged!): ", c()); +Printf("all tags (disk and top line tags should be unchanged!): ", c()); diff --git a/doc/gmsh.html b/doc/gmsh.html index 4a20454de8c0e9f49d697dc1258e0d6fb1e729cb..2277b40593030c0b700ce1f97301265a49fac80b 100644 --- a/doc/gmsh.html +++ b/doc/gmsh.html @@ -6,7 +6,7 @@ <title>Gmsh: a three-dimensional finite element mesh generator with built-in pre- and post-processing facilities</title> -<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="keywords" content="free, finite elements, mesh generator, fem, unstructured grids, delaunay, discontinuous galerkin, triangulation, automatic, maillages, mailleur 3D, mesh adaptation, postprocessing, @@ -51,7 +51,7 @@ CAO, OpenGL, GL2PS, Gmesh"> <h1>A three-dimensional finite element mesh generator with built-in pre- and post-processing facilities</h1> -<h4>Christophe Geuzaine and Jean-Fran�ois Remacle</h4> +<h4>Christophe Geuzaine and Jean-François Remacle</h4> <div id="toc"> <a href="#Download">Download</a> @@ -279,7 +279,7 @@ directly</a> for more information. </ul> Cross-patch and STL meshing (Compounds) <ul class="small"> - <li>J.-F. Remacle, C. Geuzaine, G. Comp�re and + <li>J.-F. Remacle, C. Geuzaine, G. Compère and E. Marchandise. <em><a href="doc/preprints/gmsh_stl_preprint.pdf">High-quality surface remeshing using harmonic maps</a></em>. International Journal for Numerical Methods in Engineering 83(4), pp. 403-425, 2010. @@ -301,7 +301,7 @@ directly</a> for more information. a non-uniform quadrilateral mesh generator using a minimum cost perfect matching algorithm</a></em>. International Journal for Numerical Methods in Engineering 89, pp. 1102-1119, 2012. - <li>J.-F. Remacle, F. Henrotte, T. Carrier-Baudouin, E. B�chet, + <li>J.-F. Remacle, F. Henrotte, T. Carrier-Baudouin, E. Béchet, E. Marchandise, C. Geuzaine and T. Mouton. <em><a href="doc/preprints/gmsh_quad2_preprint.pdf">A frontal Delaunay quad mesh generator using the L∞ norm</a></em>. @@ -347,7 +347,7 @@ directly</a> for more information. </ul> Biomedical meshing <ul class="small"> - <li>E. Marchandise, G. Comp�re, M. Willemet, G. Bricteux, C. Geuzaine and + <li>E. Marchandise, G. Compère, M. Willemet, G. Bricteux, C. Geuzaine and J-F Remacle. <em><a href="doc/preprints/gmsh_bio_preprint.pdf">Quality meshing based on STL triangulations for biomedical simulations</a></em>. International Journal for Numerical Methods in Biomedical Engineering diff --git a/doc/texinfo/commandline.texi b/doc/texinfo/commandline.texi index 7c23905418157d3f30e0b7a8c97359006a5d0023..a9ec3cd3e33cf708ceb9e121a61ac2bab1b4b820 100644 --- a/doc/texinfo/commandline.texi +++ b/doc/texinfo/commandline.texi @@ -30,10 +30,12 @@ Perform uniform mesh refinement, then exit Partition after batch mesh generation @item -partWeight tri|quad|tet|prism|hex int Weight of a triangle/quad/etc. during partitioning -@item -saveall +@item -save_all Save all elements (discard physical group definitions) -@item -parametric +@item -save_parametric Save vertices with their parametric coordinates +@item -save_topology +Save model topology @item -algo string Select mesh algorithm (meshadapt, del2d, front2d, delquad, del3d, front3d, mmg3d, pack) @item -smooth int diff --git a/doc/texinfo/opt_fields.texi b/doc/texinfo/opt_fields.texi index ad388855f644a1872f4b4a6adac4610cf4ed18d8..6fc5ba35f336fedb0282f7bdda6c10f75f4d28fc 100644 --- a/doc/texinfo/opt_fields.texi +++ b/doc/texinfo/opt_fields.texi @@ -578,7 +578,7 @@ Options:@* @item InField Id of the field to use as x coordinate.@* type: integer@* -default value: @code{0} +default value: @code{1752631850} @end table @item Param diff --git a/doc/texinfo/opt_geometry.texi b/doc/texinfo/opt_geometry.texi index 9e3bdbc5ef516c1ef0ce75804c0c8b5fc6a6f950..4b9c983a425d66a68c0cd650d9e959d3daa1e807 100644 --- a/doc/texinfo/opt_geometry.texi +++ b/doc/texinfo/opt_geometry.texi @@ -149,6 +149,11 @@ Use multi-threaded OCC boolean operators@* Default value: @code{0}@* Saved in: @code{General.OptionsFileName} +@item Geometry.OCCBooleanPreserveNumbering +Try to preserve numbering of entities through OCC boolean operations@* +Default value: @code{1}@* +Saved in: @code{General.OptionsFileName} + @item Geometry.OCCScaling Scale STEP, IGES and BRep model by given factor@* Default value: @code{1}@* diff --git a/doc/texinfo/opt_mesh.texi b/doc/texinfo/opt_mesh.texi index fee3bb323fc8486ef48a3b578da7a1610aec9773..6e43a4da4b5659bac09688708090ea2c02af2838 100644 --- a/doc/texinfo/opt_mesh.texi +++ b/doc/texinfo/opt_mesh.texi @@ -599,6 +599,11 @@ Type of the element tag saved in mesh formats that don't support saving physical Default value: @code{1}@* Saved in: @code{General.OptionsFileName} +@item Mesh.SaveTopology +Save model topology in MSH2 output files (this is always saved in MSH3)@* +Default value: @code{0}@* +Saved in: @code{General.OptionsFileName} + @item Mesh.SaveParametric Save parametric coordinates of nodes@* Default value: @code{0}@* diff --git a/doc/texinfo/shortcuts.texi b/doc/texinfo/shortcuts.texi index 151e945e4ebb13a393d12ea2bebbd4baaef1c163..f016ecc8b924dca56db01cedc0661eea1f62da07 100644 --- a/doc/texinfo/shortcuts.texi +++ b/doc/texinfo/shortcuts.texi @@ -37,11 +37,11 @@ Abort selection in geometry creation mode @item s Go to solver module @item x -Freeze x coordinate in geometry creation mode +Toogle x coordinate freeze in geometry creation mode @item y -Freeze y coordinate in geometry creation mode +Toogle y coordinate freeze in geometry creation mode @item z -Freeze z coordinate in geometry creation mode +Toogle z coordinate freeze in geometry creation mode @item Shift+a Bring all windows to front @item Shift+g @@ -58,6 +58,12 @@ Show solver options Show post-processing view plugins @item Shift+w Show post-processing view options +@item Shift+x +Move only along x coordinate in geometry creation mode +@item Shift+y +Move only along y coordinate in geometry creation mode +@item Shift+z +Move only along z coordinate in geometry creation mode @item Shift+Escape Enable full mouse selection @item Ctrl+d